inwudriver-weibo/app/mrs/ndm/mrs_ndm_plc.c

322 lines
9.8 KiB
C
Raw Permalink Normal View History

/*
* Copyright (c) CompanyNameMagicTag 2019-2020. All rights reserved.
* Description: MRS STA plc handle.
*/
#include "mrs_ndm_plc.h"
#include "mrs_ndm_645.h"
#include "mrs_common_tools.h"
#if defined(PRODUCT_CFG_PRODUCT_TYPE_NDM)
#ifdef __cplusplus
extern "C" {
#endif
td_u16 g_ndm_plc_seq = 0;
td_u8 g_dest_cco_addr[EXT_PLC_MAC_ADDR_LEN] = { 0 };
td_bool mrs_ndm_dut_plc_frame_check(const mrs_plc_frame_data *plc);
td_bool mrs_ndm_cco_dut_plc_frame_check(const mrs_plc_frame_data *plc);
td_void mrs_ndm_dut_init(td_void)
{
g_ndm_plc_seq = (td_u16)uapi_get_random_num32(1, 65535); /* radom number: min 1,max 65535 */
}
td_void mrs_ndm_send_cco_dut_plc_frame(const td_pbyte data, const td_u16 data_len,
const td_pbyte meter, const td_u8 meter_len)
{
errno_t err;
mrs_plc_frame_data plc;
err = memset_s(plc.addr, sizeof(plc.addr), 0xFF, sizeof(plc.addr));
if (err != EOK) {
return;
}
plc.id = PLC_CMD_ID_DUT_CCO_TEST;
plc.bc_flag = 0;
plc.option = 0;
plc.payload_len = data_len;
plc.payload = data;
/* Get seq from PLC frame */
g_ndm_plc_seq = uapi_make_u16(data[2], data[3]); /* index 2&3: sequence */
err = memcpy_s(g_dest_cco_addr, sizeof(g_dest_cco_addr), meter, meter_len);
if (err != EOK) {
return;
}
mrs_plc_frame_send(&plc);
}
td_void mrs_ndm_send_sta_dut_plc_frame(const td_pbyte data, const td_u16 data_len,
const td_pbyte meter, const td_u8 meter_len, td_bool is_no_mac)
{
mrs_dut_test_frame *frame = TD_NULL;
ext_p2p_mac_frame_ctrl ctrl;
errno_t err;
td_u16 payload_len = sizeof(mrs_dut_test_frame) + data_len;
err = memset_s(&ctrl, sizeof(ctrl), 0, sizeof(ctrl));
if (err != EOK) {
return;
}
ctrl.data = (td_pbyte)mrs_malloc(payload_len);
if (ctrl.data == TD_NULL) {
return;
}
if (memset_s(ctrl.data, payload_len, 0, payload_len) != EOK) {
mrs_free(ctrl.data);
return;
}
mrs_convert_meter_to_mac(meter, meter_len, ctrl.dest_mac, sizeof(ctrl.dest_mac));
if (is_no_mac == TD_TRUE) {
/*
* When CIU uses MAC-free communication, configure ctrl.dest_mac and ctrl.src_mac as the MAC address
* of the target site CIU sets ctrl.dest_mac to its own MAC address after successful handshake with
* the target site (except wildcard MAC addresses).
*/
err = memcpy_s(ctrl.src_mac, sizeof(ctrl.src_mac), ctrl.dest_mac, sizeof(ctrl.dest_mac));
if (err != EOK) {
mrs_free(ctrl.data);
return;
}
} else {
/*
* When the CIU uses fixed MAC communication, set ctrl.dest_mac as the MAC address of the target site,
* and configure ctrl.src_mac as its own MAC address. In addition, the identification and processing
* flow of fixed MAC communication for CIU should be added at the application layer of STA.
*/
}
ctrl.lid = 3; /* priority 3 */
ctrl.port_num = EXT_DMS_CHL_MAC_PORT_APP;
ctrl.ctrl = EXT_DMS_CHL_TX_CTRL_NA;
ctrl.id = PLC_CMD_ID_DUT_STA_TEST;
ctrl.data_size = payload_len;
frame = (mrs_dut_test_frame *)ctrl.data;
frame->stru_ver = MRS_PLC_PROTO_VERSION;
frame->stru_size = sizeof(mrs_dut_test_frame);
frame->dir = MRS_PLC_DN_FLG;
frame->seq = ++g_ndm_plc_seq;
frame->vendor = MRS_DUT_VENDOR;
frame->data_len = data_len;
err = memcpy_s(frame->data, frame->data_len, data, data_len);
if (err != EOK) {
mrs_free(ctrl.data);
return;
}
frame->crc = uapi_crc32(0, ctrl.data + ext_offset_of_member(mrs_dut_test_frame, vendor),
payload_len - ext_offset_of_member(mrs_dut_test_frame, vendor));
uapi_p2p_chl_tx(&ctrl, sizeof(ctrl));
mrs_free(ctrl.data);
}
td_void mrs_ndm_send_ciu_plc_frame(const td_pbyte data, const td_u16 data_len,
const td_pbyte meter, const td_u8 meter_len,
td_bool is_no_mac)
{
mrs_ciu_transmit_inf *frame = TD_NULL;
ext_p2p_mac_frame_ctrl ctrl;
errno_t err;
td_u16 payload_len = sizeof(mrs_ciu_transmit_inf) + data_len;
err = memset_s(&ctrl, sizeof(ctrl), 0, sizeof(ctrl));
if (err != EOK) {
return;
}
ctrl.data = (td_pbyte)mrs_malloc(payload_len);
if (ctrl.data == TD_NULL) {
return;
}
err = memset_s(ctrl.data, payload_len, 0, payload_len);
if (err != EOK) {
mrs_free(ctrl.data);
return;
}
mrs_convert_meter_to_mac(meter, meter_len, ctrl.dest_mac, sizeof(ctrl.dest_mac));
if (is_no_mac == TD_TRUE) {
/*
* When CIU uses MAC-free communication, configure ctrl.dest_mac and ctrl.src_mac as the MAC address
* of the target site CIU sets ctrl.dest_mac to its own MAC address after successful handshake with
* the target site (except wildcard MAC addresses).
*/
err = memcpy_s(ctrl.src_mac, sizeof(ctrl.src_mac), ctrl.dest_mac, sizeof(ctrl.dest_mac));
if (err != EOK) {
mrs_free(ctrl.data);
return;
}
} else {
/*
* When the CIU uses fixed MAC communication, set ctrl.dest_mac as the MAC address of the target site,
* and configure ctrl.src_mac as its own MAC address. In addition, the identification and processing
* flow of fixed MAC communication for CIU should be added at the application layer of STA.
*/
}
ctrl.lid = 3; /* priority 3 */
ctrl.port_num = EXT_DMS_CHL_MAC_PORT_APP;
ctrl.ctrl = EXT_DMS_CHL_TX_CTRL_NA;
ctrl.id = PLC_CMD_ID_CIU_TRANSMIT;
ctrl.data_size = payload_len;
frame = (mrs_ciu_transmit_inf *)ctrl.data;
frame->stru_ver = MRS_PLC_PROTO_VERSION;
frame->stru_size = sizeof(mrs_ciu_transmit_inf);
frame->dir = MRS_DIR_CIU_TO_STA;
frame->prm = MRS_PLC_PRM_HOST;
frame->seq = ++g_ndm_plc_seq;
frame->data_len = data_len;
err = memcpy_s(frame->data, frame->data_len, data, data_len);
if (err != EOK) {
mrs_free(ctrl.data);
return;
}
uapi_p2p_chl_tx(&ctrl, sizeof(ctrl));
mrs_free(ctrl.data);
}
td_void mrs_ndm_ciu_plc_frame_rx(mrs_plc_frame_data *plc)
{
mrs_ciu_transmit_inf *frame = (mrs_ciu_transmit_inf *)plc->payload;
/* Check frame direction. */
if (frame->dir != MRS_DIR_STA_TO_CIU && frame->dir != MRS_DIR_CIU_TO_STA) {
return;
}
/* Check frame length */
if ((plc->payload_len != frame->stru_size + frame->data_len) || (frame->data_len > PLC_DATA_LEN_MAX)) {
return;
}
/* Reply frame, check seq */
if ((frame->prm == MRS_PLC_PRM_SLAVE) && ((td_u8)g_ndm_plc_seq != frame->seq)) {
return;
}
uapi_app_received_p2p_pkt(plc->addr, sizeof(plc->addr));
/* Send frame to uart */
mrs_ndm_ciu_uart_frame(plc->payload + frame->stru_size, (td_u16)frame->data_len);
g_ndm_plc_seq++;
}
td_bool mrs_ndm_dut_plc_frame_check(const mrs_plc_frame_data *plc)
{
mrs_dut_test_frame *frame = (mrs_dut_test_frame *)plc->payload;
td_u32 crc;
/* Filter duplicate frames */
if (frame->seq != g_ndm_plc_seq) {
return TD_FALSE;
}
/* Check frame direction. */
if (frame->dir != MRS_PLC_UP_FLG) {
return TD_FALSE;
}
/* Check frame length */
if ((plc->payload_len != frame->stru_size + frame->data_len) || (frame->data_len > PLC_DATA_LEN_MAX)) {
return TD_FALSE;
}
/* Check vendor */
if (frame->vendor != MRS_DUT_VENDOR) {
return TD_FALSE;
}
/* Check crc */
crc = uapi_crc32(0, plc->payload + ext_offset_of_member(mrs_dut_test_frame, vendor),
plc->payload_len - ext_offset_of_member(mrs_dut_test_frame, vendor));
if (crc != frame->crc) {
return TD_FALSE;
}
return TD_TRUE;
}
td_bool mrs_ndm_cco_dut_plc_frame_check(const mrs_plc_frame_data *plc)
{
mrs_dut_cco_frame *frame = (mrs_dut_cco_frame *)plc->payload;
td_u32 crc;
/* Filters */
if (memcmp(frame->src_addr, g_dest_cco_addr, sizeof(g_dest_cco_addr)) != 0) {
return TD_FALSE;
}
/* Filter duplicate frames */
if (frame->seq != g_ndm_plc_seq) {
return TD_FALSE;
}
/* Check frame direction. */
if (frame->dir != MRS_PLC_UP_FLG) {
return TD_FALSE;
}
/* Check frame length */
if (plc->payload_len != frame->stru_size + frame->data_len) {
return TD_FALSE;
}
/* Check vendor */
if (frame->vendor != MRS_DUT_VENDOR) {
return TD_FALSE;
}
/* Check crc */
crc = uapi_crc32(0, plc->payload + ext_offset_of_member(mrs_dut_cco_frame, vendor),
plc->payload_len - ext_offset_of_member(mrs_dut_cco_frame, vendor));
if (crc != frame->crc) {
return TD_FALSE;
}
return TD_TRUE;
}
td_void mrs_ndm_cco_dut_plc_frame_rx(mrs_plc_frame_data *plc)
{
/* Check frame. */
if (mrs_ndm_cco_dut_plc_frame_check(plc) != TD_TRUE) {
return;
}
mrs_ndm_cco_dut_uart_frame(plc->payload, plc->payload_len, plc->addr, sizeof(plc->addr));
g_ndm_plc_seq++;
}
td_void mrs_ndm_sta_dut_plc_frame_rx(mrs_plc_frame_data *plc)
{
mrs_dut_test_frame *frame = (mrs_dut_test_frame *)plc->payload;
/* Check frame. */
if (mrs_ndm_dut_plc_frame_check(plc) != TD_TRUE) {
return;
}
uapi_app_received_p2p_pkt(plc->addr, sizeof(plc->addr));
mrs_ndm_sta_dut_uart_frame(plc->payload + frame->stru_size, (td_u16)frame->data_len);
g_ndm_plc_seq++;
}
#ifdef __cplusplus
}
#endif
#endif /* defined(PRODUCT_CFG_PRODUCT_TYPE_NDM) */