223 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | 
						|
 | 
						|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | 
						|
be copied by any method or incorporated into another program without
 | 
						|
the express written consent of Aerospace C.Power. This Information or any portion
 | 
						|
thereof remains the property of Aerospace C.Power. The Information contained herein
 | 
						|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | 
						|
liability for its use in any way and conveys no license or title under
 | 
						|
any patent or copyright and makes no representation or warranty that this
 | 
						|
Information is free from patent or copyright infringement.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
/* os ship includes */
 | 
						|
#include "os_mem_api.h"
 | 
						|
 | 
						|
/* common includes */
 | 
						|
#include "iot_config_api.h"
 | 
						|
#include "iot_dbglog_api.h"
 | 
						|
 | 
						|
/* protocol includes */
 | 
						|
#include "proto_3762.h"
 | 
						|
 | 
						|
/* smart grid internal header files */
 | 
						|
#include "iot_sg_cco_drv_api.h"
 | 
						|
 | 
						|
#if (IOT_GW_CCO_DRIVER_ENABLE || IOT_SG_CONTROLLER_ENABLE)
 | 
						|
 | 
						|
uint8_t proto_3762_get_checksum(uint8_t ctrl, uint8_t *data, uint32_t len)
 | 
						|
{
 | 
						|
    uint8_t result = ctrl;
 | 
						|
    for (uint32_t i = 0; i < len; ++i) {
 | 
						|
        result += data[i];
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t proto_3762_get_fn_code(uint8_t *data)
 | 
						|
{
 | 
						|
    uint8_t result = PROTO_3762_FN_INVALID;
 | 
						|
 | 
						|
    if (data == NULL) {
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
 | 
						|
    result = data[1] * 8;
 | 
						|
 | 
						|
    switch (data[0]) {
 | 
						|
    case 0x1:
 | 
						|
    result += 1;
 | 
						|
    break;
 | 
						|
 | 
						|
    case 0x2:
 | 
						|
    result += 2;
 | 
						|
    break;
 | 
						|
 | 
						|
    case 0x4:
 | 
						|
    result += 3;
 | 
						|
    break;
 | 
						|
 | 
						|
    case 0x8:
 | 
						|
    result += 4;
 | 
						|
    break;
 | 
						|
 | 
						|
    case 0x10:
 | 
						|
    result += 5;
 | 
						|
    break;
 | 
						|
 | 
						|
    case 0x20:
 | 
						|
    result += 6;
 | 
						|
    break;
 | 
						|
 | 
						|
    case 0x40:
 | 
						|
    result += 7;
 | 
						|
    break;
 | 
						|
 | 
						|
    case 0x80:
 | 
						|
    result += 8;
 | 
						|
    break;
 | 
						|
 | 
						|
    default:
 | 
						|
        result = PROTO_3762_FN_INVALID;
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_3762_sanity_check(uint8_t* data, uint16_t len)
 | 
						|
{
 | 
						|
    uint16_t min_data_len = PROTO_3762_FIX_FIELD_LEN;
 | 
						|
    uint16_t frame_len;
 | 
						|
 | 
						|
    if (data[0] != PROTO_3762_SOF_BYTE) {
 | 
						|
        return INVALID_FORMAT;
 | 
						|
    }
 | 
						|
 | 
						|
    frame_len = (uint16_t)data[2];
 | 
						|
    frame_len = (frame_len << 8) | (uint16_t)data[1];
 | 
						|
    if (len <= min_data_len) {
 | 
						|
        return INVALID_DATA;
 | 
						|
    }
 | 
						|
 | 
						|
    if (frame_len != len) {
 | 
						|
        return INVALID_DATA_LEN;
 | 
						|
    }
 | 
						|
 | 
						|
    if (data[len - 1] != PROTO_3762_EOF_BYTE) {
 | 
						|
        return VALIDATE_FAILED;
 | 
						|
    }
 | 
						|
 | 
						|
    /* 376.2 version 2013 */
 | 
						|
    if (data[len - 2] == proto_3762_get_checksum(data[PROTO_3762_CTRL_OFFSET],
 | 
						|
        data + PROTO_3762_DATA_OFFSET,
 | 
						|
        len - PROTO_3762_FIX_FIELD_LEN)) {
 | 
						|
        /* check sum is correct */
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return VALIDATE_FAILED;   /* checksum failure */
 | 
						|
}
 | 
						|
 | 
						|
void proto_3762_convert_max_fn_to_bitmap(uint16_t max_fn, uint8_t *fn_buf)
 | 
						|
{
 | 
						|
    uint8_t temp_max_fn = 0;
 | 
						|
    uint8_t idx = 0;
 | 
						|
 | 
						|
    if (max_fn > (PROTO_3762_03F11_FNLEN_BITS - 1)) {
 | 
						|
        max_fn = (PROTO_3762_03F11_FNLEN_BITS - 1);
 | 
						|
    }
 | 
						|
    temp_max_fn = (max_fn & 0x07);
 | 
						|
    idx = (uint8_t)(max_fn >> 3);
 | 
						|
    if (idx > 0) {
 | 
						|
        os_mem_set(fn_buf, 0xff, idx);
 | 
						|
    }
 | 
						|
 | 
						|
    while (temp_max_fn > 0) {
 | 
						|
        fn_buf[idx] |= (1 << (temp_max_fn - 1));
 | 
						|
        temp_max_fn--;
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void proto_3762_fn_index_add(uint8_t fn, uint8_t *fn_buf)
 | 
						|
{
 | 
						|
    uint8_t idx = 0;
 | 
						|
 | 
						|
    fn--;
 | 
						|
    idx = fn >> 3;
 | 
						|
    fn_buf[idx] |= (1 << (fn & 0x7));
 | 
						|
}
 | 
						|
 | 
						|
void proto_3762_fn_index_del(uint8_t fn, uint8_t *fn_buf)
 | 
						|
{
 | 
						|
    uint8_t idx = 0;
 | 
						|
 | 
						|
    fn--;
 | 
						|
    idx = fn >> 3;
 | 
						|
    fn_buf[idx] &= ~(1 << (fn & 0x7));
 | 
						|
}
 | 
						|
 | 
						|
void proto_3762_nid_to_buf(uint32_t nid, uint8_t *p_nid) {
 | 
						|
    p_nid[0] = (uint8_t)nid;
 | 
						|
    p_nid[1] = (uint8_t)(nid >> 8);
 | 
						|
    p_nid[2] = (uint8_t)(nid >> 16);
 | 
						|
}
 | 
						|
 | 
						|
void proto_3762_check_frame_handler(uint8_t* buffer, uint32_t buffer_len,
 | 
						|
    bool_t* is_frame)
 | 
						|
{
 | 
						|
    uint8_t *app_data;
 | 
						|
    uint16_t frame_len;
 | 
						|
    user_data_t *user_data;
 | 
						|
    if (buffer_len < PROTO_3762_FRAME_MIN_LEN) {
 | 
						|
        *is_frame = false;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    frame_len = (uint16_t)buffer[2];
 | 
						|
    frame_len = (frame_len << 8) | (uint16_t)buffer[1];
 | 
						|
 | 
						|
    if (buffer[0] != PROTO_3762_SOF_BYTE
 | 
						|
        || buffer[buffer_len - 1] != PROTO_3762_EOF_BYTE) {
 | 
						|
        *is_frame = false;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (frame_len != buffer_len) {
 | 
						|
        *is_frame = false;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (buffer[buffer_len - 2] != proto_3762_get_checksum(
 | 
						|
        buffer[PROTO_3762_CTRL_OFFSET], buffer + PROTO_3762_DATA_OFFSET,
 | 
						|
        buffer_len - PROTO_3762_FIX_FIELD_LEN)) {
 | 
						|
        /* checksum failure */
 | 
						|
        *is_frame = false;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    user_data = (user_data_t *)(buffer + PROTO_3762_DATA_OFFSET);
 | 
						|
    app_data = user_data->data;
 | 
						|
    if (user_data->res.dl_info.comm_module) {
 | 
						|
        if (buffer_len < (PROTO_3762_FRAME_MIN_LEN +
 | 
						|
            (PROTO_3762_MAC_ADDR_LEN * 2))) {
 | 
						|
                *is_frame = false;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        app_data += PROTO_3762_MAC_ADDR_LEN * 2;
 | 
						|
    }
 | 
						|
    if (proto_3762_get_fn_code(app_data + 1) == PROTO_3762_FN_INVALID) {
 | 
						|
        *is_frame = false;
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    *is_frame = true;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* IOT_GW_CCO_DRIVER_ENABLE */
 |