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