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