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 */
 |