4349 lines
		
	
	
		
			142 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			4349 lines
		
	
	
		
			142 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
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_plc_cco_api.h"
 | 
						|
#include "iot_plc_sta_api.h"
 | 
						|
#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_errno_api.h"
 | 
						|
#include "iot_io_api.h"
 | 
						|
#include "iot_dbglog_api.h"
 | 
						|
#include "iot_uart_api.h"
 | 
						|
#include "iot_utils_api.h"
 | 
						|
#include "iot_task_api.h"
 | 
						|
#include "iot_version_api.h"
 | 
						|
#include "iot_board_api.h"
 | 
						|
#include "iot_plc_led_api.h"
 | 
						|
 | 
						|
#include "iot_grapp.h"
 | 
						|
#include "iot_plctxrx.h"
 | 
						|
#include "iot_proto_common.h"
 | 
						|
#include "iot_proto_ge.h"
 | 
						|
 | 
						|
#if IOT_GE_AES_ENABLE
 | 
						|
#include "iot_crypto_aes_api.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#if IOT_GR_APP_ENABLE
 | 
						|
 | 
						|
#if (IOT_PSRAM_ENABLE)
 | 
						|
#define IOT_PLCTXRX_LIST_NODE_NUM       128
 | 
						|
#else
 | 
						|
#define IOT_PLCTXRX_LIST_NODE_NUM       40
 | 
						|
#endif
 | 
						|
 | 
						|
/* min retry send. unit is ms */
 | 
						|
#define IOT_PLCTXRX_RETRY_MIN_INTV      10
 | 
						|
 | 
						|
/* at send data packet limit size */
 | 
						|
#define IOT_PLCTXRX_MAX_SZ              255
 | 
						|
 | 
						|
/* const, max cached cmd cnt */
 | 
						|
#define IOT_PLCTXRX_CMD_MAX_CNT         32
 | 
						|
 | 
						|
/* snr good minimum threshold, below this value is weak */
 | 
						|
#define IOT_SNR_GOOD_MIN_THR                (5)
 | 
						|
/* snr strong minimum threshold */
 | 
						|
#define IOT_SNR_STRONG_MIN_THR              (20)
 | 
						|
 | 
						|
#if (HW_PLATFORM == HW_PLATFORM_SIMU)
 | 
						|
extern uint8_t ucIsClientMode;
 | 
						|
#endif
 | 
						|
 | 
						|
iot_mem_pool_t *list_mem_pool;
 | 
						|
extern greeplc_app_t *greeapp;
 | 
						|
 | 
						|
/* statistic on gree frame  */
 | 
						|
uint32_t g_gree_frm_cnt;
 | 
						|
uint32_t g_gree_frm_total_len;
 | 
						|
 | 
						|
/* plctxrx global context */
 | 
						|
plctxrx_contxt_t plctxrx_context;
 | 
						|
 | 
						|
/* proto pkt cache buffer */
 | 
						|
prot_pkt_t gbl_protpkt[TXRX_SEND_BUFF_POOL_NUM];
 | 
						|
 | 
						|
/* cmd cache buffer */
 | 
						|
plctxrx_cmdsave_node_t g_cmdhandle_node[IOT_PLCTXRX_CMD_MAX_CNT];
 | 
						|
 | 
						|
void iot_common_bin_dump(uint8_t *data, uint32_t dlen);
 | 
						|
 | 
						|
/* arguments of cmd_type, it's the source of current command.*/
 | 
						|
void
 | 
						|
plctxrx_cmd_msg_handle(iot_pkt_t *arg_pkt);
 | 
						|
 | 
						|
/* response upper layer the query */
 | 
						|
void
 | 
						|
plctxrx_cmd_resp_data_pkt(uint8_t handle_next, uint8_t oper_code,
 | 
						|
    iot_pkt_t *pkt);
 | 
						|
 | 
						|
/* prepare response pkt to upper */
 | 
						|
void
 | 
						|
plctxrx_cmd_resp_data(uint8_t cmd_id, uint8_t oper_code,
 | 
						|
    plctxrx_resp_idx_t *index, uint16_t resp, void *data, uint16_t data_len);
 | 
						|
 | 
						|
/* cmd saveq handle - pop */
 | 
						|
plctxrx_cmdsave_node_t *
 | 
						|
iot_plctxrx_commandnode_pop_front(plctxrx_cmdsave_list_t *cmdq,
 | 
						|
                                                    cmd_queue_e_t qtype);
 | 
						|
plctxrx_cmdsave_node_t *
 | 
						|
iot_plctxrx_commandnode_get_front(plctxrx_cmdsave_list_t *cmdq,
 | 
						|
                                                    cmd_queue_e_t qtype);
 | 
						|
 | 
						|
/* cmd saveq handle - push */
 | 
						|
void
 | 
						|
iot_plctxrx_commandnode_push_backend(plctxrx_cmdsave_list_t *cmdq,
 | 
						|
                                    list_node_t *node, cmd_queue_e_t qtype);
 | 
						|
 | 
						|
/* allocte a conn_less_msdu, then fill the msdu pkt with
 | 
						|
 * conn_less mode config data
 | 
						|
 */
 | 
						|
uint8_t iot_dev_test_send_mode_config(dev_test_mode_cfg_t *cfg)
 | 
						|
{
 | 
						|
    uint16_t buflen = 0;
 | 
						|
    uint8_t *ptr = NULL;
 | 
						|
    iot_pkt_t *msdu_pkt;
 | 
						|
    uint8_t dest_mac[IOT_MAC_ADDR_LEN] = { 0 };
 | 
						|
 | 
						|
    iot_set_bcast_mac(dest_mac);
 | 
						|
 | 
						|
    buflen = sizeof(dev_test_mode_cfg_t);
 | 
						|
 | 
						|
    msdu_pkt = iot_plc_alloc_conn_less_msdu(greeapp->app_handle,
 | 
						|
        IOT_PLC_MSG_TYPE_CONN_LESS_CMD, dest_mac,
 | 
						|
        plctxrx_context.local_state.sta_mac, plctxrx_context.link_id,
 | 
						|
        buflen, IOT_PLC_LOCAL_RETRY_CNT);
 | 
						|
 | 
						|
    if (msdu_pkt == NULL) {
 | 
						|
        iot_cus_printf("%s:allocate msdu failed!\n", __FUNCTION__);
 | 
						|
        return ERR_NOMEM;
 | 
						|
    }
 | 
						|
 | 
						|
    ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | 
						|
    iot_pkt_put(msdu_pkt, buflen);
 | 
						|
    os_mem_cpy(ptr, cfg, buflen);
 | 
						|
 | 
						|
    iot_cus_printf("send mode config to [%02x:%02x:%02x:%02x:%02x:%02x]"
 | 
						|
        " band id-%lu, duration-%lu sec, mask-%lu\n",
 | 
						|
        dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3],dest_mac[4],
 | 
						|
        dest_mac[5], cfg->band_id, cfg->dur, cfg->target_id_mask);
 | 
						|
    iot_plc_send_msdu(greeapp->app_handle, msdu_pkt);
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
/* check the conn_less pkt infor bufer every 500ms */
 | 
						|
static void iot_plctxrx_conn_less_buf_refresh(void)
 | 
						|
{
 | 
						|
    uint8_t i;
 | 
						|
    plcs_conn_less_pkt_info_t *pkt_info = NULL;
 | 
						|
 | 
						|
    if (0 == plctxrx_context.used_buf_cnt) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; i < IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT; i++) {
 | 
						|
        pkt_info = &plctxrx_context.conn_less_buf[i];
 | 
						|
        if (pkt_info->span_cnt >= IOT_PLCTXRX_CONN_LESS_PKT_SPAN_CNT) {
 | 
						|
            if (plctxrx_context.used_buf_cnt > 0) {
 | 
						|
                plctxrx_context.used_buf_cnt--;
 | 
						|
            }
 | 
						|
            iot_cus_printf("[gltx]conn_less pkt info[%d] is cleared, used "
 | 
						|
                "buf cnt[%d]\n", pkt_info->msdu_sn,
 | 
						|
                plctxrx_context.used_buf_cnt);
 | 
						|
            os_mem_set(pkt_info, 0, sizeof(*pkt_info));
 | 
						|
        } else {
 | 
						|
            if (pkt_info->msdu_sn != 0) {
 | 
						|
                pkt_info->span_cnt++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void iot_plctxrx_conn_less_pkt_info_save(uint16_t sn, uint8_t *mac)
 | 
						|
{
 | 
						|
    uint8_t i;
 | 
						|
    plcs_conn_less_pkt_info_t *pkt_info = NULL;
 | 
						|
 | 
						|
    if ((0 == sn) || !iot_mac_addr_valid(mac)) {
 | 
						|
        iot_cus_printf("[gltx]invalid input param: sn %d", sn);
 | 
						|
        return ;
 | 
						|
    }
 | 
						|
 | 
						|
    if (plctxrx_context.used_buf_cnt >= IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT) {
 | 
						|
        iot_cus_printf("[gltx]no slot for new a conn_less pkt info.\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; i < IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT; i++) {
 | 
						|
        pkt_info = &plctxrx_context.conn_less_buf[i];
 | 
						|
        /* msdu_sn== 0 means the buf can be used */
 | 
						|
        if (0 == pkt_info->msdu_sn) {
 | 
						|
            pkt_info->msdu_sn = sn;
 | 
						|
            iot_mac_addr_cpy(pkt_info->src_mac, mac);
 | 
						|
            pkt_info->span_cnt = 0;
 | 
						|
            if (plctxrx_context.used_buf_cnt <
 | 
						|
                IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT) {
 | 
						|
                plctxrx_context.used_buf_cnt++;
 | 
						|
            }
 | 
						|
 | 
						|
            iot_cus_printf("[gltx]conn_less pkt[%d] info saved, used buf[%d]"
 | 
						|
                "\n", sn, plctxrx_context.used_buf_cnt);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static bool_t iot_plctxrx_conn_less_rpt_check(uint16_t sn, uint8_t *mac)
 | 
						|
{
 | 
						|
    uint8_t i;
 | 
						|
    bool_t need_rpt = false;
 | 
						|
    plcs_conn_less_pkt_info_t *pkt_info = NULL;
 | 
						|
 | 
						|
    if ((0 == sn) || !iot_mac_addr_valid(mac)) {
 | 
						|
        iot_cus_printf("invalid input param: sn %d\n", sn);
 | 
						|
        return need_rpt;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; i < IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT; i++) {
 | 
						|
        pkt_info = &plctxrx_context.conn_less_buf[i];
 | 
						|
        if ((sn == pkt_info->msdu_sn) &&
 | 
						|
            (iot_mac_addr_cmp(mac, pkt_info->src_mac))) {
 | 
						|
            need_rpt =  false;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (i >= IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT) {
 | 
						|
        need_rpt =  true;
 | 
						|
        /* if a new pkt received, store into infor buffer */
 | 
						|
        iot_plctxrx_conn_less_pkt_info_save(sn, mac);
 | 
						|
    }
 | 
						|
 | 
						|
    return need_rpt;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
uint8_t iot_plctxrx_list_init(void)
 | 
						|
{
 | 
						|
    //iot_cus_printf("[gltx]rptlist num:%d\n",IOT_PLCTXRX_LIST_NODE_NUM);
 | 
						|
    if (iot_mem_pool_new(IOT_GREE_APP_MID,IOT_PLCTXRX_LIST_NODE_NUM,
 | 
						|
        sizeof(list_node_t), &list_mem_pool, 1)) {
 | 
						|
        iot_cus_printf("[gltx]mem pool init fail.\n");
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_list_free(protpkt_list_t *list)
 | 
						|
{
 | 
						|
    list_node_t *node, *next;
 | 
						|
 | 
						|
    if (!list->list_head)
 | 
						|
    {
 | 
						|
        iot_cus_printf("[gltx]list empty\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    node = list->list_head;
 | 
						|
    while (node) {
 | 
						|
        next = node->next;
 | 
						|
        iot_mem_pool_free(list_mem_pool, node);
 | 
						|
        node = next;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_queue_init(prot_pktq_t *queue)
 | 
						|
{
 | 
						|
    queue->list_head = NULL;
 | 
						|
    queue->list_tail = NULL;
 | 
						|
    queue->depth = 0;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t iot_plctxrx_queue_empty_check(prot_pktq_t *queue) {
 | 
						|
 | 
						|
    uint32_t depth;
 | 
						|
 | 
						|
    /* TODO : 32bits get is atomic opcode. Not need mutex.  */
 | 
						|
    os_acquire_mutex(queue->lock);
 | 
						|
    depth = queue->depth;
 | 
						|
    os_release_mutex(queue->lock);
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]depth:%d\n",depth);
 | 
						|
 | 
						|
    return (depth > 0) ? ERR_OK : ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
/* push in tail/backend */
 | 
						|
void iot_plctxrx_pkt_enqueue(prot_pktq_t *queue, list_node_t *pkt)
 | 
						|
{
 | 
						|
    IOT_ASSERT(pkt->next == NULL);
 | 
						|
 | 
						|
    os_acquire_mutex(queue->lock);
 | 
						|
 | 
						|
 | 
						|
    if (queue->list_head== NULL) {
 | 
						|
        queue->list_head = pkt;
 | 
						|
    }
 | 
						|
 | 
						|
    if (queue->list_tail) {
 | 
						|
        IOT_ASSERT(queue->list_head);
 | 
						|
        queue->list_tail->next = pkt;
 | 
						|
    }
 | 
						|
    queue->list_tail = pkt;
 | 
						|
    queue->depth++;
 | 
						|
    os_release_mutex(queue->lock);
 | 
						|
}
 | 
						|
 | 
						|
/* pop from head/front */
 | 
						|
list_node_t *iot_plctxrx_pkt_dequeue(prot_pktq_t *queue)
 | 
						|
{
 | 
						|
    list_node_t *entry = NULL;
 | 
						|
 | 
						|
    os_acquire_mutex(queue->lock);
 | 
						|
    if (queue->list_head) {
 | 
						|
        IOT_ASSERT(queue->list_tail);
 | 
						|
        queue->depth--;
 | 
						|
        entry = queue->list_head;
 | 
						|
        if (queue->list_head == queue->list_tail) {
 | 
						|
            queue->list_head = NULL;
 | 
						|
            queue->list_tail = NULL;
 | 
						|
        } else {
 | 
						|
            queue->list_head = queue->list_head->next;
 | 
						|
        }
 | 
						|
        entry->next = NULL;
 | 
						|
    } else {
 | 
						|
        IOT_ASSERT(queue->list_tail == NULL);
 | 
						|
    }
 | 
						|
    os_release_mutex(queue->lock);
 | 
						|
 | 
						|
    return entry;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int16_t iot_plctxrx_get_sta_indx_by_mac(uint8_t *mac)
 | 
						|
{
 | 
						|
    uint16_t indx;
 | 
						|
    for (indx = 0; indx < STA_DEV_MAX; indx++) {
 | 
						|
        if (iot_mac_addr_cmp(mac, plctxrx_context.sta[indx].sta_mac)) {
 | 
						|
            return indx;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t *iot_plctxrx_get_mac_by_tei(uint16_t tei)
 | 
						|
{
 | 
						|
    uint16_t indx;
 | 
						|
    for (indx = 0; indx < plctxrx_context.cur_stanum; indx++) {
 | 
						|
        if (plctxrx_context.sta[indx].sta_tei == tei) {
 | 
						|
            return plctxrx_context.sta[indx].sta_mac;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_timer_reset(timer_id_t task_timer, uint32_t period)
 | 
						|
{
 | 
						|
    if (os_is_timer_active(task_timer)) {
 | 
						|
        os_stop_timer(task_timer);
 | 
						|
    }
 | 
						|
 | 
						|
    os_start_timer(task_timer, period);
 | 
						|
}
 | 
						|
 | 
						|
static void iot_plctxrx_recvd_pktseq_update(iot_plc_msdu_recv_t *msdu_pkt)
 | 
						|
{
 | 
						|
    msdu_pkt_hdr_t *pkthdr = NULL;
 | 
						|
    uint8_t *ptr = NULL;
 | 
						|
    uint16_t i = 0;
 | 
						|
    uint8_t *mac = NULL;
 | 
						|
 | 
						|
    ptr = msdu_pkt->data;
 | 
						|
    pkthdr = (msdu_pkt_hdr_t *)ptr;
 | 
						|
 | 
						|
    for (i = 0; i < STA_DEV_MAX; i++) {
 | 
						|
        if (!plctxrx_context.sta[i].valid) {
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        mac = plctxrx_context.sta[i].sta_mac;
 | 
						|
        /* if the msdu src mac is the sta's mac, update the msdu seq */
 | 
						|
        if (iot_mac_addr_cmp(mac, msdu_pkt->src)) {
 | 
						|
            iot_cus_printf("[gltx]sta:%d update_msdu:%d\n", i,
 | 
						|
                pkthdr->msdusend_seq);
 | 
						|
            plctxrx_context.sta[i].lastrcv_msduseq = pkthdr->msdusend_seq;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (i >= STA_DEV_MAX) {
 | 
						|
      iot_cus_printf("[gltx][err]msduseq [%d] update failed for mac"
 | 
						|
        " mismatch\n", pkthdr->msdusend_seq);
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
uint8_t iot_plctxrx_msdu_type_check(iot_plc_msdu_recv_t *msdu)
 | 
						|
{
 | 
						|
    msdu_pkt_hdr_t *pkthdr = NULL;
 | 
						|
    uint8_t *ptr = NULL;
 | 
						|
    uint8_t ret;
 | 
						|
 | 
						|
    ptr = msdu->data;
 | 
						|
    pkthdr = (msdu_pkt_hdr_t *)ptr;
 | 
						|
 | 
						|
    if ( pkthdr->recvconf_seq != 0) {
 | 
						|
        ret = PLCTXRX_TYPE_ACK;
 | 
						|
    } else {
 | 
						|
        ret = PLCTXRX_TYPE_DATA;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
uint8_t iot_plctxrx_push_aggred_pkt_to_sendq(prot_pktq_t *queue)
 | 
						|
{
 | 
						|
    prot_pkt_t *prot_pkt = NULL;
 | 
						|
    prot_pkt_t *send_pkt = NULL;
 | 
						|
 | 
						|
    prot_pkt = plctxrx_context.aggrpkt;
 | 
						|
 | 
						|
    if (prot_pkt == NULL) {
 | 
						|
       iot_cus_printf("[gltx]aggrtimer no aggr pkt\n");
 | 
						|
       return ERR_OK;
 | 
						|
    }
 | 
						|
    prot_pkt->send_cnt = 0;
 | 
						|
    /* old aggr pkt will send. no aggrpkt cached now */
 | 
						|
    plctxrx_context.aggrpkt = NULL;
 | 
						|
    /* in send queue, push backend */
 | 
						|
    iot_plctxrx_pkt_enqueue(queue, (list_node_t*)prot_pkt);
 | 
						|
 | 
						|
    switch (prot_pkt->txinfo.send_type) {
 | 
						|
    case PLCTXRX_UNICAST:
 | 
						|
        plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt++;
 | 
						|
        break;
 | 
						|
    case PLCTXRX_BORADCAST:
 | 
						|
        plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt++;
 | 
						|
        break;
 | 
						|
    default :
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    /* get front of sendq. note: may not the aggr pkt in queue upper */
 | 
						|
    send_pkt = (prot_pkt_t *)plctxrx_context.sendq->list_head;
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]pushed into the queue "
 | 
						|
        "sendq:%d, freeq:%d, sendpkt:0x%x sendcnt:%d\n",
 | 
						|
        plctxrx_context.sendq->depth, plctxrx_context.freeq->depth, send_pkt,
 | 
						|
        send_pkt->send_cnt);
 | 
						|
 | 
						|
    /* if first send, trigger send */
 | 
						|
    if (send_pkt->send_cnt == 0) {
 | 
						|
        iot_plctxrx_msdu_send(send_pkt);
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t iot_plctxrx_msdu_duplicate_check(iot_plc_msdu_recv_t *pkt)
 | 
						|
{
 | 
						|
    msdu_pkt_hdr_t *pkthdr = NULL;
 | 
						|
    uint8_t *ptr = NULL;
 | 
						|
    uint8_t  isdup = 0;
 | 
						|
    uint8_t *mac = NULL;
 | 
						|
    uint16_t i = 0;
 | 
						|
 | 
						|
    ptr = pkt->data;
 | 
						|
    pkthdr = (msdu_pkt_hdr_t *)ptr;
 | 
						|
 | 
						|
    for (i = 0; i < STA_DEV_MAX; i++) {
 | 
						|
        if (!plctxrx_context.sta[i].valid) {
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        mac = plctxrx_context.sta[i].sta_mac;
 | 
						|
        if (iot_mac_addr_cmp(mac, pkt->src)) {
 | 
						|
            if (plctxrx_context.sta[i].lastrcv_msduseq == pkthdr->msdusend_seq) {
 | 
						|
                iot_cus_printf("[gltx]dupcheck failed mac:%x:%x:%x:%x:%x:%x(%d)\n"
 | 
						|
                    ,mac[0],mac[1],mac[2],mac[3], mac[4], mac[5],
 | 
						|
                    plctxrx_context.sta[i].lastrcv_msduseq);
 | 
						|
                isdup = 1;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!isdup) {
 | 
						|
        iot_cus_printf("[gltx]dupcheck pass stanum:%d\n",
 | 
						|
            plctxrx_context.cur_stanum);
 | 
						|
    }
 | 
						|
 | 
						|
    return isdup;
 | 
						|
}
 | 
						|
 | 
						|
#if IOT_GE_AES_ENABLE
 | 
						|
 | 
						|
#define iot_grapp_aes_get_len(x)    (((x) + 0xF) & (~0xF))
 | 
						|
#define iot_grapp_aes_get_key(key, dest_mac, seq)   do{ \
 | 
						|
    os_mem_cpy(key, dest_mac, IOT_MAC_ADDR_LEN); \
 | 
						|
    key[6] = (seq >> 8) & 0xFF; \
 | 
						|
    key[7] = seq & 0xFF; } while(0)
 | 
						|
 | 
						|
/* a complete PKT structure is shown below
 | 
						|
 * |_iot_pkt_t_|_resv_|_iot_plc_msg_header_t_|_iot_plc_msdu_send_t_|_msdu_pkt_hdr_t_|_cmd_|
 | 
						|
 * we just encrypt msdu_pkt_hdr_t and cmd
 | 
						|
*/
 | 
						|
static uint8_t iot_plctxrx_aes_encrypt(iot_pkt_t *pkt, uint16_t len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = NULL;
 | 
						|
    msdu_pkt_hdr_t *hdr_msdu_pkt = NULL;
 | 
						|
    iot_plc_msdu_send_t *hdr_msdu_send = NULL;
 | 
						|
    uint16_t buffer_len,data_len;
 | 
						|
    uint8_t delta_len = 0;
 | 
						|
    uint8_t destmac_to_key[16] = {0};
 | 
						|
    uint8_t i;
 | 
						|
    uint8_t *encrypt_buffer = NULL;
 | 
						|
 | 
						|
    if (!greeapp->aes.enable) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ptr = iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL);
 | 
						|
    hdr_msdu_pkt = (msdu_pkt_hdr_t*)ptr;
 | 
						|
    hdr_msdu_pkt->aes_encrypt = 1;
 | 
						|
    ptr += sizeof(msdu_pkt_hdr_t);
 | 
						|
    hdr_msdu_send = (iot_plc_msdu_send_t *)
 | 
						|
        (iot_pkt_data(pkt) + sizeof(iot_plc_msg_header_t));
 | 
						|
    /* The data length cannot be encrypted, otherwise it will cause crash
 | 
						|
     * when the receiving module is not decrypted
 | 
						|
    */
 | 
						|
    data_len = len - 1;
 | 
						|
    /* AES processes data in blocks of 16 bytes,
 | 
						|
     * meaning less than 16 bytes need to be filled
 | 
						|
    */
 | 
						|
    buffer_len = iot_grapp_aes_get_len(data_len);
 | 
						|
    encrypt_buffer = os_mem_malloc(IOT_GREE_APP_MID, buffer_len);
 | 
						|
    if (encrypt_buffer == NULL) {
 | 
						|
        iot_cus_printf("[gltx]memory malloc failed, aes encrypt failed\n");
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    os_mem_set(encrypt_buffer, 0, buffer_len);
 | 
						|
 | 
						|
    delta_len = buffer_len - data_len;
 | 
						|
    ptr[0] += delta_len;
 | 
						|
    hdr_msdu_pkt->aes_padding = delta_len;
 | 
						|
    os_mem_cpy(encrypt_buffer, ptr + 1, data_len);
 | 
						|
    iot_grapp_aes_get_key(destmac_to_key, hdr_msdu_pkt->dst_mac,
 | 
						|
        hdr_msdu_pkt->msdusend_seq);
 | 
						|
    iot_crypto_aes_setkey_enc(destmac_to_key, 128);
 | 
						|
    for (i = 0; i < (buffer_len / 16); i++) {
 | 
						|
        iot_crypto_aes_ecb(IOT_AES_ENCRYPT, buffer_len,
 | 
						|
            &encrypt_buffer[i*16], &encrypt_buffer[i*16]);
 | 
						|
    }
 | 
						|
 | 
						|
    os_mem_cpy(ptr + 1, encrypt_buffer, buffer_len);
 | 
						|
    hdr_msdu_send->len += delta_len;
 | 
						|
    os_mem_free(encrypt_buffer);
 | 
						|
out:
 | 
						|
    return delta_len;
 | 
						|
}
 | 
						|
 | 
						|
static bool_t iot_plctxrx_aes_decrypt(iot_pkt_t *pkt)
 | 
						|
{
 | 
						|
    uint8_t *ptr = NULL;
 | 
						|
    msdu_pkt_hdr_t *hdr_msdu_pkt = NULL;
 | 
						|
    iot_plc_msdu_recv_t *hdr_msdu_recv=  NULL;
 | 
						|
    uint16_t buffer_len,data_len;
 | 
						|
    uint8_t delta_len = 0;
 | 
						|
    uint8_t destmac_to_key[16] = {0};
 | 
						|
    uint8_t i;
 | 
						|
    proto_fn_code_e fn_list;
 | 
						|
    uint8_t *decrypt_buffer = NULL;
 | 
						|
 | 
						|
    ptr = (uint8_t *)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | 
						|
    ptr += sizeof(iot_plc_msg_header_t);
 | 
						|
    hdr_msdu_recv = (iot_plc_msdu_recv_t *)(ptr);
 | 
						|
    ptr = hdr_msdu_recv->data;
 | 
						|
    hdr_msdu_pkt = (msdu_pkt_hdr_t*)ptr;
 | 
						|
    if (hdr_msdu_pkt->aes_encrypt) {
 | 
						|
        ptr = (uint8_t *)hdr_msdu_pkt + sizeof(msdu_pkt_hdr_t);
 | 
						|
        delta_len = hdr_msdu_pkt->aes_padding;
 | 
						|
        buffer_len = hdr_msdu_recv->len - sizeof(msdu_pkt_hdr_t) - 1;
 | 
						|
        data_len = buffer_len - delta_len;
 | 
						|
        decrypt_buffer = os_mem_malloc(IOT_GREE_APP_MID, buffer_len);
 | 
						|
        if (decrypt_buffer == NULL) {
 | 
						|
            iot_cus_printf("[gltx]memory malloc failed, aes decrypt failed\n");
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        os_mem_set(decrypt_buffer, 0, buffer_len);
 | 
						|
 | 
						|
        os_mem_cpy(decrypt_buffer, ptr + 1, buffer_len);
 | 
						|
        iot_grapp_aes_get_key(destmac_to_key, hdr_msdu_pkt->dst_mac,
 | 
						|
            hdr_msdu_pkt->msdusend_seq);
 | 
						|
        iot_crypto_aes_setkey_enc(destmac_to_key, 128);
 | 
						|
        for (i = 0; i < (buffer_len / 16); i++) {
 | 
						|
            iot_crypto_aes_ecb(IOT_AES_DECRYPT, buffer_len,
 | 
						|
                &decrypt_buffer[i*16], &decrypt_buffer[i*16]);
 | 
						|
        }
 | 
						|
        os_mem_cpy(ptr + 1, decrypt_buffer, data_len);
 | 
						|
        hdr_msdu_recv->len -= delta_len;
 | 
						|
        ptr[0] -= delta_len;
 | 
						|
        os_mem_free(decrypt_buffer);
 | 
						|
 | 
						|
        /* returns true if decryption succeeds */
 | 
						|
        for (fn_list = PROTO_FNCODE_MIN;
 | 
						|
            fn_list < PROTO_FNCODE_MAX; fn_list++) {
 | 
						|
            if (ptr[1] == fn_list) {
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
#else
 | 
						|
static uint8_t iot_plctxrx_aes_encrypt(iot_pkt_t *pkt, uint16_t len)
 | 
						|
{
 | 
						|
    (void)pkt;
 | 
						|
    (void)len;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static bool_t iot_plctxrx_aes_decrypt(iot_pkt_t *pkt)
 | 
						|
{
 | 
						|
    (void)pkt;
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
void iot_plctxrx_send_msdu_to_plc(iot_pkt_t *msdu_pkt, prot_pkt_t *prot_pkt,
 | 
						|
    bool_t is_unicast, uint8_t *dst_mac, uint16_t buf_len)
 | 
						|
{
 | 
						|
    uint8_t *ptr = NULL;
 | 
						|
    msdu_pkt_hdr_t *hdr = NULL;
 | 
						|
 | 
						|
    IOT_ASSERT(msdu_pkt);
 | 
						|
 | 
						|
    ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | 
						|
    hdr = (msdu_pkt_hdr_t*)ptr;
 | 
						|
    hdr->msdusend_seq   = prot_pkt->msdu_seq;
 | 
						|
    hdr->recvconf_seq   = 0;
 | 
						|
    if (is_unicast) {
 | 
						|
        hdr->dest_cnt   = 1;
 | 
						|
    } else {
 | 
						|
        hdr->dest_cnt   = 0xFF;
 | 
						|
    }
 | 
						|
    hdr->need_ack       = prot_pkt->txinfo.need_ack;
 | 
						|
    hdr->src_module     = prot_pkt->txinfo.src_module;
 | 
						|
 | 
						|
    iot_mac_addr_cpy(hdr->org_mac, prot_pkt->txinfo.org_mac);
 | 
						|
    iot_mac_addr_cpy(hdr->src_mac, prot_pkt->txinfo.src_mac);
 | 
						|
    iot_mac_addr_cpy(hdr->dst_mac, dst_mac);
 | 
						|
 | 
						|
    ptr += sizeof(msdu_pkt_hdr_t);
 | 
						|
    os_mem_cpy(ptr, prot_pkt->buf, prot_pkt->msdu_data_len);
 | 
						|
 | 
						|
    buf_len += iot_plctxrx_aes_encrypt(msdu_pkt, prot_pkt->msdu_data_len);
 | 
						|
 | 
						|
    iot_pkt_put(msdu_pkt, sizeof(uint8_t)*buf_len);
 | 
						|
    iot_cus_printf("[gltx]unicast=%d, send msduseq:%d len:%d, ack_flag:%d, "
 | 
						|
        "sendcnt:%d\n", is_unicast, prot_pkt->msdu_seq, buf_len,
 | 
						|
        prot_pkt->ack_flag, prot_pkt->send_cnt);
 | 
						|
    iot_cus_printf("[gltx]unicast=%d,send:"
 | 
						|
        "pkt_dest_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
 | 
						|
        is_unicast, dst_mac[0], dst_mac[1], dst_mac[2],
 | 
						|
        dst_mac[3], dst_mac[4], dst_mac[5]);
 | 
						|
    iot_plc_send_msdu(greeapp->app_handle, msdu_pkt);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
  Please note, in plctxrx, sta always send to cco, no matter dest mac is cco
 | 
						|
  or other station. cco will judge handle or forward packet based on dest mac.
 | 
						|
*/
 | 
						|
uint8_t iot_plctxrx_msdu_unicast_send(prot_pkt_t *prot_pkt, uint8_t *dst_mac,
 | 
						|
    protpkt_tx_info_t* txinfo)
 | 
						|
{
 | 
						|
    uint8_t msg_type;
 | 
						|
    uint16_t buflen = 0;
 | 
						|
    iot_pkt_t *msdu_pkt = NULL;
 | 
						|
    uint8_t *destptr = NULL;
 | 
						|
 | 
						|
    buflen = sizeof(msdu_pkt_hdr_t) + prot_pkt->msdu_data_len;
 | 
						|
 | 
						|
    /* check if the device of target destination mac address is online */
 | 
						|
    if (txinfo->force_tx_connless == 0) {
 | 
						|
        if (plctxrx_context.local_state.role == IOT_PLC_DEV_ROLE_CCO) {
 | 
						|
            if (!iot_plctxrx_check_sta_in_nw_by_mac(dst_mac)) {
 | 
						|
                txinfo->force_tx_connless = 1;
 | 
						|
                txinfo->retry_cnt = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (txinfo->force_tx_connless == 0) {
 | 
						|
        /* only first send set bitmap. retry not do this */
 | 
						|
        if (prot_pkt->send_cnt == 0 && txinfo->need_ack == 1) {
 | 
						|
            prot_pkt->ack_flag = 1;
 | 
						|
        } else if (txinfo->need_ack == 0) {
 | 
						|
            prot_pkt->ack_flag = 0;
 | 
						|
        }
 | 
						|
        if (plctxrx_context.nw_role == IOT_PLC_DEV_ROLE_CCO) {
 | 
						|
            destptr = dst_mac;
 | 
						|
        } else {
 | 
						|
            /* STA always send to CCO */
 | 
						|
            destptr = plctxrx_context.local_state.cco_mac;
 | 
						|
        }
 | 
						|
        msg_type = IOT_PLC_MSG_TYPE_UNICAST;
 | 
						|
        msdu_pkt = iot_plc_alloc_msdu(greeapp->app_handle,
 | 
						|
            msg_type, IOT_PLC_ACK_TYPE_NONE, destptr,
 | 
						|
            plctxrx_context.local_state.sta_mac,
 | 
						|
            plctxrx_context.link_id, buflen, IOT_PLC_LOCAL_RETRY_CNT);
 | 
						|
    } else {
 | 
						|
        prot_pkt->ack_flag = 0;
 | 
						|
        txinfo->need_ack = 0;
 | 
						|
        destptr = dst_mac;
 | 
						|
        msg_type = IOT_PLC_MSG_TYPE_CONN_LESS_DATA;
 | 
						|
        msdu_pkt = iot_plc_alloc_conn_less_msdu(greeapp->app_handle,
 | 
						|
            msg_type, destptr, plctxrx_context.local_state.sta_mac,
 | 
						|
            plctxrx_context.link_id, buflen, IOT_PLC_LOCAL_RETRY_CNT);
 | 
						|
    }
 | 
						|
 | 
						|
    iot_plctxrx_send_msdu_to_plc(msdu_pkt, prot_pkt, true, dst_mac, buflen);
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
/* only cco  can send brdcast */
 | 
						|
extern uint8_t ge_bcast_addr[];
 | 
						|
int8_t iot_plctxrx_msdu_brdcast_send(prot_pkt_t *prot_pkt)
 | 
						|
{
 | 
						|
    uint8_t msg_type;
 | 
						|
    uint16_t buflen = 0;
 | 
						|
 | 
						|
    buflen = sizeof(msdu_pkt_hdr_t) + prot_pkt->msdu_data_len;
 | 
						|
 | 
						|
    /* connect packet send */
 | 
						|
    if (prot_pkt->txinfo.force_tx_connless == 0) {
 | 
						|
        iot_pkt_t *msdu_pkt = NULL;
 | 
						|
        msg_type = IOT_PLC_MSG_TYPE_BCAST;
 | 
						|
        msdu_pkt = iot_plc_alloc_msdu(greeapp->app_handle,
 | 
						|
            msg_type, IOT_PLC_ACK_TYPE_NONE,NULL,
 | 
						|
            plctxrx_context.local_state.sta_mac,
 | 
						|
            plctxrx_context.link_id, buflen, 1);
 | 
						|
        IOT_ASSERT(msdu_pkt);
 | 
						|
        iot_plctxrx_send_msdu_to_plc(msdu_pkt, prot_pkt, false,
 | 
						|
            prot_pkt->txinfo.dst_mac, buflen);
 | 
						|
    }
 | 
						|
    /* connless packet send */
 | 
						|
    else {
 | 
						|
        iot_pkt_t *connless_msdu_pkt = NULL;
 | 
						|
        msg_type = IOT_PLC_MSG_TYPE_CONN_LESS_DATA;
 | 
						|
        connless_msdu_pkt = iot_plc_alloc_conn_less_msdu(greeapp->app_handle,
 | 
						|
            msg_type, ge_bcast_addr,
 | 
						|
            plctxrx_context.local_state.sta_mac,
 | 
						|
            plctxrx_context.link_id, buflen, 1);
 | 
						|
        IOT_ASSERT(connless_msdu_pkt);
 | 
						|
        iot_plctxrx_send_msdu_to_plc(connless_msdu_pkt, prot_pkt,
 | 
						|
            false, prot_pkt->txinfo.dst_mac, buflen);
 | 
						|
    }
 | 
						|
 | 
						|
    prot_pkt->send_cnt++;
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t iot_plctxrx_msdu_send(prot_pkt_t* prot_pkt)
 | 
						|
{
 | 
						|
    int8_t ret = ERR_OK;
 | 
						|
    uint32_t send_type = prot_pkt->txinfo.send_type;
 | 
						|
    uint8_t *destptr = NULL;
 | 
						|
    uint8_t i;
 | 
						|
 | 
						|
    if (prot_pkt->send_cnt == 0) {
 | 
						|
        plctxrx_context.pktseq++;
 | 
						|
        if (plctxrx_context.pktseq == 0) {
 | 
						|
            plctxrx_context.pktseq = 1;
 | 
						|
        }
 | 
						|
        prot_pkt->msdu_seq =plctxrx_context.pktseq;
 | 
						|
        iot_cus_printf("[gltx]new seq alloced:%d\n",
 | 
						|
            prot_pkt->msdu_seq);
 | 
						|
    }
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]msdu send:send_type=%d,sta_cnt=%d,need ack=%d,"
 | 
						|
        "send cnt=%d,msdu_data_len=%d\n", send_type, prot_pkt->txinfo.sta_cnt,
 | 
						|
        prot_pkt->txinfo.need_ack, prot_pkt->send_cnt,prot_pkt->msdu_data_len);
 | 
						|
 | 
						|
    if (send_type == PLCTXRX_BORADCAST) {
 | 
						|
        ret = iot_plctxrx_msdu_brdcast_send(prot_pkt);
 | 
						|
        if (ret == ERR_OK) {
 | 
						|
            plctxrx_context.local_state.txrx_status.msdu_sent_brd_cnt++;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        if (prot_pkt->txinfo.sta_cnt == 1) {
 | 
						|
            plctxrx_context.local_state.txrx_status.msdu_sent_uni_cnt++;
 | 
						|
        }
 | 
						|
        for (i = 0; i< prot_pkt->txinfo.sta_cnt; i++) {
 | 
						|
            destptr = prot_pkt->txinfo.dst_mac + i * IOT_MAC_ADDR_LEN;
 | 
						|
            ret = iot_plctxrx_msdu_unicast_send(prot_pkt, destptr,\
 | 
						|
                                                &prot_pkt->txinfo);
 | 
						|
            if (ret != ERR_OK) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        prot_pkt->send_cnt++;
 | 
						|
    }
 | 
						|
    /* if need ack or one more times retry needed,reset the timer */
 | 
						|
    if ((prot_pkt->txinfo.retry_cnt != 0) || ( prot_pkt->txinfo.need_ack)) {
 | 
						|
        if (prot_pkt->txinfo.retry_intvl == 0) {
 | 
						|
            prot_pkt->txinfo.retry_intvl = IOT_PLCXRX_RETRY_INTVAL_DEFAULT;
 | 
						|
        }
 | 
						|
        iot_plctxrx_timer_reset(plctxrx_context.datapath_timer,
 | 
						|
            prot_pkt->txinfo.retry_intvl);
 | 
						|
        iot_cus_printf("[gltx]retrytimer active intvl:%d\n",
 | 
						|
            prot_pkt->txinfo.retry_intvl);
 | 
						|
    } else {
 | 
						|
        iot_plctxrx_timer_reset(plctxrx_context.datapath_timer,
 | 
						|
            IOT_PLCTXRX_RETRY_MIN_INTV);
 | 
						|
        iot_cus_printf("[gltx]retrytimer active for sending "\
 | 
						|
            "whithout retry!\n");
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_msdu_retry_handle(prot_pkt_t* prot_pkt)
 | 
						|
{
 | 
						|
    /* if the revievers need not send back ack, check the retry counter,
 | 
						|
       if the retry count don't equals the required counter, do retry!
 | 
						|
       otherwise, free the buffer, remove the pkt from the queue*/
 | 
						|
 | 
						|
    list_node_t *node = NULL;
 | 
						|
 | 
						|
    iot_cus_printf("[gltx][retry]protpkt seq:%d ackflag:%d sendcnt:%d max:%d "
 | 
						|
        "needack:%d\n", prot_pkt->msdu_seq, prot_pkt->ack_flag,
 | 
						|
        prot_pkt->send_cnt, prot_pkt->txinfo.retry_cnt,
 | 
						|
        prot_pkt->txinfo.need_ack);
 | 
						|
 | 
						|
    if (prot_pkt->txinfo.need_ack == 0) {
 | 
						|
        if (prot_pkt->send_cnt < prot_pkt->txinfo.retry_cnt + 1) {
 | 
						|
            iot_plctxrx_msdu_send(prot_pkt);
 | 
						|
        } else {
 | 
						|
            switch (prot_pkt->txinfo.send_type) {
 | 
						|
            case PLCTXRX_UNICAST:
 | 
						|
                if(plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt){
 | 
						|
                    plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt--;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            case PLCTXRX_BORADCAST:
 | 
						|
                if(plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt){
 | 
						|
                    plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt--;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            default :
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            /* reaching the assigned retry times, free the pkt */
 | 
						|
            node = iot_plctxrx_pkt_dequeue(plctxrx_context.sendq);
 | 
						|
            if (NULL == node) {
 | 
						|
               iot_cus_printf("[gltx]dequeue failed!\n");
 | 
						|
               return;
 | 
						|
            }
 | 
						|
 | 
						|
            iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, node);
 | 
						|
            /* send the next pkt in queue*/
 | 
						|
            iot_cus_printf("[gltx]retryout pkt. now sendq:%d freeq:%d\n",
 | 
						|
                plctxrx_context.sendq->depth,
 | 
						|
                plctxrx_context.freeq->depth);
 | 
						|
            if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
 | 
						|
                prot_pkt = (prot_pkt_t*)plctxrx_context.sendq->list_head;
 | 
						|
                iot_plctxrx_msdu_send(prot_pkt);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        if ((prot_pkt->ack_flag != 0) &&
 | 
						|
            (prot_pkt->send_cnt < prot_pkt->txinfo.retry_cnt + 1)) {
 | 
						|
            iot_plctxrx_msdu_send(prot_pkt);
 | 
						|
        } else {
 | 
						|
            switch (prot_pkt->txinfo.send_type) {
 | 
						|
            case PLCTXRX_UNICAST:
 | 
						|
                if(plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt){
 | 
						|
                    plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt--;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            case PLCTXRX_BORADCAST:
 | 
						|
                if(plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt){
 | 
						|
                    plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt--;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            default :
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            node = iot_plctxrx_pkt_dequeue(plctxrx_context.sendq);
 | 
						|
            if (node == NULL) {
 | 
						|
               iot_cus_printf("[gltx]dequeue failed!\n");
 | 
						|
               return;
 | 
						|
            }
 | 
						|
 | 
						|
            iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, node);
 | 
						|
            plctxrx_context.local_state.txrx_status.msdu_lost_pkt_cnt++;
 | 
						|
            iot_cus_printf("[gltx]retryout pkt forced free,"
 | 
						|
                "sendq:%d freeq:%d total lost:%d\n",
 | 
						|
                plctxrx_context.sendq->depth, plctxrx_context.freeq->depth,
 | 
						|
                plctxrx_context.local_state.txrx_status.msdu_lost_pkt_cnt);
 | 
						|
 | 
						|
            /* send the next pkt in queue*/
 | 
						|
            if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
 | 
						|
                prot_pkt = (prot_pkt_t*)plctxrx_context.sendq->list_head;
 | 
						|
                iot_plctxrx_msdu_send(prot_pkt);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void iot_plctxrx_msdu_ack_handle(iot_pkt_t* pkt)
 | 
						|
{
 | 
						|
    msdu_pkt_hdr_t* pkthdr = NULL;
 | 
						|
    uint8_t *ptr;
 | 
						|
    prot_pkt_t *prot_pkt;
 | 
						|
    list_node_t *node = NULL;
 | 
						|
 | 
						|
    iot_plc_msdu_recv_t *msdu =
 | 
						|
        (iot_plc_msdu_recv_t*)(iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA));
 | 
						|
 | 
						|
    ptr = msdu->data;
 | 
						|
    pkthdr = (msdu_pkt_hdr_t*)ptr;
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]pkt[%d]'s ack received\n",
 | 
						|
        pkthdr->recvconf_seq);
 | 
						|
 | 
						|
    prot_pkt = (prot_pkt_t*)plctxrx_context.sendq->list_head;
 | 
						|
 | 
						|
    if (prot_pkt == NULL) {
 | 
						|
       iot_cus_printf("[gltx] no pkt in sendq\n");
 | 
						|
       goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    if (pkthdr->recvconf_seq != prot_pkt->msdu_seq) {
 | 
						|
        iot_cus_printf("[gltx] ackseq mismatch%d vs %d\n",
 | 
						|
           pkthdr->recvconf_seq, prot_pkt->msdu_seq);
 | 
						|
       goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!iot_mac_addr_cmp(msdu->dst, plctxrx_context.local_state.sta_mac)) {
 | 
						|
        iot_cus_printf("[gltx]dest not for sta\n");
 | 
						|
       goto out;
 | 
						|
    } else {
 | 
						|
        /* once the msdu's dst mac matches with the local mac, clear up the
 | 
						|
         * ack flag to stop sending retry.
 | 
						|
         */
 | 
						|
        prot_pkt->ack_flag = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]ackflag:%x\n", prot_pkt->ack_flag);
 | 
						|
    if (prot_pkt->ack_flag == 0) {
 | 
						|
        iot_cus_printf("[gltx]send done.\n");
 | 
						|
        switch (prot_pkt->txinfo.send_type) {
 | 
						|
        case PLCTXRX_UNICAST:
 | 
						|
            if (plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt) {
 | 
						|
                plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt--;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        case PLCTXRX_BORADCAST:
 | 
						|
            if (plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt){
 | 
						|
                plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt--;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        default :
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        /* delete the first node in sendq */
 | 
						|
        if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
 | 
						|
            node = iot_plctxrx_pkt_dequeue(plctxrx_context.sendq);
 | 
						|
            if (node == NULL) {
 | 
						|
                iot_cus_printf("[gltx]msdu_ack:dequeue failed!\n");
 | 
						|
                iot_pkt_free(pkt);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, node);
 | 
						|
            iot_cus_printf("[gltx]sendq:%d freeq:%d,addr:%x\n",
 | 
						|
                plctxrx_context.sendq->depth, plctxrx_context.freeq->depth,
 | 
						|
                node);
 | 
						|
        }
 | 
						|
 | 
						|
        /* send the next pkt in queue*/
 | 
						|
        if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
 | 
						|
            prot_pkt = (prot_pkt_t*)plctxrx_context.sendq->list_head;
 | 
						|
            iot_plctxrx_msdu_send(prot_pkt);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 out:
 | 
						|
    iot_pkt_free(pkt);
 | 
						|
}
 | 
						|
 | 
						|
/* based on msdu data buffer, filter out each gree frame, tag head and end
 | 
						|
   with one list chain. then, reprot to upper layer. after finsed call,
 | 
						|
   msdu buffer freed.
 | 
						|
*/
 | 
						|
uint8_t iot_plctxrx_msdu_split_frame_to_propkt(iot_pkt_t *msdu_pkt,
 | 
						|
    uint8_t rx_type)
 | 
						|
{
 | 
						|
    uint16_t total_len;
 | 
						|
    uint8_t *ptr;
 | 
						|
    uint16_t frm_len;
 | 
						|
    uint16_t i;
 | 
						|
    uint8_t ret = ERR_FAIL;
 | 
						|
    list_node_t *node = NULL;
 | 
						|
    protpkt_list_t rpt_list = {NULL, 0, 0};
 | 
						|
    plctxrx_rx_data_info_t rx_info = { 0 };
 | 
						|
 | 
						|
    node = iot_mem_pool_alloc(list_mem_pool);
 | 
						|
    if (node == NULL) {
 | 
						|
        iot_cus_printf("[gltx]list mem_pool alloc failed!\n");
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    rpt_list.list_head = node;
 | 
						|
    rpt_list.frame_cnt = 0;
 | 
						|
    rpt_list.total_len = 0;
 | 
						|
 | 
						|
    iot_plc_msdu_recv_t *msdu =
 | 
						|
        (iot_plc_msdu_recv_t*)(iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_DATA));
 | 
						|
    ptr = msdu->data + sizeof(msdu_pkt_hdr_t);
 | 
						|
    total_len = msdu->len - sizeof(msdu_pkt_hdr_t);
 | 
						|
    iot_cus_printf("[gltx]recv msdu len:%d\n",total_len);
 | 
						|
 | 
						|
    IOT_ASSERT(total_len);
 | 
						|
 | 
						|
    iot_mac_addr_cpy(rx_info.mac, msdu->src);
 | 
						|
    rx_info.rx_type = rx_type;
 | 
						|
 | 
						|
    for (i = 0; i < total_len;) {
 | 
						|
        frm_len = iot_proto_get_plc_data_len(ptr + i, total_len - i);
 | 
						|
        if (frm_len == 0) {
 | 
						|
            iot_cus_printf("[gltx][err]frm_len err\n");
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        iot_cus_printf("[gltx]fn:0x%x, frm_len=%d\n",*(ptr + i + 1), frm_len);
 | 
						|
        node->len = frm_len;
 | 
						|
        node->next = NULL;
 | 
						|
        node->data = ptr + i;
 | 
						|
        i += frm_len;
 | 
						|
 | 
						|
        rpt_list.frame_cnt++;
 | 
						|
        rpt_list.total_len += frm_len;
 | 
						|
        if (i< total_len) {
 | 
						|
            node->next = iot_mem_pool_alloc(list_mem_pool);
 | 
						|
            if(node->next == NULL) {
 | 
						|
                iot_cus_printf("[gltx][err]list mem_pool alloc failed\n");
 | 
						|
                goto out;
 | 
						|
            }
 | 
						|
            node = node->next;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    iot_cus_printf("[gltx] frame cnt:%d, total len:%d\n",
 | 
						|
        rpt_list.frame_cnt,rpt_list.total_len);
 | 
						|
 | 
						|
    plctxrx_context.local_state.txrx_status.fram_report_cnt +=
 | 
						|
        rpt_list.frame_cnt;
 | 
						|
 | 
						|
    if (greeapp->uart_mode == GR_MCU_OP_MODE) {
 | 
						|
        ret = plctxrx_context.gree_cb.gree_proto_recv_cb(&rpt_list, &rx_info);
 | 
						|
    } else {
 | 
						|
        ret = plctxrx_context.dev_test_cb.dev_test_recv_cb(&rpt_list, &rx_info);
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    if (rpt_list.list_head != NULL) {
 | 
						|
        iot_plctxrx_list_free(&rpt_list);
 | 
						|
    }
 | 
						|
    iot_pkt_free(msdu_pkt);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t iot_plctxrx_msdu_frame_to_at(iot_pkt_t *msdu_pkt )
 | 
						|
{
 | 
						|
#if INCLUDE_AT_COMMAND_MODULE
 | 
						|
    uint8_t *p_data;
 | 
						|
    iot_pkt_t *p_pkt;
 | 
						|
    uint16_t pkt_len, data_len, total_len;
 | 
						|
    iot_plc_msdu_recv_t *p_plcmsdu;
 | 
						|
    plctxrx_cmd_resp_t *p_resp;
 | 
						|
    msdu_pkt_hdr_t *p_txrxmsduhr;
 | 
						|
    plctxrx_handle_recv_t *p_recv;
 | 
						|
 | 
						|
    /* pkt format */
 | 
						|
    /* plcmsdu_hdr + txrxmsdu_hdr + at_hdr + at_hdr... */
 | 
						|
 | 
						|
    if (NULL == msdu_pkt) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    p_plcmsdu = (iot_plc_msdu_recv_t *)iot_pkt_data(msdu_pkt);
 | 
						|
 | 
						|
    p_txrxmsduhr = (msdu_pkt_hdr_t *)p_plcmsdu->data;
 | 
						|
 | 
						|
    /* all aggr data length */
 | 
						|
    total_len = p_plcmsdu->len - sizeof(msdu_pkt_hdr_t);
 | 
						|
 | 
						|
    p_data =(uint8_t*)(p_txrxmsduhr + 1);
 | 
						|
 | 
						|
    while (total_len > 0) {
 | 
						|
        /* p_data include at_payload_t */
 | 
						|
        data_len = (uint16_t)((p_data[1] << 8) | p_data[0]);
 | 
						|
 | 
						|
        data_len = data_len > total_len ? total_len : data_len;
 | 
						|
 | 
						|
        pkt_len = sizeof(plctxrx_cmd_resp_t) + sizeof(plctxrx_handle_recv_t) +
 | 
						|
            data_len;
 | 
						|
 | 
						|
        if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID))) {
 | 
						|
            iot_pkt_free(msdu_pkt);
 | 
						|
            return ERR_FAIL;
 | 
						|
        }
 | 
						|
 | 
						|
        p_resp = (plctxrx_cmd_resp_t *)iot_pkt_put(p_pkt, pkt_len);
 | 
						|
        p_recv = (plctxrx_handle_recv_t *)p_resp->data;
 | 
						|
 | 
						|
        iot_mac_addr_cpy(p_recv->rxinfo.mac,p_txrxmsduhr->org_mac);
 | 
						|
        os_mem_cpy(p_recv->data, p_data, data_len);
 | 
						|
        p_recv->dlen =(uint8_t)data_len;
 | 
						|
 | 
						|
        p_resp->dlen = (uint16_t)(data_len + sizeof(plctxrx_handle_recv_t));
 | 
						|
        p_resp->cid.cid = PLCTXRX_CID_SEND;
 | 
						|
        p_resp->cid.opcode = PLCTXRX_OP_RECEIVE;
 | 
						|
        p_resp->index.current = 1;
 | 
						|
        p_resp->index.total = 1;
 | 
						|
        p_resp->resp = PLCTXRX_RESP_OK;
 | 
						|
 | 
						|
        iot_cus_printf("iot_plctxrx_msdu_frame_to_at from "\
 | 
						|
            "%02x:%02x:%02x:%02x:%02x:%02x:",
 | 
						|
            p_txrxmsduhr->org_mac[0], p_txrxmsduhr->org_mac[1],
 | 
						|
            p_txrxmsduhr->org_mac[2], p_txrxmsduhr->org_mac[3],
 | 
						|
            p_txrxmsduhr->org_mac[4], p_txrxmsduhr->org_mac[5]);
 | 
						|
        iot_cus_printf("total_len:%d datalen:%d", total_len, data_len);
 | 
						|
 | 
						|
        iot_common_bin_dump(p_recv->data, p_recv->dlen);
 | 
						|
 | 
						|
        plctxrx_context.at_cb.at_cmd_resp_cb(p_pkt);
 | 
						|
 | 
						|
        /* move to next  */
 | 
						|
        p_data += data_len;
 | 
						|
        total_len -= data_len;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    iot_pkt_free(msdu_pkt);
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
/* function to dump txrx statistic information */
 | 
						|
void iot_plctxrx_infor_print(void)
 | 
						|
{
 | 
						|
#if 1
 | 
						|
    plc_txrx_statics_t *txrx_infor = &plctxrx_context.local_state.txrx_status;
 | 
						|
    iot_cus_printf("[gltx] receive msdu:%d send frame:%d, "
 | 
						|
    "drop fram:%d report frame:%d send uni:%d remain uni:%d"
 | 
						|
    "send brd:%d remain brd:%d lost msdu:%d\n",
 | 
						|
    txrx_infor->msdu_receivd_cnt, txrx_infor->fram_send_cnt,
 | 
						|
    txrx_infor->fram_send_drop_cnt, txrx_infor->fram_report_cnt,
 | 
						|
    txrx_infor->msdu_sent_uni_cnt, txrx_infor->msdu_remain_uni_cnt,
 | 
						|
    txrx_infor->msdu_sent_brd_cnt, txrx_infor->msdu_remain_brd_cnt,
 | 
						|
    txrx_infor->msdu_lost_pkt_cnt);
 | 
						|
 | 
						|
//    iot_cus_printf("[gltx]received proto frame:%d frm_total_len:%d\n",
 | 
						|
//        g_gree_frm_cnt, g_gree_frm_total_len);
 | 
						|
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_handle_timer_msg(plctxrx_task_msg_t* task_msg)
 | 
						|
{
 | 
						|
    switch (task_msg->msg.id) {
 | 
						|
    case IOT_PLCTXRX_TIMER_DATA_PATH:
 | 
						|
    {
 | 
						|
        if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
 | 
						|
            prot_pkt_t *prot_pkt =
 | 
						|
                (prot_pkt_t *)plctxrx_context.sendq->list_head;
 | 
						|
            iot_plctxrx_msdu_retry_handle(prot_pkt);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_TIMER_TXRX_PATH:
 | 
						|
    {
 | 
						|
        plctxrx_context.txrx_tm_cnt++;
 | 
						|
        if (plctxrx_context.txrx_tm_cnt >= IOT_PLCTXRX_STASTIC_PRINT_INTVL_CNT) {
 | 
						|
            iot_plctxrx_infor_print();
 | 
						|
            plctxrx_context.txrx_tm_cnt = 0;
 | 
						|
        }
 | 
						|
 | 
						|
        if (plctxrx_context.nw_role == IOT_PLC_DEV_ROLE_STA &&
 | 
						|
            0 == plctxrx_context.txrx_tm_cnt % IOT_PLC_SINGAL_LED_SHOW_INTVAL_CNT) {
 | 
						|
            if (plctxrx_context.u_snr >= IOT_SNR_STRONG_MIN_THR) {
 | 
						|
                iot_plc_led_request(IOT_PLC_LED_SIGNAL_STRONG);
 | 
						|
            } else if (plctxrx_context.u_snr >= IOT_SNR_GOOD_MIN_THR)  {
 | 
						|
                iot_plc_led_request(IOT_PLC_LED_SIGNAL_GOOD);
 | 
						|
            } else {
 | 
						|
                iot_plc_led_request(IOT_PLC_LED_SIGNAL_WEAK);
 | 
						|
            }
 | 
						|
            iot_plc_query_dev_info(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT);
 | 
						|
        }
 | 
						|
 | 
						|
        iot_plctxrx_conn_less_buf_refresh();
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_TIMER_AGGR_PATH:
 | 
						|
    {
 | 
						|
        iot_plctxrx_push_aggred_pkt_to_sendq(plctxrx_context.sendq);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_timer_data_path_func(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)timer_id;
 | 
						|
    (void)arg;
 | 
						|
    iot_cus_printf("[gltx]data retry timer fired\n");
 | 
						|
    iot_plctxrx_post_msg(
 | 
						|
        IOT_PLCTXRX_TIMER_MSG, IOT_PLCTXRX_TIMER_DATA_PATH, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
/* txrx statstic timer */
 | 
						|
void iot_plctxrx_timer_txrx_path_func(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)timer_id;
 | 
						|
    (void)arg;
 | 
						|
    iot_cus_printf("[gltx]statistic timer fired\n");
 | 
						|
    iot_plctxrx_post_msg(
 | 
						|
        IOT_PLCTXRX_TIMER_MSG, IOT_PLCTXRX_TIMER_TXRX_PATH, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
/* aggr time out handler */
 | 
						|
void iot_plctxrx_timer_aggr_path_func(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)timer_id;
 | 
						|
    (void)arg;
 | 
						|
    iot_cus_printf("[gltx]aggr timer fired\n");
 | 
						|
    iot_plctxrx_post_msg(
 | 
						|
        IOT_PLCTXRX_TIMER_MSG, IOT_PLCTXRX_TIMER_AGGR_PATH, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
prot_pkt_t* iot_plctxrx_do_aggr(prot_pkt_t* pkt)
 | 
						|
{
 | 
						|
    prot_pkt_t* aggrpkt = plctxrx_context.aggrpkt;
 | 
						|
 | 
						|
    if (!pkt) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    /* no aggr packet,send it directly */
 | 
						|
    if (pkt->txinfo.force_noaggr == 1) {
 | 
						|
        prot_pkt_t *send_pkt = NULL;
 | 
						|
        pkt->send_cnt = 0;
 | 
						|
        /* in send queue, push backend */
 | 
						|
        iot_plctxrx_pkt_enqueue(plctxrx_context.sendq, (list_node_t*)pkt);
 | 
						|
        switch (pkt->txinfo.send_type) {
 | 
						|
        case PLCTXRX_UNICAST:
 | 
						|
            plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt++;
 | 
						|
            break;
 | 
						|
        case PLCTXRX_BORADCAST:
 | 
						|
            plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt++;
 | 
						|
            break;
 | 
						|
        default :
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        /* get front of sendq. note: may not the aggr pkt in queue upper */
 | 
						|
        send_pkt = (prot_pkt_t *)plctxrx_context.sendq->list_head;
 | 
						|
        if (!send_pkt) {
 | 
						|
            return NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        iot_cus_printf("[gltx]pushed into the queue "
 | 
						|
            "sendq:%d, freeq:%d, sendpkt:0x%x sendcnt:%d\n",
 | 
						|
            plctxrx_context.sendq->depth, plctxrx_context.freeq->depth, send_pkt,
 | 
						|
            send_pkt->send_cnt);
 | 
						|
 | 
						|
        /* if first send, trigger send */
 | 
						|
        if (send_pkt->send_cnt == 0) {
 | 
						|
            iot_plctxrx_msdu_send(send_pkt);
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        uint8_t* pdata = NULL;
 | 
						|
 | 
						|
        if (!aggrpkt) {
 | 
						|
            iot_cus_printf("[gltx][aggrcheck]no pending,add candidate:%x\n", pkt);
 | 
						|
            plctxrx_context.aggrpkt = pkt;
 | 
						|
            iot_plctxrx_timer_reset(plctxrx_context.aggr_timer,
 | 
						|
                IOT_PLCTXRX_AGGR_TIMER_INTVAL);
 | 
						|
            return NULL;
 | 
						|
        }
 | 
						|
        /* do aggr if possible. */
 | 
						|
        if (iot_plctxrx_aggr_frame_condition_check(pkt, aggrpkt) == ERR_OK) {
 | 
						|
            pdata = aggrpkt->buf + aggrpkt->msdu_data_len;
 | 
						|
            os_mem_cpy(pdata, pkt->buf, pkt->msdu_data_len);
 | 
						|
            aggrpkt->msdu_data_len += pkt->msdu_data_len;
 | 
						|
            /* if the condition is satisfied, reset the aggr timer */
 | 
						|
            iot_plctxrx_timer_reset(plctxrx_context.aggr_timer,
 | 
						|
                IOT_PLCTXRX_AGGR_TIMER_INTVAL);
 | 
						|
            /* free the aggrpkt into freeq */
 | 
						|
            iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, (list_node_t*)pkt);
 | 
						|
            return NULL;
 | 
						|
        } else {
 | 
						|
            /* if aggr condiction is not satisfied push the previous pkt into the queue*/
 | 
						|
            iot_plctxrx_push_aggred_pkt_to_sendq(plctxrx_context.sendq);
 | 
						|
            /* set the aggrpkt pointer with the new pkt*/
 | 
						|
            plctxrx_context.aggrpkt = pkt;
 | 
						|
            iot_cus_printf("[gltx][aggrcheck]aggred msdu data len:%d\n",
 | 
						|
                plctxrx_context.aggrpkt->msdu_data_len);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return aggrpkt;
 | 
						|
}
 | 
						|
 | 
						|
int8_t iot_plctxrx_get_node_level(uint8_t *mac)
 | 
						|
{
 | 
						|
    int8_t level = -1;
 | 
						|
    uint16_t indx = 0;
 | 
						|
 | 
						|
    /* first check STA is existed. */
 | 
						|
    for (indx = 0; indx < STA_DEV_MAX; indx++) {
 | 
						|
        if (iot_mac_addr_cmp(plctxrx_context.sta[indx].sta_mac, mac)) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (indx >= STA_DEV_MAX) {
 | 
						|
        iot_cus_printf("[gltx]no mac existed\n");
 | 
						|
    } else {
 | 
						|
        level = plctxrx_context.sta[indx].level;
 | 
						|
    }
 | 
						|
 | 
						|
    return level;
 | 
						|
}
 | 
						|
 | 
						|
bool_t iot_plctxrx_add_sta(plcsta_info_t* stainfo)
 | 
						|
{
 | 
						|
    uint16_t indx = 0;
 | 
						|
    plcsta_info_t* psta = NULL;
 | 
						|
    bool_t  duplicate_flag = false;
 | 
						|
 | 
						|
    /* first check if the new joined STA is existed. */
 | 
						|
    for (indx = 0; indx < STA_DEV_MAX; indx++) {
 | 
						|
        if (iot_mac_addr_cmp(plctxrx_context.sta[indx].sta_mac,
 | 
						|
                stainfo->sta_mac)) {
 | 
						|
            duplicate_flag = true;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    /**
 | 
						|
     * if duplicate_flag is false,it means
 | 
						|
     * we have not found duplicated STA.
 | 
						|
     */
 | 
						|
    if (!duplicate_flag) {
 | 
						|
        /* find a empty place to insert new joined STA. */
 | 
						|
        for (indx = 0; indx < STA_DEV_MAX; indx++) {
 | 
						|
            if (plctxrx_context.sta[indx].valid == 0) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (indx >= STA_DEV_MAX) {
 | 
						|
        iot_cus_printf("[gltx]no free sta slot indx:%d or dupmac\n", indx);
 | 
						|
    } else {
 | 
						|
        psta  = &plctxrx_context.sta[indx];
 | 
						|
        *psta = *stainfo;
 | 
						|
        psta->valid = 1;
 | 
						|
        if (!duplicate_flag) {
 | 
						|
            plctxrx_context.cur_stanum++;
 | 
						|
        } else {
 | 
						|
            iot_cus_printf("[gltx]duplicated cur_sta:%d,"
 | 
						|
                "mac-%02X:%02X:%02X:%02X:%02X:%02X\n",
 | 
						|
                plctxrx_context.cur_stanum, stainfo->sta_mac[0],
 | 
						|
                stainfo->sta_mac[1], stainfo->sta_mac[2], stainfo->sta_mac[3],
 | 
						|
                stainfo->sta_mac[4], stainfo->sta_mac[5]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]addsta cur_sta:%d\n", plctxrx_context.cur_stanum);
 | 
						|
    return duplicate_flag;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t iot_plctxrx_del_sta_by_mac(uint8_t* mac)
 | 
						|
{
 | 
						|
   uint8_t ret = ERR_OK;
 | 
						|
   uint16_t indx = 0;
 | 
						|
   plcsta_info_t* psta = NULL;
 | 
						|
 | 
						|
   for (indx = 0; indx < STA_DEV_MAX; indx++) {
 | 
						|
      psta = &plctxrx_context.sta[indx];
 | 
						|
      if (plctxrx_context.sta[indx].valid == 1) {
 | 
						|
        if (iot_mac_addr_cmp(psta->sta_mac, mac)) {
 | 
						|
           break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if (indx >= STA_DEV_MAX) {
 | 
						|
      ret = ERR_FAIL;
 | 
						|
      iot_cus_printf("[gltx]delsta no slot find\n");
 | 
						|
   } else {
 | 
						|
      os_mem_set(psta, 0, sizeof(plcsta_info_t));
 | 
						|
      plctxrx_context.cur_stanum--;
 | 
						|
   }
 | 
						|
 | 
						|
   iot_cus_printf("[gltx]delsta cur_sta:%d\n", plctxrx_context.cur_stanum);
 | 
						|
   return ret;
 | 
						|
}
 | 
						|
 | 
						|
bool_t iot_plctxrx_check_sta_in_nw_by_mac(uint8_t* mac)
 | 
						|
{
 | 
						|
   bool_t ret = false;
 | 
						|
   uint16_t indx = 0;
 | 
						|
   plcsta_info_t* psta = NULL;
 | 
						|
 | 
						|
   for (indx = 0; indx < STA_DEV_MAX; indx++) {
 | 
						|
      psta = &plctxrx_context.sta[indx];
 | 
						|
      if (plctxrx_context.sta[indx].valid == 1) {
 | 
						|
        if (iot_mac_addr_cmp(psta->sta_mac, mac)) {
 | 
						|
           break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if (indx >= STA_DEV_MAX) {
 | 
						|
      iot_cus_printf("[gltx]delsta no slot find\n");
 | 
						|
   } else {
 | 
						|
       ret = true;
 | 
						|
   }
 | 
						|
 | 
						|
   return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
uint8_t iot_plctxrx_del_sta_by_tei(uint16_t deltei)
 | 
						|
{
 | 
						|
    uint8_t ret = ERR_OK;
 | 
						|
    uint16_t indx = 0;
 | 
						|
    plcsta_info_t* psta = NULL;
 | 
						|
 | 
						|
    for (indx = 0; indx < STA_DEV_MAX; indx++) {
 | 
						|
        psta = &plctxrx_context.sta[indx];
 | 
						|
        if (plctxrx_context.sta[indx].valid == 1 &&
 | 
						|
            psta->sta_tei == deltei) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (indx >= STA_DEV_MAX) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        iot_cus_printf("[gltx]delsta no slot find\n");
 | 
						|
    } else {
 | 
						|
        os_mem_set(psta, 0, sizeof(plcsta_info_t));
 | 
						|
        plctxrx_context.cur_stanum--;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]delsta cur_sta:%d\n", plctxrx_context.cur_stanum);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_plctxrx_node_info_rpt() - report node infomation to upper layer
 | 
						|
 * @param node          node infomation v0 report from cvg
 | 
						|
 * @param total_count   node infomation total count need report
 | 
						|
 * @param count         node information count this time
 | 
						|
 * @param done          report done flag
 | 
						|
 * @retval:             report to upper layer success or not
 | 
						|
 */
 | 
						|
bool_t iot_plctxrx_node_info_rpt(iot_plc_node_info_v0_t *node,
 | 
						|
    uint16_t total_count, uint16_t count, uint8_t done)
 | 
						|
{
 | 
						|
    uint16_t i;
 | 
						|
    uint16_t last_tei;
 | 
						|
    uint16_t data_len = 0;
 | 
						|
    plctxrx_cmd_resp_t *cmd_resp;
 | 
						|
    iot_pkt_t *pkt;
 | 
						|
    node_info_v1_t *node_info_v1;
 | 
						|
    node_info_v2_t *node_info_v2;
 | 
						|
    node_info_v3_t *node_info_v3;
 | 
						|
    node_info_v4_t *node_info_v4;
 | 
						|
    node_info_v5_t *node_info_v5;
 | 
						|
 | 
						|
    iot_cus_printf("[txrx]node type=v%d reply:t_count=%d cur_cnt=%d\n",
 | 
						|
        plctxrx_context.node_info_type, total_count, count);
 | 
						|
 | 
						|
    switch (plctxrx_context.node_info_type) {
 | 
						|
    case NODE_INFO_TYPE_V1:
 | 
						|
        data_len = sizeof(node_info_v1_t) * count;
 | 
						|
        break;
 | 
						|
    case NODE_INFO_TYPE_V2:
 | 
						|
        data_len = sizeof(node_info_v2_t) * count;
 | 
						|
        break;
 | 
						|
    case NODE_INFO_TYPE_V3:
 | 
						|
        data_len = sizeof(node_info_v3_t) * count;
 | 
						|
        break;
 | 
						|
    case NODE_INFO_TYPE_V4:
 | 
						|
        data_len = sizeof(node_info_v4_t) * count;
 | 
						|
        break;
 | 
						|
    case NODE_INFO_TYPE_V5:
 | 
						|
        data_len = sizeof(node_info_v5_t) * count;
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        iot_cus_printf("[txrx] node_info_rpt error[%d]\n",
 | 
						|
            plctxrx_context.node_info_type);
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    pkt = iot_pkt_alloc(sizeof(plctxrx_cmd_resp_t) + data_len,
 | 
						|
        IOT_GREE_APP_MID);
 | 
						|
    if (NULL == pkt) {
 | 
						|
        iot_cus_printf("[txrx] alloc pkt error\n");
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(pkt);
 | 
						|
    iot_pkt_put(pkt, sizeof(plctxrx_cmd_resp_t) + data_len);
 | 
						|
 | 
						|
    /* use low byte reserved field save type and report to uplayer,
 | 
						|
     * high byte still reserved
 | 
						|
     */
 | 
						|
    cmd_resp->resv = plctxrx_context.node_info_type;
 | 
						|
    cmd_resp->done = done;
 | 
						|
    cmd_resp->cid.cid = PLCTXRX_CID_NODE_INFO;
 | 
						|
    cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
 | 
						|
    cmd_resp->resp = PLCTXRX_RESP_OK;
 | 
						|
    cmd_resp->index.current = count;
 | 
						|
    cmd_resp->index.total = total_count;
 | 
						|
    cmd_resp->dlen = data_len;
 | 
						|
 | 
						|
    switch (plctxrx_context.node_info_type) {
 | 
						|
    case NODE_INFO_TYPE_V1:
 | 
						|
    {
 | 
						|
        node_info_v1 = (node_info_v1_t *)(cmd_resp->data);
 | 
						|
        for (i = 0; i < count; i++) {
 | 
						|
            (node_info_v1+i)->sta_tei = (node+i)->sta_tei;
 | 
						|
            (node_info_v1+i)->proxy_tei = (node+i)->proxy_tei;
 | 
						|
            iot_mac_addr_cpy((node_info_v1+i)->mac, (node+i)->addr);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case NODE_INFO_TYPE_V2:
 | 
						|
    {
 | 
						|
        node_info_v2 = (node_info_v2_t *)(cmd_resp->data);
 | 
						|
        for (i = 0; i < count; i++) {
 | 
						|
            (node_info_v2+i)->snr = (node+i)->ul_snr;
 | 
						|
            (node_info_v2+i)->dev_type = (node+i)->dev_type;
 | 
						|
            (node_info_v2+i)->dl_tf_sr = (node+i)->dl_tf_sr;
 | 
						|
            (node_info_v2+i)->ul_tf_sr = (node+i)->ul_tf_sr;
 | 
						|
            (node_info_v2+i)->vendor = (node+i)->vendor;
 | 
						|
            (node_info_v2+i)->build_ver = (node+i)->build_ver;
 | 
						|
            iot_mac_addr_cpy((node_info_v2+i)->mac, (node+i)->addr);
 | 
						|
            iot_cus_printf("mac:%02X:%02X:%02X:%02X:%02X:%02X build_ver:%X\n",
 | 
						|
                (node+i)->addr[0], (node+i)->addr[1], (node+i)->addr[2],
 | 
						|
                (node+i)->addr[3], (node+i)->addr[4], (node+i)->addr[5],
 | 
						|
                (node+i)->build_ver);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case NODE_INFO_TYPE_V3:
 | 
						|
    {
 | 
						|
        node_info_v3 = (node_info_v3_t *)(cmd_resp->data);
 | 
						|
        for (i = 0; i < count; i++) {
 | 
						|
            (node_info_v3+i)->assoc_rx_cnt = (node+i)->assoc_rx_cnt;
 | 
						|
            (node_info_v3+i)->proxy_chg_rx_cnt = (node+i)->proxy_chg_rx_cnt;
 | 
						|
            (node_info_v3+i)->proxy_chg_accept_cnt =
 | 
						|
                (node+i)->proxy_chg_accept_cnt;
 | 
						|
            iot_mac_addr_cpy((node_info_v3+i)->mac, (node+i)->addr);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case NODE_INFO_TYPE_V4:
 | 
						|
    {
 | 
						|
        node_info_v4 = (node_info_v4_t *)(cmd_resp->data);
 | 
						|
        for (i = 0; i < count; i++) {
 | 
						|
            (node_info_v4+i)->inactive_time = (node+i)->inactive_time;
 | 
						|
            (node_info_v4+i)->in_network_time = (node+i)->in_network_time;
 | 
						|
            iot_mac_addr_cpy((node_info_v4+i)->mac, (node+i)->addr);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case NODE_INFO_TYPE_V5:
 | 
						|
    {
 | 
						|
        node_info_v5 = (node_info_v5_t *)(cmd_resp->data);
 | 
						|
        for (i = 0; i < count; i++) {
 | 
						|
            (node_info_v5+i)->last_assoc_rx_time = (node+i)->last_assoc_rx_time;
 | 
						|
            (node_info_v5+i)->last_proxy_chg_time =
 | 
						|
                (node+i)->last_proxy_chg_time;
 | 
						|
            iot_mac_addr_cpy((node_info_v5+i)->mac, (node+i)->addr);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        iot_pkt_free(pkt);
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    plctxrx_cmd_resp_data_pkt(done, PLCTXRX_OP_RESPONSE, pkt);
 | 
						|
    /* not report done */
 | 
						|
    if (!done) {
 | 
						|
        last_tei = node[count - 1].sta_tei;
 | 
						|
        /* query node info use query topo v0 */
 | 
						|
        iot_plc_query_nw_topo(greeapp->app_handle,
 | 
						|
            IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
 | 
						|
            IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0,
 | 
						|
            IOT_PLC_QUERY_TOPO_START_AS_TEI, last_tei + 1,
 | 
						|
            QUERY_NODE_INFO_MAX_CNT_ONCE);
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_plctxrx_topo_info_rpt() - report topo infomation to upper layer
 | 
						|
 * @param node          node infomation v1 report from cvg
 | 
						|
 * @param total_count   node infomation total count need report
 | 
						|
 * @param count         node information count this time
 | 
						|
 * @param done          report done flag
 | 
						|
 * @retval:             report to upper layer success or not
 | 
						|
 */
 | 
						|
bool_t iot_plctxrx_topo_info_rpt(iot_plc_node_info_v1_t *node,
 | 
						|
    uint16_t total_count, uint16_t count, uint8_t done)
 | 
						|
{
 | 
						|
    uint16_t i;
 | 
						|
    uint16_t last_tei;
 | 
						|
    uint16_t data_len = 0;
 | 
						|
    plctxrx_cmd_resp_t *cmd_resp;
 | 
						|
    iot_pkt_t *pkt;
 | 
						|
    plctxrx_handle_topo_t *topo_data;
 | 
						|
 | 
						|
    data_len = sizeof(plctxrx_handle_topo_t) +
 | 
						|
        sizeof(plctxrx_cmd_topo_t) * count;
 | 
						|
    pkt = iot_pkt_alloc(data_len + sizeof(plctxrx_cmd_resp_t),
 | 
						|
        IOT_GREE_APP_MID);
 | 
						|
 | 
						|
    if (!pkt) {
 | 
						|
        iot_cus_printf("[gltx]alloc pkt err\n");
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(pkt);
 | 
						|
    cmd_resp->cid.cid = PLCTXRX_CID_TOPO;
 | 
						|
    cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
 | 
						|
    cmd_resp->resp = PLCTXRX_RESP_OK;
 | 
						|
    if (0 == done) {
 | 
						|
        cmd_resp->index.current = count;
 | 
						|
    } else {
 | 
						|
        cmd_resp->index.current = total_count;
 | 
						|
    }
 | 
						|
    cmd_resp->index.total = total_count;
 | 
						|
    cmd_resp->done = done;
 | 
						|
    cmd_resp->dlen = data_len;
 | 
						|
    topo_data = (plctxrx_handle_topo_t *)cmd_resp->data;
 | 
						|
    topo_data->cnt = (uint8_t)count;
 | 
						|
    for (i = 0; i < count; ++i) {
 | 
						|
        topo_data->topo[i].logic_phase = ((node+i)->logic_phase3) << 4
 | 
						|
            | ((node+i)->logic_phase2) << 2 | ((node+i)->logic_phase1);
 | 
						|
        topo_data->topo[i].phy_phase = ((node+i)->phy_phase3) << 4
 | 
						|
            | ((node+i)->phy_phase2) << 2 | ((node+i)->phy_phase1);
 | 
						|
        iot_cus_printf("[gltx]topo reply:role=%d tei=%d proxy:%d ",
 | 
						|
            (node+i)->role, (node+i)->sta_tei, (node+i)->proxy_tei);
 | 
						|
        iot_cus_printf("mac=[%02X:%02X:%02X:%02X:%02X:%02X], level:%d," \
 | 
						|
            "logic_phase:0x%02x, phy_phase:0x%02x.\n",
 | 
						|
            (node+i)->addr[0], (node+i)->addr[1], (node+i)->addr[2],
 | 
						|
            (node+i)->addr[3], (node+i)->addr[4], (node+i)->addr[5],
 | 
						|
            (node+i)->level, topo_data->topo[i].logic_phase,
 | 
						|
            topo_data->topo[i].phy_phase);
 | 
						|
        iot_mac_addr_cpy(topo_data->topo[i].mac, (node+i)->addr);
 | 
						|
        topo_data->topo[i].level = (node+i)->level;
 | 
						|
    }
 | 
						|
 | 
						|
    last_tei = node[count - 1].sta_tei;
 | 
						|
    iot_pkt_put(pkt, data_len + sizeof(plctxrx_cmd_resp_t));
 | 
						|
    plctxrx_cmd_resp_data_pkt(done, PLCTXRX_OP_RESPONSE, pkt);
 | 
						|
    if (0 == done) {
 | 
						|
        iot_plc_query_nw_topo(greeapp->app_handle,
 | 
						|
            IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
 | 
						|
            IOT_PLC_CCO_TOPO_REQ_DATA_VER_V1,
 | 
						|
            IOT_PLC_QUERY_TOPO_START_AS_TEI, last_tei + 1,
 | 
						|
            STA_DEV_MAX);
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_plctxrx_topo_info_v2_rpt() - report topo infomation to upper layer
 | 
						|
 * @param node          node infomation v2 report from cvg
 | 
						|
 * @param total_count   node infomation total count need report
 | 
						|
 * @param count         node information count this time
 | 
						|
 * @param done          report done flag
 | 
						|
 * @retval:             report to upper layer success or not
 | 
						|
 */
 | 
						|
bool_t iot_plctxrx_topo_info_v2_rpt(iot_plc_node_info_v2_t *node,
 | 
						|
    uint16_t total_count, uint16_t count, uint8_t done)
 | 
						|
{
 | 
						|
    uint16_t i;
 | 
						|
    uint16_t data_len = 0;
 | 
						|
    plctxrx_cmd_resp_t *cmd_resp;
 | 
						|
    iot_pkt_t *pkt;
 | 
						|
    plctxrx_handle_topo_v2_t *topo_data;
 | 
						|
 | 
						|
    data_len = sizeof(plctxrx_handle_topo_v2_t) +
 | 
						|
        sizeof(plctxrx_cmd_topov2_t) * count;
 | 
						|
    pkt = iot_pkt_alloc(data_len + sizeof(plctxrx_cmd_resp_t),
 | 
						|
        IOT_GREE_APP_MID);
 | 
						|
 | 
						|
    if (!pkt) {
 | 
						|
        iot_cus_printf("[gltx]alloc pkt err\n");
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(pkt);
 | 
						|
    cmd_resp->cid.cid = PLCTXRX_CID_TOPO;
 | 
						|
    cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
 | 
						|
    cmd_resp->resp = PLCTXRX_RESP_OK;
 | 
						|
    if (0 == done) {
 | 
						|
        cmd_resp->index.current = count;
 | 
						|
    } else {
 | 
						|
        cmd_resp->index.current = total_count;
 | 
						|
    }
 | 
						|
    cmd_resp->index.total = total_count;
 | 
						|
    cmd_resp->done = done;
 | 
						|
    cmd_resp->dlen = data_len;
 | 
						|
    topo_data = (plctxrx_handle_topo_v2_t *)cmd_resp->data;
 | 
						|
    topo_data->cnt = (uint8_t)count;
 | 
						|
    for (i = 0; i < count; ++i) {
 | 
						|
        iot_cus_printf("[gltx]topo reply:role=%d tei=%d proxy:%d ",
 | 
						|
            (node+i)->role, (node+i)->sta_tei, (node+i)->proxy_tei);
 | 
						|
        iot_cus_printf("mac=[%02X:%02X:%02X:%02X:%02X:%02X], level:%d\n",
 | 
						|
            (node+i)->addr[0], (node+i)->addr[1], (node+i)->addr[2],
 | 
						|
            (node+i)->addr[3], (node+i)->addr[4], (node+i)->addr[5],
 | 
						|
            (node+i)->level);
 | 
						|
        iot_mac_addr_cpy(topo_data->node[i].mac, (node+i)->addr);
 | 
						|
        topo_data->node[i].level = (node+i)->level;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_pkt_put(pkt, data_len + sizeof(plctxrx_cmd_resp_t));
 | 
						|
    plctxrx_cmd_resp_data_pkt(true, PLCTXRX_OP_RESPONSE, pkt);
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_handle_xmit_msg(plctxrx_task_msg_t* task_msg)
 | 
						|
{
 | 
						|
    switch (task_msg->msg.id) {
 | 
						|
    case IOT_PLCTXRX_ID_RECV_MSG:
 | 
						|
    {
 | 
						|
        iot_pkt_t *msdu_pkt = task_msg->data;
 | 
						|
        iot_plc_msdu_recv_t *msdu =
 | 
						|
        (iot_plc_msdu_recv_t*)(iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_DATA));
 | 
						|
        msdu_pkt_hdr_t* pkthdr;
 | 
						|
        uint8_t *pdata;
 | 
						|
        uint16_t total_len;
 | 
						|
        bool_t is_ready = plctxrx_context.local_state.dev_ready;
 | 
						|
 | 
						|
        pkthdr = (msdu_pkt_hdr_t*)msdu->data;
 | 
						|
 | 
						|
        iot_cus_printf("[gltx]handle_xmit_msg src(%d):"
 | 
						|
            "pkt_src_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x,"
 | 
						|
            "pkt_org_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x,"
 | 
						|
            "pkt_dest_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x,"
 | 
						|
            "CCO_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", pkthdr->src_module,
 | 
						|
            pkthdr->src_mac[0], pkthdr->src_mac[1],
 | 
						|
            pkthdr->src_mac[2], pkthdr->src_mac[3],
 | 
						|
            pkthdr->src_mac[4], pkthdr->src_mac[5],
 | 
						|
            pkthdr->org_mac[0], pkthdr->org_mac[1],
 | 
						|
            pkthdr->org_mac[2], pkthdr->org_mac[3],
 | 
						|
            pkthdr->org_mac[4], pkthdr->org_mac[5],
 | 
						|
            pkthdr->dst_mac[0], pkthdr->dst_mac[1],
 | 
						|
            pkthdr->dst_mac[2], pkthdr->dst_mac[3],
 | 
						|
            pkthdr->dst_mac[4], pkthdr->dst_mac[5],
 | 
						|
            plctxrx_context.local_state.cco_mac[0],
 | 
						|
            plctxrx_context.local_state.cco_mac[1],
 | 
						|
            plctxrx_context.local_state.cco_mac[2],
 | 
						|
            plctxrx_context.local_state.cco_mac[3],
 | 
						|
            plctxrx_context.local_state.cco_mac[4],
 | 
						|
            plctxrx_context.local_state.cco_mac[5]);
 | 
						|
          /*
 | 
						|
             for cco, judge pkt is for itself or for other station.
 | 
						|
             requeue pkt to send queue if for other station.
 | 
						|
             sta to sta ack is not in plctxrx level. it's in proto level.
 | 
						|
             txrx level is do forward and do default retry.
 | 
						|
          */
 | 
						|
        if ((plctxrx_context.nw_role == IOT_PLC_DEV_ROLE_CCO)\
 | 
						|
            && (plctxrx_context.cur_stanum > 2)) {
 | 
						|
            if (iot_mac_addr_cmp(pkthdr->dst_mac,
 | 
						|
                plctxrx_context.local_state.cco_mac) ==0) {
 | 
						|
                iot_cus_printf("[gltx]handle_xmit_msg:forward pkt\n");
 | 
						|
                if (!is_ready) {
 | 
						|
                    iot_cus_printf("[glpr][err]CCO not ready!\n");
 | 
						|
                    iot_pkt_free(msdu_pkt);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
 | 
						|
                total_len = msdu->len - sizeof(msdu_pkt_hdr_t);
 | 
						|
                if(total_len > TXRX_AGGR_PKT_LEN) {
 | 
						|
                    iot_cus_printf("[gltx]len:%d, exceed\n", total_len);
 | 
						|
                    iot_pkt_free(msdu_pkt);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
 | 
						|
                prot_pkt_t* proto_pkt =
 | 
						|
                    (prot_pkt_t*)iot_plctxrx_pkt_dequeue(plctxrx_context.freeq);
 | 
						|
                if (!proto_pkt) {
 | 
						|
                   iot_cus_printf("[gltx][forward]no aviable "
 | 
						|
                    "prot_pkt, freeq:%d,sendq:%d\n",
 | 
						|
                    plctxrx_context.freeq->depth, plctxrx_context.sendq->depth);
 | 
						|
                    iot_pkt_free(msdu_pkt);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                /* not mine, and get one free slot, start to forward */
 | 
						|
                os_mem_set(proto_pkt, 0 , sizeof(prot_pkt_t));
 | 
						|
                /* build the rocket */
 | 
						|
                pdata = msdu->data + sizeof(msdu_pkt_hdr_t);
 | 
						|
                os_mem_cpy(proto_pkt->buf, pdata, total_len);
 | 
						|
                iot_mac_addr_cpy(proto_pkt->txinfo.dst_mac, pkthdr->dst_mac);
 | 
						|
                iot_mac_addr_cpy(proto_pkt->txinfo.src_mac,
 | 
						|
                    plctxrx_context.local_state.cco_mac);
 | 
						|
                iot_mac_addr_cpy(proto_pkt->txinfo.org_mac, pkthdr->org_mac);
 | 
						|
                /*
 | 
						|
                iot_cus_printf("[gltx] org mac[%2x:%2x:%2x:%2x"
 | 
						|
                  ":%2x:%2x:]\n", proto_pkt->txinfo.org_mac[0],
 | 
						|
                  proto_pkt->txinfo.org_mac[1], proto_pkt->txinfo.org_mac[2],
 | 
						|
                  proto_pkt->txinfo.org_mac[3], proto_pkt->txinfo.org_mac[4],
 | 
						|
                  proto_pkt->txinfo.org_mac[5]);
 | 
						|
                */
 | 
						|
                proto_pkt->txinfo.force_tx_connless = 0;
 | 
						|
 | 
						|
                /*check fwd is unicast or bcast based on dest mac: FF FF FF*/
 | 
						|
                if (iot_mac_addr_cmp(pkthdr->dst_mac ,ge_bcast_addr)) {
 | 
						|
                    proto_pkt->txinfo.send_type = PLCTXRX_BORADCAST;
 | 
						|
                    proto_pkt->txinfo.retry_cnt = 0;
 | 
						|
                    proto_pkt->txinfo.retry_intvl = 0;
 | 
						|
                    proto_pkt->txinfo.txpwr = 0xFF;
 | 
						|
                    proto_pkt->txinfo.sta_cnt = 0;
 | 
						|
                    proto_pkt->txinfo.need_ack = false;
 | 
						|
                    proto_pkt->msdu_data_len = total_len;
 | 
						|
                    proto_pkt->txinfo.src_module = pkthdr->src_module;
 | 
						|
                    /* the pkt sent by sta should report to proto layer
 | 
						|
                     the masked method is unicast pkt not forward to cco.
 | 
						|
                     current methos requested by gree for cco see all pkt.
 | 
						|
                    */
 | 
						|
                    //iot_plctxrx_msdu_split_frame_to_propkt(task_msg->data,
 | 
						|
                        //(uint8_t)task_msg->data2 );
 | 
						|
                } else {
 | 
						|
                    proto_pkt->txinfo.send_type = PLCTXRX_UNICAST;
 | 
						|
                    proto_pkt->txinfo.retry_cnt = 3;
 | 
						|
                    proto_pkt->txinfo.retry_intvl = 100;
 | 
						|
                    proto_pkt->txinfo.txpwr = 0xFF;
 | 
						|
                    proto_pkt->txinfo.sta_cnt = 1;
 | 
						|
                    if (proto_pkt->txinfo.force_tx_connless == 0) {
 | 
						|
                        proto_pkt->txinfo.need_ack = true;
 | 
						|
                    } else {
 | 
						|
                        proto_pkt->txinfo.need_ack = false;
 | 
						|
                    }
 | 
						|
                    proto_pkt->txinfo.src_module = pkthdr->src_module;
 | 
						|
                    proto_pkt->msdu_data_len = total_len;
 | 
						|
                    //iot_pkt_free(msdu_pkt);
 | 
						|
                }
 | 
						|
                if (pkthdr->src_module == IOT_PLCTXRX_MSDU_SRCMODULE_PROTO) {
 | 
						|
                    iot_plctxrx_msdu_split_frame_to_propkt(task_msg->data,
 | 
						|
                        (uint8_t)task_msg->data2);
 | 
						|
                } else {
 | 
						|
                    iot_plctxrx_msdu_frame_to_at(task_msg->data);
 | 
						|
                }
 | 
						|
                iot_plctxrx_post_msg(IOT_PLCTXRX_XMIT_MSG,
 | 
						|
                    IOT_PLCTXRX_ID_SEND_MSG, proto_pkt, 0);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (pkthdr->src_module == IOT_PLCTXRX_MSDU_SRCMODULE_PROTO ||
 | 
						|
            pkthdr->src_module == IOT_PLCTXRX_MSDU_SRCMODULE_DEV_TEST) {
 | 
						|
            iot_plctxrx_msdu_split_frame_to_propkt(task_msg->data,
 | 
						|
                (uint8_t)task_msg->data2);
 | 
						|
        } else {
 | 
						|
            iot_plctxrx_msdu_frame_to_at(task_msg->data);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_ID_SEND_MSG:
 | 
						|
    {
 | 
						|
         prot_pkt_t *prot_pkt = (prot_pkt_t*)task_msg->data;
 | 
						|
         iot_plctxrx_do_aggr(prot_pkt);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_ID_ACK_MSG:
 | 
						|
    {
 | 
						|
        iot_plctxrx_msdu_ack_handle(task_msg->data);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* TODO. we should split it into each small function by switchcase*/
 | 
						|
void iot_plctxrx_handle_mac_msg(iot_pkt_t *pkt)
 | 
						|
{
 | 
						|
    iot_plc_msg_header_t *hdr =
 | 
						|
        (iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | 
						|
 | 
						|
    if (hdr->app_id != IOT_PLC_APP_ID_BCAST &&
 | 
						|
        hdr->app_id != IOT_GR_APP_ID) {
 | 
						|
        // drop corrupted message
 | 
						|
        iot_pkt_free(pkt);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (hdr->msg_id) {
 | 
						|
    case IOT_PLC_MSG_APP_REG_CONF:
 | 
						|
    {
 | 
						|
        iot_plc_app_reg_conf_t* rpt = (iot_plc_app_reg_conf_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[gltx]IOT_PLC_MSG_APP_REG_CONF result:%d\n",
 | 
						|
            rpt->result);
 | 
						|
        if (rpt->result == IOT_PLC_SUCCESS ||
 | 
						|
            rpt->result == IOT_PLC_SUCCESS_MODIFIED) {
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_GRAPP_REG_CONF,
 | 
						|
                PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, NULL, 0);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_DEV_STATE_CHANGE_RPT:
 | 
						|
    {
 | 
						|
        plcsta_state_t *local = &plctxrx_context.local_state;
 | 
						|
        plcsta_info_t stainfo = { 0 };
 | 
						|
        iot_plc_dev_state_change_rpt_t* rpt =
 | 
						|
            (iot_plc_dev_state_change_rpt_t*)(hdr + 1);
 | 
						|
        local->role = rpt->dev_role;
 | 
						|
        if (!local->dev_ready && rpt->is_ready) {
 | 
						|
            /* dev becomes available to serve app request */
 | 
						|
            iot_cus_printf("[gltx]IOT_PLC_MSG_DEV_STATE_CHANGE_RPT "\
 | 
						|
                "nid=%lu, cco mac=%02X:%02X:%02X:%02X:%02X:%02X, role:%d\n",
 | 
						|
                rpt->nid, rpt->cco_mac[0], rpt->cco_mac[1],
 | 
						|
                rpt->cco_mac[2], rpt->cco_mac[3], rpt->cco_mac[4],
 | 
						|
                rpt->cco_mac[5], rpt->dev_role);
 | 
						|
 | 
						|
            local->dev_ready = rpt->is_ready;
 | 
						|
            iot_mac_addr_cpy(local->sta_mac, rpt->local_mac);
 | 
						|
            iot_mac_addr_cpy(local->cco_mac, rpt->cco_mac);
 | 
						|
            local->sta_tei = rpt->dev_tei;
 | 
						|
 | 
						|
            stainfo.role = IOT_PLC_DEV_ROLE_CCO;
 | 
						|
            stainfo.sta_tei= 1;
 | 
						|
            iot_mac_addr_cpy(stainfo.sta_mac, rpt->cco_mac);
 | 
						|
            iot_plctxrx_add_sta(&stainfo);
 | 
						|
 | 
						|
            if (rpt->dev_role != IOT_PLC_DEV_ROLE_CCO) {
 | 
						|
                stainfo.role = rpt->dev_role;
 | 
						|
                stainfo.sta_tei = rpt->dev_tei;
 | 
						|
                iot_mac_addr_cpy(stainfo.sta_mac, rpt->local_mac);
 | 
						|
                iot_plctxrx_add_sta(&stainfo);
 | 
						|
                /* report sta joined indication to protocol layer */
 | 
						|
                plctxrx_cmd_joined_network_t net = { 0 };
 | 
						|
                net.role = rpt->dev_role;
 | 
						|
                net.nid  = (uint8_t)(rpt->nid & 0xFF);
 | 
						|
                iot_mac_addr_cpy(net.mac, rpt->cco_mac);
 | 
						|
                plctxrx_cmd_resp_data(PLCTXRX_CID_JOIN_NETWORK,
 | 
						|
                    PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, (void*)&net,
 | 
						|
                    sizeof(plctxrx_cmd_joined_network_t));
 | 
						|
            } else {
 | 
						|
                /* report CCO state change event to protocol layer */
 | 
						|
                plctxrx_cmd_cco_sta_ind_t sta = { 0 };
 | 
						|
                sta.dev_ready = rpt->is_ready;
 | 
						|
                sta.nid = (uint8_t)(rpt->nid & 0xFF);
 | 
						|
                plctxrx_cmd_resp_data(PLCTXRX_CID_CCO_STATE,
 | 
						|
                    PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, (void*)&sta,
 | 
						|
                    sizeof(plctxrx_cmd_cco_sta_ind_t));
 | 
						|
            }
 | 
						|
        } else if (local->dev_ready && !rpt->is_ready) {
 | 
						|
            uint16_t pkt_data_len = sizeof(plctxrx_cmd_leave_net_t) +
 | 
						|
                IOT_MAC_ADDR_LEN;
 | 
						|
 | 
						|
            /* dev becomes unavailable. It cannot serve app request */
 | 
						|
            iot_cus_printf("[gltx]STATE_CHANGE: MAC layer is NOT ready!\n");
 | 
						|
            local->dev_ready = rpt->is_ready;
 | 
						|
            if (local->role != IOT_PLC_DEV_ROLE_CCO) {
 | 
						|
                iot_pkt_t *resp_pkt = iot_pkt_alloc(pkt_data_len +
 | 
						|
                                sizeof(plctxrx_cmd_resp_t), IOT_GREE_APP_MID);
 | 
						|
                if (!resp_pkt) {
 | 
						|
                    IOT_ASSERT(0);
 | 
						|
                }
 | 
						|
 | 
						|
                plctxrx_cmd_resp_t *cmd_resp =
 | 
						|
                    (plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
 | 
						|
                cmd_resp->cid.cid = PLCTXRX_CID_LEAVE_NETWORK;
 | 
						|
                cmd_resp->cid.opcode = PLCTXRX_OP_INDICATION;
 | 
						|
                cmd_resp->resp = PLCTXRX_RESP_OK;
 | 
						|
                cmd_resp->index.current = 0;
 | 
						|
                cmd_resp->index.total = 0;
 | 
						|
                cmd_resp->dlen = pkt_data_len;
 | 
						|
                plctxrx_cmd_leave_net_t *net =
 | 
						|
                    (plctxrx_cmd_leave_net_t*)cmd_resp->data;
 | 
						|
                net->cnt = 1;
 | 
						|
                iot_mac_addr_cpy(net->mac[0], local->cco_mac );
 | 
						|
                iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
 | 
						|
                plctxrx_cmd_resp_data_pkt(0, PLCTXRX_OP_INDICATION, resp_pkt);
 | 
						|
 | 
						|
            } else {
 | 
						|
                /* report CCO state change event to protocol layer */
 | 
						|
                plctxrx_cmd_cco_sta_ind_t sta = { 0 };
 | 
						|
                sta.dev_ready = rpt->is_ready;
 | 
						|
                sta.nid = 0;
 | 
						|
                plctxrx_cmd_resp_data(PLCTXRX_CID_CCO_STATE,
 | 
						|
                    PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, (void*)&sta,
 | 
						|
                    sizeof(plctxrx_cmd_cco_sta_ind_t));
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_DEV_INFO_RPT:
 | 
						|
    {
 | 
						|
        plcsta_state_t *local = &plctxrx_context.local_state;
 | 
						|
        iot_plc_dev_info_rpt_t* rpt = (iot_plc_dev_info_rpt_t*)(hdr + 1);
 | 
						|
        local->role= rpt->dev_role;
 | 
						|
        iot_mac_addr_cpy(local->sta_mac, rpt->local_mac);
 | 
						|
        local->dev_ready = rpt->is_ready;
 | 
						|
        plctxrx_context.u_snr = rpt->snr;
 | 
						|
        if (local->dev_ready) {
 | 
						|
            iot_cus_printf("[gltx]IOT_PLC_MSG_DEV_INFO_RPT MAC "\
 | 
						|
                "layer is ready role:%d mac:%02X:%02X:%02X:%02X:%02X:%02X\n",
 | 
						|
                rpt->dev_role, rpt->local_mac[0], rpt->local_mac[1],
 | 
						|
                rpt->local_mac[2], rpt->local_mac[3],
 | 
						|
                rpt->local_mac[4],rpt->local_mac[5]);
 | 
						|
        } else {
 | 
						|
            iot_cus_printf(
 | 
						|
                "[gltx]IOT_PLC_MSG_DEV_INFO_RPT: MAC layer is NOT ready!\n");
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_STA_JOIN_INFO:
 | 
						|
    {
 | 
						|
        plcsta_info_t stainfo = {0};
 | 
						|
        plctxrx_cmd_joined_network_t net = { 0 };
 | 
						|
        iot_plc_sta_join_info_t* rpt = (iot_plc_sta_join_info_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[gltx]IOT_PLC_MSG_STA_JOIN_INFO %d sta_joined."
 | 
						|
            "proxy=%d mac=%02X:%02X:%02X:%02X:%02X:%02X. dev_type=%d."
 | 
						|
            "physical phase[1-3]=%d.%d.%d. boot_reason=%d vendor=%04X "
 | 
						|
            "build_ver=%X, level=%d.\n",
 | 
						|
            rpt->sta_info.sta_tei, rpt->sta_info.proxy_tei,
 | 
						|
            rpt->sta_info.addr[0], rpt->sta_info.addr[1],
 | 
						|
            rpt->sta_info.addr[2], rpt->sta_info.addr[3],
 | 
						|
            rpt->sta_info.addr[4], rpt->sta_info.addr[5],
 | 
						|
            rpt->sta_info.dev_type, rpt->sta_info.logic_phase1,
 | 
						|
            rpt->sta_info.logic_phase2, rpt->sta_info.logic_phase3,
 | 
						|
            rpt->sta_info.boot_reason, rpt->sta_info.vendor,
 | 
						|
            rpt->sta_info.build_ver, rpt->sta_info.level);
 | 
						|
 | 
						|
        stainfo.role = rpt->sta_info.role;
 | 
						|
        stainfo.sta_tei= rpt->sta_info.sta_tei;
 | 
						|
        stainfo.level = rpt->sta_info.level;
 | 
						|
        iot_mac_addr_cpy(stainfo.sta_mac, rpt->sta_info.addr);
 | 
						|
        iot_plctxrx_add_sta(&stainfo);
 | 
						|
        iot_mac_addr_cpy(net.mac, rpt->sta_info.addr);
 | 
						|
        net.role = rpt->sta_info.role;
 | 
						|
        iot_mac_addr_cpy(net.pco_mac, rpt->sta_info.proxy_addr);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_JOIN_NETWORK,
 | 
						|
            PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, (void*)&net,
 | 
						|
            sizeof(plctxrx_cmd_joined_network_t));
 | 
						|
        iot_plc_led_request(IOT_PLC_LED_ASSOCIATED);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_STA_LEAVE_INFO:
 | 
						|
    {
 | 
						|
        iot_plc_sta_leave_info_t* rpt = (iot_plc_sta_leave_info_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[gltx]sta leave info sta_count = %d\n",rpt->sta_count);
 | 
						|
        if (rpt->sta_count > 0) {
 | 
						|
            uint16_t pkt_data_len = sizeof(plctxrx_cmd_leave_net_t) +
 | 
						|
                IOT_MAC_ADDR_LEN * rpt->sta_count;
 | 
						|
            iot_pkt_t *resp_pkt = iot_pkt_alloc(pkt_data_len +
 | 
						|
                sizeof(plctxrx_cmd_resp_t), IOT_GREE_APP_MID);
 | 
						|
 | 
						|
            if (!resp_pkt) {
 | 
						|
                IOT_ASSERT(0);
 | 
						|
            }
 | 
						|
 | 
						|
            plctxrx_cmd_resp_t *cmd_resp =
 | 
						|
                (plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
 | 
						|
            cmd_resp->cid.cid = PLCTXRX_CID_LEAVE_NETWORK;
 | 
						|
            cmd_resp->cid.opcode = PLCTXRX_OP_INDICATION;
 | 
						|
            cmd_resp->resp = PLCTXRX_RESP_OK;
 | 
						|
            cmd_resp->index.current = 0;
 | 
						|
            cmd_resp->index.total = 0;
 | 
						|
            cmd_resp->dlen = pkt_data_len;
 | 
						|
            plctxrx_cmd_leave_net_t *net =
 | 
						|
                (plctxrx_cmd_leave_net_t*)cmd_resp->data;
 | 
						|
            net->cnt = rpt->sta_count;
 | 
						|
 | 
						|
            for (uint8_t i = 0; i < rpt->sta_count; ++i) {
 | 
						|
                iot_cus_printf("[gltx]IOT_PLC_MSG_STA_LEAVE_INFO: "\
 | 
						|
                    "tei=%d sta_leave[%d].proxy = %d:"\
 | 
						|
                    "mac=%02X:%02X:%02X:%02X:%02X:%02X\n",
 | 
						|
                    rpt->sta[i].tei, i, rpt->sta[i].proxy,
 | 
						|
                    rpt->sta[i].mac_addr[0], rpt->sta[i].mac_addr[1],
 | 
						|
                    rpt->sta[i].mac_addr[2], rpt->sta[i].mac_addr[3],
 | 
						|
                    rpt->sta[i].mac_addr[4], rpt->sta[i].mac_addr[5]);
 | 
						|
                iot_mac_addr_cpy(net->mac[i], rpt->sta[i].mac_addr);
 | 
						|
                iot_plctxrx_del_sta_by_mac(rpt->sta[i].mac_addr);
 | 
						|
            }
 | 
						|
 | 
						|
            iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
 | 
						|
            plctxrx_cmd_resp_data_pkt(0, PLCTXRX_OP_INDICATION, resp_pkt);
 | 
						|
            iot_plc_led_request(IOT_PLC_LED_DIS_ASSOCIATED);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_STA_JOIN_REJECTED:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_resp_t *cmd_resp;
 | 
						|
        plctxrx_cmd_reject_info_t *reject_info;
 | 
						|
        iot_plc_sta_join_rejected_t *rpt =
 | 
						|
            (iot_plc_sta_join_rejected_t*)(hdr + 1);
 | 
						|
        iot_pkt_t *resp_pkt = NULL;
 | 
						|
 | 
						|
        iot_cus_printf("[gltx]reject sta:%02X%02X%02X%02X%02X%02X, reason%d\n",
 | 
						|
            rpt->addr[0], rpt->addr[1], rpt->addr[2],
 | 
						|
            rpt->addr[3], rpt->addr[4], rpt->addr[5], rpt->reason);
 | 
						|
        resp_pkt = iot_pkt_alloc(sizeof(*cmd_resp) + sizeof(*reject_info),
 | 
						|
            IOT_GREE_APP_MID);
 | 
						|
 | 
						|
        if (NULL == resp_pkt) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_put(resp_pkt,
 | 
						|
            sizeof(*cmd_resp) + sizeof(*reject_info));
 | 
						|
        cmd_resp->cid.cid = PLCTXRX_CID_REJECT_STA;
 | 
						|
        cmd_resp->cid.opcode = PLCTXRX_OP_INDICATION;
 | 
						|
        cmd_resp->resp = PLCTXRX_RESP_OK;
 | 
						|
        cmd_resp->index.current = 0;
 | 
						|
        cmd_resp->index.total = 0;
 | 
						|
        cmd_resp->dlen = sizeof(*reject_info);
 | 
						|
 | 
						|
        reject_info = (plctxrx_cmd_reject_info_t*)cmd_resp->data;
 | 
						|
        iot_mac_addr_cpy(reject_info->mac, rpt->addr);
 | 
						|
        reject_info->reason = rpt->reason;
 | 
						|
 | 
						|
        plctxrx_cmd_resp_data_pkt(0, PLCTXRX_OP_INDICATION, resp_pkt);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_CONN_LESS_RECV:
 | 
						|
    case IOT_PLC_MSG_MSDU_RECV:
 | 
						|
    {
 | 
						|
        uint8_t         *ptr = 0;
 | 
						|
        msdu_pkt_hdr_t  *pkthdr = 0;
 | 
						|
        iot_pkt_t       *msdu_pkt;
 | 
						|
        uint8_t         *msdu_ptr;
 | 
						|
        uint16_t        msdu_pkt_len;
 | 
						|
        uint8_t         msdu_pkt_type;
 | 
						|
        bool_t          connless_type;
 | 
						|
 | 
						|
        iot_plc_msdu_recv_t *msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
 | 
						|
        plctxrx_context.u_snr = (int8_t)msdu->snr;
 | 
						|
        ptr = msdu->data;
 | 
						|
        pkthdr = (msdu_pkt_hdr_t*)ptr;
 | 
						|
 | 
						|
        iot_cus_printf("[gltx]IOT_PLC_MSG_MSDU_RECV: ackseq:%d "
 | 
						|
            "msduseq:%d mac:[%2X:%2X:%2X:%2X:%2X:%2X] size=%d "
 | 
						|
            "module_src=%d dstcnt:%d needack:%d srctype:%d\n",pkthdr->recvconf_seq,
 | 
						|
            pkthdr->msdusend_seq, msdu->src[0], msdu->src[1], msdu->src[2],
 | 
						|
            msdu->src[3], msdu->src[4], msdu->src[5], msdu->len,
 | 
						|
            pkthdr->src_module, pkthdr->dest_cnt, pkthdr->need_ack,
 | 
						|
            pkthdr->src_module);
 | 
						|
 | 
						|
        iot_plctxrx_aes_decrypt(pkt);
 | 
						|
 | 
						|
        if (IOT_PLC_MSG_MSDU_RECV == hdr->msg_id) {
 | 
						|
            connless_type = 0;
 | 
						|
            if (!plctxrx_context.local_state.dev_ready) {
 | 
						|
                /* if dev is not ready, don't handle the MSDU */
 | 
						|
                iot_cus_printf("[gltx][err] dev not ready, drop pkt\n");
 | 
						|
                iot_pkt_free(pkt);
 | 
						|
                return ;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            connless_type = 1;
 | 
						|
            iot_cus_printf("[gltx][info]app connless packet recv!\n");
 | 
						|
        }
 | 
						|
        msdu_pkt_len = sizeof(iot_plc_msdu_recv_t) + msdu->len;
 | 
						|
        msdu_pkt = iot_pkt_alloc(msdu_pkt_len,IOT_GREE_APP_MID);
 | 
						|
 | 
						|
        iot_cus_printf("[gltx] msdu alloc pkt:%d\n",msdu_pkt_len);
 | 
						|
 | 
						|
        if (msdu_pkt == NULL) {
 | 
						|
            iot_cus_printf("[gltx] allocate pkt fail!\n");
 | 
						|
            iot_pkt_free(pkt);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        msdu_ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_DATA);
 | 
						|
        os_mem_cpy(msdu_ptr, msdu, msdu_pkt_len);
 | 
						|
 | 
						|
        msdu_pkt_type = iot_plctxrx_msdu_type_check(msdu);
 | 
						|
        if (msdu_pkt_type == PLCTXRX_TYPE_ACK) {
 | 
						|
            iot_plctxrx_post_msg(IOT_PLCTXRX_XMIT_MSG,
 | 
						|
                IOT_PLCTXRX_ID_ACK_MSG, msdu_pkt, 0);
 | 
						|
        } else {
 | 
						|
            /*unicast*/
 | 
						|
            if ((pkthdr->dest_cnt == 1) && pkthdr->need_ack) {
 | 
						|
                iot_plctxrx_msdu_send_ack_back(msdu);
 | 
						|
            }
 | 
						|
 | 
						|
            if (connless_type == 0) {
 | 
						|
                if (iot_plctxrx_msdu_duplicate_check(msdu)) {
 | 
						|
                    iot_pkt_free(pkt);
 | 
						|
                    iot_pkt_free(msdu_pkt);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                if (!iot_plctxrx_conn_less_rpt_check(pkthdr->msdusend_seq,
 | 
						|
                    msdu->src)) {
 | 
						|
                    iot_cus_printf("[gltx]dupplicated conn_less pkt[%d] "
 | 
						|
                        "received!\n", pkthdr->msdusend_seq);
 | 
						|
                    iot_pkt_free(pkt);
 | 
						|
                    iot_pkt_free(msdu_pkt);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            /* sta may receive cco broadcast pkt which sent out by self */
 | 
						|
            if (iot_mac_addr_cmp(plctxrx_context.local_state.sta_mac,
 | 
						|
                pkthdr->org_mac) == 1) {
 | 
						|
                iot_cus_printf("[gltx]cco forwardbcast mac:%x:%x:%x:%x:%x vs"\
 | 
						|
                    "%x:%x:%x:%x:%x:%x\n",
 | 
						|
                    plctxrx_context.local_state.sta_mac[0],
 | 
						|
                    plctxrx_context.local_state.sta_mac[1],
 | 
						|
                    plctxrx_context.local_state.sta_mac[2],
 | 
						|
                    plctxrx_context.local_state.sta_mac[3],
 | 
						|
                    plctxrx_context.local_state.sta_mac[4],
 | 
						|
                    plctxrx_context.local_state.sta_mac[5],
 | 
						|
                    pkthdr->org_mac[0],pkthdr->org_mac[1],
 | 
						|
                    pkthdr->org_mac[2],pkthdr->org_mac[3],
 | 
						|
                    pkthdr->org_mac[4],pkthdr->org_mac[5]);
 | 
						|
                iot_pkt_free(pkt);
 | 
						|
                iot_pkt_free(msdu_pkt);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            plctxrx_context.local_state.txrx_status.msdu_receivd_cnt++;
 | 
						|
 | 
						|
            iot_plctxrx_recvd_pktseq_update(msdu);
 | 
						|
            iot_plctxrx_post_msg(IOT_PLCTXRX_XMIT_MSG,
 | 
						|
                IOT_PLCTXRX_ID_RECV_MSG, msdu_pkt, connless_type);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_ID_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_nid_rpt_t *rpt = (iot_plc_nid_rpt_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[gltx] query nid reply:[0x%06X]\n", rpt->nid);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_LID_CONF:
 | 
						|
    {
 | 
						|
        iot_plc_lid_alloc_conf_t *cfm = (iot_plc_lid_alloc_conf_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[gltx]IOT_PLC_MSG_LID_CONF lid alloc:"\
 | 
						|
            "result = %d, lid=%d\n", cfm->result, cfm->lid);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NEIGHBOR_DEV_RPT:
 | 
						|
    {
 | 
						|
        uint16_t i;
 | 
						|
        iot_plc_neighbor_dev_rpt_t * nb_info =
 | 
						|
            (iot_plc_neighbor_dev_rpt_t*)(hdr + 1);
 | 
						|
        //iot_cus_printf("[gltx]IOT_PLC_MSG_NEIGHBOR_DEV_RPT :\n");
 | 
						|
        iot_cus_printf("[gltx]IOT_PLC_MSG_NEIGHBOR_DEV_RPT:count = %d "\
 | 
						|
            "total_cnt:%d done:%d\n",
 | 
						|
            nb_info->cnt, nb_info->total_cnt, nb_info->done);
 | 
						|
 | 
						|
        if (nb_info->cnt > 0) {
 | 
						|
            plctxrx_cmd_resp_t *cmd_resp;
 | 
						|
            plctxrx_net_sts_data_info_t *net;
 | 
						|
            uint16_t pkt_data_len = sizeof(plctxrx_net_sts_data_info_t) +
 | 
						|
                sizeof(plctxrx_net_sts_t) * nb_info->total_cnt;
 | 
						|
            iot_pkt_t *resp_pkt = iot_pkt_alloc(pkt_data_len +
 | 
						|
                sizeof(plctxrx_cmd_resp_t), IOT_GREE_APP_MID);
 | 
						|
 | 
						|
            if (!resp_pkt) {
 | 
						|
                IOT_ASSERT(0);
 | 
						|
            }
 | 
						|
 | 
						|
            cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
 | 
						|
            cmd_resp->cid.cid       = PLCTXRX_CID_NET_STS;
 | 
						|
            cmd_resp->cid.opcode    = PLCTXRX_OP_RESPONSE;
 | 
						|
            cmd_resp->resp          = PLCTXRX_RESP_OK;
 | 
						|
            cmd_resp->dlen          = pkt_data_len;
 | 
						|
            net = (plctxrx_net_sts_data_info_t *)cmd_resp->data;
 | 
						|
            net->count = (uint8_t)nb_info->cnt;
 | 
						|
 | 
						|
            for (i = 0; i < net->count; i++) {
 | 
						|
                net->net_sts_data[i].ul_tf_sr = nb_info->node[i].ul_tf_sr;
 | 
						|
                net->net_sts_data[i].dl_tf_sr = nb_info->node[i].dl_tf_sr;
 | 
						|
                net->net_sts_data[i].snr = nb_info->node[i].snr;
 | 
						|
                net->net_sts_data[i].nf = 0;
 | 
						|
                iot_mac_addr_cpy(net->net_sts_data[i].mac,
 | 
						|
                    nb_info->node[i].addr);
 | 
						|
                iot_cus_printf("[gltx]snr=%d,nf=%d,count=%d,"\
 | 
						|
                    "cur=%d,mac=0x%02x,0x%02x,0x%02x,tsf=%d,rsf=%d\n",\
 | 
						|
                    net->net_sts_data[i].snr, net->net_sts_data[i].nf,
 | 
						|
                    net->count, i, net->net_sts_data[i].mac[0],
 | 
						|
                    net->net_sts_data[i].mac[1],
 | 
						|
                    net->net_sts_data[i].mac[2],
 | 
						|
                    net->net_sts_data[i].ul_tf_sr,
 | 
						|
                    net->net_sts_data[i].dl_tf_sr);
 | 
						|
            }
 | 
						|
            iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
 | 
						|
            plctxrx_cmd_resp_data_pkt(1, PLCTXRX_OP_RESPONSE, resp_pkt);
 | 
						|
        } else {
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_NET_STS, PLCTXRX_OP_RESPONSE,
 | 
						|
                NULL, PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
        }
 | 
						|
        if (nb_info->cnt == 1 && iot_mac_addr_cmp(nb_info->node->addr,
 | 
						|
            plctxrx_context.local_state.sta_mac)) {
 | 
						|
            /* update local state info */
 | 
						|
            plcsta_state_t *local_state       = &plctxrx_context.local_state;
 | 
						|
            local_state->role                 = (uint8_t)nb_info->node->role;
 | 
						|
            local_state->net_status.snr       = nb_info->node->snr;
 | 
						|
            local_state->net_status.ul_tf_sr  = nb_info->node->ul_tf_sr;
 | 
						|
            local_state->net_status.dl_tf_sr  = nb_info->node->dl_tf_sr;
 | 
						|
            if (nb_info->node->phase1 > 0) {
 | 
						|
                local_state->net_status.phase = nb_info->node->phase1;
 | 
						|
            } else if (nb_info->node->phase2 > 0) {
 | 
						|
                local_state->net_status.phase = nb_info->node->phase2;
 | 
						|
            } else {
 | 
						|
                local_state->net_status.phase = nb_info->node->phase3;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_NEIGHBOR_RPT:
 | 
						|
    {
 | 
						|
        uint16_t i;
 | 
						|
        iot_plc_nb_nw_rpt_t *rpt = (iot_plc_nb_nw_rpt_t*)(hdr + 1);
 | 
						|
        plctxrx_cmd_resp_t *cmd_resp;
 | 
						|
        plctxrx_cmd_network_t *net;
 | 
						|
        iot_cus_printf("[gltx] nbnw reply: count = %d\n", rpt->count);
 | 
						|
        uint16_t pkt_data_len = sizeof(plctxrx_cmd_network_t) +
 | 
						|
            sizeof(plctxrx_cmd_network_info_t) * rpt->count;
 | 
						|
        iot_pkt_t *resp_pkt = iot_pkt_alloc(pkt_data_len +
 | 
						|
            sizeof(plctxrx_cmd_resp_t), IOT_GREE_APP_MID);
 | 
						|
 | 
						|
        if (!resp_pkt) {
 | 
						|
            IOT_ASSERT(0);
 | 
						|
        }
 | 
						|
 | 
						|
        cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
 | 
						|
        cmd_resp->cid.cid       = PLCTXRX_CID_FIND_NETWORK;
 | 
						|
        cmd_resp->cid.opcode    = PLCTXRX_OP_RESPONSE;
 | 
						|
        cmd_resp->resp          = PLCTXRX_RESP_OK;
 | 
						|
        cmd_resp->index.current = rpt->count;
 | 
						|
        cmd_resp->index.total   = rpt->count;
 | 
						|
        cmd_resp->dlen          = pkt_data_len;
 | 
						|
        net                     = (plctxrx_cmd_network_t*)cmd_resp->data;
 | 
						|
        net->count              = rpt->count;
 | 
						|
        for (i = 0; i < rpt->count; ++i) {
 | 
						|
            iot_cus_printf("[gltx]nbnw reply:nid[%d],sp_flag = %d,bd = %d\n",
 | 
						|
                rpt->nb_info[i].nid, rpt->nb_info[i].sp_flag,
 | 
						|
                rpt->nb_info[i].bandwidth);
 | 
						|
            net->node[i].nid = rpt->nb_info[i].nid;
 | 
						|
 | 
						|
            /* get best snr */
 | 
						|
            net->node[i].snr = (rpt->nb_info[i].snr[0] >=
 | 
						|
                rpt->nb_info[i].snr[1]? \
 | 
						|
                rpt->nb_info[i].snr[0]:rpt->nb_info[i].snr[1]);
 | 
						|
            net->node[i].snr = (net->node[i].snr >= rpt->nb_info[i].snr[2]?
 | 
						|
                net->node[i].snr:rpt->nb_info[i].snr[2]);
 | 
						|
            iot_mac_addr_cpy(net->node[i].mac, rpt->nb_info[i].addr);
 | 
						|
        }
 | 
						|
        iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
 | 
						|
        plctxrx_cmd_resp_data_pkt(1, PLCTXRX_OP_RESPONSE, resp_pkt);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_WL_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_wl_rpt_t *rpt = (iot_plc_wl_rpt_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[gltx] IOT_PLC_MSG_NW_WL_RPT wl reply:");
 | 
						|
        iot_cus_printf("total=%d,count=%d,done=%d\n",
 | 
						|
            rpt->total_count, rpt->count, rpt->done);
 | 
						|
        for (int i = 0; i < rpt->count; ++i) {
 | 
						|
            iot_cus_printf("[gltx]mac[%d]=%02X:%02X:%02X:%02X:%02X:%02X\n", i,
 | 
						|
                rpt->mac_addr[i][0], rpt->mac_addr[i][1],
 | 
						|
                rpt->mac_addr[i][2], rpt->mac_addr[i][3],
 | 
						|
                rpt->mac_addr[i][4], rpt->mac_addr[i][5]);
 | 
						|
        }
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_WHITELIST, PLCTXRX_OP_RESPONSE,
 | 
						|
            NULL, PLCTXRX_RESP_OK, (void*)rpt, sizeof(iot_plc_wl_rpt_t));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_WL_SET_RPT:
 | 
						|
    {
 | 
						|
        uint8_t cmdid;
 | 
						|
        iot_plc_wl_set_rpt_t *rpt = (iot_plc_wl_set_rpt_t*)(hdr + 1);
 | 
						|
        uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
 | 
						|
 | 
						|
        cmdid = plctxrx_context.command.cur_cid.cid;
 | 
						|
 | 
						|
        plctxrx_cmd_resp_data(cmdid, PLCTXRX_OP_CFM, NULL, resp, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_TOPO_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_nw_topo_rpt_t* rpt = (iot_plc_nw_topo_rpt_t*)(hdr + 1);
 | 
						|
        if (rpt->version == IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0) {
 | 
						|
            /* v0 is used for node info */
 | 
						|
            iot_plctxrx_node_info_rpt((iot_plc_node_info_v0_t *)rpt->data,
 | 
						|
                rpt->total_count, rpt->count, rpt->done);
 | 
						|
        } else if (rpt->version == IOT_PLC_CCO_TOPO_REQ_DATA_VER_V1 &&
 | 
						|
            rpt->count > 0) {
 | 
						|
            /* v1 is used for topo info */
 | 
						|
            iot_plctxrx_topo_info_rpt((iot_plc_node_info_v1_t *)rpt->data,
 | 
						|
                rpt->total_count, rpt->count, rpt->done);
 | 
						|
        } else if (rpt->version == IOT_PLC_CCO_TOPO_REQ_DATA_VER_V2 &&
 | 
						|
            rpt->count > 0) {
 | 
						|
            iot_plctxrx_topo_info_v2_rpt((iot_plc_node_info_v2_t *)rpt->data,
 | 
						|
                rpt->total_count, rpt->count, rpt->done);
 | 
						|
        } else {
 | 
						|
            plctxrx_cmd_resp_data(plctxrx_context.command.cur_cid.cid,
 | 
						|
                PLCTXRX_OP_RESPONSE, NULL, PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NODE_INFO_QUERY_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_node_info_rpt_t* rpt = (iot_plc_node_info_rpt_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[glpr]report node info count=%d\n", rpt->count);
 | 
						|
        if (rpt->version == IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0) {
 | 
						|
            iot_plctxrx_node_info_rpt((iot_plc_node_info_v0_t *)rpt->data,
 | 
						|
                rpt->total_count, rpt->count, rpt->done);
 | 
						|
        } else {
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_NODE_INFO,
 | 
						|
                PLCTXRX_OP_RESPONSE, NULL, PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_INFO_QUERY_RPT:
 | 
						|
    {
 | 
						|
        uint16_t pkt_data_len;
 | 
						|
        plctxrx_cmd_resp_t *cmd_resp;
 | 
						|
        iot_pkt_t *resp_pkt;
 | 
						|
        iot_plc_nw_info_query_rpt_t* rpt =
 | 
						|
            (iot_plc_nw_info_query_rpt_t*)(hdr + 1);
 | 
						|
 | 
						|
        iot_cus_printf("[gltx]report network max level=%d\n", rpt->max_level);
 | 
						|
        pkt_data_len = sizeof(iot_plc_nw_info_query_rpt_t) +
 | 
						|
            sizeof(iot_plc_nw_level_info_t) * rpt->max_level ;
 | 
						|
        resp_pkt = iot_pkt_alloc(pkt_data_len + sizeof(plctxrx_cmd_resp_t),
 | 
						|
            IOT_GREE_APP_MID);
 | 
						|
 | 
						|
        if (resp_pkt == NULL) {
 | 
						|
            iot_cus_printf("[glpr]alloc pkt length=%d err\n",
 | 
						|
                pkt_data_len + sizeof(plctxrx_cmd_resp_t));
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
 | 
						|
        cmd_resp->cid.cid = PLCTXRX_CID_NW_INFO;
 | 
						|
        cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
 | 
						|
        cmd_resp->resp = PLCTXRX_RESP_OK;
 | 
						|
        cmd_resp->index.current = 1;
 | 
						|
        cmd_resp->index.total = 1;
 | 
						|
        cmd_resp->dlen = pkt_data_len;
 | 
						|
        os_mem_cpy(cmd_resp->data, rpt, pkt_data_len);
 | 
						|
        iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
 | 
						|
        plctxrx_cmd_resp_data_pkt(true, PLCTXRX_OP_RESPONSE, resp_pkt);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_CFG_SET_CONF:
 | 
						|
    {
 | 
						|
        iot_plc_cfg_set_conf_t *conf = (iot_plc_cfg_set_conf_t*)(hdr + 1);
 | 
						|
        uint16_t resp = !(conf->result == IOT_PLC_SUCCESS);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_MAC, PLCTXRX_OP_CFM, NULL,
 | 
						|
            resp, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_BEACON_DATA_SET_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_beacon_data_set_rpt_t *rpt =
 | 
						|
            (iot_plc_beacon_data_set_rpt_t*)(hdr + 1);
 | 
						|
        uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
 | 
						|
        plctxrx_cmd_resp_data(plctxrx_context.command.cur_cid.cid,
 | 
						|
            PLCTXRX_OP_CFM, NULL, resp, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_BEACON_DATA_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_beacon_data_rpt_t *rpt = (iot_plc_beacon_data_rpt_t*)(hdr + 1);
 | 
						|
#if ENABLE_GE_DATA_SEND_TO_BEACON
 | 
						|
        iot_cus_printf("[gltx]beacon rpt\n");
 | 
						|
        if (!os_mem_cmp(plctxrx_context.verinfo.data, rpt->data,
 | 
						|
            sizeof(iot_plc_beacon_data_rpt_t))) {
 | 
						|
            /* only new beacon data receive, report to proto */
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        iot_pkt_t *vend_pkt = iot_pkt_alloc(sizeof(iot_plc_beacon_data_rpt_t),
 | 
						|
            IOT_GREE_APP_MID);
 | 
						|
        if (!vend_pkt) {
 | 
						|
            IOT_ASSERT(0);
 | 
						|
        }
 | 
						|
 | 
						|
        iot_pkt_put(vend_pkt, sizeof(iot_plc_beacon_data_rpt_t));
 | 
						|
        os_mem_cpy(iot_pkt_data(vend_pkt), rpt->data,
 | 
						|
            sizeof(iot_plc_beacon_data_rpt_t));
 | 
						|
 | 
						|
        os_mem_cpy(plctxrx_context.verinfo.data, rpt->data,
 | 
						|
            sizeof(iot_plc_beacon_data_rpt_t));
 | 
						|
        plctxrx_context.gree_cb.gree_vendr_cb(vend_pkt);
 | 
						|
#endif
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_FREQ_BAND_SET_RPT:
 | 
						|
    {
 | 
						|
        /* handle freq band set response */
 | 
						|
        iot_plc_freq_band_set_rpt_t *rpt =
 | 
						|
            (iot_plc_freq_band_set_rpt_t *)(hdr + 1);
 | 
						|
        uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_BAND_ID, PLCTXRX_OP_CFM, NULL,
 | 
						|
            resp, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_BAND_INFO_QUERY_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_freq_band_info_query_rpt_t *rpt =
 | 
						|
            (iot_plc_freq_band_info_query_rpt_t*)(hdr + 1);
 | 
						|
 | 
						|
        if (PLCTXRX_CID_TX_PWR == plctxrx_context.command.cur_cid.cid) {
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_TX_PWR, PLCTXRX_OP_RESPONSE,
 | 
						|
                NULL, PLCTXRX_RESP_OK, (void*)&(rpt->power_cap),
 | 
						|
                sizeof(plctxrx_cmd_tx_pwr_t));
 | 
						|
        } else if (PLCTXRX_CID_BAND_ID == plctxrx_context.command.cur_cid.cid){
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_BAND_ID, PLCTXRX_OP_RESPONSE,
 | 
						|
                NULL, PLCTXRX_RESP_OK, (void*)&(rpt->freq_band),
 | 
						|
                sizeof(plctxrx_cmd_band_info_t));
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_TX_POWER_CAP_SET_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_tx_power_cap_set_rpt_t *rpt
 | 
						|
            = (iot_plc_tx_power_cap_set_rpt_t *)(hdr + 1);
 | 
						|
        uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_TX_PWR, PLCTXRX_OP_CFM,
 | 
						|
            NULL, resp, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_ID_SET_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_nw_id_set_rpt_t *rpt = (iot_plc_nw_id_set_rpt_t*)(hdr + 1);
 | 
						|
        uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_NID,
 | 
						|
            PLCTXRX_OP_CFM, NULL, resp, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_SCANBAND_BITMAP_SET_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_set_scanband_bitmap_rpt_t *rpt = \
 | 
						|
            (iot_plc_set_scanband_bitmap_rpt_t*)(hdr + 1);
 | 
						|
        uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_FB_BITMAP, PLCTXRX_OP_CFM,
 | 
						|
            NULL, resp, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_QUERYBAND_BITMAP_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_query_band_bitmap_rpt_t *rpt = \
 | 
						|
            (iot_plc_query_band_bitmap_rpt_t*)(hdr + 1);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_FB_BITMAP,
 | 
						|
            PLCTXRX_OP_RESPONSE, NULL, PLCTXRX_RESP_OK,
 | 
						|
            (void *)&rpt->is_scan_band,
 | 
						|
            sizeof(plctxrx_cmd_fb_bitmap_resp_t));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_SET_RATE_ADAPT_MODE_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_set_rate_adapt_mode_rpt_t *rpt =
 | 
						|
            (iot_plc_set_rate_adapt_mode_rpt_t*)(hdr + 1);
 | 
						|
        uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
 | 
						|
        if (resp) {
 | 
						|
            plctxrx_context.local_state.rate_node =
 | 
						|
                plctxrx_context.local_state.rate_node_last;
 | 
						|
        } else {
 | 
						|
            plctxrx_context.local_state.rate_node_last =
 | 
						|
                plctxrx_context.local_state.rate_node;
 | 
						|
        }
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_FIXED_RATE, PLCTXRX_OP_CFM,
 | 
						|
            NULL, resp, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_WDG_SET_CONF:
 | 
						|
    {
 | 
						|
        iot_plc_wdg_set_conf_t *conf = (iot_plc_wdg_set_conf_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[gltx]IOT_PLC_MSG_WDG_SET_CONF watchdog status = %d\n",
 | 
						|
            conf->status);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_WDG, PLCTXRX_OP_CFM, NULL,
 | 
						|
            PLCTXRX_RESP_OK, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_STA_PROXY_CHANGED:
 | 
						|
    {
 | 
						|
        plcsta_info_t stainfo = {0};
 | 
						|
        iot_plc_sta_proxy_changed_t* rpt = (iot_plc_sta_proxy_changed_t*)(hdr + 1);
 | 
						|
        iot_cus_printf("[gltx]IOT_PLC_MSG_STA_PROXY_CHANGED %d sta_proxy_changed."
 | 
						|
            "proxy=%d,level=%d,proxy mac=%02X:%02X:%02X:%02X:%02X:%02X."
 | 
						|
            "sta mac=%02X:%02X:%02X:%02X:%02X:%02X.\n",
 | 
						|
            rpt->sta_tei, rpt->proxy_tei, rpt->level, rpt->proxy_addr[0],
 | 
						|
            rpt->proxy_addr[1], rpt->proxy_addr[2], rpt->proxy_addr[3],
 | 
						|
            rpt->proxy_addr[4], rpt->proxy_addr[5], rpt->sta_addr[0],
 | 
						|
            rpt->sta_addr[1], rpt->sta_addr[2], rpt->sta_addr[3],
 | 
						|
            rpt->sta_addr[4], rpt->sta_addr[5]);
 | 
						|
 | 
						|
        stainfo.level = rpt->level;
 | 
						|
        stainfo.sta_tei= rpt->sta_tei;
 | 
						|
        stainfo.role = rpt->role;
 | 
						|
        iot_mac_addr_cpy(stainfo.sta_mac, rpt->sta_addr);
 | 
						|
        iot_plctxrx_add_sta(&stainfo);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_pkt_free(pkt);
 | 
						|
}
 | 
						|
 | 
						|
static void iot_plctxrx_task_msg_exe(iot_task_h task_h, iot_task_msg_t *msg)
 | 
						|
{
 | 
						|
    plctxrx_task_msg_t *task_msg;
 | 
						|
    IOT_ASSERT(task_h == plctxrx_context.task_handle);
 | 
						|
    IOT_ASSERT(msg);
 | 
						|
 | 
						|
    task_msg = (plctxrx_task_msg_t*)msg;
 | 
						|
    switch (task_msg->msg.type) {
 | 
						|
    case IOT_PLCTXRX_MAC_MSG:
 | 
						|
    {
 | 
						|
        iot_plctxrx_handle_mac_msg(task_msg->data);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_TIMER_MSG:
 | 
						|
    {
 | 
						|
        iot_plctxrx_handle_timer_msg(task_msg);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_XMIT_MSG:
 | 
						|
    {
 | 
						|
        iot_plctxrx_handle_xmit_msg(task_msg);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    case IOT_PLCTXRX_CMD_MSG:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_msg_handle(task_msg->data);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_task_free_msg(plctxrx_context.task_handle, &task_msg->msg);
 | 
						|
}
 | 
						|
 | 
						|
static void iot_plctxrx_task_msg_cancel(iot_task_h task_h,
 | 
						|
    iot_task_msg_t *msg)
 | 
						|
{
 | 
						|
    plctxrx_task_msg_t *task_msg;
 | 
						|
    IOT_ASSERT(task_h == plctxrx_context.task_handle);
 | 
						|
    IOT_ASSERT(msg);
 | 
						|
 | 
						|
    task_msg = (plctxrx_task_msg_t*)msg;
 | 
						|
    switch (task_msg->msg.type) {
 | 
						|
    case IOT_PLCTXRX_MAC_MSG:
 | 
						|
    {
 | 
						|
        if (task_msg->data) {
 | 
						|
            iot_pkt_free(task_msg->data);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_TIMER_MSG:
 | 
						|
    {
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_XMIT_MSG:
 | 
						|
    {
 | 
						|
        if (task_msg->data) {
 | 
						|
            iot_pkt_free(task_msg->data);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLCTXRX_CMD_MSG:
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_task_free_msg(plctxrx_context.task_handle, &task_msg->msg);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_post_msg(uint16_t msg_type,uint16_t msg_id, void* data,
 | 
						|
    uint32_t data2)
 | 
						|
{
 | 
						|
    iot_task_msg_t      *msg;
 | 
						|
    plctxrx_task_msg_t  *task_msg;
 | 
						|
    msg = iot_task_alloc_msg_with_reserved(plctxrx_context.task_handle, 0);
 | 
						|
    if (!msg) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]txrx task msg post: "\
 | 
						|
        "msg_type(%d)msg_id(%d)\n",msg_type, msg_id);
 | 
						|
 | 
						|
    task_msg = (plctxrx_task_msg_t*)msg;
 | 
						|
    task_msg->msg.type = msg_type;
 | 
						|
    task_msg->msg.id = msg_id;
 | 
						|
    task_msg->data = data;
 | 
						|
    task_msg->data2 = data2;
 | 
						|
    iot_task_queue_msg(plctxrx_context.task_handle, &task_msg->msg, 0);
 | 
						|
}
 | 
						|
 | 
						|
/* pkt entry from cvg up to plctxrx */
 | 
						|
void iot_plctxrx_msdu_from_cvg(void *param, iot_pkt_t *pkt)
 | 
						|
{
 | 
						|
    (void)param;
 | 
						|
    iot_plctxrx_post_msg(IOT_PLCTXRX_MAC_MSG, 0, pkt, 0);
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
  when upper callin.
 | 
						|
  1. get one free protopkt and past it on msg queue
 | 
						|
  2. when message queue receive it, do aggr function.
 | 
						|
  3. then, generate one new protopkt or just send it down.
 | 
						|
*/
 | 
						|
uint8_t iot_plctxrx_proto_data_send_cbk(uint8_t* data, uint16_t len,
 | 
						|
    protpkt_tx_info_t *txinfo)
 | 
						|
{
 | 
						|
    prot_pkt_t* proto_pkt = NULL;
 | 
						|
 | 
						|
    if(len > TXRX_AGGR_PKT_LEN) {
 | 
						|
        iot_cus_printf("[gltx]len:%d, exceeds txrx_aggr_pkt_len\n", len);
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    plctxrx_context.local_state.txrx_status.fram_send_cnt++;
 | 
						|
    if (plctxrx_context.local_state.txrx_status.fram_send_cnt == 0) {
 | 
						|
        plctxrx_context.local_state.txrx_status.fram_send_cnt++;
 | 
						|
    }
 | 
						|
 | 
						|
    proto_pkt = (prot_pkt_t*)iot_plctxrx_pkt_dequeue(plctxrx_context.freeq);
 | 
						|
    if (proto_pkt == NULL) {
 | 
						|
        iot_cus_printf("[gltx]no aviable prot_pkt, freeq:%d,"\
 | 
						|
            "sendq:%d len:%d\n", plctxrx_context.freeq->depth,
 | 
						|
            plctxrx_context.sendq->depth, len);
 | 
						|
 | 
						|
        plctxrx_context.local_state.txrx_status.fram_send_drop_cnt++;
 | 
						|
        if (plctxrx_context.local_state.txrx_status.fram_send_drop_cnt == 0) {
 | 
						|
            plctxrx_context.local_state.txrx_status.fram_send_drop_cnt++;
 | 
						|
        }
 | 
						|
       return ERR_NOMEM;
 | 
						|
    }
 | 
						|
 | 
						|
    g_gree_frm_cnt++;
 | 
						|
    g_gree_frm_total_len += len;
 | 
						|
    iot_cus_printf("[gltx]received proto data:%d frm_cnt:%d frm_total_len:%d\n",
 | 
						|
        len,g_gree_frm_cnt,g_gree_frm_total_len);
 | 
						|
    iot_cus_printf("[gltx]txinfo:type:%d sta_cnt:%d,need_ack:%d, "
 | 
						|
        "retry_cnt:%d, retry_intvl:%d\n", txinfo->send_type, txinfo->sta_cnt,
 | 
						|
        txinfo->need_ack, txinfo->retry_cnt, txinfo->retry_intvl);
 | 
						|
 | 
						|
    os_mem_cpy(proto_pkt->buf, data, len);
 | 
						|
    os_mem_cpy(&proto_pkt->txinfo, txinfo,(uint32_t)sizeof(protpkt_tx_info_t));
 | 
						|
    proto_pkt->msdu_data_len = len;
 | 
						|
 | 
						|
    iot_plctxrx_post_msg(IOT_PLCTXRX_XMIT_MSG, IOT_PLCTXRX_ID_SEND_MSG,
 | 
						|
        proto_pkt, 0);
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
/* when unicast and needack set, send msdu-ack back */
 | 
						|
uint8_t iot_plctxrx_msdu_send_ack_back(iot_plc_msdu_recv_t *msdu)
 | 
						|
{
 | 
						|
    uint8_t msg_type = IOT_PLC_MSG_TYPE_UNICAST;
 | 
						|
    uint8_t *ptr = 0;
 | 
						|
    uint8_t *destptr = 0;
 | 
						|
    uint16_t buflen = sizeof(msdu_pkt_hdr_t);
 | 
						|
    msdu_pkt_hdr_t *send_hdr = NULL;
 | 
						|
    msdu_pkt_hdr_t *hdr = NULL;
 | 
						|
 | 
						|
    ptr = msdu->data;
 | 
						|
    hdr = (msdu_pkt_hdr_t *)ptr;
 | 
						|
 | 
						|
    destptr = msdu->src;
 | 
						|
    iot_pkt_t *pkt_msdu = iot_plc_alloc_msdu(greeapp->app_handle, msg_type,
 | 
						|
        IOT_PLC_ACK_TYPE_NONE, destptr, plctxrx_context.local_state.sta_mac,
 | 
						|
        plctxrx_context.link_id, buflen, IOT_PLC_LOCAL_RETRY_CNT);
 | 
						|
 | 
						|
    if (pkt_msdu == NULL) {
 | 
						|
        iot_cus_printf("[gltx] allocate msdu fail\n");
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    ptr = iot_pkt_block_ptr(pkt_msdu, IOT_PKT_BLOCK_TAIL);
 | 
						|
 | 
						|
    send_hdr = (msdu_pkt_hdr_t*)ptr;
 | 
						|
 | 
						|
    send_hdr->msdusend_seq = 0;
 | 
						|
    send_hdr->recvconf_seq = hdr->msdusend_seq;
 | 
						|
    send_hdr->dest_cnt     = 1;
 | 
						|
    send_hdr->need_ack     = 0;
 | 
						|
    send_hdr->src_module   = hdr->src_module;
 | 
						|
 | 
						|
    iot_pkt_put(pkt_msdu, sizeof(uint8_t)*buflen);
 | 
						|
    iot_plc_send_msdu(greeapp->app_handle, pkt_msdu);
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]ack for msduseq:%d\n",hdr->msdusend_seq);
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
uint32_t iot_plctxrx_aggr_frame_condition_check(prot_pkt_t* in_pkt,
 | 
						|
       prot_pkt_t* aggr_pkt)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
 | 
						|
    if (in_pkt->msdu_data_len > (TXRX_AGGR_PKT_LEN - aggr_pkt->msdu_data_len)) {
 | 
						|
        return REASON_NO_SPACE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (in_pkt->txinfo.sta_cnt != aggr_pkt->txinfo.sta_cnt) {
 | 
						|
        ret |= (1<< REASON_DEST_MISMATCH);
 | 
						|
        iot_cus_printf("[gltx][aggrcheck]sta_cnt mismatch:%d vs %d\n",
 | 
						|
            in_pkt->txinfo.sta_cnt, aggr_pkt->txinfo.sta_cnt);
 | 
						|
 | 
						|
    } else {
 | 
						|
        if (os_mem_cmp(in_pkt->txinfo.dst_mac, aggr_pkt->txinfo.dst_mac,
 | 
						|
            (uint32_t)(in_pkt->txinfo.sta_cnt*IOT_MAC_ADDR_LEN))) {
 | 
						|
            ret |= 1<< REASON_DEST_MISMATCH;
 | 
						|
/*
 | 
						|
            iot_cus_printf("[gltx][aggrcheck]dst mac mismatch "\
 | 
						|
                "[%2x:%2x:%2x:%2x:%2x:%2x] vs [%2x:%2x:%2x:%2x:%2x:%2x]\n",
 | 
						|
                in_pkt->txinfo.dst_mac[0],in_pkt->txinfo.dst_mac[1],
 | 
						|
                in_pkt->txinfo.dst_mac[2],in_pkt->txinfo.dst_mac[3],
 | 
						|
                in_pkt->txinfo.dst_mac[4],in_pkt->txinfo.dst_mac[5],
 | 
						|
                aggr_pkt->txinfo.dst_mac[0],aggr_pkt->txinfo.dst_mac[1],
 | 
						|
                aggr_pkt->txinfo.dst_mac[2],aggr_pkt->txinfo.dst_mac[3],
 | 
						|
                aggr_pkt->txinfo.dst_mac[4],aggr_pkt->txinfo.dst_mac[5]);
 | 
						|
*/
 | 
						|
        }
 | 
						|
 | 
						|
        if (!iot_mac_addr_cmp(in_pkt->txinfo.org_mac,
 | 
						|
            aggr_pkt->txinfo.org_mac)) {
 | 
						|
            ret |= 1<< REASON_ORG_MAC_MISMATCH;
 | 
						|
/*            iot_cus_printf("[gltx][aggrcheck]org mac mismatch "\
 | 
						|
            "in[%2x:%2x:%2x:%2x:%2x:%2x] vs aggr[%2x:%2x:%2x:%2x:%2x:%2x]\n",
 | 
						|
            in_pkt->txinfo.org_mac[0],in_pkt->txinfo.org_mac[1],
 | 
						|
            in_pkt->txinfo.org_mac[2],in_pkt->txinfo.org_mac[3],
 | 
						|
            in_pkt->txinfo.org_mac[4],in_pkt->txinfo.org_mac[5],
 | 
						|
            aggr_pkt->txinfo.org_mac[0],aggr_pkt->txinfo.org_mac[1],
 | 
						|
            aggr_pkt->txinfo.org_mac[2],aggr_pkt->txinfo.org_mac[3],
 | 
						|
            aggr_pkt->txinfo.org_mac[4],aggr_pkt->txinfo.org_mac[5]);*/
 | 
						|
        }
 | 
						|
 | 
						|
        if (!iot_mac_addr_cmp(in_pkt->txinfo.src_mac,
 | 
						|
            aggr_pkt->txinfo.src_mac)) {
 | 
						|
            ret |= 1<< REASON_ORG_MAC_MISMATCH;
 | 
						|
/*            iot_cus_printf("[gltx][aggrcheck]src mac mismatch "\
 | 
						|
            "in[%2x:%2x:%2x:%2x:%2x:%2x] vs aggr[%2x:%2x:%2x:%2x:%2x:%2x]\n",
 | 
						|
            in_pkt->txinfo.src_mac[0],in_pkt->txinfo.src_mac[1],
 | 
						|
            in_pkt->txinfo.src_mac[2],in_pkt->txinfo.src_mac[3],
 | 
						|
            in_pkt->txinfo.src_mac[4],in_pkt->txinfo.src_mac[5],
 | 
						|
            aggr_pkt->txinfo.src_mac[0],aggr_pkt->txinfo.src_mac[1],
 | 
						|
            aggr_pkt->txinfo.src_mac[2],aggr_pkt->txinfo.src_mac[3],
 | 
						|
            aggr_pkt->txinfo.src_mac[4],aggr_pkt->txinfo.src_mac[5]);*/
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ((in_pkt->txinfo.retry_cnt != aggr_pkt->txinfo.retry_cnt)
 | 
						|
        || (in_pkt->txinfo.retry_intvl != aggr_pkt->txinfo.retry_intvl)) {
 | 
						|
        ret = 1<< REASON_RETRY_CFG_MISMATCH;
 | 
						|
    }
 | 
						|
 | 
						|
    if (in_pkt->txinfo.need_ack != aggr_pkt->txinfo.need_ack) {
 | 
						|
        ret |= 1<< REASON_ACK_OPT_MISMATCH;
 | 
						|
    }
 | 
						|
 | 
						|
    if (in_pkt->txinfo.send_type != aggr_pkt->txinfo.send_type) {
 | 
						|
        ret |= 1<< REASON_TYPE_MISMATCH;
 | 
						|
    }
 | 
						|
 | 
						|
    if (in_pkt->txinfo.force_tx_connless != aggr_pkt->txinfo.force_tx_connless) {
 | 
						|
        ret |= 1<< REASON_SEND_TYPE_FLAG_MISMATCH;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ret !=0){
 | 
						|
        iot_cus_printf("[gltx]no aggred reason: %x\n",ret);
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* internal command,
 | 
						|
 * proto layer request to set device mac, plc_txrx layer received,
 | 
						|
 * and set the device mac.
 | 
						|
 * both cco and sta role need handle this event
 | 
						|
 * @param mac: the mac address get from proto layer.
 | 
						|
 */
 | 
						|
void plctxrx_set_device_mac(uint8_t *mac, uint8_t dev_type)
 | 
						|
{
 | 
						|
    iot_plc_cfg_set_req_t cfg;
 | 
						|
 | 
						|
    IOT_ASSERT(mac);
 | 
						|
    iot_cus_printf("[gltx]set_device_mac:"
 | 
						|
        "%02x,%02x,%02x,%02x,%02x,%02x dev_type=%d\n",
 | 
						|
        mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],dev_type);
 | 
						|
 | 
						|
    os_mem_set(&cfg, 0, sizeof(cfg));
 | 
						|
    cfg.addr_valid = 1;
 | 
						|
    cfg.addr_type = IOT_PLC_MAC_ADDR_TYPE_METER;
 | 
						|
    iot_mac_addr_cpy(cfg.addr, mac);
 | 
						|
    cfg.reset = 1;
 | 
						|
    cfg.dev_type_valid = 1;
 | 
						|
    cfg.dev_type = dev_type;
 | 
						|
    iot_plc_set_cfg(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
 | 
						|
}
 | 
						|
 | 
						|
#if INCLUDE_AT_COMMAND_MODULE
 | 
						|
/* set system time from Gree keep-alive packet.
 | 
						|
 * will plug-into central beacon, and broadcast to all sta.
 | 
						|
 * sta will get time and generate Gree keep-alive packet self and
 | 
						|
 * report to host mcu.
 | 
						|
 */
 | 
						|
static uint32_t plctxrx_cco_set_keepalive(time_data_t *time)
 | 
						|
{
 | 
						|
    uint32_t ret;
 | 
						|
 | 
						|
    (void)time;
 | 
						|
 | 
						|
    /* save to local */
 | 
						|
    ret =  iot_plc_set_beacon_data(greeapp->app_handle,
 | 
						|
        (uint8_t*)&plctxrx_context.verinfo, sizeof(plctxrx_cmd_vendor_info_t));
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
/* cco dev use this api.
 | 
						|
 * add mac to whitelist or delete mac from whitelist.
 | 
						|
 */
 | 
						|
static void plctxrx_set_dev_whitelist(plctxrx_cmd_whitelist_t *list)
 | 
						|
{
 | 
						|
    uint8_t action = 0;
 | 
						|
    IOT_ASSERT(list);
 | 
						|
    iot_cus_printf("action:%d cnt:%d needack:%d\n", list->action,
 | 
						|
                  list->listcnt, plctxrx_context.command.need_ack);
 | 
						|
    /* transform action between protocol and plctxrx */
 | 
						|
    switch (list->action) {
 | 
						|
    case GE_PROTO_ACTION_DEL:
 | 
						|
        action = IOT_PLC_WL_DEL;
 | 
						|
        break;
 | 
						|
    case GE_PROTO_ACTION_ADD:
 | 
						|
        action = IOT_PLC_WL_ADD;
 | 
						|
        break;
 | 
						|
    case GE_PROTO_WL_DISABLE:
 | 
						|
        action = IOT_PLC_WL_DISABLE;
 | 
						|
        break;
 | 
						|
    case GE_PROTO_WL_ENABLE:
 | 
						|
        action = IOT_PLC_WL_ENABLE;
 | 
						|
        break;
 | 
						|
    case GE_PROTO_ACTION_DEL_ALL:
 | 
						|
        action = IOT_PLC_WL_DEL_ALL;
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (IOT_PLC_WL_ENABLE == action ||
 | 
						|
        IOT_PLC_WL_DISABLE == action ||
 | 
						|
        IOT_PLC_WL_DEL_ALL == action) {
 | 
						|
        iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
            action, 0, NULL);
 | 
						|
    } else if (list->listcnt > 0) {
 | 
						|
        for (uint8_t i = 0; i < list->listcnt; i++) {
 | 
						|
            iot_cus_printf("[gltx]whitelist-MAC[%d]"
 | 
						|
                ":%x:%x:%x:%x:%x:%x\n", i,
 | 
						|
                list->maclist[i][0], list->maclist[i][1],
 | 
						|
                list->maclist[i][2], list->maclist[i][3],
 | 
						|
                list->maclist[i][4], list->maclist[i][5]);
 | 
						|
        }
 | 
						|
        iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
            action, list->listcnt, list->maclist[0]);
 | 
						|
    } else {
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_WHITELIST, PLCTXRX_OP_CFM,
 | 
						|
            NULL, PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* cco dev use only. query current white list in cvg */
 | 
						|
static void plctxrx_request_dev_whitelist(iot_plc_wl_query_t *list)
 | 
						|
{
 | 
						|
    iot_cus_printf("request_dev_whitelist--start:%d count:%d\n",
 | 
						|
        list->start, list->count);
 | 
						|
    iot_plc_query_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
        list->start, list->count);
 | 
						|
}
 | 
						|
 | 
						|
/* for control mac info, set, query or response */
 | 
						|
static void plctxrx_handle_mac(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        plctxrx_handle_mac_t *mac_hd = (plctxrx_handle_mac_t*)arg->arg;
 | 
						|
        iot_mac_addr_cpy(plctxrx_context.local_state.sta_mac, mac_hd->mac);
 | 
						|
        plctxrx_set_device_mac(mac_hd->mac, mac_hd->dev_type);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        plctxrx_handle_mac_t mac_hd;
 | 
						|
        mac_hd.dev_type = 0;
 | 
						|
        iot_mac_addr_cpy(mac_hd.mac, plctxrx_context.local_state.sta_mac);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_MAC, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
            PLCTXRX_RESP_OK, (void*)&mac_hd, sizeof(plctxrx_handle_mac_t));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_time(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
#if INCLUDE_AT_COMMAND_MODULE
 | 
						|
    uint32_t ret;
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
 | 
						|
    time_data_t *time = (time_data_t*)arg->arg;
 | 
						|
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
        /* set time */
 | 
						|
        ret = plctxrx_cco_set_keepalive(time);
 | 
						|
        if(ret != ERR_OK)
 | 
						|
        {
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_TIME, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
                PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
#else
 | 
						|
    (void)arg;
 | 
						|
#endif
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_sys_info(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        /* query system info */
 | 
						|
        plctxrx_cmd_systeminfo_t sys_info;
 | 
						|
        os_mem_set(&sys_info, 0, sizeof(plctxrx_cmd_systeminfo_t));
 | 
						|
 | 
						|
        /* get system info and response */
 | 
						|
        iot_board_get_boot_reason(&sys_info.last_reboot_reason);
 | 
						|
        sys_info.total_reboot_times =
 | 
						|
            iot_board_get_reset_count(SYSTEM_RESET_PWR) +
 | 
						|
            iot_board_get_reset_count(SYSTEM_RESET_WDT) +
 | 
						|
            iot_board_get_reset_count(SYSTEM_RESET_SOFT);
 | 
						|
        sys_info.os_running_time = (uint32_t)os_boot_time64() / 1000;
 | 
						|
        sys_info.software_ver = iot_version_hex();
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_SYSTEMINFO, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
            PLCTXRX_RESP_OK, (void*)&sys_info, sizeof(plctxrx_cmd_systeminfo_t));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_uart(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
#if INCLUDE_AT_COMMAND_MODULE
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        /* set uart */
 | 
						|
        plctxrx_handle_uart_t *uart = (plctxrx_handle_uart_t*)arg->arg;
 | 
						|
        grapp_uart_cfg_t cfg;
 | 
						|
        os_mem_set(&cfg, 0 , sizeof(grapp_uart_cfg_t));
 | 
						|
        cfg.port = uart->uart_port;
 | 
						|
        cfg.baud = uart->bandrate;
 | 
						|
        cfg.parity = uart->parity;
 | 
						|
        cfg.data = uart->data_len;
 | 
						|
        cfg.stop = uart->stop_bit;
 | 
						|
 | 
						|
        if (iot_grapp_set_uart(greeapp->uart_com, &cfg)) {
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_UART, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
                PLCTXRX_RESP_OK, NULL, 0);
 | 
						|
        } else {
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_UART, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
                PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
#else
 | 
						|
    (void)arg;
 | 
						|
#endif
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_topo(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    plctxrx_cmd_query_topo_t *cmd;
 | 
						|
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        cmd = (plctxrx_cmd_query_topo_t*)arg->arg;
 | 
						|
        /* cmd->ver :1,2 topo info */
 | 
						|
        iot_cus_printf("txrx query topo: ver:%d, start:%d cnt:%d\n",
 | 
						|
            cmd->ver, cmd->start, cmd->cnt);
 | 
						|
        if (cmd->ver != IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0) {
 | 
						|
            iot_plc_query_nw_topo(greeapp->app_handle,
 | 
						|
            IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
 | 
						|
            cmd->ver,
 | 
						|
            IOT_PLC_QUERY_TOPO_START_AS_TEI,
 | 
						|
            cmd->start, cmd->cnt);
 | 
						|
        } else {
 | 
						|
            iot_cus_printf("topo V0 not support\n");
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#if INCLUDE_AT_COMMAND_MODULE
 | 
						|
static void plctxrx_handle_send(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    plctxrx_handle_send_t *send = (plctxrx_handle_send_t*)arg->arg;
 | 
						|
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_EXECUTE:
 | 
						|
    {
 | 
						|
        iot_cus_printf("\n[gltx]plctxrx_handle_send:%p datalen:%d\n",
 | 
						|
            send->data, send->dlen);
 | 
						|
        if (send->dlen <= TXRX_AGGR_PKT_LEN) {
 | 
						|
            iot_common_bin_dump(send->data , send->dlen);
 | 
						|
 | 
						|
            /* post msg direct to send enginee */
 | 
						|
            iot_plctxrx_proto_data_send_cbk(send->data, send->dlen,
 | 
						|
                &send->txinfo);
 | 
						|
        } else {
 | 
						|
            iot_cus_printf("\n[gltx][err] send->dlen need smaller than %d\n",
 | 
						|
                TXRX_AGGR_PKT_LEN);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    plctxrx_cmd_resp_data(PLCTXRX_CID_SEND, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
        PLCTXRX_RESP_OK, NULL, 0);
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static void plctxrx_handle_whitelist(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_whitelist_t *list = (plctxrx_cmd_whitelist_t*)arg->arg;
 | 
						|
        plctxrx_set_dev_whitelist(list);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        iot_plc_wl_query_t *list = (iot_plc_wl_query_t*)arg->arg;
 | 
						|
        if (list->count > 0)
 | 
						|
            plctxrx_request_dev_whitelist(list);
 | 
						|
        else
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_WHITELIST, PLCTXRX_OP_RESPONSE,
 | 
						|
                NULL, PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_find_network(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        /* to find avail network */
 | 
						|
        iot_plc_query_nb_nw_info(greeapp->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_join_network(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_join_network_t *net_info =
 | 
						|
            (plctxrx_cmd_join_network_t*)arg->arg;
 | 
						|
        /*  join the selected nid network */
 | 
						|
        //(void)join_info;
 | 
						|
        // MCU will send command to indicate which network we connect
 | 
						|
        iot_cus_printf("join_network--mac:%x:%x:%x:%x:%x:%x\n",
 | 
						|
                   net_info->mac[0],net_info->mac[1],net_info->mac[2],
 | 
						|
                   net_info->mac[3],net_info->mac[4],net_info->mac[5]
 | 
						|
                   );
 | 
						|
        iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
            IOT_PLC_WL_ADD, 1, net_info->mac);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_leave_network(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        /* leave the network */
 | 
						|
        plctxrx_cmd_leave_net_t *leave_net = (plctxrx_cmd_leave_net_t*)arg->arg;
 | 
						|
        iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
            IOT_PLC_WL_DEL, leave_net->cnt, (uint8_t*)leave_net->mac);
 | 
						|
        iot_cus_printf("[gltx]leave_network mac:%x:%x:%x:%x:%x:%x\n",
 | 
						|
            leave_net->mac[0][0],leave_net->mac[0][1],leave_net->mac[0][2],
 | 
						|
            leave_net->mac[0][3],leave_net->mac[0][4],leave_net->mac[0][5]);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_vendor_info(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    (void)arg;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_vendor_data(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_EXECUTE:
 | 
						|
    {
 | 
						|
        /* send data, cco will add to beacon for broadcast */
 | 
						|
        iot_plc_set_beacon_data(greeapp->app_handle, (uint8_t*)arg->arg,
 | 
						|
            (uint8_t)arg->dlen);
 | 
						|
        /* wait IOT_PLC_MSG_BEACON_DATA_SET_RPT */
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_ntb(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_ntb_resp_t resp_ntb = { 0 };
 | 
						|
        /* query network time base */
 | 
						|
 | 
						|
#if HW_PLATFORM == HW_PLATFORM_SIMU
 | 
						|
        resp_ntb.ntb = os_boot_time32()/25;
 | 
						|
#else
 | 
						|
        resp_ntb.ntb = iot_plc_get_ntb(greeapp->app_handle);
 | 
						|
#endif
 | 
						|
        iot_cus_printf("[getx]get ntb=%lu\n", resp_ntb.ntb);
 | 
						|
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_NTB, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
            PLCTXRX_RESP_OK, (void*)&resp_ntb, sizeof(plctxrx_cmd_ntb_resp_t));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_swver(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        /* query software version info */
 | 
						|
        plctxrx_cmd_software_ver_resp_t swver = { 0 };
 | 
						|
        swver.version = iot_version_hex();
 | 
						|
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_SWVER, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
            PLCTXRX_RESP_OK, (void*)&swver,
 | 
						|
            sizeof(plctxrx_cmd_software_ver_resp_t));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_bootinfo(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        /* query boot info */
 | 
						|
        plctxrx_cmd_boot_info_resp_t boot_info = { 0 };
 | 
						|
 | 
						|
        iot_board_get_boot_reason(&boot_info.last_reboot_reason);
 | 
						|
        boot_info.total_boot_cnt = (uint16_t)(
 | 
						|
            iot_board_get_reset_count(SYSTEM_RESET_PWR) +
 | 
						|
            iot_board_get_reset_count(SYSTEM_RESET_WDT) +
 | 
						|
            iot_board_get_reset_count(SYSTEM_RESET_SOFT));
 | 
						|
        boot_info.os_running_time = (uint32_t)os_boot_time64() / 1000;
 | 
						|
        /* post boot info to upper layer */
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_BOOTINFO, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
            PLCTXRX_RESP_OK, (void*)&boot_info,
 | 
						|
            sizeof(plctxrx_cmd_boot_info_resp_t));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_net_sts(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    uint8_t tmp_mac[IOT_MAC_ADDR_LEN] = { 0 };
 | 
						|
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        if (plctxrx_context.local_state.role == IOT_PLC_DEV_ROLE_CCO &&
 | 
						|
            iot_mac_addr_cmp(ge_bcast_addr, arg->arg)) {
 | 
						|
            /* query all joined states info, for cco */
 | 
						|
            iot_cus_printf("[gltx]query all net states\n");
 | 
						|
            iot_plc_query_neighbor_dev(greeapp->app_handle,
 | 
						|
                IOT_PLC_API_REQ_ID_DEFAULT, 2, STA_DEV_MAX,
 | 
						|
                IOT_PLC_QUERY_TOPO_START_AS_TEI);
 | 
						|
        } else if (iot_mac_addr_cmp(tmp_mac, arg->arg)){
 | 
						|
            iot_cus_printf("[gltx]query local net states\n");
 | 
						|
            iot_plc_query_neighbor_dev(
 | 
						|
                greeapp->app_handle,
 | 
						|
                IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
                plctxrx_context.local_state.sta_tei, 1,
 | 
						|
                IOT_PLC_QUERY_TOPO_START_AS_TEI);
 | 
						|
        } else {
 | 
						|
            /* find the mac whether in local list */
 | 
						|
            iot_mac_addr_cpy(tmp_mac, arg->arg);
 | 
						|
            int16_t index = iot_plctxrx_get_sta_indx_by_mac(tmp_mac);
 | 
						|
            if (index >= 0) {
 | 
						|
                iot_cus_printf("[gltx]query tei=%d net states\n",
 | 
						|
                    plctxrx_context.sta[index].sta_tei);
 | 
						|
                iot_plc_query_neighbor_dev(
 | 
						|
                    greeapp->app_handle,
 | 
						|
                    IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
                    plctxrx_context.sta[index].sta_tei, 1,
 | 
						|
                    IOT_PLC_QUERY_TOPO_START_AS_TEI);
 | 
						|
            } else {
 | 
						|
                iot_cus_printf("[gltx]query net state, tei error!\n");
 | 
						|
                plctxrx_cmd_resp_data(PLCTXRX_CID_NET_STS, PLCTXRX_OP_RESPONSE,
 | 
						|
                    NULL, PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief plctxrx_handle_node_info() - node infomation handler
 | 
						|
 * @param arg          the command handle argument include operation code and
 | 
						|
 *                     other parameter
 | 
						|
 */
 | 
						|
static void plctxrx_handle_node_info(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    plctxrx_cmd_query_node_info_t *query_node_info =
 | 
						|
        (plctxrx_cmd_query_node_info_t*)arg->arg;
 | 
						|
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        plctxrx_context.node_info_type = query_node_info->type;
 | 
						|
        if (iot_mac_addr_cmp(query_node_info->mac, ge_bcast_addr)) {
 | 
						|
            /* query all node info use query topo v0 */
 | 
						|
            iot_plc_query_nw_topo(greeapp->app_handle,
 | 
						|
                IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
 | 
						|
                IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0,
 | 
						|
                IOT_PLC_QUERY_TOPO_START_AS_TEI, 1,
 | 
						|
                QUERY_NODE_INFO_MAX_CNT_ONCE);
 | 
						|
        } else {
 | 
						|
            /* query one node info according to mac address use query node v0 */
 | 
						|
            iot_plc_query_node_info(greeapp->app_handle,
 | 
						|
                IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
 | 
						|
                IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0,
 | 
						|
                query_node_info->mac, 1);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief plctxrx_handle_nw_info() - nwtwork infomation handler
 | 
						|
 * @param arg          the command handler argument include operation code and
 | 
						|
 *                     other parameter
 | 
						|
 */
 | 
						|
static void plctxrx_handle_nw_info(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        /* query network info */
 | 
						|
        iot_plc_query_nw_info(greeapp->app_handle,
 | 
						|
            IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief plctxrx_handle_wdg() - watchdog handler
 | 
						|
 * @param arg          the command handler argument include operation code and
 | 
						|
 *                     other parameter
 | 
						|
 */
 | 
						|
static void plctxrx_handle_wdg(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_wdg_t *wdg = (plctxrx_cmd_wdg_t *)arg->arg;
 | 
						|
        iot_plc_wdg_set(greeapp->app_handle, wdg->action, wdg->interval);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief plctxrx_handle_mode_config() - mode config handler
 | 
						|
 * @param arg          the command handler argument include operation code and
 | 
						|
 *                     other parameter
 | 
						|
 */
 | 
						|
static void plctxrx_handle_mode_config(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        dev_test_mode_cfg_t *cfg = (dev_test_mode_cfg_t *)arg->arg;
 | 
						|
        iot_dev_test_send_mode_config(cfg);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_MODE_CONF, PLCTXRX_OP_CFM, NULL,
 | 
						|
            PLCTXRX_RESP_OK, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/* TODO add plc_txrx_statics_t query command here */
 | 
						|
 | 
						|
/* internal command,
 | 
						|
 * cco device receive cmd to start group net, set group net state.
 | 
						|
 * @param arg:        command message
 | 
						|
 */
 | 
						|
static void plctxrx_handle_txrx_sts(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        plc_txrx_statics_t *txrx_state =
 | 
						|
            &plctxrx_context.local_state.txrx_status;
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_TXRX_STS, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
            PLCTXRX_RESP_OK, txrx_state, sizeof(plc_txrx_statics_t));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_start_group_net(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        /* disable whitelist and set status */
 | 
						|
        iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
            IOT_PLC_WL_DISABLE, 0, NULL);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/* internal command,
 | 
						|
 * cco device receive cmd to end group net, set end group net state.
 | 
						|
 * @param arg:        command message
 | 
						|
 */
 | 
						|
static void plctxrx_handle_end_group_net(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        /* add white list and then enable whitelist */
 | 
						|
        iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
            IOT_PLC_WL_ENABLE, 0, NULL);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/* internal command,
 | 
						|
 * set, query or response the tx power.
 | 
						|
 * @param arg:        command message
 | 
						|
 */
 | 
						|
static void plctxrx_handle_tx_pwr(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_tx_pwr_t *tx_pwr = (plctxrx_cmd_tx_pwr_t*)arg->arg;
 | 
						|
        iot_plc_set_tx_power_cap(greeapp->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT, &tx_pwr->tx_pwr, NULL);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        iot_plc_query_band_info(greeapp->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/* internal command,
 | 
						|
 * set network id
 | 
						|
 * @param arg:        command message
 | 
						|
 */
 | 
						|
static void plctxrx_handle_nid(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_nid_t *net_nid = (plctxrx_cmd_nid_t*)arg->arg;
 | 
						|
        if (net_nid->nid > 99) {
 | 
						|
            plctxrx_cmd_resp_data(PLCTXRX_CID_NID,
 | 
						|
                PLCTXRX_OP_CFM, NULL, PLCTXRX_RESP_ERROR, NULL, 0);
 | 
						|
        } else {
 | 
						|
            iot_cus_printf("[gltx]set nid=%d\n", net_nid->nid);
 | 
						|
            iot_plc_set_nid(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
                net_nid->nid);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/* internal command,
 | 
						|
 * delete the sta's information after sta leaving network positivly
 | 
						|
 * @param arg:        command message
 | 
						|
 */
 | 
						|
static void plctxrx_handle_sta_pos_leave(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_sta_pos_leave_ind_t *sta_info =
 | 
						|
            (plctxrx_cmd_sta_pos_leave_ind_t*)arg->arg;
 | 
						|
        iot_plctxrx_del_sta_by_mac(sta_info->mac);
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_STA_POS_LEAVE,
 | 
						|
                PLCTXRX_OP_CFM, NULL, PLCTXRX_RESP_OK, NULL, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/* internal command,
 | 
						|
 * band id set and query
 | 
						|
 * @param arg:        command message
 | 
						|
 */
 | 
						|
static void plctxrx_handle_band_id(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        if (plctxrx_context.local_state.role == IOT_PLC_DEV_ROLE_CCO ||
 | 
						|
            greeapp->uart_mode == GR_DEV_TEST_OP_MODE) {
 | 
						|
            plctxrx_cmd_band_info_t *band_info =
 | 
						|
                (plctxrx_cmd_band_info_t*)arg->arg;
 | 
						|
            iot_cus_printf("[gltx]set freq_band=%d\n",band_info->band_id);
 | 
						|
            iot_plc_set_freq_band(greeapp->app_handle,
 | 
						|
                IOT_PLC_API_REQ_ID_DEFAULT, band_info->band_id);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        if (plctxrx_context.local_state.role == IOT_PLC_DEV_ROLE_CCO) {
 | 
						|
            iot_cus_printf("[gltx]query freq_band\n");
 | 
						|
            iot_plc_query_band_info(greeapp->app_handle,
 | 
						|
                IOT_PLC_API_REQ_ID_DEFAULT);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/* internal command,
 | 
						|
 * STA set band bitmap
 | 
						|
 * @param arg:        command message
 | 
						|
 */
 | 
						|
static void plctxrx_handle_fb_bitmap(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        plctxrx_cmd_fb_bitmap_t *band_bitmap =
 | 
						|
            (plctxrx_cmd_fb_bitmap_t*)arg->arg;
 | 
						|
        iot_plc_set_scan_band_bitmap(greeapp->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT, band_bitmap->fb_bitmap,
 | 
						|
            IOT_GE_FB_SCAN_BITMAP_SIZE);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        uint8_t is_scan_bitmap = arg->arg[0];
 | 
						|
        IOT_ASSERT(is_scan_bitmap <= 1);
 | 
						|
        iot_plc_query_band_bitmap(greeapp->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT, is_scan_bitmap);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void plctxrx_handle_fix_rate_mode(plctxrx_cmd_arg_t *arg)
 | 
						|
{
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
    switch (arg->cid.opcode) {
 | 
						|
    case PLCTXRX_OP_CONFIG:
 | 
						|
    {
 | 
						|
        /* 1:Fix rate mode 2:auto rate mode */
 | 
						|
        uint8_t rate_mode;
 | 
						|
        plctxrx_cmd_fix_rate_t *fix_rate =
 | 
						|
            (plctxrx_cmd_fix_rate_t*)arg->arg;
 | 
						|
        IOT_ASSERT(fix_rate->fix_rate_mode <= 1);
 | 
						|
        if (1 == fix_rate->fix_rate_mode) {
 | 
						|
            /* fix rate mode */
 | 
						|
            rate_mode = GE_PLC_RATE_ADAPT_FIX_MODE;
 | 
						|
        } else {
 | 
						|
            /* auto rate mode */
 | 
						|
            rate_mode = GE_PLC_RATE_ADAPT_AUTO_MODE;
 | 
						|
        }
 | 
						|
        plctxrx_context.local_state.rate_node = rate_mode;
 | 
						|
        iot_plc_set_rate_adapt_mode(greeapp->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT, IOT_PLC_RATE_ADAPT_NODE_NETWORK,
 | 
						|
            rate_mode, IOT_PLC_RATE_ADAPT_RATE_LOW);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PLCTXRX_OP_QUERY:
 | 
						|
    {
 | 
						|
        uint8_t rate_node_rpt;
 | 
						|
        if (plctxrx_context.local_state.rate_node == 1) {
 | 
						|
            rate_node_rpt = 1;
 | 
						|
        } else {
 | 
						|
            rate_node_rpt = 0;
 | 
						|
        }
 | 
						|
        plctxrx_cmd_resp_data(PLCTXRX_CID_FIXED_RATE, PLCTXRX_OP_RESPONSE, NULL,
 | 
						|
            PLCTXRX_RESP_OK, (void*)&rate_node_rpt, sizeof(rate_node_rpt));
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static plctxrx_handle handle_table[PLCTXRX_CID_MAX] =
 | 
						|
{
 | 
						|
    plctxrx_handle_mac,             //PLCTXRX_CID_MAC
 | 
						|
    plctxrx_handle_time,            //PLCTXRX_CID_TIME
 | 
						|
    plctxrx_handle_bootinfo,        //PLCTXRX_CID_BOOTINFO
 | 
						|
    plctxrx_handle_uart,            //PLCTXRX_CID_UART
 | 
						|
    plctxrx_handle_topo,            //PLCTXRX_CID_TOPO
 | 
						|
#if INCLUDE_AT_COMMAND_MODULE
 | 
						|
    plctxrx_handle_send,            //PLCTXRX_CID_SEND
 | 
						|
#endif
 | 
						|
    plctxrx_handle_whitelist,       //PLCTXRX_CID_WHITELIST
 | 
						|
    plctxrx_handle_find_network,    //PLCTXRX_CID_FIND_NETWORK
 | 
						|
    plctxrx_handle_join_network,    //PLCTXRX_CID_JOIN_NETWORK
 | 
						|
    plctxrx_handle_leave_network,   //PLCTXRX_CID_LEAVE_NETWORK
 | 
						|
    NULL,                           //PLCTXRX_CID_CCO_STATE
 | 
						|
    plctxrx_handle_vendor_info,     //PLCTXRX_CID_VENDOR_INFO
 | 
						|
    plctxrx_handle_swver,           //PLCTXRX_CID_SWVER
 | 
						|
    plctxrx_handle_sys_info,        //PLCTXRX_CID_SYSTEMINFO
 | 
						|
    plctxrx_handle_net_sts,         //PLCTXRX_CID_NET_STS
 | 
						|
    plctxrx_handle_start_group_net, //PLCTXRX_CID_START_GROUP_NET
 | 
						|
    plctxrx_handle_end_group_net,   //PLCTXRX_CID_END_GROUP_NET
 | 
						|
    plctxrx_handle_txrx_sts,        //PLCTXRX_CID_TXRX_STS
 | 
						|
    plctxrx_handle_tx_pwr,          //PLCTXRX_CID_TX_PWR
 | 
						|
    plctxrx_handle_nid,             //PLCTXRX_CID_NID
 | 
						|
    NULL,                           //PLCTXRX_CID_COMM_FAULT
 | 
						|
    NULL,                           //PLCTXRX_CID_GRAPP_REG_CONF
 | 
						|
    plctxrx_handle_sta_pos_leave,   //PLCTXRX_CID_STA_POS_LEAVE
 | 
						|
    plctxrx_handle_band_id,         //PLCTXRX_CID_BAND_ID
 | 
						|
    plctxrx_handle_vendor_data,     //PLCTXRX_CID_VENDOR_DATA
 | 
						|
    plctxrx_handle_ntb,             //PLCTXRX_CID_NTB
 | 
						|
    plctxrx_handle_fb_bitmap,       //PLCTXRX_CID_FB_BITMAP
 | 
						|
    plctxrx_handle_fix_rate_mode,   //PLCTXRX_CID_FIXED_RATE
 | 
						|
    plctxrx_handle_node_info,       //PLCTXRX_CID_NODE_INFO
 | 
						|
    plctxrx_handle_nw_info,         //PLCTXRX_CID_NW_INFO
 | 
						|
    plctxrx_handle_wdg,             //PLCTXRX_CID_WDG
 | 
						|
    plctxrx_handle_mode_config      //PLCTXRX_CID_MODE_CONF
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
void plctxrx_cmd_resp_send_to_proto(iot_pkt_t *pkt)
 | 
						|
{
 | 
						|
    IOT_ASSERT(pkt);
 | 
						|
    if (greeapp->uart_mode == GR_AT_OP_MODE) {
 | 
						|
        plctxrx_context.at_cb.at_cmd_resp_cb(pkt);
 | 
						|
    } else if (greeapp->uart_mode == GR_MCU_OP_MODE) {
 | 
						|
        plctxrx_context.gree_cb.gree_network_event_cb(pkt);
 | 
						|
    } else if (greeapp->uart_mode == GR_DEV_TEST_OP_MODE) {
 | 
						|
        plctxrx_context.dev_test_cb.dev_test_event_cb(pkt);
 | 
						|
    } else {
 | 
						|
        /* drop this command. */
 | 
						|
        iot_pkt_free(pkt);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
   cur_cid: current handling cid
 | 
						|
   cur_opcode: current handling opcode
 | 
						|
   cur_resp_pkt : current response pkt.
 | 
						|
   each handle cmd first push in saveq, when handle complete, then,
 | 
						|
   cmd will pop from saveq and push in freeq.
 | 
						|
*/
 | 
						|
void plctxrx_cmd_handle_next(uint8_t cur_cid, uint8_t cur_opcode,
 | 
						|
                        iot_pkt_t *cur_resp_pkt)
 | 
						|
{
 | 
						|
    iot_pkt_t *savecmd_pkt;
 | 
						|
    plctxrx_cmd_arg_t *arg;
 | 
						|
    plctxrx_cmdsave_node_t *cmd_node;
 | 
						|
 | 
						|
    (void)cur_opcode;
 | 
						|
    IOT_ASSERT(plctxrx_context.command.cmd_running);
 | 
						|
 | 
						|
    cmd_node =
 | 
						|
        iot_plctxrx_commandnode_pop_front(&plctxrx_context.command.save_q,
 | 
						|
        PLCTXRX_SAVEQ);
 | 
						|
    if(cmd_node == NULL){
 | 
						|
        goto no_next;
 | 
						|
    }
 | 
						|
    savecmd_pkt = (iot_pkt_t *)cmd_node->data;
 | 
						|
    arg = (plctxrx_cmd_arg_t*)iot_pkt_data(savecmd_pkt);
 | 
						|
    iot_cus_printf("cur_cid = %d,arg->cid.cid = %d\n",cur_cid,arg->cid.cid);
 | 
						|
    if (cur_cid != arg->cid.cid) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    /* check if response need send to protocol layer */
 | 
						|
    if (arg->need_ack) {
 | 
						|
        plctxrx_cmd_resp_send_to_proto(cur_resp_pkt);
 | 
						|
    } else {
 | 
						|
        iot_pkt_free(cur_resp_pkt);
 | 
						|
    }
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]handle_next--Need ack: %d!\n", arg->need_ack);
 | 
						|
    /* free packet saved in cmdnode */
 | 
						|
    iot_pkt_free(savecmd_pkt);
 | 
						|
    /* free current node */
 | 
						|
    cmd_node->data = NULL;
 | 
						|
    /* push node into free cmd queue */
 | 
						|
    iot_plctxrx_commandnode_push_backend(&plctxrx_context.command.free_q,
 | 
						|
        &cmd_node->node, PLCTXRX_FREEQ);
 | 
						|
    /* check if next command is exist */
 | 
						|
    cmd_node =
 | 
						|
        iot_plctxrx_commandnode_get_front(&plctxrx_context.command.save_q,
 | 
						|
        PLCTXRX_SAVEQ);
 | 
						|
    if (cmd_node) {
 | 
						|
        /* handle next command */
 | 
						|
        IOT_ASSERT(cmd_node->data);
 | 
						|
        arg = (plctxrx_cmd_arg_t*)iot_pkt_data((iot_pkt_t *)cmd_node->data);
 | 
						|
        iot_cus_printf("[gltx]handle_next--"
 | 
						|
            "next cmd=%d, opcode=%d\n", arg->cid.cid, arg->cid.opcode);
 | 
						|
        plctxrx_context.command.cur_cid = arg->cid;
 | 
						|
        plctxrx_context.command.cmd_running = true;
 | 
						|
        plctxrx_context.command.need_ack    = (bool_t)arg->need_ack;
 | 
						|
        plctxrx_context.command.table.handle[arg->cid.cid](arg);
 | 
						|
    } else {
 | 
						|
no_next:
 | 
						|
        plctxrx_context.command.cmd_running = false;
 | 
						|
        plctxrx_context.command.need_ack = false;
 | 
						|
        iot_cus_printf("[gltx]handle_next--NO next cmd exists!\n");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void plctxrx_cmd_resp_data_pkt(uint8_t handle_next, uint8_t oper_code,
 | 
						|
    iot_pkt_t *pkt)
 | 
						|
{
 | 
						|
    IOT_ASSERT(pkt);
 | 
						|
 | 
						|
    if(handle_next)
 | 
						|
    {
 | 
						|
        plctxrx_cmd_handle_next(plctxrx_context.command.cur_cid.cid,
 | 
						|
            oper_code, pkt);
 | 
						|
    } else {
 | 
						|
        plctxrx_cmd_resp_send_to_proto(pkt);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void plctxrx_cmd_resp_data(uint8_t cmd_id, uint8_t oper_code,
 | 
						|
    plctxrx_resp_idx_t *index, uint16_t resp, void *data, uint16_t data_len)
 | 
						|
{
 | 
						|
 | 
						|
    iot_pkt_t *pkt = iot_pkt_alloc(data_len + sizeof(plctxrx_cmd_resp_t),
 | 
						|
        IOT_GREE_APP_MID);
 | 
						|
    iot_cus_printf("[gltx]resp_data--cid=%d,op_code=%d,resp=%d\n",
 | 
						|
        cmd_id, oper_code, resp);
 | 
						|
 | 
						|
    if (!pkt) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    plctxrx_cmd_resp_t *cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(pkt);
 | 
						|
    cmd_resp->cid.cid = cmd_id;
 | 
						|
    cmd_resp->cid.opcode = oper_code;
 | 
						|
    if (index) {
 | 
						|
        cmd_resp->index.current = index->current;
 | 
						|
        cmd_resp->index.total = index->total;
 | 
						|
    } else {
 | 
						|
        cmd_resp->index.current = 1;
 | 
						|
        cmd_resp->index.total = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    cmd_resp->resp = resp;
 | 
						|
 | 
						|
    if (data_len && data) {
 | 
						|
        os_mem_cpy(cmd_resp->data, data, data_len);
 | 
						|
        cmd_resp->dlen = data_len;
 | 
						|
 | 
						|
        iot_pkt_put(pkt, sizeof(plctxrx_cmd_resp_t) + data_len);
 | 
						|
    }
 | 
						|
 | 
						|
    if (oper_code != PLCTXRX_OP_INDICATION &&
 | 
						|
        (cmd_resp->index.total == cmd_resp->index.current)) {
 | 
						|
        plctxrx_cmd_handle_next(plctxrx_context.command.cur_cid.cid,
 | 
						|
            oper_code, pkt);
 | 
						|
    } else {
 | 
						|
        plctxrx_cmd_resp_send_to_proto(pkt);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void plctxrx_cmd_msg_handle(iot_pkt_t *arg_pkt)
 | 
						|
{
 | 
						|
    plctxrx_cmd_arg_t *arg = (plctxrx_cmd_arg_t*)iot_pkt_data(arg_pkt);
 | 
						|
    IOT_ASSERT(arg);
 | 
						|
 | 
						|
    uint8_t cid = arg->cid.cid & 0xFFFFFF;
 | 
						|
    plctxrx_cmdsave_node_t *cmd_node;
 | 
						|
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]cmd_msg_handle--cid=%d,op_code=%d\n",
 | 
						|
        cid, arg->cid.opcode);
 | 
						|
    if (cid >= PLCTXRX_CID_MAX) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    cmd_node =
 | 
						|
        iot_plctxrx_commandnode_pop_front(&plctxrx_context.command.free_q,
 | 
						|
        PLCTXRX_FREEQ);
 | 
						|
 | 
						|
    IOT_ASSERT(cmd_node);
 | 
						|
 | 
						|
    if(!cmd_node)
 | 
						|
    {
 | 
						|
       iot_cus_printf("[gltx]cmd_freeq no free");
 | 
						|
       return;
 | 
						|
    }
 | 
						|
    /** Note: Any cmd will be pushed to save queue.
 | 
						|
     *  And we will pop it out when response cmd.
 | 
						|
    */
 | 
						|
    cmd_node->data = (void *)arg_pkt;
 | 
						|
    iot_plctxrx_commandnode_push_backend(&plctxrx_context.command.save_q,
 | 
						|
        &cmd_node->node, PLCTXRX_SAVEQ);
 | 
						|
    /* check if cmd_running is false. */
 | 
						|
    if (plctxrx_context.command.cmd_running == false)
 | 
						|
    {
 | 
						|
        plctxrx_context.command.cur_cid = arg->cid;
 | 
						|
        plctxrx_context.command.cmd_running = true;
 | 
						|
        plctxrx_context.command.need_ack    = (bool_t)arg->need_ack;
 | 
						|
        plctxrx_context.command.table.handle[cid](arg);
 | 
						|
    } else {
 | 
						|
        iot_cus_printf("[gltx][war]pre-cmd:%d"\
 | 
						|
            " running cur-cmd:%d handle later!\n",
 | 
						|
            plctxrx_context.command.cur_cid.cid, arg->cid.cid);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* proto layer send message, plctxrx layer use */
 | 
						|
uint8_t plctxrx_cmd_send_mssage(iot_pkt_t *arg)
 | 
						|
{
 | 
						|
    iot_plctxrx_post_msg(IOT_PLCTXRX_CMD_MSG, 0, arg, 0);
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
/* end cmd handle */
 | 
						|
 | 
						|
uint8_t iot_plctxrx_proto_register(proto_recv_cb datacb,
 | 
						|
    proto_network_event_cb netcb, proto_vendr_cb vendrcb)
 | 
						|
{
 | 
						|
    uint8_t ret = ERR_FAIL;
 | 
						|
 | 
						|
    if (datacb && netcb && vendrcb) {
 | 
						|
       plctxrx_context.gree_cb.gree_proto_recv_cb    = datacb;
 | 
						|
       plctxrx_context.gree_cb.gree_network_event_cb = netcb;
 | 
						|
       plctxrx_context.gree_cb.gree_vendr_cb         = vendrcb;
 | 
						|
       ret = ERR_OK;
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t iot_plctxrx_at_register(at_resp_cb at_cb)
 | 
						|
{
 | 
						|
    uint8_t ret = ERR_FAIL;
 | 
						|
 | 
						|
    if (at_cb) {
 | 
						|
      plctxrx_context.at_cb.at_cmd_resp_cb = at_cb;
 | 
						|
      ret = ERR_OK;
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t iot_plctxrx_dev_test_register(dev_test_recv_cb_t recv_cb,
 | 
						|
    dev_test_event_cb_t event_cb)
 | 
						|
{
 | 
						|
    uint8_t ret = ERR_FAIL;
 | 
						|
 | 
						|
    if (recv_cb && event_cb) {
 | 
						|
        plctxrx_context.dev_test_cb.dev_test_recv_cb = recv_cb;
 | 
						|
        plctxrx_context.dev_test_cb.dev_test_event_cb = event_cb;
 | 
						|
        ret = ERR_OK;
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
   two queues. cmd free queue and save queue. used for cache cmd and
 | 
						|
   process one by one
 | 
						|
*/
 | 
						|
void iot_plctxrx_cmd_freeq_init()
 | 
						|
{
 | 
						|
    uint8_t i;
 | 
						|
 | 
						|
    os_mem_set(g_cmdhandle_node, 0,
 | 
						|
        sizeof(plctxrx_cmdsave_node_t) * IOT_PLCTXRX_CMD_MAX_CNT);
 | 
						|
    /* link node */
 | 
						|
    for (i = 1; i < IOT_PLCTXRX_CMD_MAX_CNT; i++) {
 | 
						|
        g_cmdhandle_node[i-1].node.next = &g_cmdhandle_node[i].node;
 | 
						|
    }
 | 
						|
    /* point to tail */
 | 
						|
    g_cmdhandle_node[i-1].node.next = NULL;
 | 
						|
 | 
						|
    plctxrx_context.command.free_q.first =
 | 
						|
                        &g_cmdhandle_node[0].node;
 | 
						|
    plctxrx_context.command.free_q.tail  =
 | 
						|
                        &g_cmdhandle_node[i-1].node;
 | 
						|
    plctxrx_context.command.free_q.depth = IOT_PLCTXRX_CMD_MAX_CNT;
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_cmd_saveq_init()
 | 
						|
{
 | 
						|
    os_mem_set(&plctxrx_context.command.save_q, 0,
 | 
						|
        sizeof(plctxrx_cmdsave_list_t));
 | 
						|
}
 | 
						|
 | 
						|
plctxrx_cmdsave_node_t *
 | 
						|
iot_plctxrx_commandnode_pop_front(plctxrx_cmdsave_list_t *cmdq,
 | 
						|
                                                cmd_queue_e_t qtype)
 | 
						|
{
 | 
						|
    list_node_t  *link;
 | 
						|
    plctxrx_cmdsave_node_t *ret_node;
 | 
						|
    if (cmdq->depth <= 0) {
 | 
						|
        IOT_ASSERT(!cmdq->first && !cmdq->tail);
 | 
						|
        iot_cus_printf("[gltx][war]cmd pop front:cmdq[%d] is empty!\n", qtype);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (cmdq->first == cmdq->tail) {
 | 
						|
        IOT_ASSERT(1 == cmdq->depth);
 | 
						|
        link = cmdq->first;
 | 
						|
        cmdq->first = cmdq->tail = NULL;
 | 
						|
        link->next = NULL;
 | 
						|
    } else {
 | 
						|
        link = cmdq->first;
 | 
						|
        cmdq->first = link->next;
 | 
						|
    }
 | 
						|
    cmdq->depth--;
 | 
						|
    ret_node = container_of(link, plctxrx_cmdsave_node_t, node);
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]cmd pop front--queue type:%d"
 | 
						|
        "queue depth=%d,ret_node=0x%x!\n", qtype, cmdq->depth, ret_node);
 | 
						|
    return ret_node;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_plctxrx_commandnode_get_front() - get the first data without pop
 | 
						|
 * @param cmdq: the list to get data
 | 
						|
 * @param cmdq: the type of the data
 | 
						|
 * @result : the first data of the list
 | 
						|
 */
 | 
						|
plctxrx_cmdsave_node_t *
 | 
						|
iot_plctxrx_commandnode_get_front(plctxrx_cmdsave_list_t *cmdq,
 | 
						|
                                                cmd_queue_e_t qtype)
 | 
						|
{
 | 
						|
    list_node_t  *link;
 | 
						|
    plctxrx_cmdsave_node_t *ret_node;
 | 
						|
    if (cmdq->depth <= 0) {
 | 
						|
        IOT_ASSERT(!cmdq->first && !cmdq->tail);
 | 
						|
        iot_cus_printf("[gltx][war]cmd pop front:cmdq[%d] is empty!\n", qtype);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    link = cmdq->first;
 | 
						|
    ret_node = container_of(link, plctxrx_cmdsave_node_t, node);
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]cmd nopop front--queue type:%d"
 | 
						|
        "queue depth=%d,ret_node=0x%x!\n", qtype, cmdq->depth, ret_node);
 | 
						|
    return ret_node;
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_commandnode_push_backend(plctxrx_cmdsave_list_t *cmdq,
 | 
						|
                                list_node_t *node, cmd_queue_e_t qtype)
 | 
						|
{
 | 
						|
    if (0 == cmdq->depth) {
 | 
						|
        IOT_ASSERT(!cmdq->first && !cmdq->tail);
 | 
						|
        cmdq->first = cmdq->tail = node;
 | 
						|
    } else {
 | 
						|
        cmdq->tail->next = node;
 | 
						|
        cmdq->tail = node;
 | 
						|
    }
 | 
						|
    node->next = NULL;
 | 
						|
    cmdq->depth++;
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]push_back--type:%d, queue depth=%d\n",
 | 
						|
        qtype, cmdq->depth);
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
int iot_plctxrx_task_init(void)
 | 
						|
{
 | 
						|
    uint8_t ret = ERR_OK;
 | 
						|
    uint16_t i;
 | 
						|
    iot_task_config_t task_cfg;
 | 
						|
 | 
						|
    os_mem_set(&plctxrx_context, 0, sizeof(plctxrx_contxt_t));
 | 
						|
 | 
						|
    os_mem_set(&gbl_protpkt, 0x0, sizeof(gbl_protpkt));
 | 
						|
 | 
						|
    task_cfg.stack_size = 0;
 | 
						|
    task_cfg.task_prio = IOT_PLCUART_TASK_PRIO;
 | 
						|
    task_cfg.msg_size = sizeof(plctxrx_task_msg_t);
 | 
						|
    task_cfg.msg_cnt = IOT_PLCTXRX_TASK_POOL_SIZE;
 | 
						|
    task_cfg.queue_cnt = 1;
 | 
						|
    task_cfg.queue_cfg[0].quota = 0;
 | 
						|
    task_cfg.msg_exe_func = iot_plctxrx_task_msg_exe;
 | 
						|
    task_cfg.msg_cancel_func = iot_plctxrx_task_msg_cancel;
 | 
						|
 | 
						|
    plctxrx_context.task_handle = iot_task_create(IOT_GREE_APP_MID, &task_cfg);
 | 
						|
 | 
						|
    plctxrx_context.link_id = IOT_PLCTXRX_TASK_LIKE_ID;
 | 
						|
 | 
						|
    if (NULL == plctxrx_context.task_handle)
 | 
						|
    {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto error_0;
 | 
						|
    }
 | 
						|
 | 
						|
    plctxrx_context.datapath_timer = os_create_timer(IOT_GREE_APP_MID, 0,
 | 
						|
        iot_plctxrx_timer_data_path_func, &plctxrx_context);
 | 
						|
    if (plctxrx_context.datapath_timer == 0) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto error_1;
 | 
						|
    }
 | 
						|
 | 
						|
    plctxrx_context.txrx_timer = os_create_timer(IOT_GREE_APP_MID, 1,
 | 
						|
        iot_plctxrx_timer_txrx_path_func, &plctxrx_context);
 | 
						|
    if (plctxrx_context.txrx_timer == 0) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto error_2;
 | 
						|
    }
 | 
						|
 | 
						|
    os_start_timer(plctxrx_context.txrx_timer, IOT_PLCTXRX_TXRX_TIMER_INTVAL);
 | 
						|
 | 
						|
    plctxrx_context.aggr_timer = os_create_timer(IOT_GREE_APP_MID, 0,
 | 
						|
        iot_plctxrx_timer_aggr_path_func, &plctxrx_context);
 | 
						|
    if (plctxrx_context.aggr_timer == 0) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto error_3;
 | 
						|
    }
 | 
						|
 | 
						|
    plctxrx_context.command.table.handle = handle_table;
 | 
						|
 | 
						|
 | 
						|
   /* init free queue and put all free proto pkt in queue */
 | 
						|
    plctxrx_context.sendq = os_mem_malloc(IOT_GREE_APP_MID,
 | 
						|
        sizeof(prot_pktq_t));
 | 
						|
    if (plctxrx_context.sendq == NULL) {
 | 
						|
        ret = ERR_NOMEM;
 | 
						|
        goto error_4;
 | 
						|
    }
 | 
						|
 | 
						|
    plctxrx_context.freeq = os_mem_malloc(IOT_GREE_APP_MID,
 | 
						|
        sizeof(prot_pktq_t));
 | 
						|
    if (plctxrx_context.freeq == NULL) {
 | 
						|
        ret = ERR_NOMEM;
 | 
						|
        goto error_5;
 | 
						|
    }
 | 
						|
    iot_plctxrx_queue_init(plctxrx_context.sendq);
 | 
						|
    iot_plctxrx_queue_init(plctxrx_context.freeq);
 | 
						|
 | 
						|
    plctxrx_context.sendq->lock = os_create_mutex(IOT_GREE_APP_MID);
 | 
						|
    if (plctxrx_context.sendq->lock == NULL) {
 | 
						|
        ret = ERR_NOMEM;
 | 
						|
        goto error_6;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    plctxrx_context.freeq->lock = os_create_mutex(IOT_GREE_APP_MID);
 | 
						|
    if (plctxrx_context.freeq->lock == NULL) {
 | 
						|
        ret = ERR_NOMEM;
 | 
						|
        goto error_7;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    for (i = 0; i < TXRX_SEND_BUFF_POOL_NUM; i++) {
 | 
						|
        iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, &gbl_protpkt[i].node);
 | 
						|
    }
 | 
						|
 | 
						|
    /* allocate list for aggr data split to upper layer */
 | 
						|
    ret = iot_plctxrx_list_init();
 | 
						|
    if (ret) {
 | 
						|
        goto error_8;
 | 
						|
    }
 | 
						|
 | 
						|
    /* init local device */
 | 
						|
#if (HW_PLATFORM == HW_PLATFORM_SIMU)
 | 
						|
    if (ucIsClientMode == 0) {
 | 
						|
       plctxrx_context.nw_role  = IOT_PLC_DEV_ROLE_CCO;
 | 
						|
    } else {
 | 
						|
       plctxrx_context.nw_role =  IOT_PLC_DEV_ROLE_STA;
 | 
						|
    }
 | 
						|
#else
 | 
						|
 | 
						|
#if PLC_SUPPORT_CCO_ROLE
 | 
						|
    plctxrx_context.nw_role  = IOT_PLC_DEV_ROLE_CCO;
 | 
						|
#else
 | 
						|
    plctxrx_context.nw_role =  IOT_PLC_DEV_ROLE_STA;
 | 
						|
#endif
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
    /* init  command free queue */
 | 
						|
    iot_plctxrx_cmd_freeq_init();
 | 
						|
    /* init  command save queue */
 | 
						|
    iot_plctxrx_cmd_saveq_init();
 | 
						|
 | 
						|
    iot_cus_printf("[gltx]plctxrx task init succ!\n");
 | 
						|
 | 
						|
    goto success;
 | 
						|
 | 
						|
error_8:
 | 
						|
    os_delete_mutex(plctxrx_context.freeq->lock);
 | 
						|
error_7:
 | 
						|
    os_delete_mutex(plctxrx_context.sendq->lock);
 | 
						|
error_6:
 | 
						|
    os_mem_free(plctxrx_context.freeq);
 | 
						|
error_5:
 | 
						|
    os_mem_free(plctxrx_context.sendq);
 | 
						|
error_4:
 | 
						|
    os_delete_timer(plctxrx_context.aggr_timer);
 | 
						|
error_3:
 | 
						|
    os_delete_timer(plctxrx_context.txrx_timer);
 | 
						|
error_2:
 | 
						|
    os_delete_timer(plctxrx_context.datapath_timer);
 | 
						|
error_1:
 | 
						|
    iot_task_delete(plctxrx_context.task_handle);
 | 
						|
error_0:
 | 
						|
    os_mem_set(&plctxrx_context, 0, sizeof(plctxrx_contxt_t));
 | 
						|
success:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
void iot_plctxrx_task_deinit(void)
 | 
						|
{
 | 
						|
    os_delete_timer(plctxrx_context.datapath_timer);
 | 
						|
    os_delete_timer(plctxrx_context.txrx_timer);
 | 
						|
    os_delete_timer(plctxrx_context.aggr_timer);
 | 
						|
    /* send Q free */
 | 
						|
    if (plctxrx_context.sendq) {
 | 
						|
        if (plctxrx_context.sendq->lock) {
 | 
						|
           os_delete_mutex(plctxrx_context.sendq->lock);
 | 
						|
        }
 | 
						|
 | 
						|
        if (plctxrx_context.freeq->lock) {
 | 
						|
           os_delete_mutex(plctxrx_context.freeq->lock);
 | 
						|
        }
 | 
						|
 | 
						|
        os_mem_free(plctxrx_context.sendq);
 | 
						|
    }
 | 
						|
    /* free Q free */
 | 
						|
    if (plctxrx_context.freeq) {
 | 
						|
        os_mem_free(plctxrx_context.freeq);
 | 
						|
    }
 | 
						|
    if (plctxrx_context.task_handle) {
 | 
						|
        os_delete_task(plctxrx_context.task_handle);
 | 
						|
    }
 | 
						|
    os_mem_set(&plctxrx_context, 0, sizeof(plctxrx_contxt_t));
 | 
						|
}
 | 
						|
 | 
						|
#endif /* end IOT_GR_APP_ENABLE */
 | 
						|
 |