635 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			635 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | 
						|
 | 
						|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | 
						|
be copied by any method or incorporated into another program without
 | 
						|
the express written consent of Aerospace C.Power. This Information or any portion
 | 
						|
thereof remains the property of Aerospace C.Power. The Information contained herein
 | 
						|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | 
						|
liability for its use in any way and conveys no license or title under
 | 
						|
any patent or copyright and makes no representation or warranty that this
 | 
						|
Information is free from patent or copyright infringement.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
/* os_ship header files */
 | 
						|
#include "os_task_api.h"
 | 
						|
#include "os_event_api.h"
 | 
						|
#include "os_timer_api.h"
 | 
						|
#include "os_utils_api.h"
 | 
						|
 | 
						|
/* iot common header files */
 | 
						|
#include "iot_plc_cco_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_ntoh_api.h"
 | 
						|
 | 
						|
#include "iot_ping.h"
 | 
						|
#include "iot_ip_ping.h"
 | 
						|
 | 
						|
#if IOT_PING_APP_ENABLE
 | 
						|
 | 
						|
#define PING_PAYLOAD_SIZE       900
 | 
						|
 | 
						|
#if IOT_LWIP_SUPPORT
 | 
						|
 | 
						|
#define IOT_PING_IPV4_STA       1
 | 
						|
 | 
						|
#define IOT_PING_IPV6_STA       (!IOT_PING_IPV4_STA && LWIP_IPV6)
 | 
						|
 | 
						|
#define IOT_PING_IPV4_CCO       1
 | 
						|
 | 
						|
#define IOT_PING_IPV6_CCO       (!IOT_PING_IPV4_CCO && LWIP_IPV6)
 | 
						|
 | 
						|
#if LWIP_IPV6
 | 
						|
 | 
						|
static void iot_ping_gen_ip6_addr(ip_addr_t *ip_addr, uint8_t *mac_addr)
 | 
						|
{
 | 
						|
    ip_2_ip6(ip_addr)->addr[0] = iot_htonl(0xfe800000ul);
 | 
						|
    ip_2_ip6(ip_addr)->addr[1] = 0;
 | 
						|
    ip_2_ip6(ip_addr)->addr[2] =
 | 
						|
        iot_htonl((((uint32_t)(mac_addr[0] ^ 0x02)) << 24)
 | 
						|
        | ((uint32_t)(mac_addr[1]) << 16)
 | 
						|
        | ((uint32_t)(mac_addr[2]) << 8)
 | 
						|
        | (0xff));
 | 
						|
    ip_2_ip6(ip_addr)->addr[3] = iot_htonl((0xfeul << 24)
 | 
						|
        | ((uint32_t)(mac_addr[3]) << 16)
 | 
						|
        | ((uint32_t)(mac_addr[4]) << 8)
 | 
						|
        | (mac_addr[5]));
 | 
						|
    IP_SET_TYPE(ip_addr, IPADDR_TYPE_V6);
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
#else /* IOT_LWIP_SUPPORT */
 | 
						|
 | 
						|
#define IOT_PING_IPV4_STA       0
 | 
						|
 | 
						|
#define IOT_PING_IPV6_STA       0
 | 
						|
 | 
						|
#define IOT_PING_IPV4_CCO       0
 | 
						|
 | 
						|
#define IOT_PING_IPV6_CCO       0
 | 
						|
 | 
						|
#endif /* IOT_LWIP_SUPPORT */
 | 
						|
 | 
						|
static iot_ping_task_data_t *ping_task_data = NULL;
 | 
						|
 | 
						|
void iot_ping_post_msg(uint32_t prio, uint16_t msg_type,
 | 
						|
                       uint16_t msg_id, void* data1,
 | 
						|
                       uint32_t data2)
 | 
						|
{
 | 
						|
    iot_task_msg_t          *msg;
 | 
						|
    iot_ping_task_msg_t     *task_msg;
 | 
						|
    msg = iot_task_alloc_msg_with_reserved(ping_task_data->task_handle, 0);
 | 
						|
    if (!msg) {
 | 
						|
        iot_printf("%s, no msg\n", __FUNCTION__);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    task_msg = (iot_ping_task_msg_t*)msg;
 | 
						|
    task_msg->msg.type = msg_type;
 | 
						|
    task_msg->msg.id = msg_id;
 | 
						|
    task_msg->data = data1;
 | 
						|
    task_msg->data2 = data2;
 | 
						|
    iot_task_queue_msg(ping_task_data->task_handle,
 | 
						|
                       &task_msg->msg, (uint8_t)prio);
 | 
						|
}
 | 
						|
 | 
						|
void iot_plc_ping_post_msg(uint16_t msg_type, uint16_t msg_id)
 | 
						|
{
 | 
						|
    iot_ping_post_msg(IOT_PING_TASK_QUEUE_LP, msg_type, msg_id, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
/* ping_timer_func() - timer function for ping
 | 
						|
 * it triggers a topo query periodically
 | 
						|
 * @timer_id:   id of the timer
 | 
						|
 * @arg:        argument pass back to the callback function
 | 
						|
 */
 | 
						|
void ping_timer_func(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)timer_id;
 | 
						|
    iot_ping_task_data_t *task_data = (iot_ping_task_data_t*)arg;
 | 
						|
    if (task_data->dev_ready) {
 | 
						|
        if (task_data->dev_role == IOT_PLC_DEV_ROLE_CCO) {
 | 
						|
            ++task_data->set_nid_count;
 | 
						|
            if (task_data->set_nid_count < IOT_PING_SET_NID_CNT_LIMIT) {
 | 
						|
                iot_plc_ping_post_msg(IOT_PING_TIMER_MSG,
 | 
						|
                                      IOT_TIMER_QUERY_NB_NW);
 | 
						|
                iot_plc_ping_post_msg(IOT_PING_TIMER_MSG,
 | 
						|
                                      IOT_TIMER_QUERY_NID);
 | 
						|
                iot_plc_ping_post_msg(IOT_PING_TIMER_MSG,
 | 
						|
                                      IOT_TIMER_QUERY_NW_TOPO);
 | 
						|
            } else {
 | 
						|
                task_data->set_nid_count = 0;
 | 
						|
                // disable setting nid to avoid network reset
 | 
						|
                iot_printf("%s: set_nid disabled\n", __FUNCTION__);
 | 
						|
 | 
						|
                //iot_printf("%s: set_nid to 0n%d\n", __FUNCTION__, nid);
 | 
						|
                //iot_plc_ping_post_msg(IOT_PING_TIMER_MSG,
 | 
						|
                //                      IOT_TIMER_SET_NID, nid);
 | 
						|
                ++task_data->nid;
 | 
						|
            }
 | 
						|
        } else if (task_data->dev_role == IOT_PLC_DEV_ROLE_INVALID) {
 | 
						|
            iot_printf("%s: query_dev_info\n", __FUNCTION__);
 | 
						|
            iot_plc_ping_post_msg(IOT_PING_TIMER_MSG,
 | 
						|
                                  IOT_TIMER_QUERY_DEV_INTO);
 | 
						|
        } else {
 | 
						|
            os_stop_timer(timer_id);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* iot_plc_recv_ping() - callback method to receive packet from app
 | 
						|
 * @param:  param from app
 | 
						|
 * @pkt:    iot_pkt_t from app containing the request
 | 
						|
 */
 | 
						|
void iot_plc_recv_ping(void *param, iot_pkt_t *pkt)
 | 
						|
{
 | 
						|
    (void)param;
 | 
						|
    iot_ping_post_msg((uint8_t)IOT_PING_TASK_QUEUE_LP,
 | 
						|
                      IOT_PING_MAC_MSG, 0, pkt, 0);
 | 
						|
}
 | 
						|
 | 
						|
void iot_plc_ping_handle_timer_msg(iot_ping_task_msg_t* task_msg)
 | 
						|
{
 | 
						|
    switch (task_msg->msg.id) {
 | 
						|
    case IOT_TIMER_QUERY_DEV_INTO:
 | 
						|
    {
 | 
						|
        iot_plc_query_dev_info(ping_task_data->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_TIMER_QUERY_NB_NW:
 | 
						|
    {
 | 
						|
        iot_plc_query_nb_nw_info(ping_task_data->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_TIMER_QUERY_NID:
 | 
						|
    {
 | 
						|
        iot_plc_query_nid(ping_task_data->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_TIMER_QUERY_NW_TOPO:
 | 
						|
    {
 | 
						|
        iot_plc_query_nw_topo(ping_task_data->app_handle,
 | 
						|
            IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
            IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0,
 | 
						|
            IOT_PLC_QUERY_TOPO_START_AS_TEI, 1, 5);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_TIMER_SET_NID:
 | 
						|
    {
 | 
						|
        iot_plc_set_nid(ping_task_data->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
            task_msg->data2);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void iot_plc_ping_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_PING_APP_ID) {
 | 
						|
        // drop corrupted message
 | 
						|
        iot_pkt_free(pkt);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ping_task_data->app_registered == 0 &&
 | 
						|
        hdr->msg_id != IOT_PLC_MSG_APP_REG_CONF) {
 | 
						|
        // only handle app register confirm message before app registered
 | 
						|
        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);
 | 
						|
        if (rpt->result == IOT_PLC_SUCCESS ||
 | 
						|
            rpt->result == IOT_PLC_SUCCESS_MODIFIED) {
 | 
						|
            ping_task_data->app_registered = 1;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_DEV_STATE_CHANGE_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_dev_state_change_rpt_t* rpt =
 | 
						|
            (iot_plc_dev_state_change_rpt_t*)(hdr + 1);
 | 
						|
        ping_task_data->dev_role = rpt->dev_role;
 | 
						|
        if (!ping_task_data->dev_ready && rpt->is_ready) {
 | 
						|
            /* dev becomes available to serve app request */
 | 
						|
            iot_printf("%s: MAC layer is ready!\n", __FUNCTION__);
 | 
						|
            iot_printf("%s:nid=%lu, cco mac=%02X:%02X:%02X:%02X:%02X:%02X\n",
 | 
						|
                __FUNCTION__, 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]);
 | 
						|
 | 
						|
            ping_task_data->dev_ready = rpt->is_ready;
 | 
						|
            iot_mac_addr_cpy(ping_task_data->mac_addr, rpt->local_mac);
 | 
						|
            if (ping_task_data->dev_role == IOT_PLC_DEV_ROLE_CCO) {
 | 
						|
                os_start_timer(ping_task_data->ping_timer,
 | 
						|
                               IOT_PING_CHECK_TOPO_INTERVAL);
 | 
						|
            } else {
 | 
						|
#if IOT_PING_IPV4_STA
 | 
						|
                if (!ping_task_data->ipv4_ping_start) {
 | 
						|
                    static ip_addr_t ipv4_cco_addr;
 | 
						|
                    IP_ADDR4(&ipv4_cco_addr, 10, 0, 0, 1);
 | 
						|
                    ping_init(&ipv4_cco_addr);
 | 
						|
                    ping_task_data->ipv4_ping_start = 1;
 | 
						|
                }
 | 
						|
#endif /* IOT_PING_IPV4_STA */
 | 
						|
#if IOT_PING_IPV6_STA
 | 
						|
                if (!ping_task_data->ipv6_ping_start) {
 | 
						|
                    static ip_addr_t ipv6_cco_addr;
 | 
						|
                    iot_ping_gen_ip6_addr(&ipv6_cco_addr, rpt->cco_mac);
 | 
						|
                    ping_init(&ipv6_cco_addr);
 | 
						|
                    ping_task_data->ipv6_ping_start = 1;
 | 
						|
                }
 | 
						|
#endif /* IOT_PING_IPV6_STA */
 | 
						|
            }
 | 
						|
        } else if (ping_task_data->dev_ready && !rpt->is_ready) {
 | 
						|
            /* dev becomes unavailable. It cannot serve app request */
 | 
						|
            iot_printf("%s: MAC layer is NOT ready!\n", __FUNCTION__);
 | 
						|
            ping_task_data->dev_ready = rpt->is_ready;
 | 
						|
            os_stop_timer(ping_task_data->ping_timer);
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_DEV_INFO_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_dev_info_rpt_t* rpt = (iot_plc_dev_info_rpt_t*)(hdr + 1);
 | 
						|
        ping_task_data->dev_role = rpt->dev_role;
 | 
						|
        iot_mac_addr_cpy(ping_task_data->mac_addr, rpt->local_mac);
 | 
						|
        ping_task_data->dev_ready = rpt->is_ready;
 | 
						|
        if (ping_task_data->dev_ready) {
 | 
						|
            iot_printf("%s: MAC layer is ready.\n", __FUNCTION__);
 | 
						|
        } else {
 | 
						|
            iot_printf("%s: MAC layer is NOT ready!\n", __FUNCTION__);
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_STA_JOIN_INFO:
 | 
						|
    {
 | 
						|
        iot_plc_sta_join_info_t* rpt = (iot_plc_sta_join_info_t*)(hdr + 1);
 | 
						|
        iot_printf("%s: %d sta_joined. proxy = 0n%d: \
 | 
						|
            mac=%02X:%02X:%02X:%02X:%02X:%02X. dev_type=%d. \
 | 
						|
            physical phase[1-3]=%d.%d.%d. \
 | 
						|
            software version=%X\n",
 | 
						|
            __FUNCTION__, 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.sw_ver);
 | 
						|
#if IOT_PING_IPV4_CCO
 | 
						|
            if (!ping_task_data->ipv4_ping_start) {
 | 
						|
                static ip_addr_t ipv4_sta_addr;
 | 
						|
                uint32_t tmp;
 | 
						|
                IP_ADDR4(&ipv4_sta_addr, 10, 0, 0, 0);
 | 
						|
                tmp = ip_addr_get_ip4_u32(&ipv4_sta_addr);
 | 
						|
                tmp = iot_ntohl(tmp);
 | 
						|
                tmp &= 0xFFFF0000;
 | 
						|
                tmp += rpt->sta_info.sta_tei;
 | 
						|
                tmp = iot_htonl(tmp);
 | 
						|
                ip_addr_set_ip4_u32(&ipv4_sta_addr, tmp);
 | 
						|
                ping_init(&ipv4_sta_addr);
 | 
						|
                ping_task_data->ipv4_ping_start = 1;
 | 
						|
            }
 | 
						|
#endif /* IOT_PING_IPV4_CCO */
 | 
						|
#if IOT_PING_IPV6_CCO
 | 
						|
            if (!ping_task_data->ipv6_ping_start) {
 | 
						|
                static ip_addr_t ipv6_sta_addr;
 | 
						|
                iot_ping_gen_ip6_addr(&ipv6_sta_addr, rpt->sta_info.addr);
 | 
						|
                ping_init(&ipv6_sta_addr);
 | 
						|
                ping_task_data->ipv6_ping_start = 1;
 | 
						|
            }
 | 
						|
#endif /* IOT_PING_IPV6_CCO */
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_STA_LEAVE_INFO:
 | 
						|
    {
 | 
						|
        iot_plc_sta_leave_info_t* rpt = (iot_plc_sta_leave_info_t*)(hdr + 1);
 | 
						|
        iot_printf("%s: STA_LEAVE_INFO. sta_count = %d\n",
 | 
						|
                   __FUNCTION__, rpt->sta_count);
 | 
						|
        for (uint8_t i = 0; i < rpt->sta_count; ++i) {
 | 
						|
            iot_printf("%s: %d sta_leave[%d]. proxy = 0n%d: \
 | 
						|
                mac=%02X:%02X:%02X:%02X:%02X:%02X\n",
 | 
						|
                       __FUNCTION__, 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]);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_MSDU_RECV:
 | 
						|
    {
 | 
						|
        iot_plc_msdu_recv_t *msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
 | 
						|
        iot_printf("%s:recv_msdu: %d[%02X] mac:[%2X:%2X:%2X:%2X:%2X:%2X]\n",
 | 
						|
                   __FUNCTION__, msdu->data[0], msdu->data[0],
 | 
						|
                   msdu->src[0], msdu->src[1], msdu->src[2],
 | 
						|
                   msdu->src[3], msdu->src[4], msdu->src[5]);
 | 
						|
        iot_dbglog_input(IOT_APP_PING_MID, DBGLOG_INFO_LVL_2,
 | 
						|
            IOT_PING_RECV_MSDU, 8, msdu->data[0], msdu->data[0],
 | 
						|
            msdu->src[0], msdu->src[1], msdu->src[2],
 | 
						|
            msdu->src[3], msdu->src[4], msdu->src[5]);
 | 
						|
 | 
						|
        if (!ping_task_data->dev_ready) {
 | 
						|
            /* if dev is not ready, don't handle the MSDU */
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (ping_task_data->dev_role == IOT_PLC_DEV_ROLE_STA ||
 | 
						|
            ping_task_data->dev_role == IOT_PLC_DEV_ROLE_PCO) {
 | 
						|
            iot_pkt_t*msdu_pkt;
 | 
						|
            uint8_t* ptr;
 | 
						|
            uint32_t wait_time = 500 + os_rand() % 1000;
 | 
						|
            os_delay(wait_time);
 | 
						|
            // STA shall send ack to ping, reverse src and dest.
 | 
						|
            msdu_pkt = iot_plc_alloc_msdu(ping_task_data->app_handle,
 | 
						|
                IOT_PLC_MSG_TYPE_UNICAST, IOT_PLC_ACK_TYPE_NONE, msdu->src,
 | 
						|
                ping_task_data->mac_addr, ping_task_data->link_id,
 | 
						|
                PING_PAYLOAD_SIZE, IOT_PLC_LOCAL_RETRY_CNT);
 | 
						|
            ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | 
						|
            *ptr = ping_task_data->mac_addr[5]; // reply the last mac byte
 | 
						|
            iot_pkt_put(msdu_pkt, 1);
 | 
						|
            iot_plc_send_msdu(ping_task_data->app_handle, msdu_pkt);
 | 
						|
 | 
						|
            iot_printf("%s: STA [%2X:%2X:%2X:%2X:%2X:%2X] send ping ack\n",
 | 
						|
                __FUNCTION__, ping_task_data->mac_addr[0],
 | 
						|
                ping_task_data->mac_addr[1], ping_task_data->mac_addr[2],
 | 
						|
                ping_task_data->mac_addr[3], ping_task_data->mac_addr[4],
 | 
						|
                ping_task_data->mac_addr[5]);
 | 
						|
            iot_dbglog_input(IOT_APP_PING_MID, DBGLOG_INFO_LVL_2,
 | 
						|
                IOT_PING_SEND_ACK, 6, ping_task_data->mac_addr[0],
 | 
						|
                ping_task_data->mac_addr[1], ping_task_data->mac_addr[2],
 | 
						|
                ping_task_data->mac_addr[3], ping_task_data->mac_addr[4],
 | 
						|
                ping_task_data->mac_addr[5]);
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_ID_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_nid_rpt_t *rpt = (iot_plc_nid_rpt_t*)(hdr + 1);
 | 
						|
        iot_printf("%s:query nid reply:[0x%06X]\n", __FUNCTION__, 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_printf("%s:lid alloc:result = %d, lid=%d\n", __FUNCTION__,
 | 
						|
                   cfm->result, cfm->lid);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_NEIGHBOR_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_nb_nw_rpt_t *rpt = (iot_plc_nb_nw_rpt_t*)(hdr + 1);
 | 
						|
        iot_printf("%s: nbnw reply:======================\n", __FUNCTION__);
 | 
						|
        iot_printf("%s: nbnw reply:count = %d\n", __FUNCTION__, rpt->count);
 | 
						|
        for (int i = 0; i < rpt->count; ++i) {
 | 
						|
            iot_printf("%s: nbnw reply:nid[%d], sp_flag = %d, bd = %d\n",
 | 
						|
                       __FUNCTION__, rpt->nb_info[i].nid,
 | 
						|
                       rpt->nb_info[i].sp_flag,
 | 
						|
                       rpt->nb_info[i].bandwidth);
 | 
						|
        }
 | 
						|
        iot_printf("%s: nbnw reply:----------------------\n", __FUNCTION__);
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_WL_RPT:
 | 
						|
    {
 | 
						|
        iot_plc_wl_rpt_t *rpt = (iot_plc_wl_rpt_t*)(hdr + 1);
 | 
						|
        iot_printf("%s: wl reply:========================\n", __FUNCTION__);
 | 
						|
        iot_printf("%s: wl reply:total = %d, count = %d, done = %d\n",
 | 
						|
                   __FUNCTION__, rpt->total_count, rpt->count, rpt->done);
 | 
						|
        for (int i = 0; i < rpt->count; ++i) {
 | 
						|
            iot_printf("%s: wl reply:mac=%02X:%02X:%02X:%02X:%02X:%02X\n",
 | 
						|
                       __FUNCTION__, 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]);
 | 
						|
        }
 | 
						|
        iot_printf("%s: wl reply:------------------------\n", __FUNCTION__);
 | 
						|
        if (rpt->done) {
 | 
						|
            ping_task_data->wl_entry_index = 1;
 | 
						|
        } else {
 | 
						|
            ping_task_data->wl_entry_index += rpt->count;
 | 
						|
            iot_plc_query_whitelist(ping_task_data->app_handle,
 | 
						|
                IOT_PLC_API_REQ_ID_DEFAULT, ping_task_data->wl_entry_index,
 | 
						|
                (uint16_t)12);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PLC_MSG_NW_TOPO_RPT:
 | 
						|
    {
 | 
						|
        iot_printf("%s: topo reply:======================\n", __FUNCTION__);
 | 
						|
 | 
						|
        if (hdr->req_id == IOT_PLC_API_REQ_ID_DEFAULT) {
 | 
						|
 | 
						|
            iot_plc_nw_topo_rpt_t* rpt = (iot_plc_nw_topo_rpt_t*)(hdr + 1);
 | 
						|
            iot_plc_node_info_v0_t *node = (iot_plc_node_info_v0_t *)rpt->data;
 | 
						|
            for (uint32_t i = 0; i < rpt->count; ++i) {
 | 
						|
                iot_printf("%s: 0n%d mac=[%02X:%02X:%02X:%02X:%02X:%02X], \
 | 
						|
                    proxy:0n%d\n", __FUNCTION__, node[i].sta_tei,
 | 
						|
                    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].proxy_tei);
 | 
						|
            }
 | 
						|
            iot_printf("%s: topo reply end = %d------------------\n",
 | 
						|
                __FUNCTION__, rpt->done);
 | 
						|
 | 
						|
            if (rpt->done == 0) {
 | 
						|
                iot_plc_query_nw_topo(ping_task_data->app_handle,
 | 
						|
                    IOT_PLC_API_REQ_ID_DEFAULT,
 | 
						|
                    IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0,
 | 
						|
                    IOT_PLC_QUERY_TOPO_START_AS_TEI,
 | 
						|
                    node[rpt->count - 1].sta_tei + 1, 3);
 | 
						|
            } else {
 | 
						|
                /* broadcast the ping packet to all node */
 | 
						|
                static int bcast_type = 0;
 | 
						|
                uint8_t msg_type = IOT_PLC_MSG_TYPE_BCAST;
 | 
						|
                if (bcast_type++ % 2) {
 | 
						|
                    msg_type = IOT_PLC_MSG_TYPE_BCAST_1HOP;
 | 
						|
                }
 | 
						|
 | 
						|
                iot_pkt_t*msdu_pkt = iot_plc_alloc_msdu(
 | 
						|
                    ping_task_data->app_handle, msg_type,
 | 
						|
                    IOT_PLC_ACK_TYPE_NONE, NULL, ping_task_data->mac_addr,
 | 
						|
                    ping_task_data->link_id, PING_PAYLOAD_SIZE,
 | 
						|
                    IOT_PLC_LOCAL_RETRY_CNT);
 | 
						|
                uint8_t* ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | 
						|
                *ptr = 0xAC;  // send 0xAC as ping
 | 
						|
                iot_pkt_put(msdu_pkt, 1);
 | 
						|
                iot_plc_send_msdu(ping_task_data->app_handle, msdu_pkt);
 | 
						|
                iot_dbglog_input(IOT_APP_PING_MID, DBGLOG_INFO_LVL_2,
 | 
						|
                    IOT_PING_SEND_PING_BCAST, 2, msg_type, *ptr);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_pkt_free(pkt);
 | 
						|
}
 | 
						|
 | 
						|
static void iot_ping_task_handle_msg(iot_task_h task_h, iot_task_msg_t *msg)
 | 
						|
{
 | 
						|
    iot_ping_task_msg_t *task_msg;
 | 
						|
    IOT_ASSERT(task_h == ping_task_data->task_handle);
 | 
						|
    IOT_ASSERT(msg);
 | 
						|
 | 
						|
    task_msg = (iot_ping_task_msg_t*)msg;
 | 
						|
    switch (task_msg->msg.type) {
 | 
						|
    case IOT_PING_MAC_MSG:
 | 
						|
    {
 | 
						|
        iot_plc_ping_handle_mac_msg(task_msg->data);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PING_TIMER_MSG:
 | 
						|
    {
 | 
						|
        iot_plc_ping_handle_timer_msg(task_msg);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_task_free_msg(ping_task_data->task_handle, &task_msg->msg);
 | 
						|
}
 | 
						|
 | 
						|
static void iot_ping_task_handle_msg_cancel(iot_task_h task_h,
 | 
						|
                                            iot_task_msg_t *msg)
 | 
						|
{
 | 
						|
    iot_ping_task_msg_t *task_msg;
 | 
						|
    IOT_ASSERT(task_h == ping_task_data->task_handle);
 | 
						|
    IOT_ASSERT(msg);
 | 
						|
 | 
						|
    task_msg = (iot_ping_task_msg_t*)msg;
 | 
						|
    switch (task_msg->msg.type) {
 | 
						|
    case IOT_PING_MAC_MSG:
 | 
						|
    {
 | 
						|
        if (task_msg->data) {
 | 
						|
            iot_pkt_free(task_msg->data);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case IOT_PING_TIMER_MSG:
 | 
						|
    {
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_task_free_msg(ping_task_data->task_handle, &task_msg->msg);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t iot_ping_task_init()
 | 
						|
{
 | 
						|
    uint32_t        ret = ERR_OK;
 | 
						|
    iot_plc_app_t   ping_app = {0};
 | 
						|
    ping_app.app_id = IOT_PING_APP_ID;
 | 
						|
    ping_app.param = NULL;
 | 
						|
    ping_app.prio = 3;
 | 
						|
    ping_app.recv = iot_plc_recv_ping;
 | 
						|
 | 
						|
    if (ping_task_data) {
 | 
						|
        ret = ERR_AGAIN;
 | 
						|
        goto error_0;
 | 
						|
    }
 | 
						|
 | 
						|
    ping_task_data = os_mem_malloc(IOT_APP_PING_MID, sizeof(*ping_task_data));
 | 
						|
    if (!ping_task_data) {
 | 
						|
        ret = ERR_NOMEM;
 | 
						|
        goto error_0;
 | 
						|
    }
 | 
						|
 | 
						|
    ping_task_data->app_handle = NULL;
 | 
						|
    ping_task_data->link_id = IOT_PING_TASK_LIKE_ID;
 | 
						|
    ping_task_data->dev_role = IOT_PLC_DEV_ROLE_INVALID;
 | 
						|
    ping_task_data->nid = 1;
 | 
						|
 | 
						|
    ping_task_data->task_cfg.stack_size = 0;
 | 
						|
    ping_task_data->task_cfg.task_prio = IOT_PING_TASK_PRIO;
 | 
						|
    ping_task_data->task_cfg.msg_size = sizeof(iot_ping_task_msg_t);
 | 
						|
    ping_task_data->task_cfg.msg_cnt = IOT_PING_TASK_POOL_SIZE;
 | 
						|
    ping_task_data->task_cfg.queue_cnt = IOT_PING_TASK_QUEUE_MAX_PRIO;
 | 
						|
    ping_task_data->task_cfg.queue_cfg[IOT_PING_TASK_QUEUE_HP].quota = 0;
 | 
						|
    ping_task_data->task_cfg.msg_exe_func = iot_ping_task_handle_msg;
 | 
						|
    ping_task_data->task_cfg.msg_cancel_func = iot_ping_task_handle_msg_cancel;
 | 
						|
    ping_task_data->task_handle = iot_task_create(IOT_APP_PING_MID,
 | 
						|
                                                    &ping_task_data->task_cfg);
 | 
						|
 | 
						|
    if (ping_task_data->task_handle == NULL) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto error_1;
 | 
						|
    }
 | 
						|
 | 
						|
    ping_task_data->ping_timer = os_create_timer(IOT_APP_PING_MID, 1,
 | 
						|
                                                ping_timer_func,
 | 
						|
                                                ping_task_data);
 | 
						|
    if (ping_task_data->ping_timer == 0) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto error_2;
 | 
						|
    }
 | 
						|
 | 
						|
    ping_task_data->app_handle = iot_plc_register_app(&ping_app);
 | 
						|
    if (ping_task_data->app_handle == NULL) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto error_3;
 | 
						|
    }
 | 
						|
 | 
						|
    goto success;
 | 
						|
 | 
						|
error_3:
 | 
						|
    os_delete_timer(ping_task_data->ping_timer);
 | 
						|
    ping_task_data->ping_timer = 0;
 | 
						|
error_2:
 | 
						|
    iot_task_delete(ping_task_data->task_handle);
 | 
						|
    ping_task_data->task_handle = NULL;
 | 
						|
error_1:
 | 
						|
    os_mem_free(ping_task_data);
 | 
						|
error_0:
 | 
						|
 | 
						|
success:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * app_entry: entry for ping app
 | 
						|
 * @return:
 | 
						|
 *  ERR_PENDING -   if application want to delay the plc network formation.
 | 
						|
 *  otherwise   -   plc network formation will be started automatically.
 | 
						|
 */
 | 
						|
uint32_t app_ping_entry()
 | 
						|
{
 | 
						|
    iot_ping_task_init();
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
#endif  /* IOT_PING_APP_ENABLE */
 |