1479 lines
45 KiB
C
1479 lines
45 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 header files */
|
||
#include "os_task_api.h"
|
||
#include "os_event_api.h"
|
||
#include "os_timer_api.h"
|
||
#include "os_utils_api.h"
|
||
|
||
/* iot common header files */
|
||
#include "iot_module_api.h"
|
||
#include "iot_queue_api.h"
|
||
#include "iot_mem_pool_api.h"
|
||
#include "iot_config_api.h"
|
||
#include "iot_app_api.h"
|
||
#include "iot_io_api.h"
|
||
#include "iot_uart_api.h"
|
||
#include "iot_task_api.h"
|
||
#include "iot_flash_api.h"
|
||
#include "iot_system_api.h"
|
||
#include "iot_version_api.h"
|
||
#include "iot_oem_api.h"
|
||
#include "iot_board_api.h"
|
||
|
||
#include "iot_dev_test.h"
|
||
#include "iot_grapp.h"
|
||
#include "iot_plctxrx.h"
|
||
#include "iot_proto_dl645.h"
|
||
#include "iot_proto_common.h"
|
||
#include "iot_proto_ge.h"
|
||
#include "iot_app_cus_flash.h"
|
||
|
||
#if IOT_GE_CKQ_MODE_ENABLE
|
||
|
||
devtest_645_cmd_cache_t g_dev_test_buf;
|
||
/* The dev test context. */
|
||
static dev_test_context_t *dev_test_context = NULL;
|
||
extern mcu_data_handle_t mcu_data;
|
||
extern uint8_t ge_buf[];
|
||
char dev_test_log_buf[IOT_DEV_TEST_LOG_BUF_LEN];
|
||
|
||
#define dev_test_is_firedup() (DEV_TEST_MODULE_MAGIC_KEY == \
|
||
dev_test_context->mkey)
|
||
#define dev_test_fire_now() (dev_test_context->mkey = \
|
||
DEV_TEST_MODULE_MAGIC_KEY)
|
||
|
||
static void iot_dev_test_bin_dump(uint8_t *data, uint32_t dlen)
|
||
{
|
||
uint32_t i = 0;
|
||
uint32_t offset = 0;
|
||
|
||
offset = iot_sprintf(dev_test_log_buf, "dump pkt[len:%d]",dlen);
|
||
for (i = 0; i < dlen; ++i) {
|
||
offset += iot_sprintf(dev_test_log_buf + offset, "%02X ", data[i]);
|
||
if (IOT_DEV_TEST_LOG_BUF_LEN <= offset + 4) {
|
||
break;
|
||
}
|
||
}
|
||
dev_test_log_buf[offset] = 0;
|
||
iot_cus_printf("%s\n", dev_test_log_buf);
|
||
return;
|
||
}
|
||
|
||
/* This will store config onto customer flash area. */
|
||
static uint32_t iot_dev_test_flashsave(custom_flash_info_t *p_info)
|
||
{
|
||
if (NULL == p_info) {
|
||
DERROR("Invalid argument!\n");
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
return cus_app_flash_write(IOT_DEV_TEST_FLASH_START_OFFSET, (uint8_t *)p_info,
|
||
sizeof(*p_info));
|
||
}
|
||
|
||
/* Load config from customer flash. */
|
||
static uint32_t iot_dev_test_flashload(custom_flash_info_t *p_info)
|
||
{
|
||
if (NULL == p_info) {
|
||
iot_cus_printf("Invalid argument!\n");
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
return cus_app_flash_read(IOT_DEV_TEST_FLASH_START_OFFSET, (uint8_t *)p_info,
|
||
sizeof(*p_info));
|
||
}
|
||
|
||
/* Repair this config when it is damaged. */
|
||
static void iot_dev_test_flashinfo_repair(custom_flash_info_t *p_info)
|
||
{
|
||
if (NULL == p_info) {
|
||
iot_cus_printf("Invalid argument!\n");
|
||
return;
|
||
}
|
||
|
||
p_info->magic1[0] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 24) & 0xFF;
|
||
p_info->magic1[1] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 16) & 0xFF;
|
||
p_info->magic1[2] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 8) & 0xFF;
|
||
p_info->magic1[3] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1) & 0xFF;
|
||
|
||
p_info->magic2[0] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 24) & 0xFF;
|
||
p_info->magic2[1] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 16) & 0xFF;
|
||
p_info->magic2[2] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 8) & 0xFF;
|
||
p_info->magic2[3] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2) & 0xFF;
|
||
|
||
/* Write flash. */
|
||
if (ERR_OK == iot_dev_test_flashsave(p_info)) {
|
||
iot_cus_printf("Repair flash successfully!\n");
|
||
} else {
|
||
iot_cus_printf("Repair flash failed!\n");
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/* To dump our config info on flash. */
|
||
static void iot_dev_test_dump_flash(custom_flash_info_t* p_info)
|
||
{
|
||
iot_cus_printf("\nMagic1 : 0x%02x%02x%02x%02x.",
|
||
p_info->magic1[0], p_info->magic1[1],
|
||
p_info->magic1[2], p_info->magic1[3]);
|
||
|
||
iot_cus_printf("\nLocal_dev:%d Mac: %02x-%02x-%02x-%02x-%02x-%02x.",
|
||
p_info->local_type, p_info->local_mac[0],
|
||
p_info->local_mac[1], p_info->local_mac[2],
|
||
p_info->local_mac[3], p_info->local_mac[4],
|
||
p_info->local_mac[5]);
|
||
|
||
iot_cus_printf("\nbaudidx=%d-wl_state=%d.",p_info->baudidx,
|
||
p_info->wl_state);
|
||
|
||
iot_cus_printf("\nMagic2 : 0x%02x%02x%02x%02x.",
|
||
p_info->magic2[0], p_info->magic2[1],
|
||
p_info->magic2[2], p_info->magic2[3]);
|
||
|
||
return;
|
||
}
|
||
|
||
/* Check the magic code to tell if our config damaged. */
|
||
static uint32_t iot_dev_test_flashinfo_check(custom_flash_info_t *p_info)
|
||
{
|
||
int32_t magic1, magic2;
|
||
|
||
if (NULL == p_info) {
|
||
iot_cus_printf("Invalid argument!\n");
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
magic1 = (p_info->magic1[0] << 24) | (p_info->magic1[1] << 16)
|
||
| (p_info->magic1[2] << 8) | p_info->magic1[3];
|
||
|
||
magic2 = (p_info->magic2[0] << 24) | (p_info->magic2[1] << 16)
|
||
| (p_info->magic2[2] << 8) | p_info->magic2[3];
|
||
|
||
iot_cus_printf("Magic = 0x%08x, 0x%08x!\n", magic1, magic2);
|
||
|
||
if ((IOT_PROTO_CUST_FLASHINFO_MAGIC1 != magic1)
|
||
||(IOT_PROTO_CUST_FLASHINFO_MAGIC2 != magic2)) {
|
||
iot_cus_printf("Magic dismatch!\n");
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
static void iot_dev_test_flashinfo_init(void)
|
||
{
|
||
custom_flash_info_t *p_flash = &(dev_test_context->flashinfo);
|
||
|
||
iot_cus_printf("sizeof(custom_flash_info_t) = %d\n",
|
||
sizeof(custom_flash_info_t));
|
||
|
||
/* Load and check flash info. */
|
||
if ((ERR_FAIL == iot_dev_test_flashload(p_flash)) ||
|
||
(ERR_FAIL == iot_dev_test_flashinfo_check(p_flash))) {
|
||
iot_cus_printf("Cannot get custom flash info!\n");
|
||
os_mem_set(p_flash, 0x0, sizeof(*p_flash));
|
||
#if HW_PLATFORM == HW_PLATFORM_SIMU
|
||
iot_mac_addr_cpy(p_flash->local_mac, g_ucMACAddress);
|
||
#endif
|
||
p_flash->wl_state = 1;
|
||
p_flash->baudidx = IOT_DEV_TEST_UART_BAUD_IDX_9600;
|
||
iot_dev_test_flashinfo_repair(p_flash);
|
||
}
|
||
/* config uart param */
|
||
iot_grapp_modify_uart_param(p_flash->baudidx, IOT_UART_PARITY_NONE,
|
||
IOT_UART_DLEN_8_BITS, IOT_UART_STOP_1_BITS);
|
||
/* dump flash info */
|
||
iot_dev_test_dump_flash(p_flash);
|
||
|
||
return;
|
||
}
|
||
|
||
/* cut preamble, checksum and tail of a intact frame, send data to plctxrx */
|
||
static void iot_dev_test_data_send_to_plctxrx(uint8_t *data, uint8_t len,
|
||
protpkt_tx_info_t *txinfo)
|
||
{
|
||
iot_pkt_t *send_pkt;
|
||
uint8_t *ptr;
|
||
uint8_t org_frm_len;
|
||
uint8_t cur_frm_len;
|
||
uint16_t i;
|
||
|
||
uint16_t total_frm_len = 0;
|
||
|
||
/* send connless packet, ckq always send connless pkt, no aggr */
|
||
txinfo->force_tx_connless = 1;
|
||
txinfo->force_noaggr = 1;
|
||
txinfo->need_ack = false;
|
||
|
||
send_pkt = iot_pkt_alloc(len, IOT_GREE_APP_MID);
|
||
|
||
if (!send_pkt) {
|
||
IOT_ASSERT(send_pkt);
|
||
return;
|
||
}
|
||
|
||
ptr = data;
|
||
/** del peamble code,checksum code and tail
|
||
* code of each gree frame
|
||
*/
|
||
for (i = 0; i < len;) {
|
||
org_frm_len =
|
||
ACQUIRE_DATA_LEN(ptr[GE_FRM_DATA_LEN_POS]) + GE_FRM_MIN_LEN;
|
||
IOT_ASSERT(org_frm_len >= GE_FRM_MIN_LEN &&
|
||
org_frm_len <= GE_FRM_MAX_LEN);
|
||
cur_frm_len = org_frm_len - GE_FRM_PREAMBLE_FIELD_LEN
|
||
- GE_FRM_CHECKSUM_FIELD_LEN
|
||
- GE_FRM_TAIL_FILED_LEN;
|
||
|
||
os_mem_cpy(iot_pkt_data(send_pkt) + total_frm_len,
|
||
ptr + GE_FRM_PREAMBLE_FIELD_LEN, cur_frm_len);
|
||
total_frm_len += cur_frm_len;
|
||
iot_pkt_put(send_pkt, cur_frm_len);
|
||
/* +1 means move one byte forward */
|
||
i += org_frm_len + 1;
|
||
ptr += org_frm_len;
|
||
}
|
||
|
||
if (dev_test_context->fn_callback.data_send_cb) {
|
||
/* here send data to remote peer */
|
||
(dev_test_context->fn_callback.data_send_cb)(iot_pkt_data(send_pkt),
|
||
(uint8_t)iot_pkt_data_len(send_pkt), txinfo);
|
||
}
|
||
|
||
iot_pkt_free(send_pkt);
|
||
}
|
||
|
||
static void iot_dev_test_remote_data_send_to_plctxrx(uint8_t *data, uint8_t len,
|
||
protpkt_tx_info_t *txinfo)
|
||
{
|
||
iot_cus_printf("[ckq]data_send_to_plctxrx:\n");
|
||
|
||
iot_dev_test_bin_dump(data, len);
|
||
|
||
iot_dev_test_data_send_to_plctxrx(data, len, txinfo);
|
||
}
|
||
|
||
/* This will send a iot_pkt_t of data to UART connected to mainboard. */
|
||
static void iot_dev_test_send_to_mainboard(iot_pkt_t *p_pkt)
|
||
{
|
||
iot_cus_printf("[ckq]iot_dev_test_send_to_mainboard:\n");
|
||
|
||
iot_dev_test_bin_dump(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt));
|
||
|
||
if (dev_test_context->fn_callback.up_send_cb) {
|
||
(dev_test_context->fn_callback.up_send_cb)(p_pkt);
|
||
} else {
|
||
iot_pkt_free(p_pkt);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
static void iot_dev_test_cmd_send_to_plc(iot_pkt_t *p_pkt)
|
||
{
|
||
if (!dev_test_is_firedup()) {
|
||
iot_cus_printf("dev test module not ready.\n");
|
||
return;
|
||
}
|
||
|
||
(dev_test_context->fn_callback.cmd_send_cb)(p_pkt);
|
||
|
||
return;
|
||
}
|
||
|
||
static void iot_dev_test_task_post_msg(uint16_t m_type, uint16_t m_id, iot_pkt_t *data)
|
||
{
|
||
dev_test_msg_t *task_msg;
|
||
|
||
task_msg = (dev_test_msg_t*)iot_task_alloc_msg_with_reserved
|
||
(dev_test_context->task_handle, 0);
|
||
|
||
if (NULL == task_msg) {
|
||
if (NULL != data) {
|
||
iot_pkt_free(data);
|
||
}
|
||
iot_cus_printf("%s Alloc message failed !!\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
task_msg->msg.type = m_type;
|
||
task_msg->msg.id = m_id;
|
||
task_msg->data = data;
|
||
|
||
iot_task_queue_msg(dev_test_context->task_handle, &task_msg->msg, 0);
|
||
|
||
return;
|
||
}
|
||
|
||
uint8_t iot_dev_test_fn_register_send_to_uart(fn_send_to_ext_mcu_t fn)
|
||
{
|
||
IOT_ASSERT(fn);
|
||
|
||
dev_test_context->fn_callback.up_send_cb = fn;
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
static void iot_dev_test_stop_nw_fmt(bool_t need_ack_cfm)
|
||
{
|
||
iot_pkt_t *p_pkt;
|
||
plctxrx_cmd_arg_t *p_arg;
|
||
|
||
p_pkt = iot_pkt_alloc(sizeof(*p_arg), IOT_GREE_APP_MID);
|
||
IOT_ASSERT(p_pkt);
|
||
iot_pkt_put(p_pkt, sizeof(*p_arg));
|
||
|
||
p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt);
|
||
p_arg->cid.cid = PLCTXRX_CID_END_GROUP_NET;
|
||
p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
|
||
p_arg->prio = 0;
|
||
p_arg->need_ack = need_ack_cfm;
|
||
p_arg->dlen = 0;
|
||
|
||
iot_dev_test_cmd_send_to_plc(p_pkt);
|
||
}
|
||
|
||
static void iot_dev_test_set_band(uint8_t band, bool_t need_ack_cfm)
|
||
{
|
||
iot_pkt_t *p_pkt;
|
||
plctxrx_cmd_band_info_t *p_band;
|
||
plctxrx_cmd_arg_t *p_arg;
|
||
|
||
p_pkt = iot_pkt_alloc(sizeof(*p_band) + sizeof(*p_arg), IOT_GREE_APP_MID);
|
||
IOT_ASSERT(p_pkt);
|
||
iot_pkt_put(p_pkt, sizeof(*p_band) + sizeof(*p_arg));
|
||
|
||
p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt);
|
||
p_arg->cid.cid = PLCTXRX_CID_BAND_ID;
|
||
p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
|
||
p_arg->prio = 0;
|
||
p_arg->need_ack = need_ack_cfm;
|
||
p_arg->dlen = sizeof(*p_band);
|
||
|
||
p_band = (plctxrx_cmd_band_info_t *)p_arg->arg;
|
||
p_band->band_id = band;
|
||
|
||
iot_dev_test_cmd_send_to_plc(p_pkt);
|
||
}
|
||
|
||
static void iot_dev_test_set_wdg(uint8_t action, uint16_t interval,
|
||
bool_t need_ack_cfm)
|
||
{
|
||
iot_pkt_t *p_pkt;
|
||
plctxrx_cmd_wdg_t *p_wdg;
|
||
plctxrx_cmd_arg_t *p_arg;
|
||
|
||
p_pkt = iot_pkt_alloc(sizeof(*p_wdg) + sizeof(*p_arg), IOT_GREE_APP_MID);
|
||
IOT_ASSERT(p_pkt);
|
||
iot_pkt_put(p_pkt, sizeof(*p_wdg) + sizeof(*p_arg));
|
||
|
||
p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt);
|
||
p_arg->cid.cid = PLCTXRX_CID_WDG;
|
||
p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
|
||
p_arg->prio = 0;
|
||
p_arg->need_ack = need_ack_cfm;
|
||
p_arg->dlen = sizeof(*p_wdg);
|
||
|
||
p_wdg = (plctxrx_cmd_wdg_t *)p_arg->arg;
|
||
p_wdg->action = action;
|
||
p_wdg->interval = interval;
|
||
|
||
iot_dev_test_cmd_send_to_plc(p_pkt);
|
||
}
|
||
|
||
static void iot_dev_test_set_cfg_after_app_reg(void)
|
||
{
|
||
/* stop network formation */
|
||
iot_dev_test_stop_nw_fmt(true);
|
||
|
||
/* close watchdog */
|
||
iot_dev_test_set_wdg(0, 0, true);
|
||
|
||
/* set band */
|
||
iot_dev_test_set_band(DEV_TEST_DEFAULT_FRQ_BAND, true);
|
||
|
||
/* start reload timer */
|
||
os_start_timer(dev_test_context->mod_cfg_tmr, DEV_TEST_TMR_MODE_CFG_INTVL);
|
||
}
|
||
|
||
static uint8_t iot_dev_test_check_local_dl645_cmd(proto_645_header_t *hdr)
|
||
{
|
||
uint8_t ret = false;
|
||
uint32_t di = 0;
|
||
|
||
proto_645_header_t *hdr_645 = hdr;
|
||
iot_cus_printf("[ckq]local hdr_645->control.fn = %x\n", hdr_645->control.fn);
|
||
iot_proto_645_get_di_by_sub33(hdr_645->data, hdr_645->len, &di);
|
||
iot_cus_printf("[ckq]local check di = %x\n", di);
|
||
|
||
switch (hdr_645->control.fn) {
|
||
case PROTO_645_2007_FN_READ_DATA:
|
||
{
|
||
if (iot_sta_check_local_645_di(di)) {
|
||
ret = true;
|
||
}
|
||
break;
|
||
}
|
||
case PROTO_645_2007_FN_READ_ADDR:
|
||
{
|
||
//TO DO
|
||
break;
|
||
}
|
||
case PROTO_645_2007_FN_WRITE_DATA:
|
||
{
|
||
if (iot_sta_check_local_645_di(di)) {
|
||
ret = true;
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
/* TO DO */
|
||
break;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
* @brief iot_dev_test_645_format_check_handle() - get a dl645 frame, firstly,
|
||
the 645 frame should be packed to a extern
|
||
645 frame. then, the extern 645 frame should
|
||
be packed to a FE A0 ge frame. at last,copy
|
||
to the ge_buf closely in the function.
|
||
* @param recv_data: point to the data frame to be checked
|
||
* @param pdata: point to the output ge data buffer
|
||
* @param ret_size: point to the length of output ge frame, it should be added
|
||
* if a ge frame is built
|
||
* @param checked_len: point to the length of input data checked over, it should
|
||
be added in order to check the next positon
|
||
*/
|
||
static uint8_t iot_dev_test_645_format_check_handle(mcu_data_handle_t *recv_data,
|
||
uint8_t *pdata, uint16_t *ret_size, uint16_t *checked_len)
|
||
{
|
||
uint8_t check_ret;
|
||
uint16_t intact_dl645_len = 0;
|
||
uint16_t dl645_len = 0;
|
||
uint16_t ge_len = 0;
|
||
proto_645_header_t *intact_hdr_645 = NULL;
|
||
proto_645_header_t *hdr_645 = NULL;
|
||
uint16_t len = recv_data->total_len - recv_data->data_pos;
|
||
uint8_t *data = &recv_data->data[recv_data->data_pos];
|
||
uint8_t revert_local_mac[IOT_MAC_ADDR_LEN];
|
||
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
|
||
uint8_t *ext_645_buf = NULL;
|
||
uint16_t ext_645_len = 0;
|
||
uint32_t di = 0;
|
||
iot_pkt_t *pkt = NULL;
|
||
|
||
iot_proto_645_frm_format_check(data, len, &check_ret);
|
||
|
||
if (check_ret != GET_ONE_FRAME) {
|
||
return check_ret;
|
||
}
|
||
|
||
iot_cus_printf("%s GET_ONE_FRAME!\n", __FUNCTION__);
|
||
intact_hdr_645 = (proto_645_header_t *)data;
|
||
intact_dl645_len = intact_hdr_645->len + DL645_PARSE_FRM_MIN_LEN;
|
||
iot_proto_645_get_di_by_sub33(intact_hdr_645->data, intact_hdr_645->len, &di);
|
||
|
||
iot_mac_addr_cpy(g_dev_test_buf.dst_mac, intact_hdr_645->addr);
|
||
iot_mac_addr_cpy(dst_mac, intact_hdr_645->addr);
|
||
|
||
if (DL645_07_DI_DL645_TYPE == di) {
|
||
iot_proto_645_ext_sub33_handle(intact_hdr_645->data, intact_hdr_645->len);
|
||
hdr_645 = (proto_645_header_t *)(intact_hdr_645->data + DL645_DI_LEN);
|
||
} else {
|
||
hdr_645 = intact_hdr_645;
|
||
}
|
||
|
||
dl645_len = hdr_645->len + DL645_PARSE_FRM_MIN_LEN;
|
||
iot_mac_addr_reverse(dst_mac);
|
||
|
||
if (iot_ge_buf_overflow_test(*ret_size, dl645_len +
|
||
sizeof(ge_frame_data_send_set_subfn160_t) + sizeof(ge_frm_tail_t))) {
|
||
if (g_dev_test_buf.cmd_valid) {
|
||
iot_cus_printf("%s ckq is already running a cmd\n", __FUNCTION__);
|
||
goto out;
|
||
}
|
||
|
||
os_mem_cpy(g_dev_test_buf.cmd_buf, hdr_645, dl645_len);
|
||
g_dev_test_buf.cmd_valid = 1;
|
||
|
||
if (true == iot_dev_test_check_local_dl645_cmd(hdr_645)) {
|
||
/* the dl645 data is local cmd, we skip sending the first cmd to
|
||
enable ckq mode of sta, start the timer directly for sending the
|
||
second cmd
|
||
*/
|
||
if (!os_is_timer_active(dev_test_context->ckq_cmd_intvl_tmr)) {
|
||
os_start_timer(dev_test_context->ckq_cmd_intvl_tmr, 0);
|
||
}
|
||
} else {
|
||
/* send the first cmd to enable ckq mode of sta */
|
||
iot_mac_addr_cpy(revert_local_mac, dev_test_context->mac);
|
||
iot_mac_addr_reverse(revert_local_mac);
|
||
pkt = iot_pkt_alloc(DL645_PARSE_FRM_MAX_LEN, IOT_GREE_APP_MID);
|
||
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("%s pkt alloc err!\n", __FUNCTION__);
|
||
goto out;
|
||
}
|
||
|
||
ext_645_buf = iot_pkt_data(pkt);
|
||
ext_645_len = dl645_len;
|
||
iot_proto_pack_data_to_dl645((uint8_t *)hdr_645, ext_645_buf,
|
||
&ext_645_len, DL645_07_DI_CKQ_READ_MODE_EN, revert_local_mac,
|
||
PROTO_645_2007_FN_READ_DATA, PROTO_645_DIR_MASTER);
|
||
ge_len = ext_645_len;
|
||
iot_cus_printf("[ckq]ext_645_buf:");
|
||
iot_dev_test_bin_dump(ext_645_buf, ext_645_len);
|
||
iot_pack_dl645_to_ge(ext_645_buf, &pdata[*ret_size], &ge_len,
|
||
dst_mac, true);
|
||
iot_pkt_free(pkt);
|
||
if (!os_is_timer_active(dev_test_context->ckq_cmd_intvl_tmr)) {
|
||
os_start_timer(dev_test_context->ckq_cmd_intvl_tmr,
|
||
DEV_TEST_TMR_CKQ_CMD_INTVL);
|
||
}
|
||
}
|
||
} else {
|
||
check_ret = GET_OVERFLOW;
|
||
iot_cus_printf("%s ge_buf overflow!\n", __FUNCTION__);
|
||
}
|
||
out:
|
||
*ret_size += ge_len;
|
||
*checked_len = intact_dl645_len;
|
||
return check_ret;
|
||
}
|
||
|
||
/* post uart received command to task */
|
||
static uint8_t iot_dev_test_task_post_uart_cmd(uint8_t * data, uint16_t len)
|
||
{
|
||
iot_pkt_t* send_pkt = NULL;
|
||
|
||
if (NULL == data || 0 == len) {
|
||
iot_cus_printf("%s data err!\n", __FUNCTION__);
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
send_pkt = iot_pkt_alloc(len, IOT_GREE_APP_MID);
|
||
|
||
if (send_pkt) {
|
||
/* copy data from buf to data packet */
|
||
os_mem_cpy(iot_pkt_put(send_pkt, len), data, len);
|
||
|
||
/* alloc message to insert proto task msg queue */
|
||
iot_dev_test_task_post_msg(DEV_TEST_MCU_RX_MSG, 0, send_pkt);
|
||
return ERR_OK;
|
||
} else {
|
||
iot_cus_printf("%s no mem, frame len:%d\n", __FUNCTION__, len);
|
||
return ERR_FAIL;
|
||
}
|
||
}
|
||
|
||
uint8_t iot_dev_test_uart_meter_port_func(uint8_t *buf, uint16_t len)
|
||
{
|
||
uint8_t* pdata;
|
||
uint8_t* pbuf;
|
||
uint8_t check_result = GET_NO_FRAME;
|
||
uint16_t total;
|
||
uint16_t ge_buflen;
|
||
mcu_data_handle_t* p_mcudata;
|
||
uint16_t check_over_len;
|
||
|
||
if (NULL == buf || len == 0) {
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
total = len;
|
||
pbuf = buf;
|
||
p_mcudata = &mcu_data;
|
||
|
||
/* uart drv may report len > UART_RECV_SIZE_MAX, so we handle it in times */
|
||
do {
|
||
/* data_pos indicate possible gree frame start from. if it is larger
|
||
than max gree size, means pmcudata[0] ~ p_mcudata[GE_FRM_MAX_LEN] not
|
||
valide gree frame. however, it should not happen. paser function
|
||
should alreay remove garbage bytes.*/
|
||
if (p_mcudata->data_pos >= GE_FRM_MAX_LEN) {
|
||
iot_cus_printf("[ckq][err] data_pos:%d total:%d\n",
|
||
p_mcudata->data_pos, total);
|
||
goto error;
|
||
}
|
||
|
||
pdata = &p_mcudata->data[p_mcudata->data_pos];
|
||
iot_cus_printf("[ckq]break frame pos= %d new_len=%d\n",
|
||
p_mcudata->data_pos, len);
|
||
|
||
if (total > UART_RECV_SIZE_MAX) {
|
||
os_mem_cpy(pdata, pbuf, UART_RECV_SIZE_MAX);
|
||
pbuf += UART_RECV_SIZE_MAX;
|
||
total -= UART_RECV_SIZE_MAX;
|
||
p_mcudata->total_len = UART_RECV_SIZE_MAX + p_mcudata->data_pos;
|
||
} else {
|
||
os_mem_cpy(pdata, pbuf, total);
|
||
pbuf += total;
|
||
p_mcudata->total_len = total + p_mcudata->data_pos;
|
||
total = 0;
|
||
}
|
||
/* now position should be 0, one new paser cycle starts */
|
||
p_mcudata->data_pos = 0;
|
||
/* clean ge_buf */
|
||
ge_buflen = 0;
|
||
os_mem_set(ge_buf, 0, MCU_DATA_RECV_MAX);
|
||
check_result = GET_NO_FRAME;
|
||
|
||
/*
|
||
do frame check from mcudata offset 0, and the function will return
|
||
full gree frame buffer, ge_buf, and ge_buflen. Also, wrong packet
|
||
in middle removed. remain half packet moved to head of p_mucdata.
|
||
*/
|
||
while (p_mcudata->data_pos < p_mcudata->total_len) {
|
||
check_over_len = 0;
|
||
/*
|
||
check and get the dl645 cmd from uart, firstly,the 645 frame
|
||
should be packed to a extern 645 frame. then,the extern 645 frame
|
||
should be packed to a FE A0 ge frame.
|
||
*/
|
||
check_result = iot_dev_test_645_format_check_handle(p_mcudata,
|
||
ge_buf, &ge_buflen, &check_over_len);
|
||
if (check_result == GET_ONE_FRAME) {
|
||
p_mcudata->data_pos += check_over_len;
|
||
continue;
|
||
} else {
|
||
break;
|
||
}
|
||
p_mcudata->data_pos++;
|
||
}
|
||
|
||
if ((check_result == GET_HALF_FRAME) ||
|
||
(check_result == GET_OVERFLOW)) {
|
||
/* if half frame or overflow exist, save the rest of data */
|
||
os_mem_cpy(p_mcudata->data, &p_mcudata->data[p_mcudata->data_pos],
|
||
p_mcudata->total_len - p_mcudata->data_pos);
|
||
p_mcudata->data_pos = p_mcudata->total_len - p_mcudata->data_pos;
|
||
} else {
|
||
p_mcudata->total_len = 0;
|
||
p_mcudata->data_pos = 0;
|
||
}
|
||
|
||
/* put filtered packeted in message queue */
|
||
if (ge_buflen > 0) {
|
||
iot_cus_printf("[ckq]ge_buflen:%d\n ", ge_buflen);
|
||
iot_dev_test_bin_dump(ge_buf, ge_buflen);
|
||
if (iot_dev_test_task_post_uart_cmd(ge_buf, ge_buflen)) {
|
||
goto error;
|
||
}
|
||
}
|
||
} while ((total > 0) || (check_result == GET_OVERFLOW));
|
||
|
||
return ERR_OK;
|
||
|
||
error:
|
||
p_mcudata->data_pos = 0;
|
||
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
uint8_t iot_dev_test_plc_data_recv_func(protpkt_list_t *report_framelist,
|
||
plctxrx_rx_data_info_t *rxinfo)
|
||
{
|
||
IOT_ASSERT(report_framelist && rxinfo
|
||
&& (report_framelist->frame_cnt > 0)
|
||
&& (report_framelist->total_len > 0));
|
||
uint8_t *buf, *tmp;
|
||
list_node_t* node = report_framelist->list_head;
|
||
/* alloc pkt */
|
||
iot_pkt_t *pkt = iot_pkt_alloc(report_framelist->total_len + sizeof(*rxinfo),
|
||
IOT_GREE_APP_MID);
|
||
IOT_ASSERT(pkt);
|
||
buf = iot_pkt_data(pkt);
|
||
os_mem_cpy(buf, rxinfo, sizeof(*rxinfo));
|
||
iot_pkt_put(pkt, sizeof(*rxinfo));
|
||
/* copy data from each node */
|
||
tmp = iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL);
|
||
while (report_framelist->frame_cnt--) {
|
||
IOT_ASSERT(node);
|
||
os_mem_cpy(tmp, node->data, node->len);
|
||
iot_pkt_put(pkt, node->len);
|
||
tmp += node->len;
|
||
node = node->next;
|
||
}
|
||
|
||
IOT_ASSERT(!node &&
|
||
(buf + report_framelist->total_len + sizeof(*rxinfo) == tmp));
|
||
|
||
iot_dev_test_task_post_msg(DEV_TEST_PLC_RX_MSG, 0, pkt);
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
/* local txrx cmd response */
|
||
uint8_t iot_dev_test_plctxrx_cmd_resp_func(iot_pkt_t *data)
|
||
{
|
||
IOT_ASSERT(data);
|
||
|
||
iot_dev_test_task_post_msg(PROTO_PLC_RX_MSG, PROTO_PLCTXRX_RX_CMD_MSG, data);
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
uint8_t iot_dev_test_fn_register_send_to_plc(fn_cmd_send_to_plc_t cmd_cb,
|
||
fn_data_send_to_plc_t data_cb)
|
||
{
|
||
IOT_ASSERT(cmd_cb && data_cb);
|
||
|
||
dev_test_context->fn_callback.data_send_cb = data_cb;
|
||
dev_test_context->fn_callback.cmd_send_cb = cmd_cb;
|
||
|
||
iot_dev_test_flashinfo_init();
|
||
|
||
return ERR_OK;
|
||
}
|
||
|
||
/* to check the response of dl645 cmd */
|
||
static void iot_dev_test_645_cmd_resp_check(proto_645_header_t *hdr)
|
||
{
|
||
proto_645_header_t *cmd_645 = NULL;
|
||
|
||
if (0 == g_dev_test_buf.cmd_valid) {
|
||
iot_cus_printf("dev test cmd buf not valid\n");
|
||
return;
|
||
}
|
||
|
||
cmd_645 = (proto_645_header_t *)g_dev_test_buf.cmd_buf;
|
||
/* if the mac of recieved dl645 frame same as the mac of cmd or the dst mac,
|
||
means we get the right response, not wait for timeout.
|
||
*/
|
||
if (iot_mac_addr_cmp(cmd_645->addr, hdr->addr) ||
|
||
iot_mac_addr_cmp(g_dev_test_buf.dst_mac, hdr->addr)) {
|
||
if (os_is_timer_active(dev_test_context->ckq_timeout_tmr)) {
|
||
os_stop_timer(dev_test_context->ckq_timeout_tmr);
|
||
iot_task_clean_msg(dev_test_context->task_handle,
|
||
DEV_TEST_TIMER_MSG, DEV_TEST_TIMER_CKQ_TIMEOUT);
|
||
iot_cus_printf("ckq_timeout_tmr cleared\n");
|
||
}
|
||
g_dev_test_buf.cmd_valid = 0;
|
||
}
|
||
}
|
||
|
||
static uint8_t iot_dev_test_plc_data_group_frame(uint8_t *dst, uint8_t *src)
|
||
{
|
||
/**
|
||
* payload of gree frame
|
||
* field:| data cnt | id | data |
|
||
* oct :| 1 B | 4B | data cnt B |
|
||
*/
|
||
uint8_t src_frm_len;
|
||
IOT_ASSERT(src && dst);
|
||
uint8_t *tmp_buf = dst;
|
||
uint16_t check_sum = 0;
|
||
|
||
/* add preamble */
|
||
*((uint16_t *)tmp_buf) = GE_FRM_PREAMBLE_CODE;
|
||
tmp_buf += GE_FRM_PREAMBLE_FIELD_LEN;
|
||
|
||
/* get net payload len */
|
||
src_frm_len = ACQUIRE_DATA_LEN(src[0]) + GE_FRM_DATA_CNT_FIELD_LEN +
|
||
GE_FRM_ID_FIELD_LEN;
|
||
|
||
IOT_ASSERT(src[0] <= GE_FRM_PLD_MAX_LEN &&
|
||
src[0] >= GE_FRM_PLD_MIN_LEN);
|
||
|
||
/* add payload */
|
||
os_mem_cpy(tmp_buf, src, src_frm_len);
|
||
|
||
tmp_buf += src_frm_len;
|
||
/* add check sum */
|
||
check_sum =
|
||
ge_frm_checksum_calc(dst, src_frm_len + GE_FRM_PREAMBLE_FIELD_LEN);
|
||
*tmp_buf = (uint8_t)(check_sum & 0xFF);
|
||
|
||
*(tmp_buf + 1) = (uint8_t)(check_sum >> 8);
|
||
|
||
tmp_buf += GE_FRM_CHECKSUM_FIELD_LEN;
|
||
|
||
/* add tail */
|
||
*tmp_buf = 0xFF;
|
||
|
||
return src_frm_len;
|
||
}
|
||
|
||
static bool_t iot_dev_test_data_handler(uint8_t *data, uint8_t len,
|
||
transmit_direction_e_t dir)
|
||
{
|
||
bool_t rpt2mcu = false;
|
||
protpkt_tx_info_t txinfo = { 0 };
|
||
ge_frame_data_send_set_subfn160_t *hdr =
|
||
(ge_frame_data_send_set_subfn160_t *)data;
|
||
uint8_t dest_mac[IOT_MAC_ADDR_LEN];
|
||
uint8_t retry_cnt;
|
||
transmit_direction_e_t tmp_dir;
|
||
|
||
if (CMD_LOCAL_DOWN_LINK == dir) {
|
||
if (iot_mac_addr_cmp(hdr->dest_mac, dev_test_context->mac)) {
|
||
return rpt2mcu;
|
||
}
|
||
iot_mac_addr_cpy(dest_mac, hdr->dest_mac);
|
||
tmp_dir = DATA_DOWN_LINK;
|
||
} else {
|
||
tmp_dir = DATA_UP_LINK;
|
||
}
|
||
switch (tmp_dir) {
|
||
case DATA_DOWN_LINK:
|
||
{
|
||
if(hdr->retr_cnt == 0) {
|
||
retry_cnt = DEV_TEST_UNICAST_RETRY_DEFAULT_CNT;
|
||
} else {
|
||
retry_cnt = hdr->retr_cnt;
|
||
}
|
||
if (mac_addr_is_bcast_addr(hdr->dest_mac)) {
|
||
iot_proto_fill_txinfo(&txinfo, false,
|
||
PLCTXRX_BORADCAST, PROTO_BROADCAST_RETRY_DEFAULT_CNT,
|
||
PROTO_BROADCAST_RETRY_DEFAULT_INTVL, 0,
|
||
dev_test_context->mac, NULL);
|
||
} else {
|
||
iot_proto_fill_txinfo(&txinfo, true,
|
||
PLCTXRX_UNICAST, retry_cnt,
|
||
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
|
||
dev_test_context->mac, dest_mac);
|
||
}
|
||
iot_dev_test_remote_data_send_to_plctxrx(data, len, &txinfo);
|
||
break;
|
||
}
|
||
case DATA_UP_LINK:
|
||
{
|
||
rpt2mcu = true;
|
||
break;
|
||
}
|
||
default:
|
||
IOT_ASSERT(0);
|
||
break;
|
||
}
|
||
return rpt2mcu;
|
||
}
|
||
|
||
static void iot_dev_test_handle_ge_from_plc(uint8_t *data, uint8_t *len,
|
||
transmit_direction_e_t dir, uint8_t *rpt2mcu)
|
||
{
|
||
/* the index of the input data */
|
||
uint16_t index = 0;
|
||
/* the data length of the input pkt */
|
||
uint16_t input_data_len;
|
||
/* the data length of the frame unpacked from ge frame */
|
||
uint16_t data_len_after_handle = 0;
|
||
/* the data length of each data frame */
|
||
uint16_t frame_data_len;
|
||
uint8_t* buf;
|
||
ge_frame_data_send_set_subfn160_t *p_buf;
|
||
ge_extend_fn_hdr_t *p_buf_hdr;
|
||
proto_645_header_t *hdr_645 = NULL;
|
||
|
||
buf = data;
|
||
input_data_len = *len;
|
||
|
||
if (CMD_REMOTE_UP_LINK != dir) {
|
||
iot_cus_printf("transmit direction mismatch!\n");
|
||
return;
|
||
}
|
||
|
||
while (index < input_data_len) {
|
||
p_buf = (ge_frame_data_send_set_subfn160_t *)&buf[index];
|
||
if (p_buf->resv == DL645_07_RESV0_RESV) {
|
||
frame_data_len = p_buf->hdr.hdr.data_len;
|
||
os_mem_cpy(&buf[data_len_after_handle],
|
||
&buf[index + GE_FEA0_HEAD_LEN],
|
||
frame_data_len - IOT_MAC_ADDR_LEN);
|
||
hdr_645 = (proto_645_header_t *)(&buf[data_len_after_handle]);
|
||
iot_dev_test_645_cmd_resp_check(hdr_645);
|
||
data_len_after_handle += frame_data_len - IOT_MAC_ADDR_LEN;
|
||
index += frame_data_len +
|
||
sizeof(ge_frame_data_send_set_subfn160_t) +
|
||
sizeof(ge_frm_tail_t) - IOT_MAC_ADDR_LEN;
|
||
/* other FEA0 frames */
|
||
} else {
|
||
p_buf_hdr = (ge_extend_fn_hdr_t *)&buf[index];
|
||
frame_data_len = p_buf_hdr->hdr.data_len;
|
||
os_mem_cpy(&buf[data_len_after_handle], &buf[index],
|
||
GE_FRM_MIN_LEN + frame_data_len);
|
||
index += GE_FRM_MIN_LEN + frame_data_len;
|
||
data_len_after_handle += GE_FRM_MIN_LEN + frame_data_len;
|
||
rpt2mcu = false;
|
||
}
|
||
}
|
||
*len = data_len_after_handle;
|
||
}
|
||
|
||
static void iot_dev_test_mode_config_timer(timer_id_t timer_id, void * arg)
|
||
{
|
||
(void)arg;
|
||
(void)timer_id;
|
||
|
||
iot_dev_test_task_post_msg(DEV_TEST_TIMER_MSG,
|
||
DEV_TEST_TIMER_MODE_CONFIG_INTVL, NULL);
|
||
}
|
||
|
||
static void iot_dev_test_ckq_cmd_interval_timer(timer_id_t timer_id,
|
||
void * arg)
|
||
{
|
||
(void)arg;
|
||
(void)timer_id;
|
||
|
||
iot_dev_test_task_post_msg(DEV_TEST_TIMER_MSG,
|
||
DEV_TEST_TIMER_CKQ_CMD_INTVL, NULL);
|
||
}
|
||
|
||
static void iot_dev_test_ckq_timeout_timer(timer_id_t timer_id,
|
||
void * arg)
|
||
{
|
||
(void)arg;
|
||
(void)timer_id;
|
||
|
||
iot_dev_test_task_post_msg(DEV_TEST_TIMER_MSG,
|
||
DEV_TEST_TIMER_CKQ_TIMEOUT, NULL);
|
||
}
|
||
|
||
static void iot_dev_test_plc_data_handle(iot_pkt_t *data)
|
||
{
|
||
uint16_t pos = 0;
|
||
uint16_t buf_len = (uint16_t)iot_pkt_data_len(data);
|
||
uint8_t *buf = iot_pkt_data(data);
|
||
bool_t need_report = false;
|
||
transmit_direction_e_t tmp_dir;
|
||
iot_pkt_t *tmp_pkt = NULL;
|
||
uint8_t *tmp_buf;
|
||
ge_frm_hdr_t *ge_hdr = NULL;
|
||
ge_extend_fn_hdr_t *ge_ext_hdr = NULL;
|
||
uint8_t fn = 0, subfn = 0;
|
||
|
||
tmp_pkt = iot_pkt_alloc(GE_FRM_MAX_LEN, IOT_GREE_APP_MID);
|
||
IOT_ASSERT(tmp_pkt);
|
||
iot_pkt_put(tmp_pkt, GE_FRM_MAX_LEN);
|
||
|
||
tmp_buf = iot_pkt_data(tmp_pkt);
|
||
os_mem_set(tmp_buf, 0, GE_FRM_MAX_LEN);
|
||
|
||
/* get rxinfo */
|
||
plctxrx_rx_data_info_t *rxinfo = (plctxrx_rx_data_info_t *)buf;
|
||
|
||
/* point to data & get data len */
|
||
buf = (uint8_t *)(rxinfo + 1);
|
||
buf_len -= sizeof(*rxinfo);
|
||
|
||
/* maybe a big buffer,need to extract each intact gree frame */
|
||
while (pos < buf_len) {
|
||
uint8_t src_frame_len;
|
||
/* TODO once gree enlarge pkt size, the local vair is not suitable */
|
||
uint8_t tmp_buf_len = GE_FRM_PREAMBLE_FIELD_LEN +
|
||
GE_FRM_CHECKSUM_FIELD_LEN +
|
||
GE_FRM_TAIL_FILED_LEN;
|
||
/* pure payload len */
|
||
src_frame_len = iot_dev_test_plc_data_group_frame(tmp_buf, &buf[pos]);
|
||
/* full pkt len */
|
||
tmp_buf_len += src_frame_len;
|
||
/* move analysis mark ahead */
|
||
pos += src_frame_len;
|
||
/* get fn & subfn */
|
||
ge_hdr = (ge_frm_hdr_t *)tmp_buf;
|
||
fn = ge_hdr->fn;
|
||
/*
|
||
* if fn is extended fn,then direction must be
|
||
* CMD_REMOTE_UP_LINK. since this is plc data receive path.
|
||
*/
|
||
if (PROTO_GE_PLC_SET_CMD == fn) {
|
||
tmp_dir = CMD_REMOTE_UP_LINK;
|
||
iot_dev_test_bin_dump(tmp_buf, tmp_buf_len);
|
||
ge_ext_hdr = (ge_extend_fn_hdr_t *)tmp_buf;
|
||
subfn = ge_ext_hdr->subfn;
|
||
if (PROTO_GE_DATA_CMD == subfn) {
|
||
/* handle the FE A0 ge frame */
|
||
need_report = iot_dev_test_data_handler(tmp_buf, tmp_buf_len,
|
||
tmp_dir);
|
||
/* if a dl645 frame is packed in FE A0 frame, we will unpack it,
|
||
only reserve the dl645 frame.
|
||
*/
|
||
iot_dev_test_handle_ge_from_plc(tmp_buf, &tmp_buf_len, tmp_dir,
|
||
&need_report);
|
||
}
|
||
}
|
||
|
||
if (!need_report)
|
||
continue;
|
||
|
||
/* report to MCU */
|
||
iot_pkt_t *pkt_data = iot_pkt_alloc(tmp_buf_len, IOT_GREE_APP_MID);
|
||
IOT_ASSERT(pkt_data);
|
||
/* make tail pointer of packet ponit to data tail */
|
||
iot_pkt_put(pkt_data, tmp_buf_len);
|
||
/* copy data to packet data field */
|
||
os_mem_cpy(iot_pkt_data(pkt_data), tmp_buf, tmp_buf_len);
|
||
/* report frame to MCU */
|
||
iot_dev_test_send_to_mainboard(pkt_data);
|
||
os_mem_set(tmp_buf, 0, tmp_buf_len);
|
||
}
|
||
|
||
if (tmp_pkt) {
|
||
iot_pkt_free(tmp_pkt);
|
||
}
|
||
|
||
iot_pkt_free(data);
|
||
return;
|
||
}
|
||
|
||
static void iot_dev_test_plctxrx_response_mac(iot_pkt_t *data)
|
||
{
|
||
plctxrx_cmd_resp_t *p_resp;
|
||
custom_flash_info_t *p_flash = &(dev_test_context->flashinfo);
|
||
iot_oem_base_cfg_t *oem_base_cfg;
|
||
plctxrx_cmd_arg_t *p_arg;
|
||
plctxrx_handle_mac_t *p_mac_hd;
|
||
iot_pkt_t *p_pkt;
|
||
uint32_t pkt_len;
|
||
|
||
if(NULL == data)
|
||
{
|
||
iot_cus_printf("Invalid argument!\n");
|
||
return;
|
||
}
|
||
|
||
p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(data);
|
||
if (PLCTXRX_OP_CFM == p_resp->cid.opcode) {
|
||
/* Update MAC address saved in flash. */
|
||
iot_mac_addr_cpy(p_flash->local_mac, dev_test_context->mac);
|
||
if(ERR_OK != iot_dev_test_flashsave(p_flash))
|
||
{
|
||
iot_cus_printf("Local MAC address save to flash failed!\n");
|
||
return;
|
||
}
|
||
} else if (PLCTXRX_OP_INDICATION == p_resp->cid.opcode) {
|
||
/* Get MAC address from flash firstly, need check the MAC address validity. */
|
||
if (mac_addr_in_flash_is_valid_addr(p_flash->local_mac)) {
|
||
iot_cus_printf("Flash's MAC address valid!\n");
|
||
/* Update the dev test layer local MAC address. */
|
||
iot_mac_addr_cpy(dev_test_context->mac, p_flash->local_mac);
|
||
} else {
|
||
/* If flash's MAC address invalid, get MAC address from OEM secondly. */
|
||
(void)iot_oem_get_base_cfg(&oem_base_cfg);
|
||
|
||
/* Check the MAC address validity. */
|
||
if (!mac_addr_in_flash_is_valid_addr(oem_base_cfg->module_mac))
|
||
{
|
||
iot_cus_printf("OEM's MAC address invalid!\n");
|
||
return;
|
||
}
|
||
|
||
iot_cus_printf("[ckq]we will use oem's mac address as local mac!\n");
|
||
/* Update the dev test layer local MAC address. */
|
||
iot_mac_addr_cpy(dev_test_context->mac, oem_base_cfg->module_mac);
|
||
}
|
||
|
||
pkt_len = sizeof(*p_arg) + sizeof(*p_mac_hd);
|
||
if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID)))
|
||
{
|
||
iot_cus_printf("%s No memory!\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
|
||
p_arg->cid.cid = PLCTXRX_CID_MAC;
|
||
p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
|
||
p_arg->prio = 0;
|
||
p_arg->dlen = sizeof(*p_mac_hd);
|
||
p_arg->need_ack = true;
|
||
|
||
p_mac_hd = (plctxrx_handle_mac_t *)p_arg->arg;
|
||
iot_mac_addr_cpy(p_mac_hd->mac, dev_test_context->mac);
|
||
p_mac_hd->dev_type = IOT_PLC_DEV_TYPE_METER_CONTROLLER;
|
||
|
||
iot_dev_test_cmd_send_to_plc(p_pkt);
|
||
|
||
iot_dev_test_set_cfg_after_app_reg();
|
||
}
|
||
iot_pkt_free(data);
|
||
}
|
||
|
||
static void iot_dev_test_plctxrx_cmd_handle(iot_pkt_t *data)
|
||
{
|
||
plctxrx_cmd_resp_t *resp = (plctxrx_cmd_resp_t *)iot_pkt_data(data);
|
||
switch(resp->cid.cid)
|
||
{
|
||
case PLCTXRX_CID_GRAPP_REG_CONF:
|
||
case PLCTXRX_CID_MAC:
|
||
iot_dev_test_plctxrx_response_mac(data);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void iot_dev_test_mcu_msg_handle(iot_pkt_t *data)
|
||
{
|
||
uint8_t fn = 0, subfn = 0;
|
||
uint16_t cur_pos = 0;
|
||
uint16_t total_len = (uint16_t)iot_pkt_data_len(data);
|
||
uint8_t *data_buf = iot_pkt_data(data);
|
||
uint8_t *tmp_buf;
|
||
/* data cnt in each gree frame */
|
||
uint16_t data_len;
|
||
uint8_t ret = 0;
|
||
transmit_direction_e_t tmp_dir;
|
||
ge_frm_hdr_t *ge_hdr = NULL;
|
||
ge_extend_fn_hdr_t *ge_ext_hdr = NULL;
|
||
|
||
/* handle each intact frame extracted from uart data buffer */
|
||
do {
|
||
data_len = 0;
|
||
tmp_buf = data_buf + cur_pos;
|
||
if (cur_pos >= (total_len - 1)) {
|
||
iot_cus_printf("[ckq][err] pos=%d >= %d - 1\n", cur_pos, total_len);
|
||
break;
|
||
}
|
||
|
||
ret = ge_frame_data_len(tmp_buf, total_len - cur_pos, &data_len);
|
||
if (ret != ERR_OK) {
|
||
/* not get a complete frame */
|
||
iot_cus_printf("[ckq][err] incomplete frame\n");
|
||
break;
|
||
}
|
||
|
||
/* increase current pos to reach next intact frame */
|
||
cur_pos += data_len + GE_FRM_MIN_LEN;
|
||
|
||
/* get fncode & subfncode from gree frame */
|
||
ge_hdr = (ge_frm_hdr_t *)tmp_buf;
|
||
fn = ge_hdr->fn;
|
||
|
||
if ( PROTO_GE_PLC_SET_CMD == fn ) {
|
||
ge_ext_hdr = (ge_extend_fn_hdr_t *)tmp_buf;
|
||
subfn = ge_ext_hdr->subfn;
|
||
if (PROTO_GE_DATA_CMD == subfn) {
|
||
tmp_dir = CMD_LOCAL_DOWN_LINK;
|
||
iot_dev_test_data_handler(tmp_buf, (uint8_t)(data_len) +
|
||
GE_FRM_MIN_LEN, tmp_dir);
|
||
}
|
||
}
|
||
} while (cur_pos < total_len);
|
||
|
||
iot_pkt_free(data);
|
||
}
|
||
|
||
static void iot_dev_test_plc_msg_handle(iot_task_msg_t *msg)
|
||
{
|
||
dev_test_msg_t *task_msg;
|
||
IOT_ASSERT(msg);
|
||
|
||
task_msg = (dev_test_msg_t*)msg;
|
||
|
||
switch (task_msg->msg.id)
|
||
{
|
||
case PROTO_PLC_RX_DATA_MSG:
|
||
{
|
||
iot_dev_test_plc_data_handle(task_msg->data);
|
||
break;
|
||
}
|
||
case PROTO_PLCTXRX_RX_CMD_MSG:
|
||
{
|
||
iot_dev_test_plctxrx_cmd_handle(task_msg->data);
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
if (task_msg->data)
|
||
iot_pkt_free(task_msg->data);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void iot_dev_test_mode_config_handler(void)
|
||
{
|
||
iot_pkt_t *p_pkt;
|
||
dev_test_mode_cfg_t *p_cfg;
|
||
plctxrx_cmd_arg_t *p_arg;
|
||
|
||
p_pkt = iot_pkt_alloc(sizeof(*p_cfg) + sizeof(*p_arg),
|
||
IOT_GREE_APP_MID);
|
||
IOT_ASSERT(p_pkt);
|
||
iot_pkt_put(p_pkt, sizeof(*p_cfg) + sizeof(*p_arg));
|
||
|
||
p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt);
|
||
p_arg->cid.cid = PLCTXRX_CID_MODE_CONF;
|
||
p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
|
||
p_arg->prio = 0;
|
||
p_arg->need_ack = false;
|
||
p_arg->dlen = sizeof(*p_cfg);
|
||
|
||
p_cfg = (dev_test_mode_cfg_t *)p_arg->arg;
|
||
p_cfg->band_id = DEV_TEST_DEFAULT_FRQ_BAND;
|
||
p_cfg->dur = DEV_TEST_DEFAULT_MODE_CFG_DUR;
|
||
p_cfg->target_id_mask = DEV_TEST_TARGET_ID_MSK_STA;
|
||
|
||
iot_dev_test_cmd_send_to_plc(p_pkt);
|
||
}
|
||
|
||
static void iot_dev_test_ckq_cmd_interval_handler(void)
|
||
{
|
||
proto_645_header_t *dl645_hdr = NULL;
|
||
uint16_t dl645_len = 0;
|
||
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
|
||
uint8_t src_mac[IOT_MAC_ADDR_LEN];
|
||
uint8_t *ext_645_buf = NULL;
|
||
uint8_t *ge_buf = NULL;
|
||
uint16_t ge_len = 0;
|
||
iot_pkt_t *pkt = NULL;
|
||
uint16_t pkt_len = 0;
|
||
protpkt_tx_info_t txinfo = { 0 };
|
||
|
||
if (!g_dev_test_buf.cmd_valid) {
|
||
iot_cus_printf("%s dl645 cmd is invalid!\n", __FUNCTION__);
|
||
goto out;
|
||
}
|
||
/* send the second cmd to read meter data from sta */
|
||
/* ext_645_buf and ge_buf share a big pkt */
|
||
pkt_len = DL645_PARSE_FRM_MAX_LEN + GE_FRM_MAX_LEN;
|
||
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
|
||
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("%s pkt alloc err!\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
ext_645_buf = iot_pkt_data(pkt);
|
||
ge_buf = ext_645_buf + DL645_PARSE_FRM_MAX_LEN;
|
||
|
||
dl645_hdr = (proto_645_header_t*)g_dev_test_buf.cmd_buf;
|
||
dl645_len = dl645_hdr->len + DL645_PARSE_FRM_MIN_LEN;
|
||
|
||
iot_mac_addr_cpy(dst_mac, g_dev_test_buf.dst_mac);
|
||
iot_mac_addr_reverse(dst_mac);
|
||
iot_mac_addr_cpy(src_mac, dev_test_context->mac);
|
||
iot_mac_addr_reverse(src_mac);
|
||
iot_proto_pack_data_to_dl645((uint8_t *)dl645_hdr, ext_645_buf,
|
||
&dl645_len, DL645_07_DI_CKQ_MODE_READ, src_mac,
|
||
PROTO_645_2007_FN_READ_DATA, PROTO_645_DIR_MASTER);
|
||
|
||
if (dl645_len + GE_FRM_MIN_LEN > GE_FRM_MAX_LEN) {
|
||
iot_cus_printf("%s out of max length!\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
ge_len = dl645_len;
|
||
iot_pack_dl645_to_ge(ext_645_buf, ge_buf, &ge_len, dst_mac, true);
|
||
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST,
|
||
PROTO_UNICAST_RETRY_DEFAULT_CNT, PROTO_UNICAST_RETRY_DEFAULT_INTVL,
|
||
1, dev_test_context->mac, dst_mac);
|
||
iot_dev_test_remote_data_send_to_plctxrx(ge_buf, ge_len, &txinfo);
|
||
iot_pkt_free(pkt);
|
||
out:
|
||
os_start_timer(dev_test_context->ckq_timeout_tmr,
|
||
DEV_TEST_TMR_CKQ_TIMEOUT_INTVL);
|
||
}
|
||
|
||
static void iot_dev_test_ckq_timeout_handler(void)
|
||
{
|
||
if (g_dev_test_buf.cmd_valid) {
|
||
g_dev_test_buf.cmd_valid = 0;
|
||
iot_cus_printf("%s timeout\n", __FUNCTION__);
|
||
}
|
||
}
|
||
|
||
static void iot_dev_test_handle_timer_msg(dev_test_msg_t* task_msg)
|
||
{
|
||
switch (task_msg->msg.id) {
|
||
case DEV_TEST_TIMER_MODE_CONFIG_INTVL:
|
||
{
|
||
iot_dev_test_mode_config_handler();
|
||
break;
|
||
}
|
||
case DEV_TEST_TIMER_CKQ_CMD_INTVL:
|
||
{
|
||
iot_dev_test_ckq_cmd_interval_handler();
|
||
break;
|
||
}
|
||
case DEV_TEST_TIMER_CKQ_TIMEOUT:
|
||
{
|
||
iot_dev_test_ckq_timeout_handler();
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void iot_dev_test_task_msg_handle(iot_task_h task_h, iot_task_msg_t *msg)
|
||
{
|
||
dev_test_msg_t *task_msg = (dev_test_msg_t *)msg;
|
||
|
||
IOT_ASSERT(task_h == dev_test_context->task_handle);
|
||
IOT_ASSERT(msg);
|
||
|
||
switch (task_msg->msg.type) {
|
||
/* handle msg from uart */
|
||
case DEV_TEST_MCU_RX_MSG:
|
||
{
|
||
iot_dev_test_mcu_msg_handle(task_msg->data);
|
||
break;
|
||
}
|
||
/* handle msg from plctxrx layer */
|
||
case DEV_TEST_PLC_RX_MSG:
|
||
{
|
||
iot_dev_test_plc_msg_handle(&task_msg->msg);
|
||
break;
|
||
}
|
||
/* handle msg from timer */
|
||
case DEV_TEST_TIMER_MSG:
|
||
{
|
||
iot_dev_test_handle_timer_msg(task_msg);
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
|
||
iot_task_free_msg(dev_test_context->task_handle, msg);
|
||
|
||
return;
|
||
}
|
||
|
||
static void iot_dev_test_task_msg_cancel(iot_task_h task_h, iot_task_msg_t *msg)
|
||
{
|
||
dev_test_msg_t *task_msg;
|
||
IOT_ASSERT(task_h == dev_test_context->task_handle);
|
||
IOT_ASSERT(msg);
|
||
|
||
task_msg = (dev_test_msg_t *)msg;
|
||
|
||
switch (task_msg->msg.type) {
|
||
case DEV_TEST_MCU_RX_MSG:
|
||
{
|
||
break;
|
||
}
|
||
case DEV_TEST_PLC_RX_MSG:
|
||
{
|
||
break;
|
||
}
|
||
case DEV_TEST_TIMER_MSG:
|
||
{
|
||
break;
|
||
}
|
||
default:
|
||
IOT_ASSERT(0);
|
||
break;
|
||
}
|
||
|
||
if (task_msg->data) {
|
||
iot_pkt_free(task_msg->data);
|
||
}
|
||
|
||
iot_task_free_msg(dev_test_context->task_handle, &task_msg->msg);
|
||
}
|
||
|
||
dev_test_context_t *iot_dev_test_context_get(void)
|
||
{
|
||
if (!dev_test_is_firedup()) {
|
||
iot_cus_printf("dev test module not ready.\n");
|
||
return NULL;
|
||
}
|
||
|
||
return dev_test_context;
|
||
}
|
||
|
||
void iot_dev_test_task_deinit(void)
|
||
{
|
||
if (NULL != dev_test_context->task_handle) {
|
||
iot_task_delete(dev_test_context->task_handle);
|
||
dev_test_context->task_handle = NULL;
|
||
}
|
||
|
||
if (0 != dev_test_context->mod_cfg_tmr) {
|
||
os_delete_timer(dev_test_context->mod_cfg_tmr);
|
||
dev_test_context->mod_cfg_tmr = 0;
|
||
}
|
||
|
||
if (0 != dev_test_context->ckq_cmd_intvl_tmr) {
|
||
os_delete_timer(dev_test_context->ckq_cmd_intvl_tmr);
|
||
dev_test_context->ckq_cmd_intvl_tmr = 0;
|
||
}
|
||
|
||
if (0 != dev_test_context->ckq_timeout_tmr) {
|
||
os_delete_timer(dev_test_context->ckq_timeout_tmr);
|
||
dev_test_context->ckq_timeout_tmr = 0;
|
||
}
|
||
|
||
os_mem_free(dev_test_context);
|
||
|
||
return;
|
||
}
|
||
|
||
iot_task_h iot_dev_test_task_init(void)
|
||
{
|
||
/* alloc memory first. */
|
||
dev_test_context = os_mem_malloc(IOT_GREE_APP_MID, sizeof(*dev_test_context));
|
||
|
||
if (!dev_test_context) {
|
||
iot_cus_printf("%s mem malloc failed!\n", __FUNCTION__);
|
||
goto error_handle;
|
||
}
|
||
os_mem_set(dev_test_context, 0, sizeof(dev_test_context_t));
|
||
|
||
dev_test_context->task_cfg.stack_size = 0;
|
||
dev_test_context->task_cfg.task_prio = IOT_DEV_TEST_PRIO;
|
||
dev_test_context->task_cfg.msg_size = sizeof(dev_test_msg_t);
|
||
dev_test_context->task_cfg.msg_cnt = IOT_DEV_TEST_TASK_POOL_SIZE;
|
||
dev_test_context->task_cfg.queue_cnt = IOT_DEV_TEST_TASK_QUEUE_MAX_PRIO;
|
||
dev_test_context->task_cfg.queue_cfg[IOT_DEV_TEST_TASK_QUEUE_LP].quota = 0;
|
||
dev_test_context->task_cfg.msg_exe_func = iot_dev_test_task_msg_handle;
|
||
dev_test_context->task_cfg.msg_cancel_func = iot_dev_test_task_msg_cancel;
|
||
/* create task */
|
||
dev_test_context->task_handle =
|
||
iot_task_create(IOT_GREE_APP_MID, &(dev_test_context->task_cfg));
|
||
|
||
if (dev_test_context->task_handle == NULL) {
|
||
goto error_handle;
|
||
}
|
||
|
||
dev_test_context->mod_cfg_tmr =
|
||
os_create_timer(IOT_GREE_APP_MID, true,
|
||
iot_dev_test_mode_config_timer, NULL);
|
||
if (dev_test_context->mod_cfg_tmr == 0) {
|
||
goto error_handle;
|
||
}
|
||
|
||
dev_test_context->ckq_cmd_intvl_tmr =
|
||
os_create_timer(IOT_GREE_APP_MID, false,
|
||
iot_dev_test_ckq_cmd_interval_timer, NULL);
|
||
if (dev_test_context->ckq_cmd_intvl_tmr == 0) {
|
||
goto error_handle;
|
||
}
|
||
|
||
dev_test_context->ckq_timeout_tmr =
|
||
os_create_timer(IOT_GREE_APP_MID, false,
|
||
iot_dev_test_ckq_timeout_timer, NULL);
|
||
if (dev_test_context->ckq_timeout_tmr == 0) {
|
||
goto error_handle;
|
||
}
|
||
|
||
dev_test_fire_now();
|
||
iot_cus_printf("dev test module initailized seccussfully\n");
|
||
return dev_test_context->task_handle;
|
||
|
||
error_handle:
|
||
iot_dev_test_task_deinit();
|
||
iot_cus_printf("dev test module initailized failed\n");
|
||
return NULL;
|
||
}
|
||
|
||
#endif
|