4366 lines
		
	
	
		
			130 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			4366 lines
		
	
	
		
			130 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | 
						|
 | 
						|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | 
						|
be copied by any method or incorporated into another program without
 | 
						|
the express written consent of Aerospace C.Power. This Information or any portion
 | 
						|
thereof remains the property of Aerospace C.Power. The Information contained herein
 | 
						|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | 
						|
liability for its use in any way and conveys no license or title under
 | 
						|
any patent or copyright and makes no representation or warranty that this
 | 
						|
Information is free from patent or copyright infringement.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
/* os ship includes */
 | 
						|
#include "os_mem_api.h"
 | 
						|
 | 
						|
/* common includes */
 | 
						|
#include "iot_config_api.h"
 | 
						|
#include "iot_dbglog_api.h"
 | 
						|
#include "iot_errno_api.h"
 | 
						|
#include "iot_utils_api.h"
 | 
						|
#include "iot_io_api.h"
 | 
						|
 | 
						|
/* protocol includes */
 | 
						|
#include "proto_crc16.h"
 | 
						|
#include "proto_645.h"
 | 
						|
#include "proto_69845.h"
 | 
						|
 | 
						|
/* smart grid internal header files */
 | 
						|
#include "iot_sg_cco_drv_api.h"
 | 
						|
#include "iot_sg_fr.h"
 | 
						|
 | 
						|
#define  PROTO_69845_DATA_DESC_LIST_MAX 40
 | 
						|
#define  PROTO_69845_ELEMENT_DATA_RECURSION_CNT_MAX 4
 | 
						|
#define  PROTO_69845_TANS_BAUD_MAX 11
 | 
						|
#define  PORTO_645_BAUD_ID_AUTO    255
 | 
						|
 | 
						|
const uint8_t proto_69845_preamble[PROTO_69845_PREAMBLE_LEN] =
 | 
						|
    { 0xFE, 0xFE, 0xFE, 0xFE };
 | 
						|
 | 
						|
const server_addr_info_t proto_69845_any_server_addr =
 | 
						|
{
 | 
						|
    .len = PROTO_69845_SA_LEN,
 | 
						|
    .type = PROTO_69845_SA_TYPE_WILDCARD,
 | 
						|
    .addr = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xFF},
 | 
						|
    .logical_addr = 0
 | 
						|
};
 | 
						|
 | 
						|
const uint8_t proto_69845_event_report_data[PROTO_69845_EVENT_DATA_LEN] = {
 | 
						|
    0x34, 0x48, 0x33, 0x37, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
 | 
						|
    0x33, 0x33, 0x33, 0x33, 0xdd, 0xdd};
 | 
						|
 | 
						|
const uint8_t proto_69845_rn[PROTO_69845_SECURITY_RN_LEN] = {
 | 
						|
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
    0x00, 0x00, 0x00, 0x00};
 | 
						|
 | 
						|
const uint32_t proto_69845_tans_baud[PROTO_69845_TANS_BAUD_MAX] = {
 | 
						|
    300, 600, 1200, 2400, 4800, 7200, 9600, 19200, 38400, 57600, 115200};
 | 
						|
 | 
						|
const proto_69845_app_data_desc_t proto_69845_data_desc_list[ \
 | 
						|
    PROTO_69845_DATA_DESC_LIST_MAX] = {
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_NULL,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_ARRAY,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_ELEMENT,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_STRUCTURE,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_ELEMENT,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_BOOL,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        1,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_BIT_STRING,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_DIV8,
 | 
						|
        0
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_DOUBLE_LONG,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        4,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        4,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_OCTET_STRING,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_VISIBLE_STRING,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_UTF8_SRTING,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_INTEGER,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        1,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_LONG,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        2,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_UNSIGNED,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        1,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_LONG_UNSIGNED,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        2,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_LONG64,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        8,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_LONG64_UNSIGNED,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        8,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_ENUM,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        1,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_FLOAT32,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        4,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_FLOAT64,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        8,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_DATE_TIME,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        10,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_DATE,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        5,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_TIME,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        3,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_TIME_S,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        7,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_OI,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        2,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_OAD,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        4,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_ROAD,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_ROAD,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_OMD,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        4,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_TI,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        3,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_TSA,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_TSA,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_MAC,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_UNKNOW,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_RN,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_REGION,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_UNKNOW,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_SCALER_UNIT,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        2,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_RSD,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_RSD,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_CSD,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_CSD,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_MS,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_MS,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_SID,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_UNKNOW,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_SID_MAC,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_UNKNOW,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_COMDCB,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_NORMAL,
 | 
						|
        5,
 | 
						|
    },
 | 
						|
    {
 | 
						|
        PROTO_69845_APP_DATA_RCSD,
 | 
						|
        PROTO_69845_DATA_LEN_TYPE_RCSD,
 | 
						|
        0,
 | 
						|
    },
 | 
						|
};
 | 
						|
 | 
						|
uint8_t proto_698_is_security_cmd(uint8_t *data, uint32_t len)
 | 
						|
{
 | 
						|
    uint8_t ret = 0;
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_req_resp_t *resp;
 | 
						|
    apdu_info_t apdu;
 | 
						|
 | 
						|
    if (proto_69845_parse(&data, &len, &head, &apdu) != ERR_OK) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (apdu.len < sizeof(*resp)) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    resp = (proto_69845_app_req_resp_t * )apdu.ptr;
 | 
						|
    if (resp->type == PROTO_69845_C_APP_SECURITY_REQ ||
 | 
						|
        resp->type == PROTO_69845_S_APP_SECURITY_RESP) {
 | 
						|
        ret = 1;
 | 
						|
    }
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t proto_698_interactive_cmd_check(uint8_t *data1, uint32_t len1,
 | 
						|
    uint8_t *data2, uint32_t len2)
 | 
						|
{
 | 
						|
    uint32_t apud_len1, apdu_len2;
 | 
						|
    uint8_t ret = 0, *choice1, *choice2;
 | 
						|
    proto_69845_frame_head_info_t *head1, *head2;
 | 
						|
    proto_69845_app_req_resp_t *resp1, *resp2;
 | 
						|
    proto_69845_app_piid_t *piid1 = NULL, *piid2 = NULL;
 | 
						|
    apdu_info_t apdu1, apdu2;
 | 
						|
 | 
						|
    if (!data1 || !len1 || !data2 || !len2) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (proto_69845_parse(&data1, &len1, &head1, &apdu1) != ERR_OK ||
 | 
						|
        proto_69845_parse(&data2, &len2, &head2, &apdu2) != ERR_OK) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    apud_len1 = apdu1.len;
 | 
						|
    apdu_len2 = apdu2.len;
 | 
						|
    if (apud_len1 < sizeof(*resp1) || apdu_len2 < sizeof(*resp2)) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    apud_len1 -= sizeof(*resp1);
 | 
						|
    apdu_len2 -= sizeof(*resp2);
 | 
						|
    resp1 = (proto_69845_app_req_resp_t * )apdu1.ptr;
 | 
						|
    resp2 = (proto_69845_app_req_resp_t * )apdu2.ptr;
 | 
						|
    if (((resp1->type & 0x80) == (resp2->type & 0x80)) ||
 | 
						|
        ((resp1->type & 0x7f) != (resp2->type & 0x7f))) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    switch (resp1->type & 0x7f) {
 | 
						|
    case PROTO_69845_C_APP_LINK_RESP:
 | 
						|
    case PROTO_69845_C_APP_CONNECT_REQ:
 | 
						|
    case PROTO_69845_C_APP_RELEASE_REQ:
 | 
						|
    {
 | 
						|
        if (apud_len1 < sizeof(*piid1) ||
 | 
						|
            apdu_len2 < sizeof(*piid2)) {
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        piid1 = (proto_69845_app_piid_t *)resp1->data;
 | 
						|
        piid2 = (proto_69845_app_piid_t *)resp2->data;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_C_APP_GET_REQ:
 | 
						|
    case PROTO_69845_C_APP_SET_REQ:
 | 
						|
    case PROTO_69845_C_APP_ACTION_REQ:
 | 
						|
    case PROTO_69845_C_APP_REPORT_RESP:
 | 
						|
    case PROTO_69845_C_APP_PROXY_REQ:
 | 
						|
    {
 | 
						|
        if (apud_len1 < sizeof(*choice1) ||
 | 
						|
            apdu_len2 < sizeof(*choice2)) {
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        apud_len1 -= sizeof(*choice1);
 | 
						|
        apdu_len2 -= sizeof(*choice2);
 | 
						|
        choice1 = resp1->data;
 | 
						|
        choice2 = resp2->data;
 | 
						|
        if (*choice1 != *choice2) {
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        if (apud_len1 < sizeof(*piid1) ||
 | 
						|
            apdu_len2 < sizeof(*piid2)) {
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        piid1 = (proto_69845_app_piid_t *)(choice1 + 1);
 | 
						|
        piid2 = (proto_69845_app_piid_t *)(choice2 + 1);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    if (!piid1 || !piid2) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (piid1->sn != piid2->sn) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ret = 1;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_698_oad_to_645_di(uint32_t oad_698)
 | 
						|
{
 | 
						|
    uint32_t di_645 = PROTO_645_INVALID_DI;
 | 
						|
    uint16_t oi_698 = oad_698 >> 16;
 | 
						|
 | 
						|
    switch (oi_698) {
 | 
						|
    case PROTO_69845_APP_OI_VOLTAGE:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_V_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_CURRENT:
 | 
						|
    {
 | 
						|
        if (oad_698 == PROTO_69845_APP_OAD_GND_CURRENT) {
 | 
						|
            di_645 = PROTO_645_2007_DI_I_N;
 | 
						|
        } else {
 | 
						|
            di_645 = PROTO_645_2007_DI_I_ALL;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_P:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_P_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_Q:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_Q_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_PF:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_PF_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EPT_COMP:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_COMP_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EPT_POS:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_POS_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EPT_NEG:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_NEG_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EQT_POS:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EQT_POS_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EQT_NEG:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EQT_NEG_ALL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EQT_QRT1:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EQT_QRT1_SUM;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EQT_QRT2:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EQT_QRT2_SUM;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EQT_QRT3:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EQT_QRT3_SUM;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EQT_QRT4:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EQT_QRT4_SUM;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EPT_DEMAND:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_DEMAND;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EQT_DEMAND:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EQT_DEMAND;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EPT_POS_DEMAND:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_POS_DEMAND;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OI_EPT_NEG_DEMAND:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_NEG_DEMAND;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    switch (oad_698) {
 | 
						|
    case PROTO_69845_APP_OAD_EPT_POS_A_SIG:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_POS_A;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OAD_EPT_POS_B_SIG:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_POS_B;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_OAD_EPT_POS_C_SIG:
 | 
						|
    {
 | 
						|
        di_645 = PROTO_645_2007_DI_EPT_POS_C;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return di_645;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_645_di_to_698_oad(uint32_t di)
 | 
						|
{
 | 
						|
    uint32_t oad_698 = PROTO_69845_APP_OAD_INVALID;
 | 
						|
    switch (di) {
 | 
						|
    case PROTO_645_2007_DI_V_A:
 | 
						|
    case PROTO_645_2007_DI_V_ALL:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_VOLTAGE;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_I_A:
 | 
						|
    case PROTO_645_2007_DI_I_ALL:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_CURRENT;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_PF_ALL:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_PF;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_COMP_SUM:
 | 
						|
    case PROTO_645_2007_DI_EPT_COMP_ALL:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_COMP;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_POS_ALL:
 | 
						|
    case PROTO_645_2007_DI_EPT_POS_SUM:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_POS;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_NEG_ALL:
 | 
						|
    case PROTO_645_2007_DI_EPT_NEG_SUM:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_NEG;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EQT_POS_ALL:
 | 
						|
    case PROTO_645_2007_DI_EQT_POS_SUM:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EQT_POS;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EQT_NEG_ALL:
 | 
						|
    case PROTO_645_2007_DI_EQT_NEG_SUM:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EQT_NEG;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_P_A:
 | 
						|
    case PROTO_645_2007_DI_P_T:
 | 
						|
    case PROTO_645_2007_DI_P_ALL:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_P;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_Q_ALL:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_Q;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_I_N:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_GND_CURRENT;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EQT_QRT1_SUM:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EQT_QRT1_SUM;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EQT_QRT2_SUM:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EQT_QRT2_SUM;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EQT_QRT3_SUM:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EQT_QRT3_SUM;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EQT_QRT4_SUM:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EQT_QRT4_SUM;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_DEMAND:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_DEMAND;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EQT_DEMAND:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EQT_DEMAND;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_POS_DEMAND:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_POS_DEMAND;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_NEG_DEMAND:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_NEG_DEMAND;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_TIME:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_TIME;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_POS_A:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_POS_A_SIG;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_POS_B:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_POS_B_SIG;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_EPT_POS_C:
 | 
						|
    {
 | 
						|
        oad_698 = PROTO_69845_APP_OAD_EPT_POS_C_SIG;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_2007_DI_RT_YMDHMS_LAST1:
 | 
						|
    case PROTO_645_2007_DI_RT_EP_POS_LAST1:
 | 
						|
    case PROTO_645_2007_DI_RT_EP_NEG_LAST1:
 | 
						|
    case PROTO_645_2007_DI_RT_VARIABLE_LAST1:
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return oad_698;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_is_any_server_addr(uint8_t *server_addr)
 | 
						|
{
 | 
						|
    uint8_t i;
 | 
						|
    for (i = 0; i < IOT_MAC_ADDR_LEN; i++) {
 | 
						|
        if (server_addr[i] == 0xAA) {
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t proto_69845_get_addr_info(proto_69845_frame_head_info_t* head,
 | 
						|
    addr_info_t *addr_info)
 | 
						|
{
 | 
						|
    uint8_t total_len = 0;
 | 
						|
 | 
						|
    if (head == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    total_len = head->addr.flag.sa_len + 1;
 | 
						|
    if (addr_info) {
 | 
						|
        if (head->addr.flag.flg_ext) {
 | 
						|
            addr_info->ser_info.logical_addr = head->addr.sa_and_ca[0];
 | 
						|
            addr_info->ser_info.len = total_len -
 | 
						|
                PROTO_69845_EXT_LOGICAL_ADD_LEN;
 | 
						|
            os_mem_cpy(addr_info->ser_info.addr,
 | 
						|
                &head->addr.sa_and_ca[PROTO_69845_EXT_LOGICAL_ADD_LEN],
 | 
						|
                addr_info->ser_info.len);
 | 
						|
        } else {
 | 
						|
            addr_info->ser_info.logical_addr = head->addr.flag.logical_addr;
 | 
						|
            addr_info->ser_info.len = total_len;
 | 
						|
            os_mem_cpy(addr_info->ser_info.addr, head->addr.sa_and_ca,
 | 
						|
                addr_info->ser_info.len);
 | 
						|
        }
 | 
						|
        addr_info->ser_info.type = head->addr.flag.sa_type;
 | 
						|
        addr_info->cli_addr = head->addr.sa_and_ca[total_len];
 | 
						|
    }
 | 
						|
    total_len += PROTO_69845_CA_LEN;
 | 
						|
out:
 | 
						|
    return total_len;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t *proto_69845_get_ser_addr(proto_69845_frame_head_info_t* head)
 | 
						|
{
 | 
						|
    uint8_t *addr = NULL;
 | 
						|
    if (head) {
 | 
						|
        addr = head->addr.sa_and_ca;
 | 
						|
        if (head->addr.flag.flg_ext) {
 | 
						|
            addr += PROTO_69845_EXT_LOGICAL_ADD_LEN;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return addr;
 | 
						|
}
 | 
						|
 | 
						|
static uint8_t proto_69845_server_len_calc(
 | 
						|
    const server_addr_info_t *ser_info)
 | 
						|
{
 | 
						|
    uint8_t len;
 | 
						|
 | 
						|
    len = ser_info->len;
 | 
						|
    if (ser_info->logical_addr >= PROTO_69845_EXT_LOGICAL_ADD_MIN) {
 | 
						|
        len += PROTO_69845_EXT_LOGICAL_ADD_LEN;
 | 
						|
    }
 | 
						|
    return len;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_head_sanity_check(
 | 
						|
    proto_69845_frame_head_info_t* head, uint8_t* data, uint16_t len)
 | 
						|
{
 | 
						|
    uint8_t  head_len;
 | 
						|
    uint8_t  *check_sum_start = data + 1;
 | 
						|
    uint32_t ret;
 | 
						|
 | 
						|
    if ((head->addr.flag.sa_len + 1) > PROTO_69845_SA_MAX_LEN) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    head_len = sizeof(proto_69845_frame_head_info_t) + head->addr.flag.sa_len \
 | 
						|
        + 1 + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    if (len < head_len) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    head_len = (head_len - sizeof(head->start_char));
 | 
						|
    /* 698.45 Head Check Sum */
 | 
						|
    ret = proto_fcs16_check(check_sum_start, head_len);
 | 
						|
out:
 | 
						|
    /* Invalid 698.45 protocol head */
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
proto_69845_frame_head_info_t *proto_69845_sanity_check(uint8_t* data,
 | 
						|
    uint16_t len)
 | 
						|
{
 | 
						|
    uint16_t            len_t, i = 0x0;
 | 
						|
    uint8_t             *data_s = NULL;
 | 
						|
    uint16_t min_data_len = sizeof(proto_69845_frame_head_info_t);
 | 
						|
    proto_69845_frame_head_info_t* head;
 | 
						|
 | 
						|
    for (i = 0x0, len_t = len; i < len; i++) {
 | 
						|
        if (data[i] == PROTO_69845_START_BYTE) {
 | 
						|
            data_s = data + i;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        len_t--;
 | 
						|
    }
 | 
						|
 | 
						|
    if (len_t <= min_data_len) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
 | 
						|
    head = (proto_69845_frame_head_info_t*)data_s;
 | 
						|
    if (len_t < (head->len + PROTO_69845_START_END_LEN)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
 | 
						|
    if (data_s[0] != PROTO_69845_START_BYTE
 | 
						|
        || data_s[head->len + 1] != PROTO_69845_END_BYTE) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
 | 
						|
    if (proto_69845_head_sanity_check(head, data_s, len_t)) {
 | 
						|
        /* Invalid 698.45 protocol head */
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
 | 
						|
    /* 698.45 frame check sum */
 | 
						|
    if (proto_fcs16_check(data_s + 1, head->len)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    head = NULL;
 | 
						|
out:
 | 
						|
    return head;   /* checksum success */
 | 
						|
}
 | 
						|
 | 
						|
proto_69845_frame_head_info_t *proto_69845_sanity_check_ext(uint8_t* data,
 | 
						|
    uint16_t len)
 | 
						|
{
 | 
						|
    uint16_t len_t = len, curr_len, i = 0x0;
 | 
						|
    uint8_t *data_s = data;
 | 
						|
    uint16_t min_data_len = sizeof(proto_69845_frame_head_info_t);
 | 
						|
    proto_69845_frame_head_info_t* head;
 | 
						|
 | 
						|
again:
 | 
						|
    curr_len = len_t;
 | 
						|
    for (i = 0x0; i < curr_len; i++) {
 | 
						|
        if (data_s[i] == PROTO_69845_START_BYTE) {
 | 
						|
            data_s += i;
 | 
						|
            len_t -= i;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (i == curr_len) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    if (len_t < min_data_len) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    head = (proto_69845_frame_head_info_t*)data_s;
 | 
						|
    if (len_t < (head->len + PROTO_69845_START_END_LEN)) {
 | 
						|
        data_s++;
 | 
						|
        len_t--;
 | 
						|
        goto again;
 | 
						|
    }
 | 
						|
 | 
						|
    if (data_s[0] != PROTO_69845_START_BYTE
 | 
						|
        || data_s[head->len + 1] != PROTO_69845_END_BYTE) {
 | 
						|
        data_s++;
 | 
						|
        len_t--;
 | 
						|
        goto again;
 | 
						|
    }
 | 
						|
 | 
						|
    if (proto_69845_head_sanity_check(head, data_s, len_t)) {
 | 
						|
        /* Invalid 698.45 protocol head */
 | 
						|
        data_s++;
 | 
						|
        len_t--;
 | 
						|
        goto again;
 | 
						|
    }
 | 
						|
 | 
						|
    /* 698.45 frame check sum */
 | 
						|
    if (proto_fcs16_check(data_s + 1, head->len)) {
 | 
						|
        data_s++;
 | 
						|
        len_t--;
 | 
						|
        goto again;
 | 
						|
    }
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    head = NULL;
 | 
						|
out:
 | 
						|
    return head;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_head_fill(
 | 
						|
    proto_69845_frame_head_info_t *head, uint16_t head_len,
 | 
						|
    uint16_t total_len, addr_info_t *addr_info, uint8_t fn,
 | 
						|
    uint8_t fragment, uint8_t dir_prm)
 | 
						|
{
 | 
						|
    uint8_t *data, ser_len;
 | 
						|
    uint16_t cs_len, cs;
 | 
						|
    uint32_t ret = ERR_FAIL;
 | 
						|
 | 
						|
    if (!total_len || !addr_info) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (total_len < head_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
 | 
						|
    if ((head_len < (sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN))
 | 
						|
        || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = (uint8_t*)head;
 | 
						|
    head->start_char = PROTO_69845_START_BYTE;
 | 
						|
    head->len = total_len - PROTO_69845_START_END_LEN;
 | 
						|
    head ->ctrl.fn = fn;
 | 
						|
    head->ctrl.fragment = fragment;
 | 
						|
    head->ctrl.dir_prm = dir_prm;
 | 
						|
    if (addr_info->ser_info.logical_addr < PROTO_69845_EXT_LOGICAL_ADD_MIN) {
 | 
						|
        head->addr.flag.logical_addr = addr_info->ser_info.logical_addr;
 | 
						|
        head->addr.flag.flg_ext = 0;
 | 
						|
        os_mem_cpy(head->addr.sa_and_ca, addr_info->ser_info.addr,
 | 
						|
            addr_info->ser_info.len);
 | 
						|
        head->addr.flag.sa_len = addr_info->ser_info.len;
 | 
						|
    } else {
 | 
						|
        head->addr.flag.logical_addr = 0;
 | 
						|
        head->addr.flag.flg_ext = 1;
 | 
						|
        head->addr.sa_and_ca[0] = addr_info->ser_info.logical_addr;
 | 
						|
        os_mem_cpy(&head->addr.sa_and_ca[PROTO_69845_EXT_LOGICAL_ADD_LEN],
 | 
						|
            addr_info->ser_info.addr, addr_info->ser_info.len);
 | 
						|
        head->addr.flag.sa_len = (addr_info->ser_info.len +
 | 
						|
            PROTO_69845_EXT_LOGICAL_ADD_LEN);
 | 
						|
    }
 | 
						|
    head->addr.flag.sa_len--;
 | 
						|
    head->addr.flag.sa_type = addr_info->ser_info.type;
 | 
						|
    head->addr.sa_and_ca[head->addr.flag.sa_len + 1] = addr_info->cli_addr;
 | 
						|
    cs_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN - PROTO_69845_START_LEN;
 | 
						|
    cs = proto_fcs16_get_check_sum(data + 1, cs_len);
 | 
						|
    data[cs_len + 1] = (cs & 0x00ff);
 | 
						|
    data[cs_len + 2] = ((cs >> 8) & 0x00ff);
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_tail_fill(proto_69845_frame_head_info_t *head,
 | 
						|
    uint8_t *tail_data, uint16_t len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = tail_data;
 | 
						|
    uint16_t cs_len, cs;
 | 
						|
    uint32_t ret = ERR_FAIL;
 | 
						|
    proto_69845_tailer_t *tail;
 | 
						|
 | 
						|
    if (len < sizeof(*tail)) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    /* fill 698.45 proto tailer */
 | 
						|
    tail = (proto_69845_tailer_t*)ptr;
 | 
						|
    cs_len = head->len - PROTO_69845_CHECKSUM_LEN;
 | 
						|
    cs = proto_fcs16_get_check_sum((uint8_t*)&head->len, cs_len);
 | 
						|
    tail->fcs[0] = (cs & 0x00ff);
 | 
						|
    tail->fcs[1] = ((cs >> 8) & 0x00ff);
 | 
						|
    tail->end_char = PROTO_69845_END_BYTE;
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_tail_fill_without_ts_fl(
 | 
						|
    proto_69845_frame_head_info_t *head,
 | 
						|
    uint8_t *tail_data, uint16_t len)
 | 
						|
{
 | 
						|
    uint8_t *time_tag, *flw_rpt, *ptr = tail_data;
 | 
						|
    uint16_t total_len;
 | 
						|
    uint32_t ret = ERR_FAIL;
 | 
						|
 | 
						|
    if (head->ctrl.dir_prm == PROTO_69845_D_P_SERVER_REPORT
 | 
						|
        || head->ctrl.dir_prm == PROTO_69845_D_P_SERVER_RESPONSE) {
 | 
						|
        total_len = sizeof(proto_69845_tailer_t) + sizeof(*time_tag)
 | 
						|
            + sizeof(*flw_rpt);
 | 
						|
    } else {
 | 
						|
        total_len = sizeof(proto_69845_tailer_t) + sizeof(*time_tag);
 | 
						|
    }
 | 
						|
 | 
						|
    if (len < total_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    /* There is no time tag field, so time_tag is 0 */
 | 
						|
    time_tag = ptr;
 | 
						|
    (*time_tag) = 0;
 | 
						|
    ptr += sizeof(*time_tag);
 | 
						|
    if (head->ctrl.dir_prm == PROTO_69845_D_P_SERVER_REPORT
 | 
						|
        || head->ctrl.dir_prm == PROTO_69845_D_P_SERVER_RESPONSE) {
 | 
						|
        /* There is no follow report data field, so flw_rpt is 0 */
 | 
						|
        flw_rpt = ptr;
 | 
						|
        (*flw_rpt) = 0;
 | 
						|
        ptr += sizeof(*flw_rpt);
 | 
						|
    }
 | 
						|
    /* fill 698.45 proto tailer */
 | 
						|
    proto_69845_tail_fill(head, ptr, sizeof(proto_69845_tailer_t));
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
void proto_69845_add33_handle(uint8_t *ds, uint32_t size)
 | 
						|
{
 | 
						|
    uint8_t  *ptr = ds;
 | 
						|
    while (size--)
 | 
						|
    {
 | 
						|
        (*ptr++) += 0x33;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void proto_69845_sub33_handle(uint8_t *ds, uint32_t size)
 | 
						|
{
 | 
						|
    uint8_t  *ptr = ds;
 | 
						|
    while (size--)
 | 
						|
    {
 | 
						|
        (*ptr++) -= 0x33;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_apdu(proto_69845_frame_head_info_t *hdr,
 | 
						|
    uint32_t len, apdu_info_t *apdu)
 | 
						|
{
 | 
						|
    uint8_t *data = (uint8_t*)hdr;
 | 
						|
    uint32_t head_len, total_len, min_len;
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
 | 
						|
    head_len = sizeof(*hdr) + hdr->addr.flag.sa_len \
 | 
						|
        + 1 + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    total_len = hdr->len + PROTO_69845_START_END_LEN;
 | 
						|
    min_len = head_len + sizeof(proto_69845_tailer_t);
 | 
						|
    if ((len < head_len) || (len < total_len) || (len < min_len)) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (hdr->ctrl.fragment != PROTO_69845_APDU_WHOLE) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    apdu->ptr = data + head_len;
 | 
						|
    apdu->len = len - min_len;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_parse(uint8_t **data, uint32_t *len,
 | 
						|
    proto_69845_frame_head_info_t **hdr, apdu_info_t *apdu_desc)
 | 
						|
{
 | 
						|
    uint8_t *ds = *data, *sub_data = NULL;
 | 
						|
    uint32_t len1 = *len, temp, offset, sub_len = 0;
 | 
						|
 | 
						|
    proto_69845_frame_head_info_t *hdr_temp;
 | 
						|
    proto_69845_apdu_t *apdu;
 | 
						|
    proto_69845_app_sec_req_resp_info_t *sec;
 | 
						|
    proto_69845_app_len_descript_t *len_desc;
 | 
						|
    hdr_temp = proto_69845_sanity_check(ds, (uint16_t)len1);
 | 
						|
    if (hdr_temp == NULL) {
 | 
						|
        goto err;
 | 
						|
    }
 | 
						|
 | 
						|
    offset = (uint32_t)((uint8_t *)hdr_temp - ds);
 | 
						|
    len1 -= offset;
 | 
						|
    ds += offset;
 | 
						|
 | 
						|
    temp = sizeof(*hdr_temp) + sizeof(proto_69845_addr_t) +
 | 
						|
        hdr_temp->addr.flag.sa_len + PROTO_69845_CA_LEN +
 | 
						|
        PROTO_69845_CHECKSUM_LEN;
 | 
						|
    len1 -= temp;
 | 
						|
    ds += temp;
 | 
						|
    if (len1 < sizeof(proto_69845_tailer_t)) {
 | 
						|
        goto err;
 | 
						|
    }
 | 
						|
    len1 -= sizeof(proto_69845_tailer_t);
 | 
						|
    if (hdr_temp->ctrl.flag_scramble) {
 | 
						|
        proto_69845_sub33_handle(ds, len1);
 | 
						|
        sub_data = ds;
 | 
						|
        sub_len = len1;
 | 
						|
    }
 | 
						|
    if (apdu_desc) {
 | 
						|
        apdu_desc->ptr = ds;
 | 
						|
        apdu_desc->len = len1;
 | 
						|
    }
 | 
						|
    if (len1 < sizeof(*apdu))
 | 
						|
        goto err;
 | 
						|
    apdu = (proto_69845_apdu_t *)ds;
 | 
						|
    switch (apdu->type) {
 | 
						|
    case PROTO_69845_C_APP_SECURITY_REQ:
 | 
						|
    case PROTO_69845_S_APP_SECURITY_RESP:
 | 
						|
    {
 | 
						|
        ds += sizeof(*apdu);
 | 
						|
        len1 -= sizeof(*apdu);
 | 
						|
        if (len1 < sizeof (*sec)) {
 | 
						|
            goto err;
 | 
						|
        }
 | 
						|
        sec  = (proto_69845_app_sec_req_resp_info_t*)ds;
 | 
						|
        len1 -= sizeof (*sec);
 | 
						|
        ds += sizeof (*sec);
 | 
						|
 | 
						|
        len_desc = (proto_69845_app_len_descript_t *)((uint8_t *)sec + 1);
 | 
						|
        if (!len_desc->mub_flag) {
 | 
						|
            ds = sec->data;
 | 
						|
            temp = sec->len;
 | 
						|
        } else if (len_desc->byte_num == 1) {
 | 
						|
            if (len1 < 1) {
 | 
						|
                goto err;
 | 
						|
            }
 | 
						|
            temp = sec->data[0];
 | 
						|
            ds = sec->data + 1;
 | 
						|
            len1--;
 | 
						|
        } else if (len_desc->byte_num == 2) {
 | 
						|
            if (len1 < 2) {
 | 
						|
                goto err;
 | 
						|
            }
 | 
						|
            temp = iot_bytes_to_uint16(sec->data, 1);
 | 
						|
            ds = sec->data + 2;
 | 
						|
            len1 -= 2;
 | 
						|
        } else {
 | 
						|
            goto err;
 | 
						|
        }
 | 
						|
        if (len1 < temp) {
 | 
						|
            goto err;
 | 
						|
        }
 | 
						|
        len1 = temp;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    *data = ds;
 | 
						|
    *len = len1;
 | 
						|
    *hdr = hdr_temp;
 | 
						|
    return ERR_OK;
 | 
						|
err:
 | 
						|
    if (sub_data && sub_len) {
 | 
						|
        proto_69845_add33_handle(sub_data, sub_len);
 | 
						|
    }
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_event_msg(uint8_t *addr)
 | 
						|
{
 | 
						|
    uint8_t *data;
 | 
						|
    uint32_t len;
 | 
						|
    iot_pkt_t *pkt;
 | 
						|
    proto_645_header_t *hdr;
 | 
						|
 | 
						|
    len = sizeof(*hdr) + PROTO_69845_EVENT_DATA_LEN
 | 
						|
        + sizeof(proto_645_tailer_t);
 | 
						|
    pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = (uint8_t*)iot_pkt_data(pkt);
 | 
						|
    hdr = (proto_645_header_t*)data;
 | 
						|
    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_69845_EVENT_DATA_LEN;
 | 
						|
    os_mem_cpy(hdr->data, proto_69845_event_report_data,
 | 
						|
        PROTO_69845_EVENT_DATA_LEN);
 | 
						|
    proto_645_tail_init(hdr);
 | 
						|
    iot_pkt_put(pkt, len);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_oad(uint8_t *data,
 | 
						|
    uint32_t data_len, proto_69845_app_oad_t *oad)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_FAIL;
 | 
						|
    proto_69845_app_get_req_normal_t *req =
 | 
						|
        (proto_69845_app_get_req_normal_t*)data;
 | 
						|
 | 
						|
    if (data_len < sizeof(*req)) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    oad->oi = proto_69845_byte_to_oi((uint8_t*)&req->oad.oi);
 | 
						|
    oad->element_index = req->oad.element_index;
 | 
						|
    oad->attribute_id = req->oad.attribute_id;
 | 
						|
    oad->attribute_char = req->oad.attribute_char;
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_omd(uint8_t *data,
 | 
						|
    uint32_t data_len, proto_69845_app_omd_t *omd)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_FAIL;
 | 
						|
    proto_69845_app_action_req_single_t *req =
 | 
						|
        (proto_69845_app_action_req_single_t*)data;
 | 
						|
 | 
						|
    if (data_len < sizeof(*req)) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    omd->oi = proto_69845_byte_to_oi((uint8_t*)&req->omd.oi);
 | 
						|
    omd->method_id = req->omd.method_id;
 | 
						|
    omd->operation_mode = req->omd.operation_mode;
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint8_t proto_69845_get_data_len_type(uint8_t data_type)
 | 
						|
{
 | 
						|
    uint8_t data_len_type = PROTO_69845_DATA_LEN_TYPE_UNKNOW;
 | 
						|
 | 
						|
    for (uint8_t i = 0; i < PROTO_69845_DATA_DESC_LIST_MAX; i++) {
 | 
						|
        if (data_type == proto_69845_data_desc_list[i].type) {
 | 
						|
            data_len_type = proto_69845_data_desc_list[i].len_type;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return data_len_type;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_normal_data_len(uint8_t data_type)
 | 
						|
{
 | 
						|
    uint32_t data_len = 0;
 | 
						|
 | 
						|
    for (uint8_t i = 0; i < PROTO_69845_DATA_DESC_LIST_MAX; i++) {
 | 
						|
        if (data_type == proto_69845_data_desc_list[i].type) {
 | 
						|
            data_len = proto_69845_data_desc_list[i].len;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return data_len;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_div8_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *len_data;
 | 
						|
    uint32_t ret = ERR_OK, len, bit_len = 0;
 | 
						|
    proto_69845_app_len_descript_t *len_desc;
 | 
						|
 | 
						|
    if (rec_data_len < sizeof(*len_desc)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    len_desc = (proto_69845_app_len_descript_t *)data;
 | 
						|
    if (!len_desc->mub_flag) {
 | 
						|
        bit_len = data[0];
 | 
						|
    } else {
 | 
						|
        if (rec_data_len < sizeof(*len_desc) + len_desc->byte_num) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len_data = data + sizeof(*len_desc);
 | 
						|
        if (len_desc->byte_num == 1) {
 | 
						|
            bit_len = len_data[0];
 | 
						|
        } else if (len_desc->byte_num == 2) {
 | 
						|
            bit_len = iot_bytes_to_uint16(len_data, 1);
 | 
						|
        } else {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    len = bit_len / 8;
 | 
						|
    if ((bit_len % 8) != 0) {
 | 
						|
        len++;
 | 
						|
    }
 | 
						|
    len += sizeof(*len_desc);
 | 
						|
    if (len_desc->mub_flag) {
 | 
						|
        len += len_desc->byte_num;
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t proto_69845_get_multi_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *len_data;
 | 
						|
    uint32_t ret = ERR_OK, len = 0;
 | 
						|
    proto_69845_app_len_descript_t *len_desc;
 | 
						|
 | 
						|
    if (rec_data_len < sizeof(*len_desc)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    len_desc = (proto_69845_app_len_descript_t *)data;
 | 
						|
    if (!len_desc->mub_flag) {
 | 
						|
        len = data[0];
 | 
						|
    } else {
 | 
						|
        if (rec_data_len < sizeof(*len_desc) + len_desc->byte_num) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len_data = data + sizeof(*len_desc);
 | 
						|
        if (len_desc->byte_num == 1) {
 | 
						|
            len = len_data[0];
 | 
						|
        } else if (len_desc->byte_num == 2) {
 | 
						|
            len = iot_bytes_to_uint16(len_data, 1);
 | 
						|
        } else {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    len += sizeof(*len_desc);
 | 
						|
    if (len_desc->mub_flag) {
 | 
						|
        len += len_desc->byte_num;
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_road_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK, len;
 | 
						|
    proto_69845_app_road_t *road_hdr;
 | 
						|
 | 
						|
    if (rec_data_len < sizeof(*road_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    road_hdr = (proto_69845_app_road_t*)data;
 | 
						|
    len = proto_69845_get_normal_data_len(PROTO_69845_APP_DATA_OAD);
 | 
						|
    len *= road_hdr->cnt;
 | 
						|
    len += sizeof(*road_hdr);
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_csd_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
 | 
						|
    proto_69845_app_data_csd_t *csd_hdr;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*csd_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    csd_hdr = (proto_69845_app_data_csd_t*)ptr;
 | 
						|
    len = sizeof(*csd_hdr);
 | 
						|
    ptr += sizeof(*csd_hdr);
 | 
						|
    rec_len -= sizeof(*csd_hdr);
 | 
						|
    switch (csd_hdr->type) {
 | 
						|
    case PROTO_OI_CSD_TYPE_OAD:
 | 
						|
    {
 | 
						|
        len += proto_69845_get_normal_data_len(PROTO_69845_APP_DATA_OAD);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_CSD_TYPE_ROAD:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_road_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_rcsd_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data, i;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
 | 
						|
    proto_69845_app_data_rcsd_t *rcsd_hdr;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*rcsd_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    rcsd_hdr = (proto_69845_app_data_rcsd_t*)ptr;
 | 
						|
    len = sizeof(*rcsd_hdr);
 | 
						|
    ptr += sizeof(*rcsd_hdr);
 | 
						|
    rec_len -= sizeof(*rcsd_hdr);
 | 
						|
    for (i = 0; i < rcsd_hdr->cnt; i++) {
 | 
						|
        cache_len = 0;
 | 
						|
        if (proto_69845_get_csd_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        if (rec_len < cache_len) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        ptr += cache_len;
 | 
						|
        rec_len -= cache_len;
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t proto_69845_get_tsa_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK, len;
 | 
						|
    proto_69845_app_data_tsa_t *tsa_hdr;
 | 
						|
 | 
						|
    if (rec_data_len < sizeof(*tsa_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    tsa_hdr = (proto_69845_app_data_tsa_t*)data;
 | 
						|
    len = tsa_hdr->flag.sa_len + 1;
 | 
						|
    len += sizeof(*tsa_hdr);
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t proto_69845_get_ms_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data, i;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
 | 
						|
    proto_69845_app_data_ms_t *ms_hdr;
 | 
						|
    proto_69845_app_data_ms_type_t *type_list_hdr;
 | 
						|
    proto_69845_app_data_tsa_seq_t *tsa_list_hdr;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*ms_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    ms_hdr = (proto_69845_app_data_ms_t*)ptr;
 | 
						|
    len = sizeof(*ms_hdr);
 | 
						|
    ptr += sizeof(*ms_hdr);
 | 
						|
    rec_len -= sizeof(*ms_hdr);
 | 
						|
    switch (ms_hdr->type) {
 | 
						|
    case PROTO_OI_MS_TYPE_ALL_PM:
 | 
						|
    {
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_MS_TYPE_GROUP_PM_TYPE:
 | 
						|
    {
 | 
						|
        if (rec_len < sizeof(*type_list_hdr)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        type_list_hdr = (proto_69845_app_data_ms_type_t*)ptr;
 | 
						|
        cache_len = type_list_hdr->cnt * sizeof(type_list_hdr->type_list[0])
 | 
						|
            + sizeof(*type_list_hdr);
 | 
						|
        if (rec_len < cache_len) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_MS_TYPE_GROUP_PM_ADDR:
 | 
						|
    {
 | 
						|
        if (rec_len < sizeof(*tsa_list_hdr)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        tsa_list_hdr = (proto_69845_app_data_tsa_seq_t*)ptr;
 | 
						|
        len += sizeof(*tsa_list_hdr);
 | 
						|
        ptr += sizeof(*tsa_list_hdr);
 | 
						|
        rec_len -= sizeof(*tsa_list_hdr);
 | 
						|
        for (i = 0; i < tsa_list_hdr->cnt; i++) {
 | 
						|
            cache_len = 0;
 | 
						|
            if (proto_69845_get_tsa_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
                goto drop;
 | 
						|
            }
 | 
						|
            if (rec_len < cache_len) {
 | 
						|
                goto drop;
 | 
						|
            }
 | 
						|
            len += cache_len;
 | 
						|
            ptr += cache_len;
 | 
						|
            rec_len -= cache_len;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t proto_69845_get_rsd_type_2_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data, data_len_type;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
 | 
						|
    proto_69845_app_data_rsd_type2_t *rsd_type2_hdr;
 | 
						|
    proto_69845_app_data_t *data_hdr;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*rsd_type2_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    rsd_type2_hdr = (proto_69845_app_data_rsd_type2_t*)ptr;
 | 
						|
    len = sizeof(*rsd_type2_hdr);
 | 
						|
    ptr += sizeof(*rsd_type2_hdr);
 | 
						|
    rec_len -= sizeof(*rsd_type2_hdr);
 | 
						|
    for (uint8_t i = 0; i < PROTO_OI_RSD_TYPE_2_DATA_CNT; i++) {
 | 
						|
        if (rec_len < sizeof(*data_hdr)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        data_hdr = (proto_69845_app_data_t*)ptr;
 | 
						|
        len += sizeof(*data_hdr);
 | 
						|
        ptr += sizeof(*data_hdr);
 | 
						|
        rec_len -= sizeof(*data_hdr);
 | 
						|
        data_len_type = proto_69845_get_data_len_type(data_hdr->data_type);
 | 
						|
        if (data_len_type != PROTO_69845_DATA_LEN_TYPE_NORMAL) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        cache_len = proto_69845_get_normal_data_len(data_hdr->data_type);
 | 
						|
        if (rec_len < cache_len) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        ptr += cache_len;
 | 
						|
        rec_len -= cache_len;
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t proto_69845_get_rsd_type_678_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
 | 
						|
    proto_69845_app_data_rsd_type678_t *rsd_hdr;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*rsd_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    rsd_hdr = (proto_69845_app_data_rsd_type678_t*)ptr;
 | 
						|
    len = sizeof(rsd_hdr->start_time) + sizeof(rsd_hdr->end_time)
 | 
						|
        + sizeof(rsd_hdr->ti);
 | 
						|
    ptr = (uint8_t*)&rsd_hdr->meter_set;
 | 
						|
    rec_len = rec_len - len;
 | 
						|
    if (proto_69845_get_ms_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    len += cache_len;
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t proto_69845_get_rsd_type_10_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
 | 
						|
    proto_69845_app_data_rsd_type10_t *rsd_hdr;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*rsd_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    rsd_hdr = (proto_69845_app_data_rsd_type10_t*)ptr;
 | 
						|
    len = sizeof(rsd_hdr->record_num);
 | 
						|
    ptr = (uint8_t*)&rsd_hdr->meter_set;
 | 
						|
    rec_len = rec_len - len;
 | 
						|
    if (proto_69845_get_ms_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    len += cache_len;
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_rsd_data_len(uint8_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
 | 
						|
    proto_69845_app_data_rsd_t *rsd_hdr;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*rsd_hdr)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    rsd_hdr = (proto_69845_app_data_rsd_t*)ptr;
 | 
						|
    len = sizeof(*rsd_hdr);
 | 
						|
    ptr += sizeof(*rsd_hdr);
 | 
						|
    rec_len -= sizeof(*rsd_hdr);
 | 
						|
    switch (rsd_hdr->type) {
 | 
						|
    case PROTO_OI_RSD_TYPE_2:
 | 
						|
    {
 | 
						|
        cache_len = 0;
 | 
						|
        if (proto_69845_get_rsd_type_2_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_RSD_TYPE_6:
 | 
						|
    case PROTO_OI_RSD_TYPE_7:
 | 
						|
    case PROTO_OI_RSD_TYPE_8:
 | 
						|
    {
 | 
						|
        cache_len = 0;
 | 
						|
        if (proto_69845_get_rsd_type_678_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_RSD_TYPE_9:
 | 
						|
    {
 | 
						|
        len += 1;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_RSD_TYPE_10:
 | 
						|
    {
 | 
						|
        cache_len = 0;
 | 
						|
        if (proto_69845_get_rsd_type_10_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t proto_69845_get_base_data_len(proto_69845_app_data_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data, data_len_type;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len = 0;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*data)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    ptr += sizeof(*data);
 | 
						|
    rec_len -= sizeof(*data);
 | 
						|
    len = sizeof(*data);
 | 
						|
    data_len_type = proto_69845_get_data_len_type(data->data_type);
 | 
						|
    switch (data_len_type){
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_NORMAL:
 | 
						|
    {
 | 
						|
        len += proto_69845_get_normal_data_len(data->data_type);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_ROAD:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_road_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_TSA:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_tsa_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_RSD:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_rsd_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_CSD:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_csd_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_MS:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_ms_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_RCSD:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_rcsd_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_DIV8:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_div8_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_MULTI_BTYE:
 | 
						|
    {
 | 
						|
        if (proto_69845_get_multi_data_len(ptr, rec_len, &cache_len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        len += cache_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_DATA_LEN_TYPE_UNKNOW:
 | 
						|
    default:
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t proto_69845_get_element_data_len(proto_69845_app_ele_data_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len, uint8_t recursion_cnt)
 | 
						|
{
 | 
						|
    uint8_t *ptr = (uint8_t*)data, data_len_type;
 | 
						|
    uint8_t i;
 | 
						|
    uint8_t cnt;
 | 
						|
    uint32_t ret = ERR_OK, rec_len = rec_data_len, len, cache_len;
 | 
						|
    proto_69845_app_ele_data_t *element_hdr;
 | 
						|
    proto_69845_app_data_t *base_data_hdr;
 | 
						|
 | 
						|
    if (rec_len < sizeof(*data)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    ptr += sizeof(*data);
 | 
						|
    rec_len -= sizeof(*data);
 | 
						|
    len = sizeof(*data);
 | 
						|
    cnt = data->num_of_data;
 | 
						|
    for (i = 0; i < cnt; i++) {
 | 
						|
        if (rec_len < sizeof(*base_data_hdr)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
        base_data_hdr = (proto_69845_app_data_t*)ptr;
 | 
						|
        data_len_type = proto_69845_get_data_len_type(base_data_hdr->data_type);
 | 
						|
        if (data_len_type == PROTO_69845_DATA_LEN_TYPE_ELEMENT) {
 | 
						|
            if (!recursion_cnt) {
 | 
						|
                goto drop;
 | 
						|
            }
 | 
						|
            if (rec_len < sizeof(*element_hdr)) {
 | 
						|
                goto drop;
 | 
						|
            }
 | 
						|
            element_hdr = (proto_69845_app_ele_data_t*)base_data_hdr;
 | 
						|
            cache_len = 0;
 | 
						|
            if (proto_69845_get_element_data_len(element_hdr, rec_len,
 | 
						|
                &cache_len, (recursion_cnt - 1))) {
 | 
						|
                goto drop;
 | 
						|
            }
 | 
						|
            if (rec_len < cache_len) {
 | 
						|
                goto drop;
 | 
						|
            }
 | 
						|
            ptr += cache_len;
 | 
						|
            rec_len -= cache_len;
 | 
						|
            len += cache_len;
 | 
						|
        } else {
 | 
						|
            cache_len = 0;
 | 
						|
            if (proto_69845_get_base_data_len(base_data_hdr, rec_data_len,
 | 
						|
                &cache_len)) {
 | 
						|
                goto drop;
 | 
						|
            }
 | 
						|
            if (rec_len < cache_len) {
 | 
						|
                goto drop;
 | 
						|
            }
 | 
						|
            ptr += cache_len;
 | 
						|
            rec_len -= cache_len;
 | 
						|
            len += cache_len;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_get_data_len(proto_69845_app_data_t *data,
 | 
						|
    uint32_t rec_data_len, uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint8_t data_len_type;
 | 
						|
    uint32_t ret = ERR_OK, len = 0;
 | 
						|
    proto_69845_app_ele_data_t *element_hdr;
 | 
						|
 | 
						|
    if (!rec_data_len || !data) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    data_len_type = proto_69845_get_data_len_type(data->data_type);
 | 
						|
    if (data_len_type == PROTO_69845_DATA_LEN_TYPE_ELEMENT) {
 | 
						|
        element_hdr = (proto_69845_app_ele_data_t*)data;
 | 
						|
        if (proto_69845_get_element_data_len(element_hdr, rec_data_len, &len,
 | 
						|
            PROTO_69845_ELEMENT_DATA_RECURSION_CNT_MAX)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
    }  else {
 | 
						|
        if (proto_69845_get_base_data_len(data, rec_data_len, &len)) {
 | 
						|
            goto drop;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    *data_len = len;
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    ret = ERR_FAIL;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static iot_pkt_t *proto_69845_get_rpt_noti_rcsd()
 | 
						|
{
 | 
						|
    uint8_t i = 0, *data = NULL, oad_cnt = 0;
 | 
						|
    uint16_t rcsd_len = 0;
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    proto_69845_app_data_rcsd_t *p_rcsd;
 | 
						|
    proto_69845_app_data_csd_t *p_csd;
 | 
						|
    proto_69845_app_oad_t* p_oad;
 | 
						|
    const uint16_t evt_oi[] = {
 | 
						|
        PROTO_69845_APP_OI_EVENT_REC_SEQ, PROTO_69845_APP_OI_EVENT_START_TM,
 | 
						|
        PROTO_69845_APP_OI_EVENT_END_TM, PROTO_69845_APP_OI_EVENT_OCCUR_SOURCE,
 | 
						|
        PROTO_69845_APP_OI_EVENT_RPT_STA};
 | 
						|
 | 
						|
    oad_cnt = sizeof(evt_oi)/sizeof(evt_oi[0]);
 | 
						|
 | 
						|
    rcsd_len = sizeof(proto_69845_app_data_rcsd_t) +
 | 
						|
        (sizeof(proto_69845_app_data_csd_t) +
 | 
						|
        sizeof(proto_69845_app_oad_t)) * oad_cnt;
 | 
						|
 | 
						|
    pkt = iot_pkt_alloc(rcsd_len, IOT_SMART_GRID_MID);
 | 
						|
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    p_rcsd = (proto_69845_app_data_rcsd_t *)iot_pkt_data(pkt);
 | 
						|
 | 
						|
    p_rcsd->cnt = oad_cnt;
 | 
						|
 | 
						|
    data = (uint8_t*)p_rcsd->csd_list;
 | 
						|
    for (i = 0; i < p_rcsd->cnt; i++) {
 | 
						|
        p_csd = (proto_69845_app_data_csd_t*)data;
 | 
						|
        p_csd->type = 0;
 | 
						|
        p_oad = (proto_69845_app_oad_t*)(p_csd->csd_data);
 | 
						|
        proto_69845_oi_to_byte(evt_oi[i], (uint8_t*)&p_oad->oi);
 | 
						|
        p_oad->attribute_id = 2;
 | 
						|
        p_oad->attribute_char = 0;
 | 
						|
        p_oad->element_index = 0;
 | 
						|
        data += sizeof(proto_69845_app_data_csd_t) +
 | 
						|
            sizeof(proto_69845_app_oad_t);
 | 
						|
    }
 | 
						|
    iot_pkt_put(pkt, rcsd_len);
 | 
						|
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
static iot_pkt_t *proto_69845_get_rpt_noti_ele(
 | 
						|
    proto_69845_app_data_time_s_t *evt_start_tm,
 | 
						|
    proto_69845_app_data_time_s_t *evt_end_tm, rpt_status_t *rpt_status)
 | 
						|
{
 | 
						|
    uint16_t evt_unit_len = 0;
 | 
						|
    proto_69845_app_norm_evt_unit_t *evt_unit;
 | 
						|
    proto_69845_app_unrecover_evt_unit_t *evt_unit_ab;
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
 | 
						|
    /* there is power off and power on record */
 | 
						|
    if (rpt_status->pf_rpt && rpt_status->po_rpt) {
 | 
						|
        evt_unit_len = sizeof(proto_69845_app_norm_evt_unit_t);
 | 
						|
        pkt = iot_pkt_alloc(evt_unit_len, IOT_SMART_GRID_MID);
 | 
						|
        if (!pkt) {
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
 | 
						|
        evt_unit = (proto_69845_app_norm_evt_unit_t *)
 | 
						|
            iot_pkt_put(pkt, evt_unit_len);
 | 
						|
        evt_unit->data0_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
 | 
						|
        iot_uint32_to_bytes(0x01, (uint8_t *)&evt_unit->evt_seq, 1);
 | 
						|
 | 
						|
        evt_unit->data1_type = PROTO_69845_APP_DATA_TIME_S;
 | 
						|
        os_mem_cpy(&evt_unit->evt_start_time, (uint8_t *)evt_start_tm,
 | 
						|
            sizeof(proto_69845_app_data_time_s_t));
 | 
						|
 | 
						|
        evt_unit->data2_type = PROTO_69845_APP_DATA_TIME_S;
 | 
						|
        os_mem_cpy(&evt_unit->evt_end_time, (uint8_t *)evt_end_tm,
 | 
						|
            sizeof(proto_69845_app_data_time_s_t));
 | 
						|
 | 
						|
        evt_unit->data3_type = PROTO_69845_APP_DATA_ENUM;
 | 
						|
        evt_unit->evt_soc = PROTO_69845_APP_EVT_SOC_485_FALT;
 | 
						|
 | 
						|
        evt_unit->data4_type = PROTO_69845_APP_DATA_ARRAY;
 | 
						|
        evt_unit->channel_cnt = 1;
 | 
						|
 | 
						|
        evt_unit->data5_type = PROTO_69845_APP_DATA_STRUCTURE;
 | 
						|
        evt_unit->member_cnt = 2;
 | 
						|
 | 
						|
        evt_unit->data6_type = PROTO_69845_APP_DATA_OAD;
 | 
						|
        proto_69845_oi_to_byte(PROTO_69845_APP_OI_PLC_WIRELESS_INTERFACE,
 | 
						|
            (uint8_t*)&evt_unit->channel_oad.oi);
 | 
						|
        evt_unit->channel_oad.attribute_id = 2;
 | 
						|
        evt_unit->channel_oad.attribute_char = 0;
 | 
						|
        evt_unit->channel_oad.element_index = 1;
 | 
						|
 | 
						|
        evt_unit->data7_type = PROTO_69845_APP_DATA_UNSIGNED;
 | 
						|
        evt_unit->pf_rpt = rpt_status->pf_rpt;
 | 
						|
        evt_unit->pf_rpt_ok = rpt_status->pf_rpt_ok;
 | 
						|
        evt_unit->po_rpt = rpt_status->po_rpt;
 | 
						|
        evt_unit->po_rpt_ok = rpt_status->po_rpt_ok;
 | 
						|
 | 
						|
    /* there is power off record, not power on record */
 | 
						|
    } else if (rpt_status->pf_rpt && !rpt_status->po_rpt) {
 | 
						|
        evt_unit_len = sizeof(proto_69845_app_unrecover_evt_unit_t);
 | 
						|
        pkt = iot_pkt_alloc(evt_unit_len, IOT_SMART_GRID_MID);
 | 
						|
        if (!pkt) {
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
 | 
						|
        evt_unit_ab = (proto_69845_app_unrecover_evt_unit_t *)
 | 
						|
            iot_pkt_put(pkt, evt_unit_len);
 | 
						|
        evt_unit_ab->data0_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
 | 
						|
        iot_uint32_to_bytes(0x01, (uint8_t *)&evt_unit_ab->evt_seq, 1);
 | 
						|
 | 
						|
        evt_unit_ab->data1_type = PROTO_69845_APP_DATA_TIME_S;
 | 
						|
        os_mem_cpy(&evt_unit_ab->evt_start_time, (uint8_t *)evt_start_tm,
 | 
						|
            sizeof(proto_69845_app_data_time_s_t));
 | 
						|
 | 
						|
        evt_unit_ab->data2_type = 0;
 | 
						|
 | 
						|
        evt_unit_ab->data3_type = PROTO_69845_APP_DATA_ENUM;
 | 
						|
        evt_unit_ab->evt_soc = PROTO_69845_APP_EVT_SOC_485_FALT;
 | 
						|
 | 
						|
        evt_unit_ab->data4_type = PROTO_69845_APP_DATA_ARRAY;
 | 
						|
        evt_unit_ab->channel_cnt = 1;
 | 
						|
 | 
						|
        evt_unit_ab->data5_type = PROTO_69845_APP_DATA_STRUCTURE;
 | 
						|
        evt_unit_ab->member_cnt = 2;
 | 
						|
 | 
						|
        evt_unit_ab->data6_type = PROTO_69845_APP_DATA_OAD;
 | 
						|
        proto_69845_oi_to_byte(PROTO_69845_APP_OI_PLC_WIRELESS_INTERFACE,
 | 
						|
            (uint8_t*)&evt_unit_ab->channel_oad.oi);
 | 
						|
        evt_unit_ab->channel_oad.attribute_id = 2;
 | 
						|
        evt_unit_ab->channel_oad.attribute_char = 0;
 | 
						|
        evt_unit_ab->channel_oad.element_index = 1;
 | 
						|
 | 
						|
        evt_unit_ab->data7_type = PROTO_69845_APP_DATA_UNSIGNED;
 | 
						|
        evt_unit_ab->pf_rpt = rpt_status->pf_rpt;
 | 
						|
        evt_unit_ab->pf_rpt_ok = rpt_status->pf_rpt_ok;
 | 
						|
        evt_unit_ab->po_rpt = rpt_status->po_rpt;
 | 
						|
        evt_unit_ab->po_rpt_ok = rpt_status->po_rpt_ok;
 | 
						|
 | 
						|
    /* only exist last two case when actively report pof event */
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_rpt_noti_sus_pof_msg(
 | 
						|
    proto_69845_app_rpt_noti_info_t* noti_info,
 | 
						|
    const server_addr_info_t* server_info,
 | 
						|
    proto_69845_app_data_time_s_t *evt_start_tm,
 | 
						|
    proto_69845_app_data_time_s_t *evt_end_tm, rpt_status_t *rpt_status)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL, *rcsd_pkt = NULL, *ele_pkt = NULL;
 | 
						|
    uint8_t *data, ser_len;
 | 
						|
    uint16_t length, rcsd_len = 0, ele_load_len = 0;
 | 
						|
    uint16_t head_len, tail_len;
 | 
						|
    addr_info_t addr_info = { 0 };
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_noti_resp_t *noti;
 | 
						|
    proto_69845_app_rpt_noti_t *rpt_noti;
 | 
						|
    proto_69845_app_rpt_record_list_t *record_list;
 | 
						|
    proto_69845_app_rpt_result_record_t *result_record;
 | 
						|
    proto_69845_app_rpt_noti_result_t *noti_result;
 | 
						|
    proto_69845_app_rpt_record_row_t *record_row;
 | 
						|
 | 
						|
    if (noti_info == NULL || server_info == NULL) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
 | 
						|
    ser_len = proto_69845_server_len_calc(server_info);
 | 
						|
    if (ser_len > PROTO_69845_SA_MAX_LEN || !ser_len) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    length = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
 | 
						|
        + PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t);
 | 
						|
    rcsd_pkt = proto_69845_get_rpt_noti_rcsd();
 | 
						|
    if(!rcsd_pkt)
 | 
						|
        goto drop;
 | 
						|
 | 
						|
    rcsd_len = (uint16_t)iot_pkt_data_len(rcsd_pkt);
 | 
						|
 | 
						|
    ele_pkt = proto_69845_get_rpt_noti_ele(evt_start_tm, evt_end_tm, rpt_status);
 | 
						|
 | 
						|
    if(!ele_pkt)
 | 
						|
        goto drop;
 | 
						|
 | 
						|
    ele_load_len = (uint16_t)iot_pkt_data_len(ele_pkt);
 | 
						|
 | 
						|
    switch (noti_info->type) {
 | 
						|
    case PROTO_69845_APP_REPRORT_RECORDLIST:
 | 
						|
    {
 | 
						|
        length = length + sizeof(*noti) + sizeof(*rpt_noti)
 | 
						|
            + sizeof(*record_list) + sizeof(*result_record)
 | 
						|
            + sizeof(*noti_result) + sizeof(*record_row)
 | 
						|
            + rcsd_len + ele_load_len - sizeof(proto_69845_app_data_rcsd_t);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt)
 | 
						|
        goto drop;
 | 
						|
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_data(pkt);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    addr_info.ser_info = *server_info;
 | 
						|
    addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len, length,
 | 
						|
        &addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_SERVER_REPORT);
 | 
						|
    data += head_len;
 | 
						|
 | 
						|
    /* fill apdu data */
 | 
						|
    noti = (proto_69845_app_noti_resp_t*)data;
 | 
						|
    noti->type = PROTO_69845_S_APP_REPORT_NOTI;
 | 
						|
    rpt_noti = (proto_69845_app_rpt_noti_t*)noti->data;
 | 
						|
    rpt_noti->data_type = noti_info->type;
 | 
						|
    data = data + sizeof(proto_69845_app_noti_resp_t)
 | 
						|
         + sizeof(proto_69845_app_rpt_noti_t);
 | 
						|
    switch (rpt_noti->data_type) {
 | 
						|
    case PROTO_69845_APP_REPRORT_RECORDLIST:
 | 
						|
    {
 | 
						|
        record_list =
 | 
						|
            (proto_69845_app_rpt_record_list_t*)rpt_noti->data;
 | 
						|
        record_list->piid_acd = noti_info->piid_acd;
 | 
						|
        record_list->att_cnt = 1;
 | 
						|
 | 
						|
        data += sizeof(proto_69845_app_rpt_record_list_t);
 | 
						|
 | 
						|
        result_record = (proto_69845_app_rpt_result_record_t*)data;
 | 
						|
        proto_69845_oi_to_byte(noti_info->oad.oi,
 | 
						|
            (uint8_t*)&result_record->oad.oi);
 | 
						|
        result_record->oad.attribute_id = noti_info->oad.attribute_id;
 | 
						|
        result_record->oad.attribute_char = noti_info->oad.attribute_char;
 | 
						|
        result_record->oad.element_index = noti_info->oad.element_index;
 | 
						|
 | 
						|
        os_mem_cpy(&result_record->rcsd, iot_pkt_data(rcsd_pkt), rcsd_len);
 | 
						|
 | 
						|
        data = data + sizeof(proto_69845_app_rpt_result_record_t) +
 | 
						|
            rcsd_len - sizeof(proto_69845_app_data_rcsd_t);
 | 
						|
 | 
						|
        noti_result = (proto_69845_app_rpt_noti_result_t *)data;
 | 
						|
        noti_result->type = PROTO_69845_APP_RPT_RESULT_DATA;
 | 
						|
        data += sizeof(proto_69845_app_rpt_noti_result_t);
 | 
						|
 | 
						|
        record_row = (proto_69845_app_rpt_record_row_t *)data;
 | 
						|
        record_row->record_num = 1;
 | 
						|
 | 
						|
        os_mem_cpy(record_row->data, iot_pkt_data(ele_pkt), ele_load_len);
 | 
						|
 | 
						|
        data = data + sizeof(proto_69845_app_rpt_record_row_t) + ele_load_len;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t);
 | 
						|
    proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
 | 
						|
    iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    if (pkt) {
 | 
						|
        iot_pkt_free(pkt);
 | 
						|
        pkt = NULL;
 | 
						|
    }
 | 
						|
out:
 | 
						|
    if (rcsd_pkt) {
 | 
						|
        iot_pkt_free(rcsd_pkt);
 | 
						|
    }
 | 
						|
    if (ele_pkt) {
 | 
						|
        iot_pkt_free(ele_pkt);
 | 
						|
    }
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_rpt_noti_list_msg(
 | 
						|
    uint8_t* result_list, uint16_t list_len, uint8_t list_cnt,
 | 
						|
    const server_addr_info_t* server_info, uint8_t sn)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data, ser_len;
 | 
						|
    uint16_t length;
 | 
						|
    uint16_t head_len, tail_len;
 | 
						|
    addr_info_t addr_info = { 0 };
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_noti_resp_t *noti;
 | 
						|
    proto_69845_app_rpt_noti_t *rpt_noti;
 | 
						|
    proto_69845_app_rpt_nor_list_t *nor_list;
 | 
						|
 | 
						|
    if (server_info == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    ser_len = proto_69845_server_len_calc(server_info);
 | 
						|
    if (ser_len > PROTO_69845_SA_MAX_LEN || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    length = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
 | 
						|
        + PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t) + sizeof(*noti) + sizeof(*rpt_noti)
 | 
						|
        + sizeof(*nor_list) + list_len;
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_data(pkt);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    addr_info.ser_info = *server_info;
 | 
						|
    addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len, length,
 | 
						|
        &addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_SERVER_REPORT);
 | 
						|
    data += head_len;
 | 
						|
 | 
						|
    /* fill apdu data */
 | 
						|
    noti = (proto_69845_app_noti_resp_t*)data;
 | 
						|
    noti->type = PROTO_69845_S_APP_REPORT_NOTI;
 | 
						|
    rpt_noti = (proto_69845_app_rpt_noti_t*)noti->data;
 | 
						|
    rpt_noti->data_type = PROTO_69845_APP_REPRORT_NORMALLIST;
 | 
						|
    nor_list = (proto_69845_app_rpt_nor_list_t*)rpt_noti->data;
 | 
						|
    nor_list->piid_acd.sn = sn;
 | 
						|
    nor_list->piid_acd.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
 | 
						|
    nor_list->piid_acd.acd = 0;
 | 
						|
    nor_list->att_cnt = list_cnt;
 | 
						|
    os_mem_cpy(nor_list->data, result_list, list_len);
 | 
						|
    data = data + sizeof(*noti) + sizeof(*rpt_noti) + sizeof(*nor_list)
 | 
						|
        + list_len;
 | 
						|
    tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t);
 | 
						|
    proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
 | 
						|
    iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
void proto_69845_check_frame_handler(uint8_t* buffer, uint32_t buffer_len,
 | 
						|
    bool_t* is_frame)
 | 
						|
{
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    do {
 | 
						|
        if (buffer_len < sizeof(proto_69845_frame_head_info_t)) {
 | 
						|
            *is_frame = false;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        head = (proto_69845_frame_head_info_t*)buffer;
 | 
						|
        if ((uint16_t)buffer_len != (head->len + PROTO_69845_START_END_LEN)) {
 | 
						|
            *is_frame = false;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        if (buffer[0] != PROTO_69845_START_BYTE
 | 
						|
            || buffer[head->len + 1] != PROTO_69845_END_BYTE) {
 | 
						|
            *is_frame = false;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        /* 698.45 frame check sum */
 | 
						|
        if (proto_fcs16_check(buffer + 1, head->len)) {
 | 
						|
            *is_frame = false;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        *is_frame = true;
 | 
						|
    } while(0);
 | 
						|
}
 | 
						|
 | 
						|
proto_69845_app_data_time_s_t *proto_69845_get_time_rsp_msg_handle(
 | 
						|
    uint8_t *data, uint16_t len)
 | 
						|
{
 | 
						|
    uint32_t ret, data_len;
 | 
						|
    proto_69845_frame_head_info_t *hdr_698;
 | 
						|
    proto_69845_app_req_resp_t *resp;
 | 
						|
    proto_69845_app_get_resp_t *get_resp;
 | 
						|
    proto_69845_app_get_resp_normal_t *resp_normal;
 | 
						|
    proto_69845_app_data_time_s_t *time = NULL;
 | 
						|
    proto_69845_app_data_t *app_data;
 | 
						|
    apdu_info_t apdu;
 | 
						|
    hdr_698 = proto_69845_sanity_check(data, len);
 | 
						|
    if (!hdr_698) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if ((hdr_698->ctrl.dir_prm != PROTO_69845_D_P_SERVER_RESPONSE) &&
 | 
						|
        (hdr_698->ctrl.dir_prm != PROTO_69845_D_P_SERVER_REPORT)) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ret = proto_69845_get_apdu(hdr_698, len, &apdu);
 | 
						|
    if (ret != ERR_OK) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data_len = sizeof(*resp) + sizeof(*get_resp) + sizeof(*resp_normal) +
 | 
						|
        sizeof(*app_data) + sizeof(*time);
 | 
						|
    if (apdu.len < data_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    resp = (proto_69845_app_req_resp_t*)(apdu.ptr);
 | 
						|
    if (resp->type == PROTO_69845_S_APP_GET_RESP) {
 | 
						|
        get_resp = (proto_69845_app_get_resp_t *)resp->data;
 | 
						|
        if (get_resp->data_type == PROTO_69845_APP_GET_NORMAL) {
 | 
						|
            resp_normal =
 | 
						|
                (proto_69845_app_get_resp_normal_t *)get_resp->data;
 | 
						|
            if ((proto_69845_byte_to_oi((uint8_t *)&resp_normal->oad.oi)
 | 
						|
                == PROTO_69845_APP_OI_TIME) &&
 | 
						|
                (resp_normal->oad.attribute_id == 2) &&
 | 
						|
                (resp_normal->result_type ==
 | 
						|
                PROTO_69845_APP_GET_RESULT_DATA)) {
 | 
						|
                app_data = (proto_69845_app_data_t*)resp_normal->result;
 | 
						|
                if (app_data->data_type == PROTO_69845_APP_DATA_TIME_S) {
 | 
						|
                    time = (proto_69845_app_data_time_s_t *)app_data->data;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
out:
 | 
						|
    return time;
 | 
						|
}
 | 
						|
 | 
						|
uint64_t proto_69845_ti_data_to_sec(proto_69845_app_data_ti_t *ti)
 | 
						|
{
 | 
						|
    uint64_t uint = 0;
 | 
						|
 | 
						|
    switch (ti->uint) {
 | 
						|
    case PROTO_OI_TI_INTERVAL_UNIT_TYPE_SEC:
 | 
						|
    {
 | 
						|
        uint = PROTO_OI_TI_INTERVAL_UNIT_SEC;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_TI_INTERVAL_UNIT_TYPE_MIN:
 | 
						|
    {
 | 
						|
        uint = PROTO_OI_TI_INTERVAL_UNIT_MIN;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_TI_INTERVAL_UNIT_TYPE_HOUR:
 | 
						|
    {
 | 
						|
        uint = PROTO_OI_TI_INTERVAL_UNIT_HOUR;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_TI_INTERVAL_UNIT_TYPE_DAY:
 | 
						|
    {
 | 
						|
        uint = PROTO_OI_TI_INTERVAL_UNIT_DAY;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_TI_INTERVAL_UNIT_TYPE_MON:
 | 
						|
    {
 | 
						|
        uint = PROTO_OI_TI_INTERVAL_UNIT_MON;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_OI_TI_INTERVAL_UNIT_TYPE_YEAR:
 | 
						|
    {
 | 
						|
        uint = PROTO_OI_TI_INTERVAL_UNIT_YEAR;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return (uint * ti->value);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_apdu_sec_ciphertext_check(uint8_t *apdu,
 | 
						|
    uint32_t len)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_FAIL;
 | 
						|
    proto_69845_app_req_resp_t *req;
 | 
						|
    proto_69845_app_sec_req_resp_info_t *req_info;
 | 
						|
 | 
						|
    if (len < (sizeof(*req) + sizeof(*req_info))) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    req = (proto_69845_app_req_resp_t*)apdu;
 | 
						|
    if (req->type != PROTO_69845_C_APP_SECURITY_REQ
 | 
						|
        && req->type != PROTO_69845_S_APP_SECURITY_RESP) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    req_info = (proto_69845_app_sec_req_resp_info_t*)req->data;
 | 
						|
    if (req_info->type != PROTO_69845_SEC_DATA_TYPE_CIPHERTEXT) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_corr_msg_check(uint8_t *data, uint32_t len, uint8_t *addr)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_INVAL;
 | 
						|
    uint16_t oi;
 | 
						|
    proto_69845_frame_head_info_t *hdr_698 = NULL;
 | 
						|
    proto_69845_apdu_t *apdu_hdr;
 | 
						|
    proto_69845_app_action_req_t *req_hdr;
 | 
						|
    proto_69845_app_action_req_single_t *action_hdr;
 | 
						|
    apdu_info_t apdu = { 0 };
 | 
						|
    addr_info_t addr_info = {0};
 | 
						|
 | 
						|
    if (!data || !len || !addr) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (proto_69845_parse(&data, &len, &hdr_698, &apdu) != ERR_OK) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (apdu.len < (sizeof(*apdu_hdr) + sizeof(*req_hdr)
 | 
						|
        + sizeof(*action_hdr) + sizeof(proto_69845_app_data_time_s_t))) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    proto_69845_oi_to_byte(PROTO_69845_APP_OI_TIME, (uint8_t*)&oi);
 | 
						|
    apdu_hdr = (proto_69845_apdu_t*)apdu.ptr;
 | 
						|
    req_hdr = (proto_69845_app_action_req_t*)apdu_hdr->data;
 | 
						|
    action_hdr = (proto_69845_app_action_req_single_t*)req_hdr->data;
 | 
						|
    if (apdu_hdr->type != PROTO_69845_C_APP_ACTION_REQ
 | 
						|
        || req_hdr->data_type != PROTO_69845_APP_ACTION_NORMAL
 | 
						|
        || action_hdr->omd.oi != oi
 | 
						|
        || action_hdr->omd.method_id != PROTO_OMD_CORRECT_TIME_METHOD_ID
 | 
						|
        || action_hdr->data.data_type != PROTO_69845_APP_DATA_TIME_S) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    proto_69845_get_addr_info(hdr_698, &addr_info);
 | 
						|
    if (addr_info.ser_info.type == PROTO_69845_SA_TYPE_SIG) {
 | 
						|
        if (addr_info.ser_info.len != IOT_MAC_ADDR_LEN) {
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        iot_mac_addr_cpy(addr, addr_info.ser_info.addr);
 | 
						|
    } else if (hdr_698->addr.flag.sa_type == PROTO_69845_SA_TYPE_BROADCAST) {
 | 
						|
        os_mem_set(addr, 0xAA, IOT_MAC_ADDR_LEN);
 | 
						|
    } else {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    if (hdr_698 && hdr_698->ctrl.flag_scramble) {
 | 
						|
        /* the message is forwarded after recovery */
 | 
						|
        proto_69845_add33_handle(apdu.ptr, apdu.len);
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
#if PLC_SUPPORT_STA_ROLE
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_get_req_msg(
 | 
						|
    proto_69845_app_get_req_info_t* req_info,
 | 
						|
    const server_addr_info_t* server_info)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data, ser_len;
 | 
						|
    uint16_t length, head_len, tail_len;
 | 
						|
    addr_info_t addr_info = { 0 };
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_req_resp_t *req;
 | 
						|
    proto_69845_app_get_req_t *get_req;
 | 
						|
    proto_69845_app_get_req_normal_t *get_req_normal;
 | 
						|
 | 
						|
    if (req_info == NULL || server_info == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ser_len = proto_69845_server_len_calc(server_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
 | 
						|
        + ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
 | 
						|
        + PROTO_69845_NO_TIME_TAG_LEN + sizeof(proto_69845_tailer_t);
 | 
						|
    switch (req_info->type) {
 | 
						|
        case PROTO_69845_APP_GET_NORMAL:
 | 
						|
            length = length + sizeof(*req) + sizeof(*get_req)
 | 
						|
                + sizeof(*get_req_normal);
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt)
 | 
						|
        goto out;
 | 
						|
    iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
 | 
						|
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_data(pkt);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    addr_info.ser_info = *server_info;
 | 
						|
    addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len,
 | 
						|
        length - PROTO_69845_PREAMBLE_LEN,
 | 
						|
        &addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_CLIENT_REQUEST);
 | 
						|
    data += head_len;
 | 
						|
 | 
						|
    /* fill apdu data */
 | 
						|
    req = (proto_69845_app_req_resp_t*)data;
 | 
						|
    req->type = PROTO_69845_C_APP_GET_REQ;
 | 
						|
    get_req = (proto_69845_app_get_req_t*)req->data;
 | 
						|
    get_req->data_type = req_info->type;
 | 
						|
    data = data + sizeof(proto_69845_app_req_resp_t)
 | 
						|
         + sizeof(proto_69845_app_get_req_t);
 | 
						|
    switch (get_req->data_type) {
 | 
						|
        case PROTO_69845_APP_GET_NORMAL:
 | 
						|
            get_req_normal =
 | 
						|
                (proto_69845_app_get_req_normal_t*)get_req->data;
 | 
						|
            get_req_normal->piid = req_info->piid;
 | 
						|
            proto_69845_oi_to_byte(req_info->oad.oi,
 | 
						|
                (uint8_t*)&get_req_normal->oad.oi);
 | 
						|
            get_req_normal->oad.attribute_id = req_info->oad.attribute_id;
 | 
						|
            get_req_normal->oad.attribute_char = req_info->oad.attribute_char;
 | 
						|
            get_req_normal->oad.element_index = req_info->oad.element_index;
 | 
						|
            data += sizeof(proto_69845_app_get_req_normal_t);
 | 
						|
        break;
 | 
						|
        default:
 | 
						|
            IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    tail_len = PROTO_69845_NO_TIME_TAG_LEN + sizeof(proto_69845_tailer_t);
 | 
						|
    proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
 | 
						|
    iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_get_req_msg_with_rn(
 | 
						|
    proto_69845_app_get_list_req_info_t* req_info,
 | 
						|
    const server_addr_info_t* server_info)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data, *time_tag;
 | 
						|
    uint8_t plaintext_len, ser_len;
 | 
						|
    uint16_t length, head_len;
 | 
						|
    addr_info_t addr_info = { 0 };
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_sec_req_resp_info_t *sec_req;
 | 
						|
    proto_69845_app_req_resp_t *req;
 | 
						|
    proto_69845_app_get_req_t *get_req;
 | 
						|
    proto_69845_app_get_req_normal_list_t *get_req_normal;
 | 
						|
    proto_69845_app_sec_req_resp_vali_info_t *vali_data;
 | 
						|
    proto_69845_app_sec_rn_info_t *rn;
 | 
						|
 | 
						|
    if (req_info == NULL || server_info == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ser_len = proto_69845_server_len_calc(server_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
 | 
						|
        + ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
 | 
						|
        + sizeof(*req) + sizeof(*sec_req) + sizeof(*vali_data)
 | 
						|
        + sizeof(*rn) + PROTO_69845_SECURITY_RN_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t);
 | 
						|
    switch (req_info->type) {
 | 
						|
        case PROTO_69845_APP_GET_NORMALLIST:
 | 
						|
            plaintext_len = sizeof(*req) + sizeof(*get_req)
 | 
						|
                + sizeof(*get_req_normal)
 | 
						|
                + sizeof(proto_69845_app_oad_t) * req_info->oad_cnt
 | 
						|
                + PROTO_69845_NO_TIME_TAG_LEN;
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            goto out;
 | 
						|
    }
 | 
						|
    length += plaintext_len;
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt)
 | 
						|
        goto out;
 | 
						|
    iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
 | 
						|
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_data(pkt);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    addr_info.ser_info = *server_info;
 | 
						|
    addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len,
 | 
						|
        length - PROTO_69845_PREAMBLE_LEN,
 | 
						|
        &addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_CLIENT_REQUEST);
 | 
						|
    data += head_len;
 | 
						|
 | 
						|
    /* fill security request */
 | 
						|
    req = (proto_69845_app_req_resp_t*)data;
 | 
						|
    req->type = PROTO_69845_C_APP_SECURITY_REQ;
 | 
						|
    sec_req = (proto_69845_app_sec_req_resp_info_t*)req->data;
 | 
						|
    sec_req->type = PROTO_69845_SEC_DATA_TYPE_PLAINTEXT;
 | 
						|
    sec_req->len = plaintext_len;
 | 
						|
    data = data + sizeof(proto_69845_app_req_resp_t)
 | 
						|
         + sizeof(proto_69845_app_sec_req_resp_info_t);
 | 
						|
 | 
						|
    /* fill plaintext apdu data */
 | 
						|
    req = (proto_69845_app_req_resp_t*)sec_req->data;
 | 
						|
    req->type = PROTO_69845_C_APP_GET_REQ;
 | 
						|
    get_req = (proto_69845_app_get_req_t*)req->data;
 | 
						|
    get_req->data_type = req_info->type;
 | 
						|
    data = data + sizeof(proto_69845_app_req_resp_t)
 | 
						|
         + sizeof(proto_69845_app_get_req_t);
 | 
						|
    switch (get_req->data_type) {
 | 
						|
    case PROTO_69845_APP_GET_NORMALLIST:
 | 
						|
    {
 | 
						|
        get_req_normal =
 | 
						|
            (proto_69845_app_get_req_normal_list_t*)get_req->data;
 | 
						|
        get_req_normal->piid = req_info->piid;
 | 
						|
        get_req_normal->oad_cnt = req_info->oad_cnt;
 | 
						|
        data += sizeof(proto_69845_app_get_req_normal_list_t);
 | 
						|
        for (uint8_t i = 0; i < req_info->oad_cnt; i++) {
 | 
						|
            proto_69845_oi_to_byte(req_info->oad[i].oi,
 | 
						|
                (uint8_t*)&get_req_normal->oad[i].oi);
 | 
						|
            get_req_normal->oad[i].attribute_id =
 | 
						|
                req_info->oad[i].attribute_id;
 | 
						|
            get_req_normal->oad[i].attribute_char =
 | 
						|
                req_info->oad[i].attribute_char;
 | 
						|
            get_req_normal->oad[i].element_index =
 | 
						|
                req_info->oad[i].element_index;
 | 
						|
            data += sizeof(proto_69845_app_oad_t);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    /* There is no time tag field, so time_tag is 0 */
 | 
						|
    time_tag = data;
 | 
						|
    (*time_tag) = 0;
 | 
						|
    data += 1;
 | 
						|
 | 
						|
    /* fill 698.45 proto security validation data */
 | 
						|
    vali_data = (proto_69845_app_sec_req_resp_vali_info_t*)data;
 | 
						|
    vali_data->type = PROTO_69845_SEC_REQ_VALI_TYPE_RN;
 | 
						|
    rn = (proto_69845_app_sec_rn_info_t*)vali_data->data;
 | 
						|
    rn->len = PROTO_69845_SECURITY_RN_LEN;
 | 
						|
    os_mem_cpy(rn->data, proto_69845_rn, PROTO_69845_SECURITY_RN_LEN);
 | 
						|
    data = data + sizeof(proto_69845_app_sec_req_resp_vali_info_t)
 | 
						|
        + sizeof(proto_69845_app_sec_rn_info_t) + PROTO_69845_SECURITY_RN_LEN;
 | 
						|
 | 
						|
    /* fill 698.45 proto tailer */
 | 
						|
    proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
 | 
						|
    iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
 | 
						|
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_action_req_single_msg(
 | 
						|
    const proto_69845_app_action_req_single_t *req_info, uint16_t app_data_len,
 | 
						|
    const server_addr_info_t* server_info)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_req_resp_t *apdu_head;
 | 
						|
    proto_69845_app_action_req_single_t *src_req_info;
 | 
						|
    proto_69845_app_action_req_t *req;
 | 
						|
    uint8_t ser_len;
 | 
						|
    uint16_t length, head_len;
 | 
						|
    uint8_t *data, *time_tag;
 | 
						|
    addr_info_t addr_info = { 0 };
 | 
						|
 | 
						|
    if (req_info == NULL || server_info == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    ser_len = proto_69845_server_len_calc(server_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
 | 
						|
        + ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN +
 | 
						|
        sizeof(*apdu_head) + sizeof(*req) + sizeof(*req_info) + app_data_len +
 | 
						|
        PROTO_69845_NO_TIME_TAG_LEN + sizeof(proto_69845_tailer_t);
 | 
						|
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt)
 | 
						|
        goto out;
 | 
						|
    iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
 | 
						|
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_data(pkt);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    addr_info.ser_info = *server_info;
 | 
						|
    addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len,
 | 
						|
        length - PROTO_69845_PREAMBLE_LEN,
 | 
						|
        &addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_CLIENT_REQUEST);
 | 
						|
    data += head_len;
 | 
						|
 | 
						|
    /* fill apdu data */
 | 
						|
    apdu_head = (proto_69845_app_req_resp_t*)data;
 | 
						|
    apdu_head->type = PROTO_69845_C_APP_ACTION_REQ;
 | 
						|
    data += sizeof(*apdu_head);
 | 
						|
 | 
						|
    /* fill 698.45 action req single object header */
 | 
						|
    req = (proto_69845_app_action_req_t *)data;
 | 
						|
    req->data_type = PROTO_69845_APP_ACTION_NORMAL;
 | 
						|
    data += sizeof(*req);
 | 
						|
 | 
						|
    /* fill 698.45 action req single object info */
 | 
						|
    os_mem_cpy(data, req_info, sizeof(*req_info));
 | 
						|
    src_req_info = (proto_69845_app_action_req_single_t *)data;
 | 
						|
    proto_69845_oi_to_byte(req_info->omd.oi,
 | 
						|
        (uint8_t *)&(src_req_info->omd.oi));
 | 
						|
    data += sizeof(*req_info);
 | 
						|
 | 
						|
    /* fill 698.45 action req single object app data */
 | 
						|
    if (app_data_len) {
 | 
						|
        os_mem_cpy(data, req_info->data.data, app_data_len);
 | 
						|
        data += app_data_len;
 | 
						|
    }
 | 
						|
 | 
						|
    /* There is no time tag field, so time_tag is 0 */
 | 
						|
    time_tag = data;
 | 
						|
    (*time_tag) = 0;
 | 
						|
    data += 1;
 | 
						|
 | 
						|
    /* fill 698.45 proto tailer */
 | 
						|
    proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
 | 
						|
    iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t proto_69845_oad_cmp(proto_69845_app_oad_t *oad_1,
 | 
						|
    proto_69845_app_oad_t *oad_2)
 | 
						|
{
 | 
						|
    if (!oad_1 || !oad_2) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    if (oad_1->oi == oad_2->oi && oad_1->attribute_id == oad_2->attribute_id &&
 | 
						|
        oad_1->attribute_char == oad_2->attribute_char &&
 | 
						|
        oad_1->element_index == oad_2->element_index) {
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_apdu_data_with_rn_msg(uint8_t *apdu_data,
 | 
						|
    uint32_t data_len, const server_addr_info_t* server_info)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data, *len, ser_len, info_len_byte = 0;
 | 
						|
    uint16_t head_len;
 | 
						|
    uint32_t length;
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_req_resp_t *req;
 | 
						|
    proto_69845_app_sec_req_resp_info_t *req_info;
 | 
						|
    proto_69845_app_sec_req_resp_vali_info_t *vali_data;
 | 
						|
    proto_69845_app_sec_rn_info_t *rn;
 | 
						|
    proto_69845_app_len_descript_t *len_desc;
 | 
						|
    addr_info_t addr_info = { 0 };
 | 
						|
 | 
						|
    if (apdu_data == NULL || server_info == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ser_len = proto_69845_server_len_calc(server_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (data_len > 255) {
 | 
						|
        info_len_byte = 2;
 | 
						|
    } else if (data_len > 127) {
 | 
						|
        info_len_byte = 1;
 | 
						|
    }
 | 
						|
    length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
 | 
						|
        + ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
 | 
						|
        + sizeof(*req) + sizeof(*req_info)
 | 
						|
        + sizeof(*vali_data) + sizeof(*rn) + PROTO_69845_SECURITY_RN_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t) + data_len + info_len_byte;
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_put(pkt, length - PROTO_69845_PREAMBLE_LEN);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    addr_info.ser_info = *server_info;
 | 
						|
    addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len,
 | 
						|
        (uint16_t)(length - PROTO_69845_PREAMBLE_LEN),
 | 
						|
        &addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_CLIENT_REQUEST);
 | 
						|
    data += head_len;
 | 
						|
    /* fill app req */
 | 
						|
    req = (proto_69845_app_req_resp_t *)data;
 | 
						|
    req->type = PROTO_69845_C_APP_SECURITY_REQ;
 | 
						|
    req_info = (proto_69845_app_sec_req_resp_info_t *)req->data;
 | 
						|
    req_info->type = PROTO_69845_SEC_DATA_TYPE_PLAINTEXT;
 | 
						|
    if (!info_len_byte) {
 | 
						|
        req_info->len = (uint8_t)data_len;
 | 
						|
        data += (sizeof(*req) + sizeof(*req_info));
 | 
						|
    } else {
 | 
						|
        len_desc = (proto_69845_app_len_descript_t*)&req_info->len;
 | 
						|
        len_desc->mub_flag = 1;
 | 
						|
        len_desc->byte_num = info_len_byte;
 | 
						|
        len = (uint8_t*)req_info->data;
 | 
						|
        if (info_len_byte == 2) {
 | 
						|
            *len = (uint8_t)(data_len >> 8);
 | 
						|
            len++;
 | 
						|
        }
 | 
						|
        *len = (uint8_t)data_len;
 | 
						|
        data += (sizeof(*req) + sizeof(*req_info) + info_len_byte);
 | 
						|
    }
 | 
						|
    /* fill apdu data */
 | 
						|
    os_mem_cpy(req_info->data, apdu_data, data_len);
 | 
						|
    data += data_len;
 | 
						|
    /* fill 698.45 proto security validation data */
 | 
						|
    vali_data = (proto_69845_app_sec_req_resp_vali_info_t*)data;
 | 
						|
    vali_data->type = PROTO_69845_SEC_REQ_VALI_TYPE_RN;
 | 
						|
    rn = (proto_69845_app_sec_rn_info_t*)vali_data->data;
 | 
						|
    rn->len = PROTO_69845_SECURITY_RN_LEN;
 | 
						|
    os_mem_cpy(rn->data, proto_69845_rn, PROTO_69845_SECURITY_RN_LEN);
 | 
						|
    data = data + sizeof(proto_69845_app_sec_req_resp_vali_info_t)
 | 
						|
        + sizeof(proto_69845_app_sec_rn_info_t) + PROTO_69845_SECURITY_RN_LEN;
 | 
						|
    /* fill 698.45 proto tailer */
 | 
						|
    proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
static uint8_t proto_69845_get_tans_baud_id(uint32_t baud)
 | 
						|
{
 | 
						|
    uint8_t i = 0;
 | 
						|
 | 
						|
    for (i = 0; i < PROTO_69845_TANS_BAUD_MAX; i++) {
 | 
						|
        if (proto_69845_tans_baud[i] == baud) {
 | 
						|
            return i;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return PORTO_645_BAUD_ID_AUTO;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_proxy_trans_data_msg(uint8_t *data,
 | 
						|
    uint32_t data_len, uint32_t baud, uint8_t port, uint8_t parity,
 | 
						|
    uint16_t timeout, const server_addr_info_t* server_info, uint8_t sn)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *time_flag, *data_in, ser_len;
 | 
						|
    uint16_t head_len;
 | 
						|
    uint32_t length;
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_apdu_t *apdu_req;
 | 
						|
    proto_69845_app_data_proxy_req_t *proxy_request;
 | 
						|
    proto_69845_app_data_proxy_tans_req_t *proxy_cmd_request;
 | 
						|
    addr_info_t addr_info;
 | 
						|
 | 
						|
    if (!data || !server_info) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (port != PROTO_PORT_RS485_1 && port != PROTO_PORT_RS485_2) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ser_len = proto_69845_server_len_calc(server_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
 | 
						|
        + ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
 | 
						|
        + sizeof(*proxy_request) + sizeof(*proxy_cmd_request)
 | 
						|
        + sizeof(*apdu_req) + sizeof(proto_69845_tailer_t)
 | 
						|
        + sizeof(*time_flag) + data_len;
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data_in = iot_pkt_put(pkt, length - PROTO_69845_PREAMBLE_LEN);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data_in;
 | 
						|
    addr_info.ser_info = *server_info;
 | 
						|
    addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len,
 | 
						|
        (uint16_t)(length - PROTO_69845_PREAMBLE_LEN),
 | 
						|
        &addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_CLIENT_REQUEST);
 | 
						|
    data_in += head_len;
 | 
						|
    /* fill app req */
 | 
						|
    apdu_req = (proto_69845_apdu_t *)data_in;
 | 
						|
    apdu_req->type = PROTO_69845_C_APP_PROXY_REQ;
 | 
						|
 | 
						|
    proxy_request = (proto_69845_app_data_proxy_req_t *)apdu_req->data;
 | 
						|
    proxy_request->proxy_type = PROTO_69845_PROXY_TRANS_COMMAND_REQUEST;
 | 
						|
 | 
						|
    proxy_cmd_request =
 | 
						|
        (proto_69845_app_data_proxy_tans_req_t*)proxy_request->data;
 | 
						|
    proxy_cmd_request->piid.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
 | 
						|
    proxy_cmd_request->piid.sn = sn;
 | 
						|
 | 
						|
    if (port == PROTO_PORT_RS485_1) {
 | 
						|
        iot_uint32_to_bytes(PROTO_69845_APP_OAD_PORT_RS485I,
 | 
						|
            (uint8_t*)&proxy_cmd_request->oad, 1);
 | 
						|
    } else {
 | 
						|
        iot_uint32_to_bytes(PROTO_69845_APP_OAD_PORT_RS485II,
 | 
						|
            (uint8_t*)&proxy_cmd_request->oad, 1);
 | 
						|
    }
 | 
						|
 | 
						|
    proxy_cmd_request->comdcb.buad = proto_69845_get_tans_baud_id(baud);
 | 
						|
    proxy_cmd_request->comdcb.parity = parity;
 | 
						|
    proxy_cmd_request->comdcb.stop = PROTO_69845_STOP_1_BITS;
 | 
						|
    proxy_cmd_request->comdcb.data_bit = PROTO_69845_DLEN_8_BITS;
 | 
						|
    proxy_cmd_request->comdcb.flow_mode = 0;
 | 
						|
    iot_uint16_to_bytes(timeout, (uint8_t*)&proxy_cmd_request->timeout1, 1);
 | 
						|
    iot_uint16_to_bytes(30, (uint8_t*)&proxy_cmd_request->timeout2, 1);
 | 
						|
    proxy_cmd_request->data_len = (uint8_t)data_len;
 | 
						|
    /* fill trans data */
 | 
						|
    os_mem_cpy(proxy_cmd_request->data, data, data_len);
 | 
						|
    time_flag = proxy_cmd_request->data + data_len;
 | 
						|
    *time_flag = 0;
 | 
						|
 | 
						|
    /* fill 698.45 proto tailer */
 | 
						|
    proto_69845_tail_fill(head, time_flag + sizeof(*time_flag),
 | 
						|
        sizeof(proto_69845_tailer_t));
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_get_version_msg_with_rn(
 | 
						|
    const server_addr_info_t *server_info, uint8_t sn)
 | 
						|
{
 | 
						|
    uint8_t *data = NULL;
 | 
						|
    proto_69845_apdu_t *apdu;
 | 
						|
    proto_69845_app_get_req_t *get_req = NULL;
 | 
						|
    proto_69845_app_get_req_normal_t *normal = NULL;
 | 
						|
    uint32_t req_size = 0;
 | 
						|
    iot_pkt_t *pkt = NULL, *req = NULL;
 | 
						|
 | 
						|
    req_size = sizeof(*apdu) + sizeof(*get_req) + sizeof(*normal)
 | 
						|
        + PROTO_69845_NO_TIME_TAG_LEN;
 | 
						|
    req = iot_pkt_alloc(req_size, IOT_SMART_GRID_MID);
 | 
						|
    if (!req) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = iot_pkt_put(req, req_size);
 | 
						|
    apdu = (proto_69845_apdu_t *)data;
 | 
						|
    apdu->type = PROTO_69845_C_APP_GET_REQ;
 | 
						|
    get_req = (proto_69845_app_get_req_t *)apdu->data;
 | 
						|
    get_req->data_type = PROTO_69845_APP_GET_NORMAL;
 | 
						|
    normal = (proto_69845_app_get_req_normal_t *)get_req->data;
 | 
						|
    normal->piid.sn = sn;
 | 
						|
    normal->piid.priority = PROTO_69845_APP_PIID_PRIORITY_GENERAL;
 | 
						|
    proto_69845_oi_to_byte(PROTO_69845_APP_OI_GET_VERSION,
 | 
						|
        (uint8_t *)&normal->oad.oi);
 | 
						|
    normal->oad.attribute_id = 3;
 | 
						|
    normal->oad.attribute_char = 0;
 | 
						|
    normal->oad.element_index = 1;
 | 
						|
    pkt = proto_69845_build_apdu_data_with_rn_msg(data, req_size, server_info);
 | 
						|
    iot_pkt_free(req);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_comdcb_msg(uint32_t baud,
 | 
						|
    const server_addr_info_t *server_info, uint8_t sn)
 | 
						|
{
 | 
						|
    uint16_t data_len = 0;
 | 
						|
    iot_pkt_t *ret = NULL, *pkt = NULL;
 | 
						|
    proto_69845_app_action_req_single_t *request = NULL;
 | 
						|
    proto_69845_app_ele_data_t *app_ele_data = NULL;
 | 
						|
    proto_69845_app_oad_t *app_oad = NULL;
 | 
						|
    proto_69845_app_data_t *app_data = NULL;
 | 
						|
    proto_69845_app_data_comdcb_t *comdcb = NULL;
 | 
						|
 | 
						|
    data_len = sizeof(*app_data) + sizeof(*app_data) + sizeof(*app_oad) +
 | 
						|
               sizeof(*app_data) + sizeof(*comdcb);
 | 
						|
    pkt = iot_pkt_alloc(data_len + sizeof(*request), IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    request = (proto_69845_app_action_req_single_t *)iot_pkt_data(pkt);
 | 
						|
    request->piid.sn = sn;
 | 
						|
    request->omd.oi = PROTO_69845_APP_OI_PLC_WIRELESS_INTERFACE;
 | 
						|
    request->omd.method_id = 0x80;
 | 
						|
    request->omd.operation_mode = 0x00;
 | 
						|
 | 
						|
    app_ele_data = (proto_69845_app_ele_data_t *)&request->data;
 | 
						|
    app_ele_data->data_type = PROTO_69845_APP_DATA_STRUCTURE;
 | 
						|
    app_ele_data->num_of_data = 2;
 | 
						|
    app_data = (proto_69845_app_data_t *)app_ele_data->data;
 | 
						|
    app_data->data_type = PROTO_69845_APP_DATA_OAD;
 | 
						|
 | 
						|
    app_oad = (proto_69845_app_oad_t *)app_data->data;
 | 
						|
    app_oad->oi = PROTO_69845_APP_OI_PLC_WIRELESS_INTERFACE;
 | 
						|
    proto_69845_oi_to_byte(app_oad->oi, (uint8_t *)&(app_oad->oi));
 | 
						|
 | 
						|
    app_oad->attribute_id = 0x02;
 | 
						|
    app_oad->element_index = 0xFD;
 | 
						|
 | 
						|
    app_data = (proto_69845_app_data_t *)(app_oad + 1);
 | 
						|
    app_data->data_type = PROTO_69845_APP_DATA_COMDCB;
 | 
						|
 | 
						|
    comdcb = (proto_69845_app_data_comdcb_t *)app_data->data;
 | 
						|
    comdcb->buad = proto_69845_get_tans_baud_id(baud);
 | 
						|
    comdcb->parity = PROTO_69845_PARITY_EVEN;
 | 
						|
    comdcb->data_bit = PROTO_69845_DLEN_8_BITS;
 | 
						|
    comdcb->stop = PROTO_69845_STOP_1_BITS;
 | 
						|
    comdcb->flow_mode = 0;
 | 
						|
    ret = proto_69845_build_action_req_single_msg(
 | 
						|
            request, data_len, server_info);
 | 
						|
out:
 | 
						|
    if (pkt) {
 | 
						|
        iot_pkt_free(pkt);
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_proxy_trans_resp_parse(uint8_t **data,
 | 
						|
    uint16_t *len, uint8_t *seq)
 | 
						|
{
 | 
						|
    uint32_t oad, apdu_len, err = ERR_OK;
 | 
						|
    proto_69845_frame_head_info_t *hdr_698;
 | 
						|
    apdu_info_t apdu_desc = { 0 };
 | 
						|
    proto_69845_apdu_t *apdu_resq;
 | 
						|
    proto_69845_app_data_proxy_req_t *proxy_resq;
 | 
						|
    proto_69845_app_data_proxy_tans_resp_t *proxy_tans_resp;
 | 
						|
    if (!data || !(*data) || !len) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    hdr_698 = proto_69845_sanity_check(*data, *len);
 | 
						|
    if (!hdr_698) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (proto_69845_get_apdu(hdr_698, *len, &apdu_desc) != ERR_OK) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (!apdu_desc.len || !apdu_desc.ptr) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    apdu_len = apdu_desc.len;
 | 
						|
    if (apdu_len < sizeof(*apdu_resq) + sizeof(*proxy_resq)
 | 
						|
        + sizeof(*proxy_tans_resp)) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    apdu_len -= sizeof(*apdu_resq) + sizeof(*proxy_resq)
 | 
						|
        + sizeof(*proxy_tans_resp);
 | 
						|
    apdu_resq = (proto_69845_apdu_t *)apdu_desc.ptr;
 | 
						|
    if (apdu_resq->type != PROTO_69845_S_APP_PROXY_RESP) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    proxy_resq = (proto_69845_app_data_proxy_req_t *)apdu_resq->data;
 | 
						|
    if (proxy_resq->proxy_type != PROTO_69845_PROXY_TRANS_COMMAND_REQUEST) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    proxy_tans_resp =
 | 
						|
        (proto_69845_app_data_proxy_tans_resp_t *)proxy_resq->data;
 | 
						|
    oad = iot_bytes_to_uint32((uint8_t*)&proxy_tans_resp->oad, 1);
 | 
						|
    if (oad != PROTO_69845_APP_OAD_PORT_RS485I
 | 
						|
        && oad != PROTO_69845_APP_OAD_PORT_RS485II) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (proxy_tans_resp->data_type != PROTO_69845_APP_DATA_ARRAY
 | 
						|
        || !proxy_tans_resp->data_len) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (apdu_len < proxy_tans_resp->data_len) {
 | 
						|
        err = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    *len = proxy_tans_resp->data_len;
 | 
						|
    *data = proxy_tans_resp->data;
 | 
						|
    *seq = proxy_tans_resp->piid.sn;
 | 
						|
out:
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_apdu_data_msg(uint8_t *apdu_data,
 | 
						|
    uint32_t data_len, addr_info_t* addr_info, uint8_t dir_and_prm)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data, ser_len;
 | 
						|
    uint16_t head_len;
 | 
						|
    uint32_t length;
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
 | 
						|
    if (apdu_data == NULL || addr_info == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
 | 
						|
        + ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
 | 
						|
        + data_len + sizeof(proto_69845_tailer_t);
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_put(pkt, length - PROTO_69845_PREAMBLE_LEN);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len,
 | 
						|
        (uint16_t)(length - PROTO_69845_PREAMBLE_LEN),
 | 
						|
        addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        dir_and_prm);
 | 
						|
    data += head_len;
 | 
						|
    /* fill apdu data */
 | 
						|
    os_mem_cpy(data, apdu_data, data_len);
 | 
						|
    data += data_len;
 | 
						|
    /* fill 698.45 proto tailer */
 | 
						|
    proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_apdu_data_with_security_resp_msg(uint8_t *apdu_data,
 | 
						|
    uint32_t data_len, addr_info_t* addr_info)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data, *len, info_len_byte = 0, ser_len;
 | 
						|
    uint16_t head_len;
 | 
						|
    uint32_t length;
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_req_resp_t *resp;
 | 
						|
    proto_69845_app_sec_req_resp_info_t *resp_info;
 | 
						|
    proto_69845_app_sec_optinon_info_t *vali_data;
 | 
						|
    proto_69845_app_sec_mac_info_t *sec_mac;
 | 
						|
    proto_69845_app_len_descript_t *len_desc;
 | 
						|
 | 
						|
    if (apdu_data == NULL || addr_info == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (data_len > 255) {
 | 
						|
        info_len_byte = 2;
 | 
						|
    } else if (data_len > 127) {
 | 
						|
        info_len_byte = 1;
 | 
						|
    }
 | 
						|
    length = PROTO_69845_PREAMBLE_LEN + sizeof(*head)
 | 
						|
        + ser_len + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN
 | 
						|
        + sizeof(*resp) + sizeof(*resp_info)
 | 
						|
        + sizeof(*vali_data) + sizeof(*sec_mac)
 | 
						|
        + info_len_byte + PROTO_69845_SECURITY_SEQUEN_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t) + data_len;
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    iot_pkt_reserve(pkt, PROTO_69845_PREAMBLE_LEN);
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_put(pkt, length - PROTO_69845_PREAMBLE_LEN);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    head_len = sizeof(*head) + ser_len
 | 
						|
        + PROTO_69845_CA_LEN + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len,
 | 
						|
        (uint16_t)(length - PROTO_69845_PREAMBLE_LEN),
 | 
						|
        addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_SERVER_RESPONSE);
 | 
						|
    data += head_len;
 | 
						|
    /* fill app req */
 | 
						|
    resp = (proto_69845_app_req_resp_t *)data;
 | 
						|
    resp->type = PROTO_69845_S_APP_SECURITY_RESP;
 | 
						|
    resp_info = (proto_69845_app_sec_req_resp_info_t *)resp->data;
 | 
						|
    resp_info->type = PROTO_69845_SEC_DATA_TYPE_PLAINTEXT;
 | 
						|
    if (!info_len_byte) {
 | 
						|
        resp_info->len = (uint8_t)data_len;
 | 
						|
        data += (sizeof(*resp) + sizeof(*resp_info));
 | 
						|
    } else {
 | 
						|
        len_desc = (proto_69845_app_len_descript_t*)&resp_info->len;
 | 
						|
        len_desc->mub_flag = 1;
 | 
						|
        len_desc->byte_num = info_len_byte;
 | 
						|
        len = (uint8_t*)resp_info->data;
 | 
						|
        if (info_len_byte == 2) {
 | 
						|
            *len = (uint8_t)(data_len >> 8);
 | 
						|
            len++;
 | 
						|
        }
 | 
						|
        *len = (uint8_t)data_len;
 | 
						|
        data += (sizeof(*resp) + sizeof(*resp_info) + info_len_byte);
 | 
						|
    }
 | 
						|
 | 
						|
    /* fill apdu data */
 | 
						|
    os_mem_cpy(data, apdu_data, data_len);
 | 
						|
    data += data_len;
 | 
						|
    /* fill 698.45 proto security validation data */
 | 
						|
    vali_data = (proto_69845_app_sec_optinon_info_t*)data;
 | 
						|
    vali_data->type = PROTO_69845_SEC_RESP_VALI_TYPE_MAC_RN;
 | 
						|
    vali_data->choice = PROTO_69845_SEC_DATA_TYPE_PLAINTEXT;
 | 
						|
    sec_mac = (proto_69845_app_sec_mac_info_t*)vali_data->data;
 | 
						|
    sec_mac->len = PROTO_69845_SECURITY_SEQUEN_LEN;
 | 
						|
    os_mem_cpy(sec_mac->data, proto_69845_rn, PROTO_69845_SECURITY_SEQUEN_LEN);
 | 
						|
    data = data + sizeof(proto_69845_app_sec_optinon_info_t)
 | 
						|
        + sizeof(proto_69845_app_sec_mac_info_t)
 | 
						|
        + PROTO_69845_SECURITY_SEQUEN_LEN;
 | 
						|
    /* fill 698.45 proto tailer */
 | 
						|
    proto_69845_tail_fill(head, data, sizeof(proto_69845_tailer_t));
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_set_normal_ack(addr_info_t *addr_info,
 | 
						|
    proto_69845_app_piid_t *piid, proto_69845_app_oad_t *oad,
 | 
						|
    uint8_t dar)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data, ser_len;
 | 
						|
    uint16_t length, head_len, tail_len;
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_req_resp_t *resp;
 | 
						|
    proto_69845_app_set_resp_t *set_resp;
 | 
						|
    proto_69845_app_set_resp_normal_t *set_normal;
 | 
						|
 | 
						|
    if (addr_info == NULL || piid == NULL || oad == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    length = sizeof(*head) + ser_len + PROTO_69845_CA_LEN
 | 
						|
        + PROTO_69845_CHECKSUM_LEN + sizeof(*resp) + sizeof(*set_resp)
 | 
						|
        + sizeof(*set_normal) + PROTO_69845_NO_TIME_TAG_LEN
 | 
						|
        + PROTO_69845_NO_FLW_DATA_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t);
 | 
						|
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt)
 | 
						|
        goto out;
 | 
						|
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_data(pkt);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    head_len = sizeof(*head) + ser_len + PROTO_69845_CA_LEN
 | 
						|
        + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len, length,
 | 
						|
        addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_SERVER_RESPONSE);
 | 
						|
    data += head_len;
 | 
						|
 | 
						|
    /* fill plaintext apdu data */
 | 
						|
    resp = (proto_69845_app_req_resp_t*)data;
 | 
						|
    resp->type = PROTO_69845_S_APP_SET_RESP;
 | 
						|
    set_resp = (proto_69845_app_set_resp_t*)resp->data;
 | 
						|
    set_resp->data_type = PROTO_69845_APP_SET_NORMAL;
 | 
						|
    data = data + sizeof(*resp) + sizeof(*set_resp);
 | 
						|
    set_normal = (proto_69845_app_set_resp_normal_t*)set_resp->data;
 | 
						|
    set_normal->piid_acd.sn = piid->sn;
 | 
						|
    set_normal->piid_acd.priority = piid->priority;
 | 
						|
    set_normal->piid_acd.acd = 0;
 | 
						|
    proto_69845_oi_to_byte(oad->oi, (uint8_t*)&set_normal->result.oad.oi);
 | 
						|
    set_normal->result.oad.attribute_char = oad->attribute_char;
 | 
						|
    set_normal->result.oad.attribute_id = oad->attribute_id;
 | 
						|
    set_normal->result.oad.element_index = oad->element_index;
 | 
						|
    set_normal->result.dar = dar;
 | 
						|
    data += sizeof(*set_normal);
 | 
						|
    /* There is no time tag field, so time_tag is 0 */
 | 
						|
    tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t);
 | 
						|
    proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
 | 
						|
    iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_action_single_ack(addr_info_t *addr_info,
 | 
						|
    proto_69845_app_piid_t *piid, proto_69845_app_omd_t *omd,
 | 
						|
    uint8_t dar)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data, ser_len;
 | 
						|
    uint16_t length, head_len, tail_len;
 | 
						|
    proto_69845_frame_head_info_t *head;
 | 
						|
    proto_69845_app_req_resp_t *resp;
 | 
						|
    proto_69845_app_action_resp_t *action_resp;
 | 
						|
    proto_69845_app_action_resp_normal_t *action_normal;
 | 
						|
 | 
						|
    if (addr_info == NULL || piid == NULL || omd == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    ser_len = proto_69845_server_len_calc(&addr_info->ser_info);
 | 
						|
    if ((ser_len > PROTO_69845_SA_MAX_LEN) || !ser_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    length = sizeof(*head) + ser_len + PROTO_69845_CA_LEN
 | 
						|
        + PROTO_69845_CHECKSUM_LEN + sizeof(*resp) + sizeof(*action_resp)
 | 
						|
        + sizeof(*action_normal) + PROTO_69845_NO_TIME_TAG_LEN
 | 
						|
        + PROTO_69845_NO_FLW_DATA_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t);
 | 
						|
 | 
						|
    pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt)
 | 
						|
        goto out;
 | 
						|
 | 
						|
    /* fill 698.45 proto header */
 | 
						|
    data = iot_pkt_data(pkt);
 | 
						|
    head = (proto_69845_frame_head_info_t *)data;
 | 
						|
    head_len = sizeof(*head) + ser_len + PROTO_69845_CA_LEN
 | 
						|
        + PROTO_69845_CHECKSUM_LEN;
 | 
						|
    proto_69845_head_fill(head, head_len, length,
 | 
						|
        addr_info, PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
 | 
						|
        PROTO_69845_D_P_SERVER_RESPONSE);
 | 
						|
    data += head_len;
 | 
						|
 | 
						|
    /* fill plaintext apdu data */
 | 
						|
    resp = (proto_69845_app_req_resp_t*)data;
 | 
						|
    resp->type = PROTO_69845_S_APP_ACTION_RESP;
 | 
						|
    action_resp = (proto_69845_app_action_resp_t*)resp->data;
 | 
						|
    action_resp->data_type = PROTO_69845_APP_ACTION_NORMAL;
 | 
						|
    data = data + sizeof(*resp) + sizeof(*action_resp);
 | 
						|
    action_normal = (proto_69845_app_action_resp_normal_t*)action_resp->data;
 | 
						|
    action_normal->piid_acd.sn = piid->sn;
 | 
						|
    action_normal->piid_acd.priority = piid->priority;
 | 
						|
    action_normal->piid_acd.acd = 0;
 | 
						|
    proto_69845_oi_to_byte(omd->oi, (uint8_t*)&action_normal->result.omd.oi);
 | 
						|
    action_normal->result.omd.method_id = omd->method_id;
 | 
						|
    action_normal->result.omd.operation_mode = omd->operation_mode;
 | 
						|
    action_normal->result.dar = dar;
 | 
						|
    action_normal->result.optional = PROTO_69845_APP_OPTIONAL_NO_DATA;
 | 
						|
    data += sizeof(*action_normal);
 | 
						|
    /* There is no time tag field, so time_tag is 0 */
 | 
						|
    tail_len = PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN
 | 
						|
        + sizeof(proto_69845_tailer_t);
 | 
						|
    proto_69845_tail_fill_without_ts_fl(head, data, tail_len);
 | 
						|
    iot_pkt_put(pkt, head->len + PROTO_69845_START_END_LEN);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
/* create a meter correcting time message for the 69845 protocol  */
 | 
						|
iot_pkt_t *proto_69845_build_corr_msg(server_addr_info_t *server_addr,
 | 
						|
    iot_time_tm_t *tm, proto_69845_app_piid_t *piid, uint8_t with_rn)
 | 
						|
{
 | 
						|
    uint8_t *time_tag, *data;
 | 
						|
    uint32_t action_req_size;
 | 
						|
    proto_69845_apdu_t *apdu;
 | 
						|
    proto_69845_app_action_req_t *act_req;
 | 
						|
    proto_69845_app_action_req_single_t *req_single;
 | 
						|
    proto_69845_app_data_time_s_t *time;
 | 
						|
    iot_pkt_t *pkt = NULL, *get_action_req = NULL;
 | 
						|
    addr_info_t addr_info = { 0 };
 | 
						|
 | 
						|
    if (!tm || !piid) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    action_req_size = sizeof(*apdu) + sizeof(*act_req) + sizeof(*req_single)
 | 
						|
        + sizeof(*time) + sizeof(*time_tag);
 | 
						|
    get_action_req = iot_pkt_alloc(action_req_size, IOT_SMART_GRID_MID);
 | 
						|
    if (!get_action_req) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = iot_pkt_put(get_action_req, action_req_size);
 | 
						|
    apdu = (proto_69845_apdu_t *)data;
 | 
						|
    apdu->type = PROTO_69845_C_APP_ACTION_REQ;
 | 
						|
    act_req = (proto_69845_app_action_req_t *)apdu->data;
 | 
						|
    act_req->data_type = PROTO_69845_APP_ACTION_NORMAL;
 | 
						|
    req_single = (proto_69845_app_action_req_single_t *)act_req->data;
 | 
						|
    req_single->piid.priority = piid->priority;
 | 
						|
    req_single->piid.sn = piid->sn;
 | 
						|
    proto_69845_oi_to_byte(PROTO_69845_APP_OI_TIME,
 | 
						|
        (uint8_t*)&req_single->omd.oi);
 | 
						|
    req_single->omd.method_id = PROTO_OMD_CORRECT_TIME_METHOD_ID;
 | 
						|
    req_single->omd.operation_mode = 0;
 | 
						|
    req_single->data.data_type = PROTO_69845_APP_DATA_TIME_S;
 | 
						|
    time = (proto_69845_app_data_time_s_t *)req_single->data.data;
 | 
						|
    time->year = iot_bytes_to_uint16((uint8_t *)&tm->tm_year, 1);
 | 
						|
    time->month = tm->tm_mon;
 | 
						|
    time->day = tm->tm_mday;
 | 
						|
    time->hour = tm->tm_hour;
 | 
						|
    time->minute = tm->tm_min;
 | 
						|
    time->second = tm->tm_sec;
 | 
						|
    time_tag = data + sizeof(*apdu) + sizeof(*act_req) + sizeof(*req_single)
 | 
						|
        + sizeof(*time);
 | 
						|
    *time_tag = 0;
 | 
						|
    if (!server_addr) {
 | 
						|
        if (with_rn) {
 | 
						|
            pkt = proto_69845_build_apdu_data_with_rn_msg((uint8_t *)apdu,
 | 
						|
                action_req_size, &proto_69845_any_server_addr);
 | 
						|
        } else {
 | 
						|
            addr_info.ser_info = proto_69845_any_server_addr;
 | 
						|
            pkt = proto_69845_build_apdu_data_msg((uint8_t *)apdu,
 | 
						|
                action_req_size, &addr_info, PROTO_69845_D_P_CLIENT_REQUEST);
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        if (with_rn) {
 | 
						|
            pkt = proto_69845_build_apdu_data_with_rn_msg((uint8_t *)apdu,
 | 
						|
                action_req_size, server_addr);
 | 
						|
        } else {
 | 
						|
            addr_info.ser_info = *server_addr;
 | 
						|
            pkt = proto_69845_build_apdu_data_msg((uint8_t *)apdu,
 | 
						|
                action_req_size, &addr_info, PROTO_69845_D_P_CLIENT_REQUEST);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    iot_pkt_free(get_action_req);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_dlong_unsign_data_to_meter_bcd_data(
 | 
						|
    uint8_t *dlong_data, uint8_t dlong_data_len, uint8_t *meter_bcd_data,
 | 
						|
    uint8_t bcd_len)
 | 
						|
{
 | 
						|
    uint32_t data;
 | 
						|
    if (dlong_data == NULL
 | 
						|
        || dlong_data_len != PROTO_69845_METER_DATA_DOUBLE_LONG_LEN
 | 
						|
        || meter_bcd_data == NULL
 | 
						|
        || !bcd_len) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    data = iot_bytes_to_uint32(dlong_data, 1);
 | 
						|
    iot_uint32_to_bcd(data, bcd_len, meter_bcd_data);
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_long_unsign_to_meter_bcd_data(
 | 
						|
    uint8_t *long_data, uint8_t long_data_len, uint8_t *meter_bcd_data,
 | 
						|
    uint8_t bcd_len)
 | 
						|
{
 | 
						|
    uint8_t high, low;
 | 
						|
    uint16_t data;
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
    if (long_data == NULL
 | 
						|
        || long_data_len != PROTO_69845_METER_DATA_LONG_LEN
 | 
						|
        || meter_bcd_data == NULL
 | 
						|
        || !bcd_len) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = iot_bytes_to_uint16(long_data, 1);
 | 
						|
    high = (uint8_t)(data / 100);
 | 
						|
    low = (uint8_t)(data % 100);
 | 
						|
    if (bcd_len > sizeof(data)) {
 | 
						|
        bcd_len = sizeof(data);
 | 
						|
    }
 | 
						|
    if (!bcd_len) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    meter_bcd_data[0] = iot_byte_to_bcd(low);
 | 
						|
    bcd_len--;
 | 
						|
    if (!bcd_len) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    meter_bcd_data[1] = iot_byte_to_bcd(high);
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_dlong_data_to_meter_bcd_data(
 | 
						|
    uint8_t *dlong_data, uint8_t dlong_data_len, uint8_t *meter_bcd_data,
 | 
						|
    uint8_t bcd_len)
 | 
						|
{
 | 
						|
    uint8_t flag_neg = 0;
 | 
						|
    int32_t data;
 | 
						|
    if (dlong_data == NULL
 | 
						|
        || dlong_data_len != PROTO_69845_METER_DATA_DOUBLE_LONG_LEN
 | 
						|
        || meter_bcd_data == NULL
 | 
						|
        || !bcd_len) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    data = (int32_t)iot_bytes_to_uint32(dlong_data, 1);
 | 
						|
    if (data < 0) {
 | 
						|
        flag_neg = 1;
 | 
						|
        data = 0 - data;
 | 
						|
    }
 | 
						|
    iot_uint32_to_bcd((uint32_t)data, bcd_len, meter_bcd_data);
 | 
						|
    if (flag_neg) {
 | 
						|
        meter_bcd_data[bcd_len - 1] |= 0x80;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_long_data_to_meter_bcd_data(
 | 
						|
    uint8_t *long_data, uint8_t long_data_len, uint8_t *meter_bcd_data,
 | 
						|
    uint8_t bcd_len)
 | 
						|
{
 | 
						|
    uint8_t high, low, flag_neg = 0;;
 | 
						|
    int16_t data;
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
    if (long_data == NULL
 | 
						|
        || long_data_len != PROTO_69845_METER_DATA_LONG_LEN
 | 
						|
        || meter_bcd_data == NULL
 | 
						|
        || !bcd_len) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = (int16_t)iot_bytes_to_uint16(long_data, 1);
 | 
						|
    if (data < 0) {
 | 
						|
        flag_neg = 1;
 | 
						|
        data = 0 - data;
 | 
						|
    }
 | 
						|
    high = (uint8_t)(data / 100);
 | 
						|
    low = (uint8_t)(data % 100);
 | 
						|
    if (bcd_len > sizeof(data)) {
 | 
						|
        bcd_len = sizeof(data);
 | 
						|
    }
 | 
						|
    if (!bcd_len) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    meter_bcd_data[0] = iot_byte_to_bcd(low);
 | 
						|
    bcd_len--;
 | 
						|
    if (!bcd_len) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    meter_bcd_data[1] = iot_byte_to_bcd(high);
 | 
						|
    if (flag_neg) {
 | 
						|
        meter_bcd_data[1] |= 0x80;
 | 
						|
    }
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_pf_ele_data_handle(proto_645_07_pf_t *meter_pf,
 | 
						|
    proto_69845_app_ele_data_t *ele_data, uint32_t data_len)
 | 
						|
{
 | 
						|
    uint8_t i, *meter_data, *data;
 | 
						|
    uint32_t ele_len, ret = ERR_OK;;
 | 
						|
    proto_69845_app_data_t *app_data;
 | 
						|
 | 
						|
    ele_len = sizeof(*app_data) + PROTO_69845_METER_DATA_LONG_LEN;
 | 
						|
    if (data_len < ele_len * ele_data->num_of_data) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = ele_data->data;
 | 
						|
    BUILD_BUG_ON(sizeof(meter_pf->total) == PROTO_645_07_PF_LEN);
 | 
						|
    meter_data = meter_pf->total;
 | 
						|
    for (i = 0; i < ele_data->num_of_data && i < PROTO_69845_POWER_MAX_ELE_NUM;
 | 
						|
        i++) {
 | 
						|
        app_data = (proto_69845_app_data_t *)data;
 | 
						|
        if (app_data->data_type == PROTO_69845_APP_DATA_LONG) {
 | 
						|
            if (proto_69845_long_data_to_meter_bcd_data(app_data->data,
 | 
						|
                PROTO_69845_METER_DATA_LONG_LEN,
 | 
						|
                meter_data, PROTO_645_07_PF_LEN) != ERR_OK) {
 | 
						|
                ret = ERR_FAIL;
 | 
						|
                goto out;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        data += ele_len;
 | 
						|
        meter_data += PROTO_645_07_PF_LEN;
 | 
						|
    }
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_v_data_handle(proto_645_v_t *meter_v,
 | 
						|
    proto_69845_app_ele_data_t *ele_data, uint32_t data_len)
 | 
						|
{
 | 
						|
    uint8_t i, *meter_data, *data;
 | 
						|
    uint32_t ele_len, ret = ERR_OK;
 | 
						|
    proto_69845_app_data_t *app_data;
 | 
						|
 | 
						|
    ele_len = sizeof(*app_data) + PROTO_69845_METER_DATA_LONG_LEN;
 | 
						|
    if (data_len < ele_len * ele_data->num_of_data) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = ele_data->data;
 | 
						|
    meter_data = meter_v->a;
 | 
						|
    BUILD_BUG_ON(sizeof(meter_v->a) == PROTO_645_V_LEN);
 | 
						|
    for (i = 0; i < ele_data->num_of_data &&
 | 
						|
        i < PROTO_69845_SPLIT_PHASE_MAX_ELE_NUM; i++) {
 | 
						|
        app_data = (proto_69845_app_data_t *)data;
 | 
						|
        if (app_data->data_type == PROTO_69845_APP_DATA_LONG_UNSIGNED) {
 | 
						|
            if (proto_69845_long_unsign_to_meter_bcd_data(app_data->data,
 | 
						|
                PROTO_69845_METER_DATA_LONG_LEN,
 | 
						|
                meter_data, PROTO_645_V_LEN) != ERR_OK) {
 | 
						|
                ret = ERR_FAIL;
 | 
						|
                goto out;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        data += ele_len;
 | 
						|
        meter_data += PROTO_645_V_LEN;
 | 
						|
    }
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_a_data_handle(proto_645_07_a_t *meter_a,
 | 
						|
    proto_69845_app_ele_data_t *ele_data, uint32_t data_len)
 | 
						|
{
 | 
						|
    uint8_t i, *meter_data, *data;
 | 
						|
    uint32_t ele_len, ret = ERR_OK;
 | 
						|
    proto_69845_app_data_t *app_data;
 | 
						|
 | 
						|
    ele_len = sizeof(*app_data) + PROTO_69845_METER_DATA_DOUBLE_LONG_LEN;
 | 
						|
    if (data_len < ele_len * ele_data->num_of_data) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    data = ele_data->data;
 | 
						|
    meter_data = meter_a->a;
 | 
						|
    BUILD_BUG_ON(sizeof(meter_a->a) == PROTO_645_07_A_LEN);
 | 
						|
    for (i = 0; i < ele_data->num_of_data &&
 | 
						|
        i < PROTO_69845_SPLIT_PHASE_MAX_ELE_NUM; i++) {
 | 
						|
        app_data = (proto_69845_app_data_t *)data;
 | 
						|
        if (app_data->data_type == PROTO_69845_APP_DATA_DOUBLE_LONG) {
 | 
						|
            if (proto_69845_dlong_data_to_meter_bcd_data(app_data->data,
 | 
						|
                PROTO_69845_METER_DATA_DOUBLE_LONG_LEN,
 | 
						|
                meter_data, PROTO_645_07_A_LEN) != ERR_OK){
 | 
						|
                ret = ERR_FAIL;
 | 
						|
                goto out;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        data += ele_len;
 | 
						|
        meter_data += PROTO_645_07_A_LEN;
 | 
						|
    }
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_gnd_a_data_handle(uint8_t *meter_gnd_a, uint8_t gnd_a_len,
 | 
						|
    uint8_t *data, uint32_t data_len)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
    proto_69845_app_data_t *app_data;
 | 
						|
 | 
						|
    if (data_len < sizeof(*app_data) || gnd_a_len < PROTO_645_07_A_LEN) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    app_data = (proto_69845_app_data_t *)data;
 | 
						|
    data_len -= sizeof(*app_data);
 | 
						|
    if (app_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (data_len < PROTO_69845_METER_DATA_DOUBLE_LONG_LEN) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ret = proto_69845_dlong_data_to_meter_bcd_data(app_data->data,
 | 
						|
        PROTO_69845_METER_DATA_DOUBLE_LONG_LEN, meter_gnd_a,
 | 
						|
        PROTO_645_07_A_LEN);
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_power_data_handle(int32_t power[],
 | 
						|
    uint8_t **data, uint32_t *len)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
    uint8_t *ds = *data, i, ele_len;
 | 
						|
    proto_69845_app_data_t *fix_data;
 | 
						|
    proto_69845_app_ele_data_t *var_data = (proto_69845_app_ele_data_t *)ds;
 | 
						|
    if (*len < sizeof(*var_data)) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    *len -= sizeof(*var_data);
 | 
						|
    ds += sizeof(*var_data);
 | 
						|
 | 
						|
    ele_len = PROTO_69845_METER_DATA_DOUBLE_LONG_LEN + sizeof(*fix_data);
 | 
						|
 | 
						|
    for (i = 0; i < var_data->num_of_data && *len > ele_len; i++) {
 | 
						|
        fix_data = (proto_69845_app_data_t *)ds;
 | 
						|
        if (fix_data->data_type == PROTO_69845_APP_DATA_DOUBLE_LONG) {
 | 
						|
            power[i] = (int32_t)iot_bytes_to_uint32(fix_data->data, 1);
 | 
						|
        } else {
 | 
						|
            ret = ERR_FAIL;
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        ds += ele_len;
 | 
						|
        *len -= ele_len;
 | 
						|
    }
 | 
						|
    *data = ds;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_time_data_handle(iot_time_tm_t *meter_time,
 | 
						|
    uint8_t **data, uint32_t *len)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
    proto_69845_app_data_t *app_data;
 | 
						|
    proto_69845_app_data_time_s_t *time;
 | 
						|
    app_data = (proto_69845_app_data_t*)(*data);
 | 
						|
    if (*len < sizeof(*app_data) + sizeof(*time)) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    *data += sizeof(*app_data) + sizeof(*time);
 | 
						|
    *len -= sizeof(*app_data) + sizeof(*time);
 | 
						|
    if (app_data->data_type != PROTO_69845_APP_DATA_TIME_S) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    time = (proto_69845_app_data_time_s_t *)app_data->data;
 | 
						|
    meter_time->tm_year = iot_bytes_to_uint16((uint8_t *)&time->year, 1);
 | 
						|
    meter_time->tm_mon = time->month;;
 | 
						|
    meter_time->tm_mday = time->day;
 | 
						|
    meter_time->tm_hour = time->hour;
 | 
						|
    meter_time->tm_min = time->minute;
 | 
						|
    meter_time->tm_sec = time->second;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_run_state_data_handle(proto_69845_rs_word_t *rs_word,
 | 
						|
    uint8_t **data, uint32_t *len)
 | 
						|
{
 | 
						|
    uint8_t i, *ds;
 | 
						|
    uint16_t *word;
 | 
						|
    uint32_t ele_len, ret = ERR_OK;
 | 
						|
    proto_69845_app_ele_data_t *var_data;
 | 
						|
    proto_69845_app_ele_data_t *word_data;
 | 
						|
    if (*len < sizeof(*var_data)) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    var_data = (proto_69845_app_ele_data_t *)(*data);
 | 
						|
    *len -= sizeof(*var_data);
 | 
						|
 | 
						|
    if (var_data->num_of_data != PROTO_69845_RS_WORDS_NUM) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ele_len = sizeof(*var_data) + PROTO_69845_METER_DATA_LONG_LEN;
 | 
						|
 | 
						|
    ds = var_data->data;
 | 
						|
    word = (uint16_t *)rs_word;
 | 
						|
    BUILD_BUG_ON(sizeof(*rs_word) == PROTO_69845_RS_WORDS_NUM * \
 | 
						|
        PROTO_69845_METER_DATA_LONG_LEN);
 | 
						|
    for (i = 0; i < var_data->num_of_data && *len > ele_len; i++) {
 | 
						|
        word_data = (proto_69845_app_ele_data_t *)ds;
 | 
						|
        if (word_data->data_type != PROTO_69845_APP_DATA_BIT_STRING ||
 | 
						|
            word_data->num_of_data != PROTO_69845_APP_DATA_LONG) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        *word = iot_bytes_to_uint16(word_data->data, 1);
 | 
						|
        *len -= ele_len;
 | 
						|
        ds += ele_len;
 | 
						|
        word++;
 | 
						|
    }
 | 
						|
    if (i != PROTO_69845_RS_WORDS_NUM)
 | 
						|
        ret = ERR_FAIL;
 | 
						|
    *data = ds;
 | 
						|
 out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_evt_cur_info_parse(uint32_t *occur_n, uint32_t *acc_time,
 | 
						|
    uint8_t **data, uint32_t *len)
 | 
						|
{
 | 
						|
    uint8_t *ds = *data, evt_src_len, ele_len;
 | 
						|
    proto_69845_app_data_t *fix_data;
 | 
						|
    proto_69845_app_ele_data_t *var_data;
 | 
						|
    if (*len < sizeof (*var_data))
 | 
						|
        goto err;
 | 
						|
 | 
						|
    var_data = (proto_69845_app_ele_data_t *)ds;
 | 
						|
    ds += sizeof (*var_data);
 | 
						|
    *len -= sizeof (*var_data);
 | 
						|
 | 
						|
    if (var_data->data_type != PROTO_69845_APP_DATA_ARRAY)
 | 
						|
        goto err;
 | 
						|
    if (var_data->num_of_data != 1)
 | 
						|
        goto err;
 | 
						|
    if (*len < sizeof (*var_data))
 | 
						|
        goto err;
 | 
						|
 | 
						|
    var_data = (proto_69845_app_ele_data_t *)ds;
 | 
						|
    ds += sizeof (*var_data);
 | 
						|
    *len -= sizeof (*var_data);
 | 
						|
 | 
						|
    if (var_data->data_type != PROTO_69845_APP_DATA_STRUCTURE)
 | 
						|
        goto err;
 | 
						|
    if (var_data->num_of_data != 2)
 | 
						|
        goto err;
 | 
						|
 | 
						|
    /* parsing the event source */
 | 
						|
    if (*len < sizeof(*fix_data)) {
 | 
						|
        goto err;
 | 
						|
    }
 | 
						|
 | 
						|
    fix_data = (proto_69845_app_data_t *)ds;
 | 
						|
    ds += sizeof (*fix_data);
 | 
						|
    *len -= sizeof (*fix_data);
 | 
						|
    switch (fix_data->data_type) {
 | 
						|
    case PROTO_69845_APP_DATA_NULL:
 | 
						|
        evt_src_len = 0;
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        goto err;
 | 
						|
    }
 | 
						|
    if (*len  < evt_src_len)
 | 
						|
        goto err;
 | 
						|
    ds += evt_src_len;
 | 
						|
    *len -= evt_src_len;
 | 
						|
 | 
						|
     if (*len < sizeof (*var_data))
 | 
						|
        goto err;
 | 
						|
     var_data = (proto_69845_app_ele_data_t *)ds;
 | 
						|
     ds += sizeof (*var_data);
 | 
						|
    *len -= sizeof (*var_data);
 | 
						|
    if (var_data->data_type != PROTO_69845_APP_DATA_STRUCTURE) {
 | 
						|
        goto err;
 | 
						|
    }
 | 
						|
    if (var_data->num_of_data != 2) {
 | 
						|
        goto err;
 | 
						|
    }
 | 
						|
 | 
						|
    ele_len = PROTO_69845_METER_DATA_DOUBLE_LONG_LEN + sizeof(*fix_data);
 | 
						|
    fix_data = (proto_69845_app_data_t *)ds;
 | 
						|
    if (fix_data->data_type == PROTO_69845_APP_DATA_NULL) {
 | 
						|
        ds += sizeof(*fix_data);
 | 
						|
        *len -= sizeof(*fix_data);
 | 
						|
    } else if (fix_data->data_type ==
 | 
						|
        PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED) {
 | 
						|
        if (occur_n)
 | 
						|
            *occur_n = iot_bytes_to_uint32(fix_data->data, 1);
 | 
						|
        ds += ele_len;
 | 
						|
        *len -= ele_len;
 | 
						|
    } else {
 | 
						|
        goto err;
 | 
						|
    }
 | 
						|
 | 
						|
    fix_data = (proto_69845_app_data_t *)ds;
 | 
						|
    if (fix_data->data_type == PROTO_69845_APP_DATA_NULL) {
 | 
						|
        ds += sizeof (*fix_data);
 | 
						|
        *len -= sizeof (*fix_data);
 | 
						|
    } else if (fix_data->data_type ==
 | 
						|
        PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED) {
 | 
						|
        if (acc_time)
 | 
						|
            *acc_time = iot_bytes_to_uint32(fix_data->data, 1);
 | 
						|
        ds += ele_len;
 | 
						|
        *len -= ele_len;
 | 
						|
    } else {
 | 
						|
        goto err;
 | 
						|
    }
 | 
						|
    *data = ds;
 | 
						|
    return ERR_OK;
 | 
						|
 | 
						|
err:
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_energy_data_handle(uint32_t *energy,
 | 
						|
    uint8_t **data, uint32_t *in_len)
 | 
						|
{
 | 
						|
    uint8_t *ds = *data, i, cnt;
 | 
						|
    uint32_t len = *in_len;
 | 
						|
    proto_69845_app_data_t *fix_data;
 | 
						|
    uint32_t ele_len;
 | 
						|
    if (len < sizeof(proto_69845_app_ele_data_t)) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    switch (ds[0]) {
 | 
						|
    case PROTO_69845_APP_DATA_DOUBLE_LONG:
 | 
						|
    case PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED:
 | 
						|
    {
 | 
						|
        cnt = 1;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_DATA_ARRAY:
 | 
						|
    {
 | 
						|
        cnt = ds[1];
 | 
						|
        ds += sizeof(proto_69845_app_ele_data_t);
 | 
						|
        len -= sizeof(proto_69845_app_ele_data_t);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    ele_len = sizeof(*fix_data) + PROTO_69845_METER_DATA_DOUBLE_LONG_LEN;
 | 
						|
    for (i = 0; i < cnt && len > ele_len ; i++) {
 | 
						|
        fix_data = (proto_69845_app_data_t *)ds;
 | 
						|
        if (fix_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG &&
 | 
						|
            fix_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED) {
 | 
						|
            return ERR_FAIL;
 | 
						|
        }
 | 
						|
        energy[i] = iot_bytes_to_uint32(fix_data->data, 1);
 | 
						|
        ds += ele_len;
 | 
						|
        len -= ele_len;
 | 
						|
    }
 | 
						|
    *data = ds;
 | 
						|
    *in_len = len;
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_energy_sum_data_handle(uint8_t *energy_sum,
 | 
						|
    uint8_t *data, uint32_t data_len)
 | 
						|
{
 | 
						|
    proto_69845_app_data_t *app_data;
 | 
						|
 | 
						|
    if (data_len < sizeof(*app_data)) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    app_data = (proto_69845_app_data_t *)data;
 | 
						|
    data_len -= sizeof(*app_data);
 | 
						|
    if (app_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG &&
 | 
						|
        app_data->data_type != PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    if (data_len < PROTO_69845_METER_DATA_DOUBLE_LONG_LEN) {
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    BUILD_BUG_ON(PROTO_645_07_ENERGY_DATA_LEN ==
 | 
						|
        PROTO_69845_METER_DATA_DOUBLE_LONG_LEN);
 | 
						|
    if (app_data->data_type == PROTO_69845_APP_DATA_DOUBLE_LONG) {
 | 
						|
        proto_69845_dlong_data_to_meter_bcd_data(app_data->data,
 | 
						|
            PROTO_69845_METER_DATA_DOUBLE_LONG_LEN, energy_sum,
 | 
						|
            PROTO_645_07_ENERGY_DATA_LEN);
 | 
						|
    } else {
 | 
						|
        proto_69845_dlong_unsign_data_to_meter_bcd_data(app_data->data,
 | 
						|
            PROTO_69845_METER_DATA_DOUBLE_LONG_LEN, energy_sum,
 | 
						|
            PROTO_645_07_ENERGY_DATA_LEN);
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
drop:
 | 
						|
    return ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_pf_data_handle(int16_t *pf,
 | 
						|
    uint8_t **data, uint32_t *in_len)
 | 
						|
{
 | 
						|
    uint8_t *ds = *data, i, cnt;
 | 
						|
    uint32_t len = *in_len;
 | 
						|
    proto_69845_app_data_t *fix_data;
 | 
						|
    uint32_t ele_len;
 | 
						|
    if (len < sizeof(proto_69845_app_ele_data_t)) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    switch (ds[0]) {
 | 
						|
    case PROTO_69845_APP_DATA_LONG:
 | 
						|
    {
 | 
						|
        cnt = 1;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_69845_APP_DATA_ARRAY:
 | 
						|
    {
 | 
						|
        cnt = ds[1];
 | 
						|
        ds += sizeof(proto_69845_app_ele_data_t);
 | 
						|
        len -= sizeof(proto_69845_app_ele_data_t);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    ele_len = sizeof(*fix_data) + PROTO_69845_METER_DATA_LONG_LEN;
 | 
						|
    for (i = 0; i < cnt && len > ele_len ; i++) {
 | 
						|
        fix_data = (proto_69845_app_data_t *)ds;
 | 
						|
        if (fix_data->data_type != PROTO_69845_APP_DATA_LONG) {
 | 
						|
            return ERR_FAIL;
 | 
						|
        }
 | 
						|
        pf[i] = (int16_t)iot_bytes_to_uint16(fix_data->data, 1);
 | 
						|
        ds += ele_len;
 | 
						|
        len -= ele_len;
 | 
						|
    }
 | 
						|
    *data = ds;
 | 
						|
    *in_len = len;
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_p_data_handle(proto_645_07_p_t *meter_p,
 | 
						|
    proto_69845_app_ele_data_t *ele_data, uint32_t data_len)
 | 
						|
{
 | 
						|
    uint8_t i, *meter_data, *data;
 | 
						|
    uint32_t ele_len;
 | 
						|
    proto_69845_app_data_t *app_data;
 | 
						|
 | 
						|
    ele_len = sizeof(*app_data) + PROTO_69845_METER_DATA_DOUBLE_LONG_LEN;
 | 
						|
    if (data_len < ele_len * ele_data->num_of_data) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    data = ele_data->data;
 | 
						|
    BUILD_BUG_ON(sizeof(meter_p->total) == PROTO_645_07_P_LEN);
 | 
						|
    meter_data = meter_p->total;
 | 
						|
    for (i = 0; i < ele_data->num_of_data && i < PROTO_69845_POWER_MAX_ELE_NUM;
 | 
						|
        i++) {
 | 
						|
        app_data = (proto_69845_app_data_t *)data;
 | 
						|
        if (app_data->data_type == PROTO_69845_APP_DATA_DOUBLE_LONG) {
 | 
						|
            proto_69845_dlong_data_to_meter_bcd_data(app_data->data,
 | 
						|
                PROTO_69845_METER_DATA_DOUBLE_LONG_LEN,
 | 
						|
                meter_data, PROTO_645_07_P_LEN);
 | 
						|
        }
 | 
						|
        data += ele_len;
 | 
						|
        meter_data += PROTO_645_07_P_LEN;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t * proto_69845_build_file_info_msg(uint32_t file_size,
 | 
						|
    uint16_t file_crc, uint16_t block_size, uint32_t hw_ver, uint32_t sw_ver,
 | 
						|
    uint32_t loader_id, uint8_t *server_addr) {
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    iot_pkt_t *tmp_pkt = NULL;
 | 
						|
    proto_69845_app_action_req_single_t *req_info;
 | 
						|
    uint8_t *app_data;
 | 
						|
    uint16_t i;
 | 
						|
    server_addr_info_t server_info = {0};
 | 
						|
    char ver_string[16];
 | 
						|
 | 
						|
    server_info.len = PROTO_69845_SA_LEN;
 | 
						|
    server_info.type = PROTO_69845_SA_TYPE_SIG;
 | 
						|
    iot_mac_addr_cpy(server_info.addr, server_addr);
 | 
						|
 | 
						|
    tmp_pkt = iot_pkt_alloc(PROTO_69845_ACTION_REQUEST_COMMON_LEN,
 | 
						|
        IOT_SMART_GRID_MID);
 | 
						|
    if (tmp_pkt == NULL) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    req_info = (proto_69845_app_action_req_single_t *)iot_pkt_data(tmp_pkt);
 | 
						|
    req_info->omd.method_id = PROTO_OMD_TRANSFILE_INFO_START_METHOD_ID;
 | 
						|
    req_info->omd.oi = PROTO_69845_APP_OI_FILETRANS_BLOCK;
 | 
						|
    req_info->omd.operation_mode = 0;
 | 
						|
 | 
						|
    req_info->data.data_type = PROTO_69845_APP_DATA_STRUCTURE;
 | 
						|
    app_data = (iot_pkt_data(tmp_pkt) + sizeof(*req_info));
 | 
						|
    i = 0;
 | 
						|
    app_data[i++] = 6;
 | 
						|
    /* file info, type is struct */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_STRUCTURE;
 | 
						|
    app_data[i++] = 6;
 | 
						|
    /* src file path, type is visible string */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
 | 
						|
    app_data[i++] = 1;
 | 
						|
    /* src file is null */
 | 
						|
    app_data[i++] = 0x30;
 | 
						|
    /* destination file path, type is visible string */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
 | 
						|
    app_data[i++] = 1;
 | 
						|
    /* destination file is null */
 | 
						|
    app_data[i++] = 0x30;
 | 
						|
    /* file size type is double long unsigned */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
 | 
						|
    iot_uint32_to_bytes(file_size, app_data + i, 1);
 | 
						|
    i += PROTO_69845_METER_DATA_DOUBLE_LONG_LEN;
 | 
						|
    /* file attribute, type is bit-string size 3, bit0 - 1 read, 0 not read;
 | 
						|
       bit1 - 1 write, 0 not write; bit2 - 1 exe, 0 not exe.
 | 
						|
     */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_BIT_STRING;
 | 
						|
    app_data[i++] = 3;
 | 
						|
    app_data[i++] = 0x07;
 | 
						|
    /* file version, type is visible string */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
 | 
						|
    app_data[i++] = 1;
 | 
						|
    app_data[i++] = 0x30;
 | 
						|
    /* file type, type is enum, 0 - local file, 1 - other file */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_ENUM;
 | 
						|
    app_data[i++] = 1;
 | 
						|
    /* translate block size, type is  long unsigned */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_LONG_UNSIGNED;
 | 
						|
    iot_uint16_to_bytes(block_size, app_data + i, 1);
 | 
						|
    i += PROTO_69845_METER_DATA_LONG_LEN;
 | 
						|
    /* check type, type is struct */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_STRUCTURE;
 | 
						|
    app_data[i++] = 2;
 | 
						|
    /* check mode, type is enum, 0 - crc, 1 -mdt, 2 - sha1, 255 - other */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_ENUM;
 | 
						|
    app_data[i++] = 0;
 | 
						|
    /* check value, type is octet-string */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_OCTET_STRING;
 | 
						|
    app_data[i++] = sizeof(file_crc);
 | 
						|
    iot_uint16_to_bytes(file_crc, app_data + i, 1);
 | 
						|
    i += sizeof(file_crc);
 | 
						|
    /* compatible soft version, type is array visible string */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_ARRAY;
 | 
						|
    app_data[i++] = 2;
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
 | 
						|
    app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", sw_ver);
 | 
						|
    os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
 | 
						|
    i += app_data[i] + 1;
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
 | 
						|
    app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", sw_ver);
 | 
						|
    os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
 | 
						|
    i += app_data[i] + 1;
 | 
						|
 | 
						|
    /* compatible hardware version, type is array visible string */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_ARRAY;
 | 
						|
    app_data[i++] = 2;
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
 | 
						|
    app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", hw_ver);
 | 
						|
    os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
 | 
						|
    i += app_data[i] + 1;
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
 | 
						|
    app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", hw_ver);
 | 
						|
    os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
 | 
						|
    i += app_data[i] + 1;
 | 
						|
 | 
						|
    /* loader id type is visible string */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_VISIBLE_STRING;
 | 
						|
    app_data[i] = (uint8_t)iot_sprintf(ver_string, "%d", loader_id);
 | 
						|
    os_mem_cpy(app_data + i + 1, ver_string, app_data[i]);
 | 
						|
    i += app_data[i] + 1;
 | 
						|
 | 
						|
    pkt = proto_69845_build_action_req_single_msg(req_info, i, &server_info);
 | 
						|
 | 
						|
    if (tmp_pkt) {
 | 
						|
        iot_pkt_free(tmp_pkt);
 | 
						|
    }
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_handle_file_info_rsp(uint8_t *data, uint32_t data_len)
 | 
						|
{
 | 
						|
    uint8_t reason = 0;
 | 
						|
    uint32_t oad_value;
 | 
						|
    apdu_info_t apdu_desc = { 0 };
 | 
						|
    proto_69845_frame_head_info_t *hdr_698;
 | 
						|
    proto_69845_apdu_t *apdu;
 | 
						|
    proto_69845_app_action_resp_t *act_resp;
 | 
						|
    proto_69845_app_action_resp_normal_t *act_resp_single;
 | 
						|
 | 
						|
    if (ERR_OK != proto_69845_parse(&data, &data_len, &hdr_698, &apdu_desc)) {
 | 
						|
        reason = 1;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    apdu = (proto_69845_apdu_t *)apdu_desc.ptr;
 | 
						|
    if (apdu_desc.len < (sizeof(*apdu) + sizeof(*act_resp) +
 | 
						|
        sizeof(*act_resp_single))) {
 | 
						|
        reason = 2;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (apdu->type != PROTO_69845_S_APP_ACTION_RESP) {
 | 
						|
        reason = 3;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    act_resp = (proto_69845_app_action_resp_t*)apdu->data;
 | 
						|
    if (act_resp->data_type != PROTO_69845_APP_ACTION_NORMAL) {
 | 
						|
        reason = 4;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    act_resp_single = (proto_69845_app_action_resp_normal_t*)act_resp->data;
 | 
						|
    oad_value = iot_bytes_to_uint32((uint8_t*)&act_resp_single->result.omd.oi,
 | 
						|
        1);
 | 
						|
    if (oad_value != PROTO_69845_APP_OAD_TRANSFILE_START) {
 | 
						|
        reason = 5;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (act_resp_single->result.dar != PROTO_69845_APP_DAR_SUCCESS) {
 | 
						|
        reason = 6;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    if (reason) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_file_data_msg(uint8_t *file_data,
 | 
						|
    uint16_t data_len, uint16_t block_index, uint8_t *server_addr)
 | 
						|
{
 | 
						|
    uint16_t i = 0;
 | 
						|
    uint16_t len;
 | 
						|
    uint8_t *data;
 | 
						|
    uint8_t info_len_byte = 0;
 | 
						|
    uint8_t *app_data;
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    iot_pkt_t *tmp_pkt = NULL;
 | 
						|
    server_addr_info_t server_info = { 0 };
 | 
						|
    proto_69845_app_action_req_single_t *req_info;
 | 
						|
 | 
						|
    server_info.len = PROTO_69845_SA_LEN;
 | 
						|
    server_info.type = PROTO_69845_SA_TYPE_SIG;
 | 
						|
    iot_mac_addr_cpy(server_info.addr, server_addr);
 | 
						|
 | 
						|
    len = sizeof(*req_info) + data_len;
 | 
						|
    if (data_len > 255) {
 | 
						|
        info_len_byte = 2;
 | 
						|
    } else if (data_len > 127) {
 | 
						|
        info_len_byte = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    tmp_pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
 | 
						|
    if (tmp_pkt == NULL) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    data = iot_pkt_data(tmp_pkt);
 | 
						|
 | 
						|
    req_info = (proto_69845_app_action_req_single_t *)data;
 | 
						|
    req_info->omd.method_id = PROTO_OMD_TRANSFILE_DATA_METHOD_ID;
 | 
						|
    req_info->omd.oi = PROTO_69845_APP_OI_FILETRANS_BLOCK;
 | 
						|
    req_info->omd.operation_mode = 0;
 | 
						|
 | 
						|
    req_info->data.data_type = PROTO_69845_APP_DATA_STRUCTURE;
 | 
						|
    app_data = data + sizeof(*req_info);
 | 
						|
    /* element cnt in structure, it's always 2 */
 | 
						|
    app_data[i++] = 2;
 | 
						|
    /* element1, block number, type is  long-unsigned */
 | 
						|
    app_data[i++]  = PROTO_69845_APP_DATA_LONG_UNSIGNED;
 | 
						|
    /* long-unsigned size, 2 bytes */
 | 
						|
    iot_uint16_to_bytes(block_index, app_data + i, 1);
 | 
						|
    i += PROTO_69845_METER_DATA_LONG_LEN;
 | 
						|
    /* element2, block data, type is octet-string */
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_OCTET_STRING;
 | 
						|
    if (info_len_byte == 0) {
 | 
						|
        app_data[i++] = (uint8_t)data_len;
 | 
						|
    } else if (info_len_byte == 1) {
 | 
						|
        app_data[i++] = 0x80 | info_len_byte;
 | 
						|
        app_data[i++] = (uint8_t)data_len;
 | 
						|
    } else if (info_len_byte == 2) {
 | 
						|
        app_data[i++] = 0x80 | info_len_byte;
 | 
						|
        iot_uint16_to_bytes(data_len, app_data + i, 1);
 | 
						|
        i += PROTO_69845_METER_DATA_LONG_LEN;
 | 
						|
    }
 | 
						|
 | 
						|
    os_mem_cpy(app_data + i, file_data, data_len);
 | 
						|
    i += data_len;
 | 
						|
    pkt = proto_69845_build_action_req_single_msg(req_info, i, &server_info);
 | 
						|
 | 
						|
    if (tmp_pkt) {
 | 
						|
        iot_pkt_free(tmp_pkt);
 | 
						|
    }
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_handle_file_data_rsp(uint8_t *data, uint32_t data_len)
 | 
						|
{
 | 
						|
    uint8_t reason = 0;
 | 
						|
    uint32_t oad_value;
 | 
						|
    apdu_info_t apdu_desc = { 0 };
 | 
						|
    proto_69845_frame_head_info_t *hdr_698;
 | 
						|
    proto_69845_apdu_t *apdu;
 | 
						|
    proto_69845_app_action_resp_t *act_resp;
 | 
						|
    proto_69845_app_action_resp_normal_t *act_resp_single;
 | 
						|
 | 
						|
    if (ERR_OK != proto_69845_parse(&data, &data_len, &hdr_698, &apdu_desc)) {
 | 
						|
        reason = 1;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    apdu = (proto_69845_apdu_t *)apdu_desc.ptr;
 | 
						|
    if (apdu_desc.len < (sizeof(*apdu) + sizeof(*act_resp) +
 | 
						|
        sizeof(*act_resp_single))) {
 | 
						|
        reason = 2;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (apdu->type != PROTO_69845_S_APP_ACTION_RESP) {
 | 
						|
        reason = 3;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    act_resp = (proto_69845_app_action_resp_t*)apdu->data;
 | 
						|
    if (act_resp->data_type != PROTO_69845_APP_ACTION_NORMAL) {
 | 
						|
        reason = 4;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    act_resp_single = (proto_69845_app_action_resp_normal_t*)act_resp->data;
 | 
						|
    oad_value = iot_bytes_to_uint32((uint8_t*)&act_resp_single->result.omd.oi,
 | 
						|
        1);
 | 
						|
    if (oad_value != PROTO_69845_APP_OAD_TRANSFILE_DATA) {
 | 
						|
        reason = 5;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (act_resp_single->result.dar != PROTO_69845_APP_DAR_SUCCESS) {
 | 
						|
        reason = 6;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    if (reason) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_file_exe_msg(iot_time_tm_t *time,
 | 
						|
    uint8_t *server_addr)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    iot_pkt_t *tmp_pkt = NULL;
 | 
						|
    uint16_t i = 0;
 | 
						|
    uint8_t *app_data;
 | 
						|
    proto_69845_app_action_req_single_t *req_info;
 | 
						|
    proto_69845_app_data_time_s_t *times;
 | 
						|
    server_addr_info_t server_info = {0};
 | 
						|
 | 
						|
    server_info.len = PROTO_69845_SA_LEN;
 | 
						|
    server_info.type = PROTO_69845_SA_TYPE_SIG;
 | 
						|
    iot_mac_addr_cpy(server_info.addr, server_addr);
 | 
						|
 | 
						|
    tmp_pkt = iot_pkt_alloc(PROTO_69845_ACTION_REQUEST_COMMON_LEN,
 | 
						|
        IOT_SMART_GRID_MID);
 | 
						|
    if (tmp_pkt == NULL) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
    req_info = (proto_69845_app_action_req_single_t *)iot_pkt_data(tmp_pkt);
 | 
						|
    req_info->omd.method_id = PROTO_OMD_TRANSFILE_INFO_EXE_METHOD_ID;
 | 
						|
    req_info->omd.oi = PROTO_69845_APP_OI_FILETRANS_BLOCK;
 | 
						|
    req_info->omd.operation_mode = 0;
 | 
						|
 | 
						|
    req_info->data.data_type = PROTO_69845_APP_DATA_STRUCTURE;
 | 
						|
    app_data = (iot_pkt_data(tmp_pkt) + sizeof(*req_info));
 | 
						|
    app_data[i++] = 2;
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_TIME_S;
 | 
						|
    times = (proto_69845_app_data_time_s_t*)(app_data + i);
 | 
						|
    times->year = time->tm_year;
 | 
						|
    times->month = time->tm_mon;
 | 
						|
    times->day = time->tm_mday;
 | 
						|
    times->hour = time->tm_hour;
 | 
						|
    times->minute = time->tm_min;
 | 
						|
    times->second = time->tm_sec;
 | 
						|
    i += sizeof(proto_69845_app_data_time_s_t);
 | 
						|
    app_data[i++] = PROTO_69845_APP_DATA_NULL;
 | 
						|
    pkt = proto_69845_build_action_req_single_msg(req_info, i, &server_info);
 | 
						|
 | 
						|
    if (tmp_pkt) {
 | 
						|
        iot_pkt_free(tmp_pkt);
 | 
						|
    }
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_handle_file_exe_rsp(uint8_t *data, uint32_t data_len)
 | 
						|
{
 | 
						|
    uint8_t reason = 0;
 | 
						|
    uint32_t oad_value;
 | 
						|
    apdu_info_t apdu_desc = { 0 };
 | 
						|
    proto_69845_frame_head_info_t *hdr_698;
 | 
						|
    proto_69845_apdu_t *apdu;
 | 
						|
    proto_69845_app_action_resp_t *act_resp;
 | 
						|
    proto_69845_app_action_resp_normal_t *act_resp_single;
 | 
						|
 | 
						|
    if (ERR_OK != proto_69845_parse(&data, &data_len, &hdr_698, &apdu_desc)) {
 | 
						|
        reason = 1;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    apdu = (proto_69845_apdu_t *)apdu_desc.ptr;
 | 
						|
    if (apdu_desc.len < (sizeof(*apdu) + sizeof(*act_resp) +
 | 
						|
        sizeof(*act_resp_single))) {
 | 
						|
        reason = 2;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (apdu->type != PROTO_69845_S_APP_ACTION_RESP) {
 | 
						|
        reason = 3;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    act_resp = (proto_69845_app_action_resp_t*)apdu->data;
 | 
						|
    if (act_resp->data_type != PROTO_69845_APP_ACTION_NORMAL) {
 | 
						|
        reason = 4;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    act_resp_single = (proto_69845_app_action_resp_normal_t*)act_resp->data;
 | 
						|
    oad_value = iot_bytes_to_uint32((uint8_t*)&act_resp_single->result.omd.oi,
 | 
						|
        1);
 | 
						|
    if (oad_value != PROTO_69845_APP_OAD_TRANSFILE_EXE) {
 | 
						|
        reason = 5;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (act_resp_single->result.dar != PROTO_69845_APP_DAR_SUCCESS) {
 | 
						|
        reason = 6;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    if (reason) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
#else /* PLC_SUPPORT_STA_ROLE */
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_get_req_msg(
 | 
						|
    proto_69845_app_get_req_info_t* req_info,
 | 
						|
    const server_addr_info_t* server_info)
 | 
						|
{
 | 
						|
    (void)req_info;
 | 
						|
    (void)server_info;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_comdcb_msg(uint32_t baud,
 | 
						|
    const server_addr_info_t *server_info, uint8_t sn)
 | 
						|
{
 | 
						|
    (void)baud;
 | 
						|
    (void)server_info;
 | 
						|
    (void)sn;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_get_req_msg_with_rn(
 | 
						|
    proto_69845_app_get_list_req_info_t* req_info,
 | 
						|
    const server_addr_info_t* server_info)
 | 
						|
{
 | 
						|
    (void)req_info;
 | 
						|
    (void)server_info;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_get_version_msg_with_rn(
 | 
						|
    const server_addr_info_t *server_info, uint8_t sn)
 | 
						|
{
 | 
						|
    (void)server_info;
 | 
						|
    (void)sn;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_apdu_data_with_rn_msg(uint8_t *apdu_data,
 | 
						|
    uint32_t data_len, const server_addr_info_t* server_info)
 | 
						|
{
 | 
						|
    (void)apdu_data;
 | 
						|
    (void)data_len;
 | 
						|
    (void)server_info;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_action_single_ack(addr_info_t *addr_info,
 | 
						|
    proto_69845_app_piid_t *piid, proto_69845_app_omd_t *omd,
 | 
						|
    uint8_t dar)
 | 
						|
{
 | 
						|
    (void)addr_info;
 | 
						|
    (void)piid;
 | 
						|
    (void)omd;
 | 
						|
    (void)dar;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t * proto_69845_build_file_info_msg(uint32_t file_size,
 | 
						|
    uint16_t file_crc, uint16_t block_size, uint32_t hw_ver, uint32_t sw_ver,
 | 
						|
    uint32_t loader_id, uint8_t *server_addr)
 | 
						|
{
 | 
						|
    (void)file_size;
 | 
						|
    (void)file_crc;
 | 
						|
    (void)block_size;
 | 
						|
    (void)hw_ver;
 | 
						|
    (void)sw_ver;
 | 
						|
    (void)loader_id;
 | 
						|
    (void)server_addr;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_handle_file_info_rsp(uint8_t *data, uint32_t data_len)
 | 
						|
{
 | 
						|
    (void)data;
 | 
						|
    (void)data_len;
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_file_data_msg(uint8_t *data,
 | 
						|
    uint16_t data_len, uint16_t block_index, uint8_t *server_addr)
 | 
						|
{
 | 
						|
    (void)data;
 | 
						|
    (void)data_len;
 | 
						|
    (void)block_index;
 | 
						|
    (void)server_addr;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_handle_file_data_rsp(uint8_t *data, uint32_t data_len)
 | 
						|
{
 | 
						|
    (void)data;
 | 
						|
    (void)data_len;
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_69845_build_file_exe_msg(iot_time_tm_t *time,
 | 
						|
    uint8_t *server_addr)
 | 
						|
{
 | 
						|
    (void)time;
 | 
						|
    (void)server_addr;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_69845_handle_file_exe_rsp(uint8_t *data, uint32_t data_len)
 | 
						|
{
 | 
						|
    (void)data;
 | 
						|
    (void)data_len;
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* PLC_SUPPORT_STA_ROLE */
 |