322 lines
9.8 KiB
C
322 lines
9.8 KiB
C
/*
|
|
* 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) */
|