211 lines
5.9 KiB
C
211 lines
5.9 KiB
C
|
|
/*
|
||
|
|
* Copyright (c) CompanyNameMagicTag 2019-2020. All rights reserved.
|
||
|
|
* Description: MRS protocol
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "mrs_proto_645.h"
|
||
|
|
#include "mrs_common_tools.h"
|
||
|
|
#include "mrs_dfx.h"
|
||
|
|
|
||
|
|
#define MRS_645_HEAD_BYTE 0x68
|
||
|
|
#define MRS_645_TAIL_BYTE 0x16
|
||
|
|
|
||
|
|
static td_void mrs_proto_645_rx_notify(EXT_CONST mrs_proto_buffer *buf);
|
||
|
|
static td_void mrs_proto_645_parse(mrs_proto_buffer *buf);
|
||
|
|
|
||
|
|
td_u32 mrs_proto_645_find_frame(const td_pbyte buffer, const td_u16 length, td_u16 *start_pos, td_u16 *frm_len)
|
||
|
|
{
|
||
|
|
td_u16 in_len = length;
|
||
|
|
td_pbyte in_buf = buffer;
|
||
|
|
|
||
|
|
if (in_buf == TD_NULL) {
|
||
|
|
return EXT_ERR_BAD_DATA;
|
||
|
|
}
|
||
|
|
|
||
|
|
while (in_len > 0) {
|
||
|
|
td_u16 frame_length;
|
||
|
|
td_pbyte head = mrs_find_byte_in_stream(in_buf, (td_u16)in_len, MRS_645_HEAD_BYTE);
|
||
|
|
if (head == TD_NULL) {
|
||
|
|
return EXT_ERR_BAD_DATA;
|
||
|
|
}
|
||
|
|
|
||
|
|
in_len -= (td_u16)(head - in_buf);
|
||
|
|
in_buf = head;
|
||
|
|
if (in_len < MRS_645_FRAME_LEN_MIN) {
|
||
|
|
return EXT_ERR_BAD_DATA;
|
||
|
|
}
|
||
|
|
|
||
|
|
frame_length = (td_u16)in_buf[9] + MRS_645_FRAME_LEN_MIN; /* index 9: data length */
|
||
|
|
if ((frame_length <= MRS_645_FRAME_LEN_MAX) &&
|
||
|
|
(in_len >= frame_length) &&
|
||
|
|
(mrs_proto_645_check(in_buf, frame_length) == TD_TRUE)) {
|
||
|
|
*start_pos = (td_u16)(in_buf - buffer);
|
||
|
|
*frm_len = frame_length;
|
||
|
|
return EXT_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
in_buf++;
|
||
|
|
in_len--;
|
||
|
|
}
|
||
|
|
|
||
|
|
return EXT_ERR_BAD_DATA;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_bool mrs_proto_645_check(const td_pbyte buffer, const td_u16 length)
|
||
|
|
{
|
||
|
|
td_u8 cs;
|
||
|
|
|
||
|
|
if ((buffer == TD_NULL) ||
|
||
|
|
(length < MRS_645_FRAME_LEN_MIN) ||
|
||
|
|
(length > MRS_645_FRAME_LEN_MAX)) {
|
||
|
|
return TD_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((buffer[0] != MRS_645_HEAD_BYTE) ||
|
||
|
|
(buffer[7] != MRS_645_HEAD_BYTE) || /* index 7: head byte */
|
||
|
|
(buffer[length - 1] != MRS_645_TAIL_BYTE)) {
|
||
|
|
return TD_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
cs = mrs_checksum8(buffer, length - 2); /* check sum excepts 2bytes */
|
||
|
|
if (cs != buffer[length - 2]) { /* check sum excepts 2bytes */
|
||
|
|
return TD_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return TD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_u32 mrs_proto_645_init(td_void)
|
||
|
|
{
|
||
|
|
mrs_proto_handler handler = { mrs_proto_645_rx_notify, (mrs_proto_rx_full)TD_NULL, mrs_proto_645_parse };
|
||
|
|
mrs_proto_register_handler(&handler);
|
||
|
|
|
||
|
|
uapi_register_judge_is_rcv_p2p_pkt_by_dest_mac(mrs_proto_is_rcv_p2p_pkt_by_dest_mac);
|
||
|
|
return EXT_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
static td_void mrs_proto_645_rx_notify(EXT_CONST mrs_proto_buffer *buf)
|
||
|
|
{
|
||
|
|
ext_unref_param(buf);
|
||
|
|
mrs_timer_start(MRS_TIMER_ID_UART, MRS_UART_FRAME_INTERVAL, EXT_TIMER_TYPE_ONCE);
|
||
|
|
}
|
||
|
|
|
||
|
|
static td_void mrs_proto_645_parse(mrs_proto_buffer *buf)
|
||
|
|
{
|
||
|
|
td_u16 start_pos = 0;
|
||
|
|
td_u16 frm_len = 0;
|
||
|
|
td_u32 ret;
|
||
|
|
|
||
|
|
ret = mrs_proto_645_find_frame(buf->buffer, buf->rx_len, &start_pos, &frm_len);
|
||
|
|
if (ret == EXT_ERR_SUCCESS) {
|
||
|
|
td_u16 payload_len = frm_len;
|
||
|
|
td_pbyte payload = mrs_malloc(payload_len);
|
||
|
|
if (payload == TD_NULL) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (memcpy_s(payload, payload_len, buf->buffer + start_pos, frm_len) != EOK) {
|
||
|
|
mrs_free(payload);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
mrs_dfx_uart_chl_rx_frame(frm_len, EXT_ERR_SUCCESS, TD_FALSE);
|
||
|
|
ret = mrs_msg_queue_send(MRS_MSG_ID_APP_FRAME_RX_645, frm_len, (uintptr_t)payload, 0);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
mrs_dfx_uart_chl_rx_frame(frm_len, ret, TD_FALSE);
|
||
|
|
mrs_free(payload);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_proto_645_on_timer(td_void)
|
||
|
|
{
|
||
|
|
mrs_proto_parse(TD_TRUE);
|
||
|
|
}
|
||
|
|
|
||
|
|
td_u32 mrs_proto_645_create_frame(const mrs_proto_645_frame_inf *frame_inf, td_u8 **frame, td_u16 *frame_len)
|
||
|
|
{
|
||
|
|
const td_u16 buff_len = MRS_645_FRAME_LEN_MIN + frame_inf->data_len;
|
||
|
|
td_u16 offset = 0;
|
||
|
|
td_u8 *buff = TD_NULL;
|
||
|
|
|
||
|
|
buff = mrs_malloc(buff_len);
|
||
|
|
if (buff == TD_NULL) {
|
||
|
|
return EXT_ERR_MALLOC_FAILUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
(td_void) memset_s(buff, buff_len, 0, buff_len);
|
||
|
|
|
||
|
|
/* First HEAD byte */
|
||
|
|
buff[offset++] = MRS_645_HEAD_BYTE;
|
||
|
|
|
||
|
|
/* ADDR byte */
|
||
|
|
if (memcpy_s(buff + offset, buff_len - offset, frame_inf->addr, sizeof(frame_inf->addr)) != EOK) {
|
||
|
|
mrs_free(buff);
|
||
|
|
return EXT_ERR_BAD_DATA;
|
||
|
|
}
|
||
|
|
offset += MRS_METER_ADDR_LEN;
|
||
|
|
|
||
|
|
/* Second HEAD byte */
|
||
|
|
buff[offset++] = MRS_645_HEAD_BYTE;
|
||
|
|
|
||
|
|
/* CTRL byte */
|
||
|
|
buff[offset++] = frame_inf->ctrl;
|
||
|
|
|
||
|
|
/* LEN byte */
|
||
|
|
buff[offset++] = frame_inf->data_len;
|
||
|
|
|
||
|
|
/* DATA field */
|
||
|
|
if (frame_inf->data_len > 0) {
|
||
|
|
if (memcpy_s(buff + offset, buff_len - offset, frame_inf->data, frame_inf->data_len) != EOK) {
|
||
|
|
mrs_free(buff);
|
||
|
|
return EXT_ERR_FAILURE;
|
||
|
|
}
|
||
|
|
mrs_proto_645_data_encode(buff + offset, frame_inf->data_len);
|
||
|
|
offset += frame_inf->data_len;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* checksum */
|
||
|
|
buff[offset] = mrs_checksum8(buff, offset);
|
||
|
|
offset++;
|
||
|
|
|
||
|
|
buff[offset++] = MRS_645_TAIL_BYTE;
|
||
|
|
|
||
|
|
*frame = buff;
|
||
|
|
*frame_len = buff_len;
|
||
|
|
|
||
|
|
return EXT_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_u32 mrs_proto_645_decode_frame(const td_pbyte buffer, const td_u16 length, mrs_proto_645_frame_inf *frame)
|
||
|
|
{
|
||
|
|
if (mrs_proto_645_check(buffer, length) != TD_TRUE) {
|
||
|
|
return EXT_ERR_BAD_DATA;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (memcpy_s(frame->addr, sizeof(frame->addr), buffer + MRS_645_FRAME_METERADD_OFFSET,
|
||
|
|
MRS_METER_ADDR_LEN) != EOK) {
|
||
|
|
return EXT_ERR_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
frame->ctrl = buffer[MRS_645_FRAME_CTRL_OFFSET];
|
||
|
|
frame->data_len = buffer[MRS_645_FRAME_LEN_OFFSET];
|
||
|
|
frame->data = buffer + MRS_645_FRAME_DATA_OFFSET;
|
||
|
|
|
||
|
|
return EXT_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_proto_645_data_decode(td_u8 *buf, td_u32 len)
|
||
|
|
{
|
||
|
|
while (len--) {
|
||
|
|
buf[len] -= MRS_645_FRAME_HEX33;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
td_void mrs_proto_645_data_encode(td_u8 *buf, td_u32 len)
|
||
|
|
{
|
||
|
|
while (len--) {
|
||
|
|
buf[len] += MRS_645_FRAME_HEX33;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|