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