/**************************************************************************** Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT be copied by any method or incorporated into another program without the express written consent of Aerospace C.Power. This Information or any portion thereof remains the property of Aerospace C.Power. The Information contained herein is believed to be accurate and Aerospace C.Power assumes no responsibility or liability for its use in any way and conveys no license or title under any patent or copyright and makes no representation or warranty that this Information is free from patent or copyright infringement. ****************************************************************************/ /* os_ship header files */ #include "os_task_api.h" #include "os_event_api.h" #include "os_timer_api.h" #include "os_utils_api.h" /* iot common header files */ #include "iot_plc_cco_api.h" #include "iot_module_api.h" #include "iot_queue_api.h" #include "iot_mem_pool_api.h" #include "iot_config_api.h" #include "iot_app_api.h" #include "iot_errno_api.h" #include "iot_io_api.h" #include "iot_dbglog_api.h" #include "iot_uart_api.h" #include "iot_task_api.h" #include "iot_flash_api.h" #include "iot_system_api.h" #include "iot_version_api.h" #include "iot_oem_api.h" #include "iot_plc_msg_api.h" #include "iot_grapp.h" #include "iot_plctxrx.h" #include "iot_proto_ge.h" #include "iot_gr_upgrade.h" #include "iot_board_api.h" #include "iot_gpio_api.h" #include "iot_flashinfo.h" #include "iot_proto_dl645.h" #if IOT_GR_APP_ENABLE static uint16_t overflow_index = CCO_RX_TIME + 1; #define IOT_PROTO_INVALID_GPIO_INDEX 0xFF void iot_proto_node_info_report(uint8_t *data, uint16_t dlen, uint16_t total_cnt, uint16_t cur_cnt, uint8_t type, uint8_t done); void iot_proto_nw_info_report(uint8_t max_level, uint8_t *data, uint8_t length); extern void iot_common_bin_dump(uint8_t *data, uint32_t dlen); extern void iot_proto_set_local_mac(void); #if HW_PLATFORM == HW_PLATFORM_SIMU extern uint8_t g_ucMACAddress[IOT_MAC_ADDR_LEN]; bool_t iot_proto_cache_data_for_window_rpt(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { uint32_t wind_tmr = 0; uint16_t saved_len = 0; bool_t ret = false; ge_extend_fn_hdr_t *frm_hdr = (ge_extend_fn_hdr_t *)data; ge_frame_data_send_set_subfn160_t *frm = NULL; iot_pkt_t *send_pkt = NULL; uint8_t *pkt_ptr = NULL; if (CMD_REMOTE_UP_LINK != dir) { return ret; } if (frm_hdr->subfn == PROTO_GE_DATA_CMD) { frm = (ge_frame_data_send_set_subfn160_t *)data; if (mac_addr_is_bcast_addr(frm->dest_mac)) { saved_len = prototask_contxt.rpt_cache.data_len; if (saved_len + len > PROTO_WIN_CACHE_LEN) { if (saved_len != 0) { send_pkt = iot_pkt_alloc(saved_len, IOT_GREE_APP_MID); if (send_pkt == NULL) { iot_cus_printf("[grpr]NO memery, sending cached pkt " "failed\n"); return false; } pkt_ptr = iot_pkt_data(send_pkt); iot_pkt_put(send_pkt, len); os_mem_cpy(pkt_ptr, prototask_contxt.rpt_cache.data, saved_len); iot_proto_send_to_mainboard(send_pkt); os_mem_set(&prototask_contxt.rpt_cache, 0, sizeof(proto_rpt_cache_t)); } /* if the cache buffer is full, send the cached data immediately */ if (os_is_timer_active(prototask_contxt.rpt_window_tmr)) { os_stop_timer(prototask_contxt.rpt_window_tmr); } return false; } os_mem_cpy(&prototask_contxt.rpt_cache.data[saved_len], data, len); prototask_contxt.rpt_cache.data_len += len; if (!os_is_timer_active(prototask_contxt.rpt_window_tmr)) { wind_tmr = os_rand() % PROTO_RTP_WINDOW_DEFAULT_SPAN; os_start_timer(prototask_contxt.rpt_window_tmr, wind_tmr); iot_cus_printf("[grpr]window timer started, act_window %d" " ms\n", wind_tmr); } ret = true; } } return ret; } #else /* HW_PLATFORM == HW_PLATFORM_SIMU */ bool_t iot_proto_cache_data_for_window_rpt(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)data; (void)len; (void)dir; return false; } #endif /** * @brief iot_delay_timer_get() - get a delay time (ntb) * @param data input data to get the time * @param time_type witch time to get * @param set_time the time to set if need */ void iot_delay_timer_get(uint32_t *data, uint8_t time_type, uint32_t set_time) { uint32_t cur_time; if (set_time == 0) { cur_time = iot_plc_get_ntb(greeapp->app_handle); } else { cur_time = set_time; } if (time_type > CCO_RX_TIME) { iot_cus_printf("[ERR] %s get type error\n", __FUNCTION__); return; } os_mem_cpy(data + time_type, &cur_time, sizeof(uint32_t)); } void iot_proto_query_mcu_mac() { /* Query MCU for mac addr assigned */ proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); #if PLC_SUPPORT_STA_ROLE /* send 645 read address */ iot_pkt_t *pkt = iot_pkt_alloc(sizeof(proto_645_header_t) + sizeof(proto_645_tailer_t), IOT_GREE_APP_MID); IOT_ASSERT(pkt); iot_pkt_put(pkt, sizeof(proto_645_header_t) + sizeof(proto_645_tailer_t)); iot_proto_dl645_read_addr(iot_pkt_data(pkt)); #else iot_pkt_t *pkt = iot_pkt_alloc(sizeof(ge_frame_local_mac_query_subfn1_t), IOT_GREE_APP_MID); IOT_ASSERT(pkt); ge_frame_local_mac_query_subfn1_t *cmd = (ge_frame_local_mac_query_subfn1_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*cmd)); os_mem_set(cmd, 0, sizeof(*cmd)); /* Hint, normall, we shuld add seq, but, since this is repeat cmd, so, skip increase seq currently. */ EXT_FN_FRM_PREPARE(cmd, PROTO_GE_PLC_QUERY_CMD, PROTO_LOCAL_MAC_QUERY_CMD); cmd->dir = DIR_UP_TO_MCU; cmd->nw_role = prototask_contxt.local_dev.nw_role; cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)cmd, sizeof(*cmd)-sizeof(ge_frm_tail_t)); #endif /* send to MCU */ if (prototask_contxt.proto_sendto_mainboard_fn) { if (PROTO_CMD_IDLE == sm->state || PROTO_CMD_WAIT_MAC_RESP == sm->state) { iot_proto_send_to_mainboard(pkt); /* set state to wait for mac response */ sm->dir = CMD_LOCAL_DOWN_LINK; sm->state = PROTO_CMD_WAIT_MAC_RESP; } } else { iot_pkt_free(pkt); } } #if PLC_SUPPORT_CCO_ROLE void iot_proto_cco_groupnet_cfm_send(uint8_t seq, uint8_t dir, uint8_t sub_fn, uint8_t result, uint8_t reason) { iot_pkt_t *cfm_pkt = iot_pkt_alloc(sizeof(ge_frame_cmd_cfm_set_subfn20_t), IOT_GREE_APP_MID); IOT_ASSERT(cfm_pkt); iot_pkt_put(cfm_pkt, sizeof(ge_frame_cmd_cfm_set_subfn20_t)); os_mem_set(iot_pkt_data(cfm_pkt), 0, sizeof(ge_frame_cmd_cfm_set_subfn20_t)); iot_proto_cfm_cmd_group(iot_pkt_data(cfm_pkt), sub_fn, result, reason, seq); if (CMD_LOCAL_DOWN_LINK == dir) { /* send start group net confirm cmd to MCU */ iot_proto_send_to_mainboard(cfm_pkt); } else { iot_pkt_free(cfm_pkt); } } static void iot_update_proxy_info(uint8_t *pco_mac) { uint16_t i; if (iot_mac_addr_cmp(prototask_contxt.local_dev.mac, pco_mac)) { /* if proxy is cco, not update */ return; } for (i = 0; i < STA_DEV_MAX; i++) { if (iot_mac_addr_cmp(prototask_contxt.dev_lst.dev[i].mac, pco_mac)) { if (prototask_contxt.dev_lst.dev[i].dev_role != IOT_PLC_DEV_ROLE_PCO) { /* update pco role */ iot_cus_printf("update pco role mac:%02X%02X%02X%02X%02X%02X\n", pco_mac[0], pco_mac[1], pco_mac[2], pco_mac[3], pco_mac[4], pco_mac[5]); prototask_contxt.dev_lst.dev[i].dev_role = IOT_PLC_DEV_ROLE_PCO; } break; } } return; } void iot_proto_cco_groupnet_sm(uint8_t *data, uint8_t subfn, transmit_direction_e_t dir, void *info) { uint8_t state = prototask_contxt.groupnet_state.state; proto_dev_list_t *dev_lst= &prototask_contxt.dev_lst; uint16_t i, j; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; uint8_t tmp_mac[IOT_MAC_ADDR_LEN] = { 0 }; switch (state) { case CCO_STATE_GROUPNET_IDLE: { switch (subfn) { case PROTO_CONN_IND_RPT_CMD: { plctxrx_cmd_joined_network_t *join_info = (plctxrx_cmd_joined_network_t *)info; /* here device list must not be empty, we just need * to change the device's network flag.whitelist must * be enable. */ /* first check if STA is in the device list */ for (i = 0; i < STA_DEV_MAX; i++) { if (iot_mac_addr_cmp(join_info->mac, dev_lst->dev[i].mac)) { iot_update_proxy_info(join_info->pco_mac); /* save device role */ dev_lst->dev[i].dev_role = join_info->role; iot_mac_addr_cpy(dev_lst->dev_pco[i], join_info->pco_mac); if (dev_lst->online_flag[i] == false) { prototask_contxt.dev_lst.online_dev_cnt++; /* save device join state */ dev_lst->online_flag[i] = true; } break; } } if (i == STA_DEV_MAX) { iot_cus_printf("[glpr][err]cco_groupnet_sm idle:" "STA is not in dev list!!!mac[0]=0x%x," "mac[1]=0x%x,mac[2]=0x%x\n", join_info->mac[0], join_info->mac[1],join_info->mac[2]); return; } break; } case PROTO_DISCONN_IND_RPT_CMD: { plctxrx_cmd_leave_net_t *leave_info = (plctxrx_cmd_leave_net_t *)info; for (i = 0; i < leave_info->cnt; i++) { /* first check if the sta is in nw sta list */ for (j = 0; j < STA_DEV_MAX; j++) { if (iot_mac_addr_cmp(leave_info->mac[i], dev_lst->dev[j].mac)) { os_mem_set(dev_lst->dev_pco[j], 0, IOT_MAC_ADDR_LEN); if (dev_lst->online_flag[j] == true) { if (prototask_contxt.dev_lst.online_dev_cnt > 0) prototask_contxt.dev_lst.online_dev_cnt--; /* clean online flag */ dev_lst->online_flag[j] = false; } break; } } if (j == STA_DEV_MAX) { iot_cus_printf("[glpr][war]not find\n"); } /* report disconn event to MCU */ iot_proto_report_disconn_event2mcu(leave_info->mac[i]); } break; } case PROTO_CCO_START_GROUP_NET_CMD: { ge_frame_start_group_set_subfn13_t *src_cmd = (ge_frame_start_group_set_subfn13_t *)data; dev_lst->valid_dev_tmp_cnt = dev_lst->valid_dev_cnt; os_mem_cpy(dev_lst->dev_tmp, dev_lst->dev, sizeof(proto_dev_t) * STA_DEV_MAX); /* 1st: empty whitelist in CVG */ iot_proto_whitelist_add_remove(GE_PROTO_ACTION_DEL, NULL, false); iot_proto_whitelist_state_init(); /* 2nd: empty whitelist in device list */ os_mem_set(dev_lst->dev, 0, sizeof(proto_dev_t) * STA_DEV_MAX); /* 3rd: clean online flag */ os_mem_set(dev_lst->online_flag, 0, sizeof(bool_t) * STA_DEV_MAX); dev_lst->valid_dev_cnt = 0; /* 4ur: empty whitelist in flash */ p_flash->public.pub.dev_cnt = 0; os_mem_set(p_flash->public.pub.dev_tbl, 0, STA_DEV_MAX * sizeof(proto_dev_t)); (void)iot_proto_flashsave(p_flash); /** * disable whitelist, do not need to handle cmd confirm, * so do not record wait_cmd_cfm state, just drop cmd cfm * when recv it from PLCTXRX. * */ iot_proto_whitelist_en_disable(GE_PROTO_WL_DISABLE, false); /* confirm response */ iot_proto_cco_groupnet_cfm_send(src_cmd->seq, dir, PROTO_CCO_START_GROUP_NET_CMD, 0, 0); /* set vendor info */ prototask_contxt.net_start_flag = 1; /* next state */ prototask_contxt.groupnet_state.state = CCO_STATE_GROUPNETING; break; } case PROTO_CCO_END_GROUP_NET_CMD: { /** * when recv start groupnet cmd in groupneting state, * we should response a groupnet start cfm to MCU. */ ge_frame_end_group_set_subfn14_t *src_cmd = (ge_frame_end_group_set_subfn14_t *)data; /* confirm response */ iot_proto_cco_groupnet_cfm_send(src_cmd->seq, dir, PROTO_CCO_END_GROUP_NET_CMD, 1, PROTO_REASON_CCO_GROUPNETING_IDLE); break; } default: break; } break; } case CCO_STATE_GROUPNETING: { switch (subfn) { case PROTO_CONN_IND_RPT_CMD: { plctxrx_cmd_joined_network_t *join_info = (plctxrx_cmd_joined_network_t *)info; /* check if there is duplicated sta in sta list */ for (i = 0; i < STA_DEV_MAX; i++) { if (iot_mac_addr_cmp(join_info->mac, dev_lst->dev[i].mac)) { dev_lst->dev[i].dev_role = join_info->role; iot_cus_printf("[glpr][war]cco_groupnet_sm grouping:" "duplicate sta\n"); return; } } /* not find duplicated sta,then find a free place to record it */ for (i = 0; i < STA_DEV_MAX; i++) { if (iot_mac_addr_cmp(tmp_mac, dev_lst->dev[i].mac)) { /* record new sta in sta list */ iot_mac_addr_cpy(dev_lst->dev[i].mac, join_info->mac); dev_lst->dev[i].dev_role = join_info->role; if (dev_lst->online_flag[i] == false) { prototask_contxt.dev_lst.online_dev_cnt++; /* save device join state */ dev_lst->online_flag[i] = true; } break; } } /* check if dev cnt is over range */ if (STA_DEV_MAX == i) { iot_cus_printf("[glpr][war]cco_groupnet_sm:" "sta cnt over-range\n"); return; } break; } case PROTO_DISCONN_IND_RPT_CMD: { plctxrx_cmd_leave_net_t *leave_info = (plctxrx_cmd_leave_net_t *)info; for (i = 0; i < leave_info->cnt; i++) { /* first check if the sta is in nw sta list */ for (j = 0; j < STA_DEV_MAX; j++) { if (iot_mac_addr_cmp(leave_info->mac[i], dev_lst->dev[j].mac)) { if (dev_lst->online_flag[j] == true) { if (prototask_contxt.dev_lst.online_dev_cnt > 0) prototask_contxt.dev_lst.online_dev_cnt--; /* clean online flag */ dev_lst->online_flag[j] = false; } break; } } if (j == STA_DEV_MAX) { /* not find the sta in nw sta list */ iot_cus_printf("[glpr][war]cco_groupnet_sm grouping:" "not find leave sta in sta list\n"); continue; } /* report disconn event to MCU */ iot_proto_report_disconn_event2mcu(leave_info->mac[i]); /* del leave sta in nw sta list */ os_mem_set(&dev_lst->dev[j], 0, sizeof(proto_dev_t)); } break; } case PROTO_CCO_END_GROUP_NET_CMD: { /** * disable whitelist, do not need to handle cmd confirm, * so do not record wait_cmd_cfm state, just drop cmd cfm * when recv from PLCTXRX. * */ ge_frame_end_group_set_subfn14_t *src_cmd = (ge_frame_end_group_set_subfn14_t *)data; /* confirm response */ iot_proto_cco_groupnet_cfm_send(src_cmd->seq, dir, PROTO_CCO_END_GROUP_NET_CMD, 0, 0); /* update whitelist to flash */ os_mem_set(p_flash->public.pub.dev_tbl, 0, STA_DEV_MAX*sizeof(proto_dev_t)); for (i = 0, j = 0; i < STA_DEV_MAX; i++) { if (!iot_mac_addr_cmp(tmp_mac, prototask_contxt.dev_lst.dev[i].mac)) { os_mem_cpy(&p_flash->public.pub.dev_tbl[j++], &prototask_contxt.dev_lst.dev[i], sizeof(proto_dev_t)); } } prototask_contxt.dev_lst.valid_dev_cnt = j; p_flash->public.pub.dev_cnt = j; iot_cus_printf("[glpr][info]group end :valid dev cnt=%d\n", p_flash->public.pub.dev_cnt); /* sync dev list and flash dev list */ os_mem_set(prototask_contxt.dev_lst.dev, 0, STA_DEV_MAX*sizeof(proto_dev_t)); os_mem_cpy(prototask_contxt.dev_lst.dev, p_flash->public.pub.dev_tbl, p_flash->public.pub.dev_cnt * sizeof(proto_dev_t)); dev_lst->valid_dev_tmp_cnt = dev_lst->valid_dev_cnt; os_mem_cpy(dev_lst->dev_tmp, dev_lst->dev, sizeof(proto_dev_t) * STA_DEV_MAX); /* save whitelist to flash */ (void)iot_proto_flashsave(p_flash); /* add whitelist to CVG */ iot_proto_whitelist_add_remove(GE_PROTO_ACTION_ADD, NULL, false); /* enable whitelist in CVG */ iot_proto_whitelist_en_disable(GE_PROTO_WL_ENABLE, false); /* set vendor info */ prototask_contxt.net_start_flag = 0; /* next state */ prototask_contxt.groupnet_state.state = CCO_STATE_GROUPNET_IDLE; break; } case PROTO_CCO_START_GROUP_NET_CMD: { /** * when recv start groupnet cmd in groupneting state, * we should response a groupnet start cfm to MCU. */ ge_frame_start_group_set_subfn13_t *src_cmd = (ge_frame_start_group_set_subfn13_t *)data; /* confirm response */ iot_proto_cco_groupnet_cfm_send(src_cmd->seq, dir, PROTO_CCO_START_GROUP_NET_CMD, 1, PROTO_REASON_CCO_GROUPNETING); break; } default: break; } break; } default: break; } return; } #else void iot_proto_cco_groupnet_sm(uint8_t *data, uint8_t subfn, transmit_direction_e_t dir, void *info) { (void)data; (void)subfn; (void)dir; (void)info; } #endif bool_t iot_proto_set_local_mac_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; ge_frame_local_mac_set_subfn1_t *frm = (ge_frame_local_mac_set_subfn1_t *)data; proto_cmd_hdl_state_t* sm = iot_proto_cmd_handle_state_get(); uint8_t mac_addr[IOT_MAC_ADDR_LEN] = { 0 }; uint32_t reason = 0; if (len != sizeof(ge_frame_local_mac_set_subfn1_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (iot_mac_addr_cmp(frm->mac, mac_addr)) { reason = PROTO_REASON_MAC_ADDR_ZERO; } else if (iot_mac_addr_cmp(prototask_contxt.local_dev.mac, frm->mac)) { reason = PROTO_REASON_DUP_SETTING; } if (0 != reason) { iot_proto_resp_cfm_frame(reason, dir, PROTO_LOCAL_MAC_SET_CMD, frm->seq, NULL); iot_cus_printf("[glpr][err]set_local_mac failed, " "reason--%d\n", reason); return rpt2mcu; } /* Set cmd handle state */ sm->dir = CMD_LOCAL_UP_LINK; sm->cur_subfn = frm->hdr.subfn; sm->seq = frm->seq; sm->state = PROTO_CMD_WAIT_CMD_CFM; /* set mac and type to CVG layer */ iot_proto_set_mac(frm->mac, 0, true); return rpt2mcu; } bool_t iot_proto_local_mac_resp_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; IOT_ASSERT(CMD_LOCAL_DOWN_LINK == dir); sta_dev_t *local_dev = &prototask_contxt.local_dev; uint8_t tmp_mac[IOT_MAC_ADDR_LEN] = { 0 }; ge_frame_local_mac_resp_subfn1_t *cmd = (ge_frame_local_mac_resp_subfn1_t *)data; if (len != sizeof(ge_frame_local_mac_resp_subfn1_t)) { iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "mac resp"); return rpt2mcu; } iot_cus_printf("[glpr]local_mac_resp_handler:mac:%x:%x:%x:%x:%x:%x\n", cmd->mac[0], cmd->mac[1], cmd->mac[2], cmd->mac[3], cmd->mac[4], cmd->mac[5]); /* check if mac addr is valid */ if (iot_mac_addr_cmp(tmp_mac, cmd->mac)) { iot_cus_printf("[glpr][err]mac addr is not valid\n"); return rpt2mcu; } /* check if set the same mac and dev type */ if (iot_mac_addr_cmp(local_dev->mac, cmd->mac)) { iot_cus_printf("[glpr]set the same mac and type\n"); return rpt2mcu; } /* set mac and type to CVG layer */ iot_proto_set_mac(cmd->mac, 0, false); return rpt2mcu; } bool_t iot_proto_query_local_mac_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; ge_frame_local_mac_resp_subfn1_t *resp_cmd; ge_frame_local_mac_query_subfn1_t *query_cmd = (ge_frame_local_mac_query_subfn1_t *)data; iot_pkt_t *pkt = iot_pkt_alloc(sizeof(*resp_cmd), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_cmd = (ge_frame_local_mac_resp_subfn1_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_cmd)); os_mem_set(resp_cmd, 0, sizeof(*resp_cmd)); EXT_FN_FRM_PREPARE(resp_cmd, PROTO_GE_PLC_RESP_CMD, PROTO_LOCAL_MAC_RESP_CMD); if (len == sizeof(ge_frame_local_mac_query_subfn1_t)) { resp_cmd->seq = query_cmd->seq; iot_mac_addr_cpy(resp_cmd->mac, prototask_contxt.local_dev.mac); resp_cmd->dir = DIR_UP_TO_MCU; resp_cmd->nw_role = prototask_contxt.local_dev.nw_role; } else { iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey local mac"); } resp_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_cmd, sizeof(*resp_cmd)-sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); return rpt2mcu; } bool_t iot_proto_conn_ind_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; sta_dev_t *local_dev = &prototask_contxt.local_dev; proto_dev_list_t *dev_lst= &prototask_contxt.dev_lst; bool_t rpt2mcu = false; plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_joined_network_t *info; iot_pkt_t *pkt; ge_frame_conn_ind_rpt_set_subfn9_t *ind_frm; uint8_t need_save_flash = 0; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; info = (plctxrx_cmd_joined_network_t *)cmd->data; if (IOT_PLC_DEV_ROLE_CCO != local_dev->nw_role) { iot_mac_addr_cpy(prototask_contxt.cco_dev.mac, info->mac); local_dev->nw_role = info->role; local_dev->nid = info->nid; local_dev->dev_ready = true; if (!iot_mac_addr_cmp(p_flash->public.pub.cco_mac, info->mac)) { iot_mac_addr_cpy(p_flash->public.pub.cco_mac, info->mac); need_save_flash = 1; } if (need_save_flash) { iot_proto_flashsave(p_flash); } } else { iot_cus_printf("join: role=%d pco_mac=%02X:%02X:%02X:%02X:%02X:%02X\n", info->role, info->pco_mac[0], info->pco_mac[1], info->pco_mac[2], info->pco_mac[3], info->pco_mac[4], info->pco_mac[5]); iot_proto_cco_groupnet_sm(NULL, PROTO_CONN_IND_RPT_CMD, dir, info); } /* report connect event to MCU */ pkt = iot_pkt_alloc(sizeof(ge_frame_conn_ind_rpt_set_subfn9_t), IOT_GREE_APP_MID); IOT_ASSERT(pkt); iot_pkt_put(pkt, sizeof(ge_frame_conn_ind_rpt_set_subfn9_t)); ind_frm = (ge_frame_conn_ind_rpt_set_subfn9_t *)iot_pkt_data(pkt); /* fill connect indication frame field */ os_mem_set(ind_frm, 0 , sizeof(*ind_frm)); EXT_FN_FRM_PREPARE(ind_frm, PROTO_GE_PLC_SET_CMD, PROTO_CONN_IND_RPT_CMD); /* nid will be recorded when MCU set it - TODO */ ind_frm->nid = local_dev->nid; iot_mac_addr_cpy(ind_frm->mac, info->mac); ind_frm->rssi = 0; ind_frm->snr = 0; ind_frm->seq = local_dev->ind_seq++; ind_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)ind_frm, sizeof(*ind_frm)-sizeof(ge_frm_tail_t)); /* report connected indication event to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr]connect ind,valid_cnt=%d,online_cnt=%d\n", dev_lst->valid_dev_cnt, dev_lst->online_dev_cnt); return rpt2mcu; } void iot_proto_report_disconn_event2mcu(uint8_t *mac) { iot_pkt_t *pkt; ge_frame_disc_ind_rpt_set_subfn10_t *ind_frm; pkt = iot_pkt_alloc(sizeof(ge_frame_disc_ind_rpt_set_subfn10_t), IOT_GREE_APP_MID); IOT_ASSERT(pkt); iot_pkt_put(pkt, sizeof(ge_frame_disc_ind_rpt_set_subfn10_t)); ind_frm = (ge_frame_disc_ind_rpt_set_subfn10_t *)iot_pkt_data(pkt); /* fill connect indication frame field */ os_mem_set(ind_frm, 0 , sizeof(*ind_frm)); EXT_FN_FRM_PREPARE(ind_frm, PROTO_GE_PLC_SET_CMD, PROTO_DISCONN_IND_RPT_CMD); ind_frm->nid = prototask_contxt.local_dev.nid; iot_mac_addr_cpy(ind_frm->mac, mac); /* TODO */ ind_frm->reason = 0; ind_frm->seq = prototask_contxt.local_dev.ind_seq++; ind_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)ind_frm, sizeof(*ind_frm)-sizeof(ge_frm_tail_t)); /* report sta leave network event to MCU */ iot_proto_send_to_mainboard(pkt); } bool_t iot_proto_set_nid_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; uint8_t reason = PROTO_REASON_OK; iot_pkt_t *cmd_pkt; ge_frame_cco_nid_set_subfn17_t *frm = (ge_frame_cco_nid_set_subfn17_t *)data; plctxrx_cmd_arg_t cmd = { 0 }; plctxrx_cmd_nid_t set_nid = { 0 }; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); sta_dev_t *local_dev = &prototask_contxt.local_dev; if (len != sizeof(ge_frame_cco_nid_set_subfn17_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (!iot_mac_addr_cmp(local_dev->mac, frm->mac)) { reason = PROTO_REASON_MAC_MISSMATCH; } else if (local_dev->nid == frm->nid) { reason = PROTO_REASON_NID_DUP; } else if (0 == frm->nid || 99 < frm->nid) { reason = PROTO_REASON_NID_MISSMATCH; } if (reason != PROTO_REASON_OK) { iot_cus_printf("[glpr]set_nid error reason%d!\n", reason); iot_proto_resp_cfm_frame(reason, dir, PROTO_CCO_NID_SET_CMD, frm->seq, NULL); return rpt2mcu; } cmd.cid.cid = PLCTXRX_CID_NID; cmd.cid.opcode = PLCTXRX_OP_CONFIG; cmd.prio = 0; cmd.need_ack = true; cmd.dlen = sizeof(plctxrx_cmd_nid_t); /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd) + cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); set_nid.nid = frm->nid; iot_pkt_put(cmd_pkt, sizeof(cmd) + cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); os_mem_cpy(iot_pkt_data(cmd_pkt) + sizeof(cmd), &set_nid, cmd.dlen); sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); /* save nid to local */ local_dev->nid = frm->nid; iot_cus_printf("[glpr]set nid succ!\n"); return rpt2mcu; } bool_t iot_proto_set_sta_leave_handler (uint8_t *data, uint16_t len, transmit_direction_e_t dir) { ge_frame_leave_nw_set_subfn4_t *p_frame = (ge_frame_leave_nw_set_subfn4_t *)data; uint8_t reason = PROTO_REASON_OK; protpkt_tx_info_t txinfo = { 0 }; ge_frame_sta_leave_ind_set_subfn154_t ind_frm = {0}; uint8_t *local_mac = prototask_contxt.local_dev.mac; if (len != sizeof(ge_frame_leave_nw_set_subfn4_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if ((CMD_LOCAL_DOWN_LINK != dir) && (DATA_DOWN_LINK != dir)) { reason = PROTO_REASON_CMD_DIR_ERR; } else if (IOT_PLC_DEV_ROLE_CCO == prototask_contxt.local_dev.nw_role) { reason = PROTO_REASON_ROLE_MISMATCH; } else if (!prototask_contxt.local_dev.dev_ready) { reason = PROTO_REASON_NOT_READY; } else if (p_frame->nid != prototask_contxt.local_dev.nid) { reason = PROTO_REASON_NID_MISSMATCH; } iot_cus_printf("[glpr]set_sta_leave:myrole=%d,ready=%d,nid=%d\n", prototask_contxt.local_dev.nw_role, prototask_contxt.local_dev.dev_ready, prototask_contxt.local_dev.nid); if (reason == PROTO_REASON_OK) { iot_mac_addr_cpy(ind_frm.mac, local_mac); ind_frm.seq = p_frame->seq; EXT_FN_FRM_PREPARE((&ind_frm), PROTO_GE_PLC_SET_CMD, PROTO_STA_LEAVE_IND); ind_frm.tail.check_sum = ge_frm_checksum_calc((uint8_t *)(&ind_frm), sizeof(ind_frm)-sizeof(ge_frm_tail_t)); iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 3, 200, 1, local_mac, NULL); iot_proto_remote_cmd_send_to_plctxrx((uint8_t *)(&ind_frm), sizeof(ge_frame_sta_leave_ind_set_subfn154_t), &txinfo); iot_cus_printf("[glpr]sta will leave netowork in 5 sec\n"); os_start_timer(prototask_contxt.leave_tmr, PROTO_TIMER_LEAVE_DELAY_INTVL); } else { iot_cus_printf("[glpr]leave error, reason%d!\n",reason); } iot_proto_resp_cfm_frame(reason, dir, PROTO_LEAVE_NW_SET_CMD, p_frame->seq, NULL); return 0; } bool_t iot_proto_grapp_reg_conf_ind_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; (void)data; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; iot_cus_printf("[glpr]load_local_dev=%d, mac-%x:%x:%x:%x:%x:%x\n", p_flash->public.pub.local_type, p_flash->public.pub.local_mac[0], p_flash->public.pub.local_mac[1], p_flash->public.pub.local_mac[2], p_flash->public.pub.local_mac[3], p_flash->public.pub.local_mac[4], p_flash->public.pub.local_mac[5]); /* set tx power */ iot_proto_set_tx_power(DEFAULT_TX_POWER, false); if (IOT_PLC_DEV_ROLE_CCO == prototask_contxt.local_dev.nw_role) { /* cco enable whitelist as default */ iot_proto_whitelist_en_disable(GE_PROTO_WL_ENABLE, false); iot_proto_whitelist_add_remove(GE_PROTO_ACTION_ADD, NULL, false); } else { /* sta set whitelist state from flash */ if (p_flash->public.pub.wl_state == 1) { iot_proto_whitelist_en_disable(GE_PROTO_WL_ENABLE, false); } else { iot_proto_whitelist_en_disable(GE_PROTO_WL_DISABLE, false); } if (iot_mac_addr_valid(p_flash->public.pub.cco_mac)) { iot_proto_whitelist_add_remove(GE_PROTO_ACTION_ADD, p_flash->public.pub.cco_mac, false); } } if (prototask_contxt.local_dev.nw_role != IOT_PLC_DEV_ROLE_CCO && !iot_hwver_is_ledc_v3_0_jy()) { /* 启动探测mac */ os_start_timer(prototask_contxt.detect_timer, 0); } else { /* 设置mac */ iot_proto_set_local_mac(); } /* if STA role, set scan bitmap saved in app pib or default value */ #if PLC_SUPPORT_STA_ROLE iot_proto_set_fb_bitmap(NULL, false); #endif return 0; } bool_t iot_proto_reboot_sta_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; bool_t rpt_cfm = false; ge_frame_reboot_sta_set_subfn18_t *frm = (ge_frame_reboot_sta_set_subfn18_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 }; uint8_t *local_mac = prototask_contxt.local_dev.mac; protpkt_tx_info_t txinfo = { 0 }; uint8_t reason = PROTO_REASON_OK; if (len != sizeof(ge_frame_reboot_sta_set_subfn18_t)) { reason = PROTO_REASON_LEN_MISSMATCH; iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "set reboot"); rpt_cfm = true; goto cfm; } iot_mac_addr_cpy(dst_mac, frm->dst_mac); switch (dir) { case CMD_LOCAL_DOWN_LINK: { if (iot_mac_addr_cmp(dst_mac, local_mac)) { reason = PROTO_REASON_OK; } else if (frm->nid != prototask_contxt.local_dev.nid) { reason = PROTO_REASON_NID_MISSMATCH; } else { iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 3, 200, 1, local_mac, dst_mac); iot_cus_printf("[glpr]reboot[%2x:%2x:%2x:" "%2x:%2x:%2x]cmd forward, dir:%d\n", dst_mac[0],dst_mac[1],dst_mac[2],dst_mac[3],dst_mac[4], dst_mac[5], dir); iot_proto_remote_cmd_send_to_plctxrx(data, sizeof(ge_frame_reboot_sta_set_subfn18_t), &txinfo); sm->dir = CMD_REMOTE_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; return rpt2mcu; } rpt_cfm = true; goto cfm; } case CMD_REMOTE_UP_LINK: { iot_cus_printf("[glpr]remote reboot cmd excuted\n"); if (frm->nid != prototask_contxt.local_dev.nid) { reason = PROTO_REASON_NID_MISSMATCH; } else if (!iot_mac_addr_cmp(dst_mac, local_mac)) { reason = PROTO_REASON_MAC_MISSMATCH; } iot_cus_printf("[glpr]send remote reboot cfm to[%2x:%2x:%2x:%2x" "%2x:%2x] result:%d\n", frm->src_mac[0],frm->src_mac[1], frm->src_mac[2], frm->src_mac[3], frm->src_mac[4], frm->src_mac[5], reason); rpt_cfm = true; goto cfm; } default: break; } cfm: if (rpt_cfm) { iot_proto_resp_cfm_frame(reason, dir, PROTO_REBOOT_STA_CMD, frm->seq, frm->src_mac); } if (reason == PROTO_REASON_OK) { prototask_contxt.reboot_reason = frm->reboot_type; iot_cus_printf("[glpr]reboot after %dsec reason=%d\n", PROTO_TIMER_REBOOT_DELAY_INTVL, prototask_contxt.reboot_reason); os_start_timer(prototask_contxt.reboot_tmr, PROTO_TIMER_REBOOT_DELAY_INTVL); } return rpt2mcu; } bool_t iot_proto_set_uart_param_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; uint8_t reason = 0; uint32_t baud_val[] = PROTO_GE_UART_BAUD_VALUE; iot_pkt_t *pkt; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; ge_frame_cmd_cfm_set_subfn20_t *cfm_cmd; ge_frame_uart_param_set_subfn161_t *set_cmd = (ge_frame_uart_param_set_subfn161_t *)data; /* check param */ if (len == sizeof(*set_cmd)) { if ((iot_proto_uart_param_check(set_cmd->baudrate, set_cmd->parity, set_cmd->data_bit, set_cmd->stop_bit) == false) || (p_flash->public.pub.baudidx >= PROTO_GE_UART_BAUD_IDX_MAX)) { reason = PROTO_REASON_UART_PARAM_ERR; } else if ((baud_val[p_flash->public.pub.baudidx] == set_cmd->baudrate) && (p_flash->public.pub.parity == set_cmd->parity) && (p_flash->public.pub.data == set_cmd->data_bit) && (p_flash->public.pub.stop == set_cmd->stop_bit)) { reason = PROTO_REASON_DUP_SETTING; } } else { reason = PROTO_REASON_LEN_MISSMATCH; } if (reason == 0) { /* save uart param to flash */ p_flash->public.pub.baudidx = uart_baud_find_index(set_cmd->baudrate); p_flash->public.pub.parity = set_cmd->parity; p_flash->public.pub.data = set_cmd->data_bit; p_flash->public.pub.stop = set_cmd->stop_bit; iot_proto_flashsave(p_flash); } /* send set confirm cmd to HOST */ pkt = iot_pkt_alloc(sizeof(*cfm_cmd), IOT_GREE_APP_MID); IOT_ASSERT(pkt); cfm_cmd = (ge_frame_cmd_cfm_set_subfn20_t *)iot_pkt_data(pkt); os_mem_set(cfm_cmd, 0, sizeof(*cfm_cmd)); iot_pkt_put(pkt, sizeof(*cfm_cmd)); cfm_cmd->seq = set_cmd->seq; cfm_cmd->cmd = set_cmd->hdr.subfn; cfm_cmd->reason = reason; if (reason) { cfm_cmd->result = 1; } else { cfm_cmd->result = 0; } EXT_FN_FRM_PREPARE(cfm_cmd, PROTO_GE_PLC_SET_CMD, PROTO_CMD_CFM_CMD); cfm_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)cfm_cmd, sizeof(*cfm_cmd) - sizeof(ge_frm_tail_t)); iot_proto_send_to_mainboard(pkt); return rpt2mcu; } void iot_proto_send_bc_data_as_internal_data(uint8_t *data) { ge_frm_tail_t *tail; ge_frame_data_send_set_subfn160_t *bc_data; iot_pkt_t *p_pkt; uint8_t bc_data_len = GE_FRM_MIN_LEN + IOT_MAC_ADDR_LEN + IOT_PLC_BEACON_DATA_MAX ; p_pkt = iot_pkt_alloc(bc_data_len, IOT_GREE_APP_MID); if (NULL == p_pkt) { iot_cus_printf("[glpr][err]send_bc_data No Mem!\n"); return; } bc_data = (ge_frame_data_send_set_subfn160_t *)iot_pkt_put(p_pkt, bc_data_len); bc_data->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE; bc_data->hdr.hdr.data_len = bc_data_len - GE_FRM_MIN_LEN; bc_data->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD; bc_data->hdr.subfn = PROTO_GE_DATA_CMD; bc_data->force_tx_connless = 0x1; bc_data->resv = 0; bc_data->force_noaggr = 0x1; bc_data->data_type = GE_INTERNAL_BCN_DATA_TYPE; iot_mac_addr_cpy(bc_data->dest_mac, ge_bcast_addr); os_mem_cpy(bc_data->data, data, IOT_PLC_BEACON_DATA_MAX); tail = (ge_frm_tail_t *)(bc_data->data + IOT_PLC_BEACON_DATA_MAX); tail->check_sum = ge_frm_checksum_calc((uint8_t *)bc_data, bc_data_len - sizeof(ge_frm_tail_t)); tail->tail = GE_FRM_TAIL_CODE; iot_proto_data_handler((uint8_t*)bc_data, bc_data_len, CMD_LOCAL_DOWN_LINK); iot_pkt_free(p_pkt); } bool_t iot_proto_bc_data_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; uint32_t reason = 0; plctxrx_cmd_arg_t cmd = { 0 }; iot_pkt_t *cmd_pkt; ge_frame_bc_data_send_subfn162_t *frm = (ge_frame_bc_data_send_subfn162_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); if (len != sizeof(ge_frame_bc_data_send_subfn162_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (prototask_contxt.local_dev.nw_role != IOT_PLC_DEV_ROLE_CCO) { reason = PROTO_REASON_NO_AUTHORITY; } if (0 != reason) { iot_proto_resp_cfm_frame(reason, dir, PROTO_GE_BC_DATA_CMD, 0, NULL); iot_cus_printf("[glpr][err]send bc data err:%d\n", reason); return rpt2mcu; } /* Broadcast beacon data as connless pkt at the same time in case that * off-line STAs can not report beacon data up to app layer */ iot_proto_send_bc_data_as_internal_data(frm->data); sm->dir = CMD_LOCAL_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; cmd.cid.cid = PLCTXRX_CID_VENDOR_DATA; cmd.cid.opcode = PLCTXRX_OP_EXECUTE; cmd.prio = 0; cmd.need_ack = 1; cmd.dlen = IOT_PLC_BEACON_DATA_MAX; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd) + cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd) + cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); os_mem_cpy(iot_pkt_data(cmd_pkt) + sizeof(cmd), frm->data, IOT_PLC_BEACON_DATA_MAX); iot_cus_printf("[glpr]send bc data\n"); /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } bool_t iot_proto_set_fb_bitmap_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; uint32_t reason = 0; ge_frame_fb_scan_bitmap_set_subfn30_t *frm = (ge_frame_fb_scan_bitmap_set_subfn30_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); if (len != sizeof(ge_frame_fb_scan_bitmap_set_subfn30_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (prototask_contxt.local_dev.nw_role == IOT_PLC_DEV_ROLE_CCO) { reason = PROTO_REASON_NO_AUTHORITY; } if (0 != reason) { iot_proto_resp_cfm_frame(reason, dir, PROTO_SET_FB_BITMAP_CMD, 0, NULL); iot_cus_printf("[glpr][err]set band bitmap err:%d\n", reason); return rpt2mcu; } sm->dir = CMD_LOCAL_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; iot_proto_set_fb_bitmap(&frm->fb_scan_bitmap, true); iot_cus_printf("[glpr]set band bitmap\n"); return rpt2mcu; } bool_t iot_proto_set_fix_rate_mode_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; iot_pkt_t *p_pkt; plctxrx_cmd_fix_rate_t p_fix_rate = { 0 }; plctxrx_cmd_arg_t *p_arg; ge_frame_fix_rate_set_subfn31_t *frm = (ge_frame_fix_rate_set_subfn31_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); if (len != sizeof(ge_frame_fix_rate_set_subfn31_t)) { iot_proto_resp_cfm_frame(PROTO_REASON_LEN_MISSMATCH, dir, PROTO_SET_FIX_RATE_MODE_CMD, 0, NULL); iot_cus_printf("[glpr][err]set fixed rate err\n"); return rpt2mcu; } sm->dir = CMD_LOCAL_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; p_fix_rate.fix_rate_mode = frm->enable; p_pkt = iot_pkt_alloc(sizeof(*p_arg) + sizeof(p_fix_rate), IOT_GREE_APP_MID); IOT_ASSERT(p_pkt); iot_pkt_put(p_pkt, sizeof(*p_arg) + sizeof(p_fix_rate)); p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt); p_arg->cid.cid = PLCTXRX_CID_FIXED_RATE; p_arg->cid.opcode = PLCTXRX_OP_CONFIG; p_arg->need_ack = true; p_arg->dlen = sizeof(p_fix_rate); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(p_pkt), p_arg, sizeof(*p_arg)); os_mem_cpy(iot_pkt_data(p_pkt) + sizeof(*p_arg), &p_fix_rate, p_arg->dlen); iot_proto_cmd_send_to_plctxrx(p_pkt); iot_cus_printf("[glpr]set fixed rate\n"); return rpt2mcu; } bool_t iot_proto_sta_paging_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; uint32_t reason = 0; uint8_t i = 0; ge_frame_sta_paging_subfn32_t *frm = (ge_frame_sta_paging_subfn32_t *)data; uint8_t frm_len = sizeof(*frm) + frm->count * IOT_MAC_ADDR_LEN + GE_FRM_CHECKSUM_FIELD_LEN + GE_FRM_TAIL_FILED_LEN; if (dir != CMD_REMOTE_UP_LINK) { reason = PROTO_REASON_CMD_DIR_ERR; } else if (IOT_PLC_DEV_ROLE_CCO == prototask_contxt.local_dev.nw_role) { reason = PROTO_REASON_NO_AUTHORITY; } else if (len != frm_len) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (prototask_contxt.local_dev.dev_ready) { reason = PROTO_REASON_JOINED; } else if (iot_mac_addr_cmp(prototask_contxt.paging_cco_mac, frm->cco_mac)) { reason = PROTO_REASON_DUP_SETTING; } iot_cus_printf("[glpr]recv sta paging mac\n"); if (0 != reason) { iot_cus_printf("err:%d\n", reason); return rpt2mcu; } iot_cus_printf("count:%d\n", frm->count); /* check paging mac */ for (i = 0; i < frm->count; i++) { if (iot_mac_addr_cmp(frm->sta_mac[i], prototask_contxt.local_dev.mac)) { iot_mac_addr_cpy(prototask_contxt.paging_cco_mac, frm->cco_mac); if (prototask_contxt.update_cco_mac) { iot_cus_printf("[glpr]post cco mac:%02X,%02X,%02X,%02X,%02X," "%02X to custom app\n", frm->cco_mac[0], frm->cco_mac[1], frm->cco_mac[2], frm->cco_mac[3], frm->cco_mac[4], frm->cco_mac[5]); prototask_contxt.update_cco_mac(frm->cco_mac); break; } } } return rpt2mcu; } /** * @brief iot_proto_switch_boot_part_ind_handler(): switch boot part ind handler * @param dst_mac: the dest mac decide command direction, * if dest mac is local mac, will send to uart, * otherwise send to remote address. * @param reason: the reason of the switch boot part */ static void iot_proto_switch_boot_part_ind_handler(uint8_t *dst_mac, uint8_t reason) { iot_pkt_t *pkt; protpkt_tx_info_t txinfo = { 0 }; ge_frame_sw_bt_part_ind_subfn95_t *ind_frm; if (dst_mac == NULL || !iot_mac_addr_valid(dst_mac) || iot_mac_is_bcast(dst_mac)) { iot_cus_printf("[glpr]switch_boot_part_ind dst mac invalid\n"); return; } pkt = iot_pkt_alloc(sizeof(*ind_frm), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr] alloc pkt err\n"); return; } iot_pkt_put(pkt, sizeof(*ind_frm)); ind_frm = (ge_frame_sw_bt_part_ind_subfn95_t *)iot_pkt_data(pkt); /* fill indication frame field */ os_mem_set(ind_frm, 0 , sizeof(*ind_frm)); EXT_FN_FRM_PREPARE(ind_frm, PROTO_GE_PLC_SET_CMD, PROTO_SWITCH_BOOT_PART_IND_CMD); iot_mac_addr_cpy(ind_frm->mac, prototask_contxt.local_dev.mac); ind_frm->reason = reason; ind_frm->seq = prototask_contxt.local_dev.ind_seq++; ind_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)ind_frm, sizeof(*ind_frm) - sizeof(ge_frm_tail_t)); /* if dest mac is local mac, will send to uart, * otherwise send to remote address.*/ if (iot_mac_addr_cmp(prototask_contxt.local_dev.mac, dst_mac)) { iot_proto_send_to_mainboard(pkt); } else { iot_cus_printf("[glpr]send remote sw bootpart ind to[%2x:%2x:%2x:%2x" "%2x:%2x] result:%d\n", dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], reason); iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, prototask_contxt.local_dev.mac, dst_mac); /* set to remote dst mac */ iot_proto_remote_cmd_send_to_plctxrx((uint8_t*)ind_frm, sizeof(*ind_frm), &txinfo); iot_pkt_free(pkt); } } /** * @brief iot_proto_switch_boot_part_handler(): switch boot part handler, * support local and remote command. * @param data: switch boot part command frame * @param len: the data length * @param dir: the direction of command come from. */ bool_t iot_proto_switch_boot_part_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; ge_frame_sw_bt_part_subfn34_t *frm = (ge_frame_sw_bt_part_subfn34_t *)data; uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 }; uint8_t *local_mac = prototask_contxt.local_dev.mac; protpkt_tx_info_t txinfo = { 0 }; uint8_t reason = PROTO_REASON_OK; if (len != sizeof(*frm)) { reason = PROTO_REASON_LEN_MISSMATCH; iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "sw boot part"); goto cfm; } iot_mac_addr_cpy(dst_mac, frm->dst_mac); if (!iot_mac_addr_valid(dst_mac)) { reason = PROTO_REASON_MAC_MISSMATCH; iot_cus_printf("[glpr][err]%s mac is mismatch\n", "sw boot part"); goto cfm; } switch (dir) { case CMD_LOCAL_DOWN_LINK: { if (iot_mac_is_bcast(dst_mac)) { /* not support broadcast switch boot part */ reason = PROTO_REASON_NOT_SUPPORT; } else if (!iot_mac_addr_cmp(dst_mac, local_mac)) { iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, local_mac, dst_mac); iot_cus_printf("[glpr]sw bt part[%2x:%2x:%2x:" "%2x:%2x:%2x]cmd forward, dir:%d\n", dst_mac[0],dst_mac[1],dst_mac[2],dst_mac[3],dst_mac[4], dst_mac[5], dir); iot_proto_remote_cmd_send_to_plctxrx(data, len, &txinfo); } break; } case CMD_REMOTE_UP_LINK: { iot_cus_printf("[glpr]remote sw boot part cmd excuted\n"); if (!iot_mac_addr_cmp(dst_mac, local_mac)) { reason = PROTO_REASON_MAC_MISSMATCH; /* dest mac is not equal to local mac will drop */ } break; } default: reason = PROTO_REASON_NOT_SUPPORT; break; } cfm: /* only report confirm when received command from uart */ if (CMD_LOCAL_DOWN_LINK == dir) { iot_proto_resp_cfm_frame(reason, dir, PROTO_SET_SWITCH_BOOT_PART_CMD, frm->seq, NULL); } /* only report indication if command dest mac is equal to local mac */ if (iot_mac_addr_cmp(dst_mac, local_mac)) { iot_proto_switch_boot_part_ind_handler(frm->src_mac, reason); /* only reason is ok need to switch boot part */ if (reason == PROTO_REASON_OK) { iot_switch_boot_part(); /* after swicth boot part need to reboot */ os_start_timer(prototask_contxt.reboot_tmr, PROTO_TIMER_REBOOT_DELAY_INTVL); } } return rpt2mcu; } bool_t iot_proto_set_local_ip4_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; uint8_t ip_addr[IOT_IP4_ADDR_LEN] = { 0 }; uint8_t ip_mask[IOT_IP4_ADDR_LEN] = { 0 }; uint32_t reason = 0; ge_frame_local_ip4_set_subfn35_t *frm = ( ge_frame_local_ip4_set_subfn35_t *)data; iot_oem_get_local_ip4_addr(ip_addr); iot_oem_get_local_ip4_netmask(ip_mask); if (len != sizeof(ge_frame_local_ip4_set_subfn35_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if ((IOT_OEM_IP4_IS_INVALID == iot_oem_ip4_addr_is_valid( frm->ip4_addr)) || (IOT_OEM_IP4_MASK_IS_INVALID == iot_oem_ip4_netmask_is_valid( frm->ip4_mask))) { reason = PROTO_REASON_IP4_IS_INVALID; } else if (iot_ip4_addr_cmp(ip_addr, frm->ip4_addr) && iot_ip4_addr_cmp(ip_mask, frm->ip4_mask)) { reason = PROTO_REASON_DUP_SETTING; } else if (ERR_OK != iot_oem_set_local_ip4_info(frm->ip4_addr, frm->ip4_mask)) { reason = PROTO_REASON_NO_IP4_SETTED; } iot_proto_resp_cfm_frame(reason, dir, PROTO_LOCAL_IP4_INFO_SET_CMD, frm->seq, NULL); if (0 != reason) { iot_cus_printf("[glpr][err]set_local_ip4 failed, " "reason--%d\n", reason); } return rpt2mcu; } /* Get operable gpio index */ static uint8_t iot_proto_get_gpio_index(uint8_t gpio) { uint8_t index = 0, gpio_max = 0; uint8_t board_id = iot_board_get_board_id(); if ((CUS_BOARD_ID_LEDCSTA01 == board_id) || (CUS_BOARD_ID_LEDCCCO01 == board_id)) { gpio_max = IOT_GE_LEDC01_VALID_GPIO_MAX; } for (; index < gpio_max; index++) { if (gpio == iot_ge_gpio_g[index].gpio_num) { return index; } } return IOT_PROTO_INVALID_GPIO_INDEX; } /** * @brief iot_proto_config_gpio_handler(): config gpio handler. * @param data: config gpio command frame * @param len: the data length * @param dir: the direction of command come from. */ bool_t iot_proto_config_gpio_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; bool_t rpt_cfm = false; ge_frame_gpio_config_subfn164_t *frm = (ge_frame_gpio_config_subfn164_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 }; uint8_t *local_mac = prototask_contxt.local_dev.mac; protpkt_tx_info_t txinfo = { 0 }; uint8_t reason = PROTO_REASON_OK; transmit_direction_e_t tmp_dir = 0; uint8_t gpio_index = 0; if (len != sizeof(ge_frame_gpio_config_subfn164_t)) { reason = PROTO_REASON_LEN_MISSMATCH; iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "config gpio"); rpt_cfm = true; goto cfm; } else if (iot_mac_addr_cmp(frm->dest_mac, dst_mac)) { reason = PROTO_REASON_MAC_ADDR_ZERO; iot_cus_printf("[glpr][err]%s cmd dest mac addr is zero\n", "config gpio"); rpt_cfm = true; goto cfm; } else if (IOT_PROTO_INVALID_GPIO_INDEX == (gpio_index = iot_proto_get_gpio_index(frm->gpio_num))) { reason = PROTO_REASON_NOT_SUPPORT; iot_cus_printf("[glpr][err]%s cmd gpio num is invalid\n", "config gpio"); rpt_cfm = true; goto cfm; } else if ((IOT_GE_GPIO_DIR_OUTPUT != frm->dir_mode) && (IOT_GE_GPIO_DIR_INPUT != frm->dir_mode)) { reason = PROTO_REASON_PARAME_ERR; iot_cus_printf("[glpr][err]%s cmd dir mode is invalid\n", "config gpio"); rpt_cfm = true; goto cfm; } else if ((IOT_GE_GPIO_PULL_NONE != frm->pull_mode) && (IOT_GE_GPIO_PULL_UP != frm->pull_mode) && (IOT_GE_GPIO_PULL_DOWN != frm->pull_mode)) { reason = PROTO_REASON_PARAME_ERR; iot_cus_printf("[glpr][err]%s cmd pull mode is invalid\n", "config gpio"); rpt_cfm = true; goto cfm; } iot_mac_addr_cpy(dst_mac, frm->dest_mac); if (iot_mac_addr_cmp(dst_mac, local_mac)) { tmp_dir = CMD_LOCAL_DOWN_LINK; } else { tmp_dir = CMD_REMOTE_DOWN_LINK; } switch (tmp_dir) { case CMD_LOCAL_DOWN_LINK: { if (iot_ge_gpio_g[gpio_index].dir_mode != frm->dir_mode) { if (IOT_GE_GPIO_DIR_OUTPUT == frm->dir_mode) { if (ERR_OK != iot_gpio_switch_io_mode_dynamic(frm->gpio_num, GPIO_OUTPUT)) { iot_cus_printf("[glpr][err] open gpio as output err, gpio num:%d\n", frm->gpio_num); goto not_ready; } } else if (IOT_GE_GPIO_DIR_INPUT == frm->dir_mode) { if (ERR_OK != iot_gpio_switch_io_mode_dynamic(frm->gpio_num, GPIO_INPUT)) { iot_cus_printf("[glpr][err] open gpio as input err, gpio num:%d\n", frm->gpio_num); goto not_ready; } } } if (iot_ge_gpio_g[gpio_index].pull_mode != frm->pull_mode) { if (IOT_GE_GPIO_PULL_UP == frm->pull_mode) { if (ERR_OK != iot_gpio_set_pull_mode(frm->gpio_num, GPIO_PULL_UP)) { iot_cus_printf("[glpr][err] pull up gpio err, gpio num:%d\n", frm->gpio_num); goto not_ready; } } else if (IOT_GE_GPIO_PULL_DOWN == frm->pull_mode) { if (ERR_OK != iot_gpio_set_pull_mode(frm->gpio_num, GPIO_PULL_DOWN)) { iot_cus_printf("[glpr][err] pull down gpio err, gpio num:%d\n", frm->gpio_num); goto not_ready; } } } if (IOT_GE_GPIO_DIR_OUTPUT == frm->dir_mode) { iot_gpio_value_set(frm->gpio_num, frm->output_value? 1:0); } iot_ge_gpio_g[gpio_index].gpio_num = frm->gpio_num; iot_ge_gpio_g[gpio_index].dir_mode = frm->dir_mode; iot_ge_gpio_g[gpio_index].pull_mode = frm->pull_mode; iot_ge_gpio_g[gpio_index].gpio_state = IOT_GE_GPIO_OPEN; reason = PROTO_REASON_OK; rpt_cfm = true; goto cfm; } case CMD_REMOTE_DOWN_LINK: { iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, PROTO_UNICAST_RETRY_DEFAULT_CNT, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, local_mac, dst_mac); iot_proto_remote_cmd_send_to_plctxrx(data, sizeof(ge_frame_gpio_config_subfn164_t), &txinfo); sm->dir = CMD_REMOTE_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; return rpt2mcu; } default: break; } not_ready: reason = PROTO_REASON_NOT_READY; rpt_cfm = true; cfm: if (rpt_cfm) { iot_proto_resp_cfm_frame(reason, dir, PROTO_GE_GPIO_CONFIG_CMD, frm->seq, frm->src_mac); } return rpt2mcu; } bool_t iot_proto_set_gpio_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; bool_t rpt_cfm = false; ge_frame_gpio_set_subfn165_t *frm = (ge_frame_gpio_set_subfn165_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 }; uint8_t *local_mac = prototask_contxt.local_dev.mac; protpkt_tx_info_t txinfo = { 0 }; uint8_t reason = PROTO_REASON_OK; transmit_direction_e_t tmp_dir = 0; uint8_t gpio_index = 0; if (len != sizeof(ge_frame_gpio_set_subfn165_t)) { reason = PROTO_REASON_LEN_MISSMATCH; iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "set gpio"); rpt_cfm = true; goto cfm; } else if (iot_mac_addr_cmp(frm->dest_mac, dst_mac)) { reason = PROTO_REASON_MAC_ADDR_ZERO; iot_cus_printf("[glpr][err]%s cmd dest mac addr is zero\n", "set gpio"); rpt_cfm = true; goto cfm; } else if (IOT_PROTO_INVALID_GPIO_INDEX == (gpio_index = iot_proto_get_gpio_index(frm->gpio_num))) { reason = PROTO_REASON_NOT_SUPPORT; iot_cus_printf("[glpr][err]%s cmd gpio num is invalid\n", "set gpio"); rpt_cfm = true; goto cfm; } iot_mac_addr_cpy(dst_mac, frm->dest_mac); if (iot_mac_addr_cmp(dst_mac, local_mac)) { tmp_dir = CMD_LOCAL_DOWN_LINK; } else { tmp_dir = CMD_REMOTE_DOWN_LINK; } switch (tmp_dir) { case CMD_LOCAL_DOWN_LINK: { if ((IOT_GE_GPIO_OPEN != iot_ge_gpio_g[gpio_index].gpio_state) || (IOT_GE_GPIO_DIR_OUTPUT != iot_ge_gpio_g[gpio_index].dir_mode)) { reason = PROTO_REASON_NOT_READY; iot_cus_printf("[glpr][err]%s need to config the gpio before\n", "set gpio"); rpt_cfm = true; goto cfm; } iot_gpio_value_set(frm->gpio_num, frm->value); reason = PROTO_REASON_OK; rpt_cfm = true; goto cfm; } case CMD_REMOTE_DOWN_LINK: { iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, PROTO_UNICAST_RETRY_DEFAULT_CNT, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, local_mac, dst_mac); iot_proto_remote_cmd_send_to_plctxrx(data, sizeof(ge_frame_gpio_set_subfn165_t), &txinfo); sm->dir = CMD_REMOTE_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; return rpt2mcu; } default: break; } cfm: if (rpt_cfm) { iot_proto_resp_cfm_frame(reason, dir, PROTO_GE_GPIO_SET_CMD, frm->seq, frm->src_mac); } return rpt2mcu; } /* only for cco */ void iot_proto_sta_paging_mac() { uint32_t index; iot_pkt_t *p_pkt; ge_frame_sta_paging_subfn32_t *frame ; ge_frm_tail_t *tail; protpkt_tx_info_t txinfo = { 0 }; uint8_t frm_len; uint8_t cnt = 0; if (IOT_PLC_DEV_ROLE_CCO != prototask_contxt.local_dev.nw_role) { iot_cus_printf("[glpr]paging only support cco\n"); return ; } frm_len = sizeof(*frame) + PROTO_STA_PAGING_MAX_CNT * IOT_MAC_ADDR_LEN + GE_FRM_CHECKSUM_FIELD_LEN + GE_FRM_TAIL_FILED_LEN; p_pkt = iot_pkt_alloc(frm_len, IOT_GREE_APP_MID); if (NULL == p_pkt) { iot_cus_printf("[glpr][err]sta_paging_mac No Mem!\n"); return; } frame = (ge_frame_sta_paging_subfn32_t *)iot_pkt_data(p_pkt); index = prototask_contxt.paging_index; /* check disconnect sta mac */ for (; index < STA_DEV_MAX; index++) { if (iot_mac_addr_valid(prototask_contxt.dev_lst.dev[index].mac)) { if (false == prototask_contxt.dev_lst.online_flag[index]) { iot_mac_addr_cpy((uint8_t *)frame->sta_mac[cnt], prototask_contxt.dev_lst.dev[index].mac); cnt++; /* send paging message one time can include max mac count */ if (cnt >= PROTO_STA_PAGING_MAX_CNT) { index++; break; } } } } if (index >= STA_DEV_MAX) { index = 0; } prototask_contxt.paging_index = index; if (cnt > 0) { frm_len = sizeof(*frame) + cnt * IOT_MAC_ADDR_LEN + GE_FRM_CHECKSUM_FIELD_LEN + GE_FRM_TAIL_FILED_LEN; iot_mac_addr_cpy(frame->cco_mac, prototask_contxt.local_dev.mac); frame->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE; frame->hdr.hdr.data_len = frm_len - GE_FRM_MIN_LEN; frame->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD; frame->hdr.subfn = PROTO_SEND_STA_PAGING_CMD; frame->count = cnt; tail = (ge_frm_tail_t *)(frame->sta_mac + cnt); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) + cnt * IOT_MAC_ADDR_LEN); tail->tail = GE_FRM_TAIL_CODE; iot_pkt_put(p_pkt, frm_len); iot_proto_fill_txinfo(&txinfo, false, PLCTXRX_BORADCAST, PROTO_BROADCAST_RETRY_DEFAULT_CNT, PROTO_BROADCAST_RETRY_DEFAULT_INTVL, 0, prototask_contxt.local_dev.mac, NULL); txinfo.force_noaggr = true; txinfo.force_tx_connless = true; txinfo.need_ack = false; txinfo.retry_cnt = 0; iot_proto_remote_cmd_send_to_plctxrx((uint8_t*)frame, frm_len, &txinfo); } iot_pkt_free(p_pkt); } #if IOT_GE_AES_ENABLE bool_t iot_proto_set_aes_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; uint32_t reason = 0; ge_frame_aes_set_subfn163_t *hdr = (ge_frame_aes_set_subfn163_t *)data; if (dir != CMD_LOCAL_DOWN_LINK) { reason = PROTO_REASON_CMD_DIR_ERR; goto out; } else if (os_mem_cmp(hdr->dest_mac, prototask_contxt.local_dev.mac, IOT_MAC_ADDR_LEN)) { reason = PROTO_REASON_MAC_MISSMATCH; goto out; } else if (len != sizeof(ge_frame_aes_set_subfn163_t)) { reason = PROTO_REASON_LEN_MISSMATCH; goto out; } else { reason = PROTO_REASON_OK; } if (hdr->aes.enable) { greeapp->aes.enable = 1; } else { greeapp->aes.enable = 0; } out: iot_proto_resp_cfm_frame(reason, dir, PROTO_AES_SET_CMD, hdr->seq, NULL); return rpt2mcu; } bool_t iot_proto_resp_aes_frame(uint8_t seq) { bool_t rpt2mcu = false; ge_frame_aes_resp_subfn26_t *resp_cmd; iot_pkt_t *pkt = iot_pkt_alloc(sizeof(*resp_cmd), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_cmd = (ge_frame_aes_resp_subfn26_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_cmd)); os_mem_set(resp_cmd, 0, sizeof(*resp_cmd)); EXT_FN_FRM_PREPARE(resp_cmd, PROTO_GE_PLC_RESP_CMD, PROTO_AES_RESP_CMD); resp_cmd->seq = seq; os_mem_cpy(&resp_cmd->aes, &greeapp->aes, sizeof(ge_aes_contxt_t)); resp_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_cmd, sizeof(*resp_cmd) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); return rpt2mcu; } bool_t iot_proto_resp_aes_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; return rpt2mcu; } bool_t iot_proto_query_aes_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; ge_frame_aes_query_subfn26_t *hdr = (ge_frame_aes_query_subfn26_t *)data; rpt2mcu = iot_proto_resp_aes_frame(hdr->seq); return rpt2mcu; } #else bool_t iot_proto_set_aes_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)data; (void)len; (void)dir; return false; } bool_t iot_proto_resp_aes_frame(uint8_t seq) { (void)seq; return false; } bool_t iot_proto_query_aes_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)data; (void)len; (void)dir; return false; } bool_t iot_proto_resp_aes_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)data; (void)len; (void)dir; return false; } #endif bool_t iot_proto_data_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; uint8_t role = prototask_contxt.local_dev.nw_role, retry_cnt; transmit_direction_e_t tmp_dir; ge_frame_data_send_set_subfn160_t *hdr = (ge_frame_data_send_set_subfn160_t *)data; protpkt_tx_info_t txinfo = { 0 }; uint8_t dest_mac[IOT_MAC_ADDR_LEN]; if (CMD_LOCAL_DOWN_LINK == dir) { if (iot_mac_addr_cmp(hdr->dest_mac, prototask_contxt.local_dev.mac)) { if ((IOT_PLC_DEV_ROLE_STA == role) && (prototask_contxt.local_dev.dev_ready)) { iot_mac_addr_cpy(dest_mac, prototask_contxt.cco_dev.mac); } else { return rpt2mcu; } } else { iot_mac_addr_cpy(dest_mac, hdr->dest_mac); } tmp_dir = DATA_DOWN_LINK; } else { tmp_dir = DATA_UP_LINK; } switch (tmp_dir) { case DATA_DOWN_LINK: { if(hdr->retr_cnt == 0) { retry_cnt = PROTO_UNICAST_RETRY_DEFAULT_CNT; } else { retry_cnt = hdr->retr_cnt; } if (IOT_PLC_DEV_ROLE_CCO == role) { if (mac_addr_is_bcast_addr(hdr->dest_mac)) { iot_proto_fill_txinfo(&txinfo, false, PLCTXRX_BORADCAST, PROTO_BROADCAST_RETRY_DEFAULT_CNT, PROTO_BROADCAST_RETRY_DEFAULT_INTVL, 0, prototask_contxt.local_dev.mac, NULL); } else { iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, retry_cnt, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, prototask_contxt.local_dev.mac, dest_mac); } } else { if (mac_addr_is_bcast_addr(hdr->dest_mac)) { iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, retry_cnt, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, prototask_contxt.local_dev.mac, NULL); } else { iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, retry_cnt, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, prototask_contxt.local_dev.mac, dest_mac); } } txinfo.force_noaggr = hdr->force_noaggr; txinfo.force_tx_connless = hdr->force_tx_connless; /* connless or not need ack pkt need no ack */ if (hdr->force_tx_connless == 1) { txinfo.need_ack = false; txinfo.retry_cnt = 0; } if (hdr->not_need_ack == 1) { txinfo.need_ack = false; txinfo.retry_cnt = hdr->retr_cnt; txinfo.retry_intvl = PROTO_UNICAST_RETRY_NOACK_INTVL; } iot_proto_data_send_to_plctxrx(data, len, &txinfo); break; } case DATA_UP_LINK: { if (GE_INTERNAL_BCN_DATA_TYPE == hdr->data_type) { iot_pkt_t *pkt; proto_vendor_info_t *vendr_info; pkt = iot_pkt_alloc(sizeof(proto_vendor_info_t), IOT_GREE_APP_MID); IOT_ASSERT(pkt); vendr_info = (proto_vendor_info_t *)iot_pkt_data(pkt); os_mem_cpy(vendr_info->data, hdr->data, sizeof(proto_vendor_info_t)); iot_pkt_put(pkt, sizeof(proto_vendor_info_t)); iot_proto_update_vendr(pkt); rpt2mcu = false; } else { rpt2mcu = true; } break; } default: IOT_ASSERT(0); break; } return rpt2mcu; } bool_t iot_proto_query_topo_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; uint8_t dev_role = prototask_contxt.local_dev.nw_role; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); iot_pkt_t *cmd_pkt; ge_frame_topo_query_subfn5_t *query_cmd = (ge_frame_topo_query_subfn5_t *)data; ge_frame_topo_resp_subfn5_t *resp_frm; uint16_t resp_len = 0; uint16_t topo_info_len = 0; uint16_t txrx_cmd_len; ge_frm_tail_t *tail; plctxrx_cmd_arg_t *cmd; plctxrx_cmd_query_topo_t *topo_cmd; switch (query_cmd->type) { case TOPO_INFO_TYPE_V0: topo_info_len = sizeof(topo_info_v0_t); break; case TOPO_INFO_TYPE_V1: topo_info_len = sizeof(topo_info_v1_t); break; default: iot_cus_printf("[glpr][err]topo info quary error with type[%d]\n", query_cmd->type); return rpt2mcu; } resp_len = sizeof(ge_frame_topo_resp_subfn5_t) + topo_info_len + sizeof(ge_frm_tail_t); if (len != sizeof(ge_frame_topo_query_subfn5_t)) { iot_pkt_t *pkt = iot_pkt_alloc(resp_len, IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_frm = (ge_frame_topo_resp_subfn5_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, resp_len); os_mem_set(resp_frm, 0, resp_len); resp_frm->type = query_cmd->type; GE_FRM_HDR_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_TOPO_RESP_CMD, resp_len); tail = (ge_frm_tail_t *)(resp_frm->info + topo_info_len); tail->check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, resp_len - sizeof(ge_frm_tail_t)); tail->tail = GE_FRM_TAIL_CODE; /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey topo"); return rpt2mcu; } prototask_contxt.topo_info_type = query_cmd->type; txrx_cmd_len = sizeof(plctxrx_cmd_arg_t) + sizeof(plctxrx_cmd_query_topo_t); /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(txrx_cmd_len, IOT_GREE_APP_MID); if (cmd_pkt == NULL) { iot_cus_printf("[glpr][err]pkt alloc fail\n"); return rpt2mcu; } cmd = (plctxrx_cmd_arg_t*)iot_pkt_put(cmd_pkt, txrx_cmd_len); cmd->cid.cid = PLCTXRX_CID_TOPO; cmd->cid.opcode = PLCTXRX_OP_QUERY; cmd->need_ack = true; cmd->prio = 0; cmd->dlen = sizeof(plctxrx_cmd_query_topo_t); topo_cmd = (plctxrx_cmd_query_topo_t*)cmd->arg; topo_cmd->ver = IOT_PLC_CCO_TOPO_REQ_DATA_VER_V1; topo_cmd->start = 1; topo_cmd->cnt = STA_DEV_MAX; /* judge local device role */ switch (dir) { case CMD_LOCAL_DOWN_LINK: { /* if device is not ready. */ if (!prototask_contxt.local_dev.dev_ready) { ge_frame_topo_resp_subfn5_t *frame; iot_pkt_t *data_pkt = iot_pkt_alloc(resp_len, IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); frame = (ge_frame_topo_resp_subfn5_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, resp_len); /* if txrx return zero sta cnt */ os_mem_set(frame, 0, resp_len); frame->type = query_cmd->type; frame->total_cnt = 1; frame->cur_cnt = 1; frame->seq = query_cmd->seq; switch (query_cmd->type) { case TOPO_INFO_TYPE_V0: { topo_info_v0_t *topo_info_v0 = (topo_info_v0_t *)frame->info; iot_mac_addr_cpy(topo_info_v0->mac, prototask_contxt.local_dev.mac); break; } case TOPO_INFO_TYPE_V1: { topo_info_v1_t *topo_info_v1 = (topo_info_v1_t *)frame->info; os_mem_set(topo_info_v1, 0, sizeof(topo_info_v1)); iot_mac_addr_cpy(topo_info_v1->mac, prototask_contxt.local_dev.mac); break; } default: iot_pkt_free(data_pkt); return rpt2mcu; } GE_FRM_HDR_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_TOPO_RESP_CMD, resp_len); tail = (ge_frm_tail_t *)(frame->info + topo_info_len); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, resp_len - sizeof(ge_frm_tail_t)); tail->tail = GE_FRM_TAIL_CODE; /* report topo to MCU */ iot_proto_send_to_mainboard(data_pkt); iot_cus_printf("[glpr]topo cmd send error,"\ " device is not ready!\n"); return rpt2mcu; } if (IOT_PLC_DEV_ROLE_CCO == dev_role) { /* if async cmd, we need to set a state for response cmd. */ sm->state = PROTO_CMD_WAIT_TOPO_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); } else { /* send cmd to CCO */ protpkt_tx_info_t txinfo = { 0 }; iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 3, 500, 1, prototask_contxt.local_dev.mac, prototask_contxt.cco_dev.mac); /* if async cmd, we need to set a state for response cmd. */ sm->state = PROTO_CMD_WAIT_TOPO_RESP; sm->dir = CMD_REMOTE_UP_LINK; sm->seq = query_cmd->seq; iot_proto_remote_cmd_send_to_plctxrx(data, len, &txinfo); } break; } case CMD_REMOTE_UP_LINK: { /* if async cmd, we need to set a state for response cmd. */ sm->state = PROTO_CMD_WAIT_TOPO_RESP; sm->dir = CMD_REMOTE_DOWN_LINK; sm->seq = query_cmd->seq; iot_mac_addr_cpy(sm->dev.mac, prototask_contxt.rx_info.mac); /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); break; } default: iot_cus_printf("[glpr][err]query topo:dir=%d\n", dir); IOT_ASSERT(0); break; } return rpt2mcu; } bool_t iot_proto_query_nw_detailinfo_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)data; (void)len; (void)dir; return false; } bool_t iot_proto_query_uart_param_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; uint32_t baud_val[] = PROTO_GE_UART_BAUD_VALUE; ge_frame_uart_param_query_subfn14_t *query_cmd = (ge_frame_uart_param_query_subfn14_t *)data; ge_frame_uart_param_resp_subfn14_t *resp_cmd; iot_pkt_t *pkt; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; pkt = iot_pkt_alloc(sizeof(*resp_cmd), IOT_GREE_APP_MID); IOT_ASSERT(pkt); resp_cmd = (ge_frame_uart_param_resp_subfn14_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_cmd)); os_mem_set(resp_cmd, 0, sizeof(*resp_cmd)); if (p_flash->public.pub.baudidx >= PROTO_GE_UART_BAUD_IDX_MAX) { p_flash->public.pub.baudidx = 0; } resp_cmd->baudrate = baud_val[p_flash->public.pub.baudidx]; resp_cmd->parity = p_flash->public.pub.parity; resp_cmd->data_bit = p_flash->public.pub.data; resp_cmd->stop_bit = p_flash->public.pub.stop; resp_cmd->seq = query_cmd->seq; EXT_FN_FRM_PREPARE(resp_cmd, PROTO_GE_PLC_RESP_CMD, PROTO_GE_UART_PARAM_RESP_CMD); resp_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_cmd, sizeof(*resp_cmd) - sizeof(ge_frm_tail_t)); iot_proto_send_to_mainboard(pkt); return rpt2mcu; } bool_t iot_proto_ext_query_wl_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; ge_frame_ext_wl_query_subfn15_t *query_cmd = (ge_frame_ext_wl_query_subfn15_t *)data; ge_frame_ext_wl_resp_subfn15_t *resp_cmd; proto_dev_list_t *p_devlist = &prototask_contxt.dev_lst; uint16_t total_cnt = p_devlist->valid_dev_cnt; uint16_t rpt_cnt = 0; iot_pkt_t *pkt; uint16_t rpt_size = 0; uint16_t i; uint16_t index = 0; uint16_t start_index = 0; uint16_t req_sta_cnt = query_cmd->sta_cnt; ge_frm_tail_t *resp_tail; if (len != sizeof(ge_frame_ext_wl_query_subfn15_t)) { iot_cus_printf("[gepr][err]%s cmd len mismatch\n", " query_ext_wl"); rpt_cnt = 0; } else if (query_cmd->index == 0 || query_cmd->index > total_cnt) { iot_cus_printf("[gepr][err]%s cmd err!\n", " query_ext_wl"); rpt_cnt = 0; } else { start_index = query_cmd->index - 1; rpt_cnt = total_cnt - start_index; if (req_sta_cnt > WL_QUERY_REQ_MAX_STA_CNT) { req_sta_cnt = WL_QUERY_REQ_MAX_STA_CNT; } if (rpt_cnt > req_sta_cnt) { rpt_cnt = req_sta_cnt; } } rpt_size = sizeof(ge_frame_ext_wl_resp_subfn15_t) + rpt_cnt * IOT_MAC_ADDR_LEN + sizeof(ge_frm_tail_t); pkt = iot_pkt_alloc(rpt_size, IOT_GREE_APP_MID); IOT_ASSERT(pkt); resp_cmd = (ge_frame_ext_wl_resp_subfn15_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, rpt_size); os_mem_set(resp_cmd, 0, rpt_size); resp_cmd->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE; resp_cmd->hdr.hdr.data_len = (uint8_t)(rpt_size - GE_FRM_MIN_LEN + GE_FRM_PLD_MIN_LEN); resp_cmd->hdr.hdr.fn = PROTO_GE_PLC_RESP_CMD; resp_cmd->hdr.subfn = PROTO_GE_EXT_WL_RESP_CMD; resp_cmd->resv[0] = 0; resp_cmd->resv[1] = 0; resp_cmd->total = total_cnt; resp_cmd->rpt_cnt = rpt_cnt; resp_cmd->seq = query_cmd->seq; if (rpt_cnt > 0) { /* fill mac */ for (i = 0; i < STA_DEV_MAX; i++) { if (mac_addr_is_valid_addr(p_devlist->dev[i].mac)) { if (index >= start_index) { if (index - start_index <= rpt_cnt) { iot_mac_addr_cpy(resp_cmd->mac[index - start_index], p_devlist->dev[i].mac); } else { break; } } index++; } } } resp_tail = (ge_frm_tail_t *)(resp_cmd->mac + rpt_cnt); resp_tail->check_sum = ge_frm_checksum_calc((uint8_t *)resp_cmd, rpt_size - sizeof(ge_frm_tail_t)); resp_tail->tail = GE_FRM_TAIL_CODE; /* response result */ iot_proto_send_to_mainboard(pkt); return rpt2mcu; } bool_t iot_proto_query_nid_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; (void)dir; bool_t rpt2mcu = false; ge_frame_nid_query_subfn16_t *query_cmd = (ge_frame_nid_query_subfn16_t *)data; ge_frame_nid_resp_subfn16_t *resp_cmd; iot_pkt_t *pkt; pkt = iot_pkt_alloc(sizeof(*resp_cmd), IOT_GREE_APP_MID); IOT_ASSERT(pkt); resp_cmd = (ge_frame_nid_resp_subfn16_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_cmd)); os_mem_set(resp_cmd, 0, sizeof(*resp_cmd)); resp_cmd->seq = query_cmd->seq; resp_cmd->nid = prototask_contxt.local_dev.nid; EXT_FN_FRM_PREPARE(resp_cmd, PROTO_GE_PLC_RESP_CMD, PROTO_NID_RESP_CMD); resp_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_cmd, sizeof(*resp_cmd)-sizeof(ge_frm_tail_t)); iot_proto_send_to_mainboard(pkt); return rpt2mcu; } bool_t iot_proto_query_wl_state_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; iot_pkt_t *pkt; ge_frame_wl_state_query_subfn17_t *query_cmd = (ge_frame_wl_state_query_subfn17_t *)data; ge_frame_wl_state_resp_subfn17_t *resp_frm; pkt = iot_pkt_alloc(sizeof(*resp_frm), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_frm = (ge_frame_wl_state_resp_subfn17_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_WHITELIST_STATE_RESP_CMD); //check cmd length if (len != sizeof(ge_frame_wl_state_query_subfn17_t)) { iot_cus_printf("[glpr][err]%s cmd len mismatch\n", " query_wl_state"); } else { resp_frm->seq = query_cmd->seq; resp_frm->state = p_flash->public.pub.wl_state; iot_cus_printf("[gepr]query_wl_state %d\n", resp_frm->state); } resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); return rpt2mcu; } bool_t iot_proto_query_module_info_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; ge_frame_module_info_query_subfn18_t *query_cmd = (ge_frame_module_info_query_subfn18_t *)data; ge_frame_module_info_resp_subfn18_t *resp_frm; iot_pkt_t *pkt = iot_pkt_alloc(sizeof(ge_frame_module_info_resp_subfn18_t), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_frm = (ge_frame_module_info_resp_subfn18_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_MODULE_INFO_RESP_CMD); if (len != sizeof(ge_frame_module_info_query_subfn18_t) ) { iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "query_module_info"); } else { resp_frm->seq = query_cmd->seq; resp_frm->role = prototask_contxt.local_dev.nw_role; os_mem_cpy(resp_frm->mac, prototask_contxt.local_dev.mac, IOT_MAC_ADDR_LEN); os_mem_cpy(resp_frm->cco_mac, prototask_contxt.cco_dev.mac, IOT_MAC_ADDR_LEN); resp_frm->nid = prototask_contxt.local_dev.nid; resp_frm->state = prototask_contxt.local_dev.dev_ready; resp_frm->wl_state = p_flash->public.pub.wl_state; resp_frm->swver = iot_version_hex(); iot_cus_printf("[gepr]query_module_info\n"); } resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); return rpt2mcu; } bool_t iot_proto_query_ntb_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm; iot_pkt_t *cmd_pkt; ge_frame_ntb_query_subfn19_t *query_cmd = (ge_frame_ntb_query_subfn19_t *)data; plctxrx_cmd_arg_t cmd = { 0 }; ge_frame_ntb_resp_subfn19_t *resp_frm; if (len != sizeof(ge_frame_ntb_query_subfn19_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(*resp_frm), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_frm = (ge_frame_ntb_resp_subfn19_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_NTB_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey ntb"); return rpt2mcu; } cmd.cid.cid = PLCTXRX_CID_NTB; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = 0; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd)+cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd)+cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); /* if async cmd, we need to set a state for response */ sm = iot_proto_cmd_handle_state_get(); sm->state = PROTO_CMD_WAIT_NTB_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } bool_t iot_proto_query_fb_bitmap_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm; iot_pkt_t *cmd_pkt; ge_frame_fb_bitmap_query_subfn20_t *query_cmd = (ge_frame_fb_bitmap_query_subfn20_t *)data; plctxrx_cmd_arg_t cmd = { 0 }; ge_frame_fb_bitmap_resp_subfn20_t *resp_frm; if (len != sizeof(ge_frame_fb_bitmap_query_subfn20_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(*resp_frm), IOT_GREE_APP_MID); IOT_ASSERT(pkt); resp_frm = (ge_frame_fb_bitmap_resp_subfn20_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_FB_BITMAP_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey fb bitmap"); return rpt2mcu; } cmd.cid.cid = PLCTXRX_CID_FB_BITMAP; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = sizeof(query_cmd->is_scan_bitmap); /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd)+cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd)+cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); /* copy query_cmd->is_scan_bitmap */ os_mem_cpy(iot_pkt_data(cmd_pkt)+sizeof(cmd), &query_cmd->is_scan_bitmap, sizeof(query_cmd->is_scan_bitmap)); /* if async cmd, we need to set a state for response */ sm = iot_proto_cmd_handle_state_get(); sm->state = PROTO_CMD_WAIT_FB_BITMAP_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } bool_t iot_proto_query_fix_rate_mode_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm; iot_pkt_t *cmd_pkt; ge_frame_fix_rate_query_subfn21_t *query_cmd = (ge_frame_fix_rate_query_subfn21_t *)data; plctxrx_cmd_arg_t cmd = { 0 }; ge_frame_fix_rate_mode_resp_subfn21_t *resp_frm; if (len != sizeof(ge_frame_fix_rate_query_subfn21_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(*resp_frm), IOT_GREE_APP_MID); IOT_ASSERT(pkt); resp_frm = (ge_frame_fix_rate_mode_resp_subfn21_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_FIX_RATE_MODE_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey fix rate mode"); return rpt2mcu; } cmd.cid.cid = PLCTXRX_CID_FIXED_RATE; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = 0; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd)+cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd)+cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); /* if async cmd, we need to set a state for response */ sm = iot_proto_cmd_handle_state_get(); sm->state = PROTO_CMD_WAIT_FIX_RATE_MODE_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } bool_t iot_proto_query_work_band_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm; iot_pkt_t *cmd_pkt; ge_frame_work_band_query_subfn22_t *query_cmd = (ge_frame_work_band_query_subfn22_t *)data; plctxrx_cmd_arg_t cmd = { 0 }; ge_frame_work_band_resp_subfn22_t *resp_frm; if (len != sizeof(ge_frame_work_band_query_subfn22_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(*resp_frm), IOT_GREE_APP_MID); IOT_ASSERT(pkt); resp_frm = (ge_frame_work_band_resp_subfn22_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_WORK_BAND_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey work band"); return rpt2mcu; } cmd.cid.cid = PLCTXRX_CID_BAND_ID; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = 0; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd)+cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd)+cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); /* if async cmd, we need to set a state for response */ sm = iot_proto_cmd_handle_state_get(); sm->state = PROTO_CMD_WAIT_WORK_BAND_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } /* handle wl set from local or remote mcu */ bool_t iot_proto_whitelist_set_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { proto_dev_list_t *p_table = &prototask_contxt.dev_lst; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); proto_dev_t wlist; uint32_t reason = 0; uint16_t i; bool_t need_ack = false; ge_frame_op_wl_set_subfn5_t *p_frame = (ge_frame_op_wl_set_subfn5_t *)data; if (len != sizeof(ge_frame_op_wl_set_subfn5_t)) { /* check command length */ reason = PROTO_REASON_LEN_MISSMATCH; goto check; } else if ((p_frame->action == GE_PROTO_ACTION_ADD || p_frame->action == GE_PROTO_ACTION_DEL || p_frame->action == GE_PROTO_ACTION_DEL_ALL) && !prototask_contxt.local_dev.dev_ready) { /* add and delete whitelist condition: * 1.CCO state is started, * 2.STA is already in network, */ reason = PROTO_REASON_NOT_READY; goto check; } else if (p_frame->action == GE_PROTO_ACTION_DEL_ALL && IOT_PLC_DEV_ROLE_CCO != prototask_contxt.local_dev.nw_role) { /* only cco support clear whitelist */ reason = PROTO_REASON_WL_CLR_NOTSUPPORT; goto check; } sm->seq = p_frame->seq; #if (WHITELIST_PAIR_DEBUG == 1) iot_cus_printf("[glpr]whitelist_set_handler-" "%02x:%02x:%02x:%02x:%02x:%02x, action %d, dir=%d!\n", p_frame->mac[0], p_frame->mac[1], p_frame->mac[2], p_frame->mac[3], p_frame->mac[4], p_frame->mac[5], p_frame->action, dir); #endif if (GE_PROTO_ACTION_DEL == p_frame->action || GE_PROTO_ACTION_ADD == p_frame->action) { if ((0 == p_frame->total_frame) || (0 == p_frame->cur_frame)) { /* when add/delete whitelist, total_frame & cur_frame can not be 0 */ reason = PROTO_REASON_PARAME_ERR; } else if (!iot_mac_addr_valid(p_frame->mac)) { /* when add/delete whitelist, make sure the mac is valid */ reason = PROTO_REASON_MAC_ADDR_ZERO; } } check: if (0 != reason) { iot_proto_resp_cfm_frame(reason, dir, p_frame->hdr.subfn, p_frame->seq, prototask_contxt.rx_info.mac); iot_proto_whitelist_state_init(); iot_proto_cmd_handle_state_init(); return false; } /* Set when every single frame received. */ sm->state = PROTO_CMD_WAIT_WHITE_LIST_SET; sm->cur_subfn = PROTO_OP_WHITELIST_SET_CMD; os_mem_set(&wlist, 0x00, sizeof(wlist)); iot_mac_addr_cpy(wlist.mac, p_frame->mac); if (IOT_PLC_DEV_ROLE_CCO != prototask_contxt.local_dev.nw_role) { if (p_frame->action == GE_PROTO_WL_DISABLE || p_frame->action == GE_PROTO_WL_ENABLE) { /* STA can enable and disable whitelist */ sm->dir = CMD_LOCAL_UP_LINK; iot_proto_whitelist_en_disable(p_frame->action, true); return false; } else { /* STA does not have "ADD", "DEL" operation, so send it to CCO * So we set sm->dir = CMD_LOCAL_UP_LINK; */ sm->dir = CMD_REMOTE_UP_LINK; return iot_proto_wl_or_pt_remote_set_or_query_to_cco(data, len, dir, PROTO_CMD_WAIT_RMT_WHITELIST_CFM); } } /** * CCO role could set local whitelist and allow remote STA to set, * so,we should judge where current cmd comes from. * when TO,in state PROTO_CMD_WAIT_WHITE_LIST_SET, * we should send TO cfm or response to dir device. */ if (CMD_LOCAL_DOWN_LINK == dir) { sm->dir = CMD_LOCAL_UP_LINK; } else if (CMD_REMOTE_UP_LINK == dir) { sm->dir = CMD_REMOTE_DOWN_LINK; iot_mac_addr_cpy(sm->dev.mac, prototask_contxt.rx_info.mac); } /* clear tmp dev list for current completed recving */ if (FIRST_WL_FRAME == p_frame->cur_frame) iot_proto_whitelist_state_init(); p_table->wl_ccofrag_cnt++; if (GE_PROTO_ACTION_ADD == p_frame->action) { if (iot_proto_check_mac_exists(p_frame->mac, p_table->dev, p_table->valid_dev_cnt) >= 0) { iot_cus_printf("[glpr]Mac exist, frame dropped!\n"); } else { if (iot_proto_check_mac_exists(p_frame->mac, p_table->dev_tmp, p_table->valid_dev_tmp_cnt) < 0) { iot_proto_add_wl_to_tmp(&wlist); } else { iot_cus_printf("[glpr]Mac exist, frame dropped!\n"); } } /* cur_frame = total_frame means this is the last frame in this opration. */ if (p_frame->cur_frame == p_frame->total_frame) { /* dev_frame_cnt = total_frame means we received all the frames. */ if (p_table->wl_ccofrag_cnt == p_frame->total_frame) { iot_cus_printf("[glpr]whitelist completed!\n"); if (p_table->valid_dev_tmp_cnt > 0) { sm->state = PROTO_CMD_WAIT_CMD_CFM; iot_proto_add_wl_tmp2formal(); /* sync whitelist to cvg */ iot_proto_whitelist_add_remove(GE_PROTO_ACTION_ADD, NULL, true); iot_proto_wl_save2flash(); } else { /* Nothing to be set so response OK here. */ iot_proto_resp_cfm_frame(PROTO_REASON_OK, dir, p_frame->hdr.subfn, p_frame->seq, prototask_contxt.rx_info.mac); iot_proto_cmd_handle_state_init(); } } else { iot_cus_printf("[glpr]frame lost!\n"); iot_proto_resp_cfm_frame(PROTO_REASON_WL_LOST_FRM, dir, p_frame->hdr.subfn, p_frame->seq, prototask_contxt.rx_info.mac); iot_proto_cmd_handle_state_init(); } iot_proto_whitelist_state_init(); } } else if (GE_PROTO_ACTION_DEL == p_frame->action) { if (iot_proto_check_mac_exists(p_frame->mac, p_table->dev, p_table->valid_dev_cnt) < 0) { iot_cus_printf("[glpr]frame repeated!\n"); } else { /* record MAC(s) to tmp dev list that we need to delete. */ if (iot_proto_check_mac_exists(p_frame->mac, p_table->dev_tmp, p_table->valid_dev_tmp_cnt) < 0) { iot_proto_add_wl_to_tmp(&wlist); } else { iot_cus_printf("[glpr]frame repeated!\n"); } } /* cur_frame = total_frame means this * is the last frame in this opration. */ if (p_frame->cur_frame == p_frame->total_frame) { /* dev_frame_cnt = total_frame means we received all the frames. */ if (p_table->wl_ccofrag_cnt == p_frame->total_frame) { iot_cus_printf("[glpr]whitelist completed!\n"); if (p_table->valid_dev_tmp_cnt > 0) { sm->state = PROTO_CMD_WAIT_CMD_CFM; /* remove del whitelist in CVG one by one, * if the last whitelist,then need ack. */ for (i = 0; i < p_table->valid_dev_tmp_cnt; i++) { if (i == (p_table->valid_dev_tmp_cnt - 1)) { need_ack = true; } iot_proto_whitelist_add_remove(GE_PROTO_ACTION_DEL, p_table->dev_tmp[i].mac, need_ack); } iot_proto_del_wl_from_formal(); iot_proto_wl_save2flash(); } else { /* Nothing to be set so response OK here. */ iot_proto_resp_cfm_frame(PROTO_REASON_OK, dir, p_frame->hdr.subfn, p_frame->seq, prototask_contxt.rx_info.mac); iot_proto_cmd_handle_state_init(); } } else { iot_cus_printf("[glpr]frame lost!\n"); iot_proto_resp_cfm_frame(PROTO_REASON_WL_LOST_FRM, dir, p_frame->hdr.subfn, p_frame->seq, prototask_contxt.rx_info.mac); iot_proto_cmd_handle_state_init(); } iot_proto_whitelist_state_init(); } } else if (GE_PROTO_ACTION_DEL_ALL == p_frame->action) { if (p_table->valid_dev_cnt > 0) { p_table->valid_dev_cnt = 0; os_mem_set(p_table->dev, 0, sizeof(proto_dev_t) * STA_DEV_MAX); iot_proto_wl_save2flash(); iot_proto_whitelist_remove_all(true); iot_cus_printf("[glpr]clear whitelist!\n"); } else { /* whitelist already clear, so response OK here. */ iot_proto_resp_cfm_frame(PROTO_REASON_OK, dir, p_frame->hdr.subfn, p_frame->seq, prototask_contxt.rx_info.mac); iot_proto_cmd_handle_state_init(); } } return false; } bool_t iot_proto_query_whitelist_handler (uint8_t *data, uint16_t len, transmit_direction_e_t dir) { uint16_t i, total; uint8_t cco_flag, *p_buf = NULL; proto_dev_list_t *p_table = &prototask_contxt.dev_lst; protpkt_tx_info_t info = { 0 }; iot_pkt_t *resp_pkt = NULL, *p_pkt_buf = NULL; uint32_t buf_index = 0, buf_len = TXRX_AGGR_PKT_LEN; ge_frame_wl_resp_subfn7_t *frame; ge_frame_wl_query_subfn7_t *query_cmd = (ge_frame_wl_query_subfn7_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); /* alloc packet for response frame */ resp_pkt = iot_pkt_alloc(sizeof(*frame), IOT_GREE_APP_MID); IOT_ASSERT(resp_pkt); iot_pkt_put(resp_pkt, sizeof(*frame)); os_mem_set(iot_pkt_data(resp_pkt), 0, sizeof(*frame)); frame = (ge_frame_wl_resp_subfn7_t *)iot_pkt_data(resp_pkt); /* check parameter */ if (len != sizeof(ge_frame_wl_query_subfn7_t)) { EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_WHITELIST_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(resp_pkt); return 0; } cco_flag = query_cmd->cco_flag? 1 : 0; sm->seq = query_cmd->seq; /* SEQ byte is 7th */ if (cco_flag && IOT_PLC_DEV_ROLE_CCO != prototask_contxt.local_dev.nw_role) { /* if CCO_FLAG set and this dev is not cco, forward this frame to cco */ iot_proto_wl_or_pt_remote_set_or_query_to_cco (data, len, dir, PROTO_CMD_WAIT_RMT_WHITELIST_RESP); return 0; } #if (WHITELIST_PAIR_DEBUG == 1) iot_cus_printf("[glpr]Query whitelist! " \ "dir=%d, mac=%02x:%02x:%02x:%02x:%02x:%02x.\n", dir, prototask_contxt.rx_info.mac[0], prototask_contxt.rx_info.mac[1], prototask_contxt.rx_info.mac[2], prototask_contxt.rx_info.mac[3], prototask_contxt.rx_info.mac[4], prototask_contxt.rx_info.mac[5]); #endif /* fill tx info to prepare for remote sending */ iot_proto_fill_txinfo(&info, 1, PLCTXRX_UNICAST, 2, 200, 1, prototask_contxt.local_dev.mac, prototask_contxt.rx_info.mac); EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_WHITELIST_RESP_CMD); frame->cco_flag = cco_flag; frame->total_cnt = p_table->valid_dev_cnt; total = p_table->valid_dev_cnt; frame->seq = sm->seq; if (CMD_REMOTE_UP_LINK == dir) { p_pkt_buf = iot_pkt_alloc(buf_len, IOT_GREE_APP_MID); if (NULL == p_pkt_buf) { iot_cus_printf("[glpr][err]No Mem!\n"); frame->cur_cnt = 0; frame->total_cnt = 0; frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); iot_proto_remote_cmd_send_to_plctxrx ((uint8_t*)frame, sizeof(*frame), &info); return 0; } p_buf = iot_pkt_data(p_pkt_buf); } if (CMD_REMOTE_UP_LINK == dir) { i = 0; do { if (total > 0) { frame->cur_cnt = i + 1; iot_mac_addr_cpy(frame->mac, p_table->dev[i].mac); } else { frame->cur_cnt = 0; os_mem_set(frame->mac, 0, IOT_MAC_ADDR_LEN); } frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); os_mem_cpy(p_buf + buf_index, frame, sizeof(*frame)); buf_index += sizeof(*frame); if (buf_index + sizeof(*frame) > buf_len) { iot_proto_remote_cmd_send_to_plctxrx(p_buf, buf_index, &info); buf_index = 0; } i++; } while (i < total); } else { if (total > 0) { #define PROTO_WL_RPT_FRAG_CNT 30 uint16_t frag_cnt = 0, loop_cnt = 0, m, j; iot_pkt_t *frag_pkt = NULL; uint8_t *data_t = NULL; loop_cnt = (total <= PROTO_WL_RPT_FRAG_CNT)? 1:(total/PROTO_WL_RPT_FRAG_CNT + (((total%PROTO_WL_RPT_FRAG_CNT) == 0)?0:1)); for (m = 1; m <= loop_cnt; m++) { if (m*PROTO_WL_RPT_FRAG_CNT > total) { frag_cnt = total - (m - 1)*PROTO_WL_RPT_FRAG_CNT; } else { frag_cnt = PROTO_WL_RPT_FRAG_CNT; } frag_pkt = iot_pkt_alloc(sizeof(*frame)*frag_cnt, IOT_GREE_APP_MID); IOT_ASSERT(frag_pkt); data_t = iot_pkt_data(frag_pkt); iot_pkt_put(frag_pkt, sizeof(*frame)*frag_cnt); for (j = 0; j < frag_cnt; j++) { frame->cur_cnt = (m-1)*PROTO_WL_RPT_FRAG_CNT + j + 1; iot_mac_addr_cpy(frame->mac, p_table->dev[(m-1)*PROTO_WL_RPT_FRAG_CNT + j].mac); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); os_mem_cpy(data_t+j*sizeof(*frame), frame, sizeof(*frame)); } iot_proto_send_to_mainboard(frag_pkt); } } else { /* whitelist is empty, report all 0 frame to MCU. */ iot_pkt_t *rpt_pkt = NULL; uint8_t *buf_pkt = NULL; frame->cur_cnt = 0; os_mem_set(frame->mac, 0, IOT_MAC_ADDR_LEN); rpt_pkt = iot_pkt_alloc(sizeof(*frame), IOT_GREE_APP_MID); IOT_ASSERT(rpt_pkt); buf_pkt = iot_pkt_data(rpt_pkt); iot_pkt_put(rpt_pkt, sizeof(*frame)); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); os_mem_cpy(buf_pkt, frame, sizeof(*frame)); iot_proto_send_to_mainboard(rpt_pkt); } } /* Only CMD_REMOTE_UP_LINK == dir will lead buf_index > 0 */ if (buf_index > 0) { iot_proto_remote_cmd_send_to_plctxrx(p_buf, buf_index, &info); } if (p_pkt_buf) { iot_pkt_free(p_pkt_buf); } if (resp_pkt) { iot_pkt_free(resp_pkt); } return 0; } bool_t iot_proto_whitelist_resp_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; (void)dir; /* Response and indicate have the same frame type with set. */ ge_frame_wl_resp_subfn7_t *p_frame = (ge_frame_wl_resp_subfn7_t *)data; proto_dev_list_t *p_table = &prototask_contxt.dev_lst; iot_pkt_t *p_pkt; uint8_t cco_flag; uint32_t pkt_len, frame_index; proto_dev_t wlist; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); sm->seq = p_frame->seq; cco_flag = p_frame->cco_flag ? 1 : 0; #if (WHITELIST_PAIR_DEBUG == 1) iot_cus_printf("\n[glpr]whitelist_resp_handler," \ " dir=%d, seq=%d, cur=%d, total=%d, " "mac=%02x:%02x:%02x:%02x:%02x:%02x, cco_flag=%d!\n", dir, p_frame->seq, p_frame->cur_cnt, p_frame->total_cnt, p_frame->mac[0], p_frame->mac[1], p_frame->mac[2], p_frame->mac[3], p_frame->mac[4], p_frame->mac[5], p_frame->cco_flag); #endif if ((0 == p_frame->total_cnt) && (0 == p_frame->cur_cnt)) { iot_proto_cmd_handle_state_init(); /* It is queried by mcu, so forword this frame to MCU. */ if (cco_flag) return true; return false; } if (FIRST_WL_FRAME == p_frame->cur_cnt) iot_proto_whitelist_state_init(); p_table->wl_ccofrag_cnt++; os_mem_set(&wlist, 0x00, sizeof(wlist)); iot_mac_addr_cpy(wlist.mac, p_frame->mac); if (iot_proto_check_mac_exists(p_frame->mac, p_table->dev_tmp, p_table->valid_dev_tmp_cnt) < 0) { iot_proto_add_wl_to_tmp(&wlist); } if (p_frame->cur_cnt == p_frame->total_cnt) { if (p_table->wl_ccofrag_cnt == p_frame->total_cnt) { iot_cus_printf("[glpr]whitelist completed, toltal=%d, valid=%d!\n", p_frame->total_cnt, p_table->valid_dev_tmp_cnt); if (cco_flag) { /* It is queried by mcu, so send all those frame to MCU. */ pkt_len = sizeof(*p_frame) * p_table->valid_dev_tmp_cnt; p_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID); if (p_pkt) { p_frame = (ge_frame_wl_resp_subfn7_t*)iot_pkt_put(p_pkt, pkt_len); /* A big packet of frames to MCU. */ for (frame_index = 0; frame_index < p_table->valid_dev_tmp_cnt; frame_index++) { os_mem_cpy(p_frame, data, sizeof(*p_frame)); p_frame->cur_cnt = (uint16_t)(frame_index + 1); p_frame->cco_flag = 1; p_frame->total_cnt = p_table->valid_dev_tmp_cnt; iot_mac_addr_cpy(p_frame->mac, p_table->dev_tmp[frame_index].mac); p_frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)p_frame, sizeof(*p_frame) - sizeof(ge_frm_tail_t)); p_frame++; } iot_proto_send_to_mainboard(p_pkt); } else { /* TODO : Every single frame to MCU */ IOT_ASSERT(0); } } } else { iot_cus_printf("[glpr]frame lost!\n"); } iot_proto_whitelist_state_init(); iot_proto_cmd_handle_state_init(); } return 0; } bool_t iot_proto_topo_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_handle_topo_t *topo_info = (plctxrx_handle_topo_t *)cmd->data; uint8_t type = prototask_contxt.topo_info_type; uint16_t frm_len = 0; uint16_t topo_info_len = 0; ge_frm_tail_t *tail = NULL; if (sm->state == PROTO_CMD_DL645_WAIT_TOPO_INFO_RESP) { /* for cctt send dl645 query topo */ iot_proto_cctt_dl645_topo_resp(data, len, dir); return rpt2mcu; } switch (type) { case TOPO_INFO_TYPE_V0: topo_info_len = sizeof(topo_info_v0_t); break; case TOPO_INFO_TYPE_V1: topo_info_len = sizeof(topo_info_v1_t); break; default: iot_cus_printf("[glpr][err]topo info resp error with type[%d]\n", type); return rpt2mcu; } frm_len = sizeof(ge_frame_topo_resp_subfn5_t) + topo_info_len + sizeof(ge_frm_tail_t); switch (sm->dir) { /* report to MCU */ case CMD_LOCAL_UP_LINK: { ge_frame_topo_resp_subfn5_t *frame; uint16_t i; iot_pkt_t *data_pkt; uint8_t *data_p; uint16_t size = frm_len * topo_info->cnt; if (size == 0) size = frm_len; data_pkt = iot_pkt_alloc(size, IOT_GREE_APP_MID); if (!data_pkt) { iot_cus_printf("[glpr][err]alloc pkt err\n"); return rpt2mcu; } data_p = iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, size); os_mem_set(data_p, 0, size); if (topo_info->cnt > 0) { for (i = 0; i < topo_info->cnt; i++) { frame = (ge_frame_topo_resp_subfn5_t *)(data_p + i * frm_len); frame->type = type; frame->total_cnt = cmd->index.total; frame->cur_cnt = prototask_contxt.topo_resp_index + i + 1; frame->seq = sm->seq; switch (type) { case TOPO_INFO_TYPE_V0: { topo_info_v0_t *topo_info_v0 = (topo_info_v0_t *)frame->info; topo_info_v0->level = topo_info->topo[i].level; iot_mac_addr_cpy(topo_info_v0->mac, topo_info->topo[i].mac); break; } case TOPO_INFO_TYPE_V1: { topo_info_v1_t *topo_info_v1 = (topo_info_v1_t *)frame->info; topo_info_v1->level = topo_info->topo[i].level; topo_info_v1->logic_phase = topo_info->topo[i].logic_phase; topo_info_v1->phy_phase = topo_info->topo[i].phy_phase; iot_mac_addr_cpy(topo_info_v1->mac, topo_info->topo[i].mac); break; } default: iot_pkt_free(data_pkt); return rpt2mcu; } GE_FRM_HDR_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_TOPO_RESP_CMD, frm_len); tail = (ge_frm_tail_t *)(frame->info + topo_info_len); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, frm_len - sizeof(ge_frm_tail_t)); tail->tail = GE_FRM_TAIL_CODE; } prototask_contxt.topo_resp_index += topo_info->cnt; } else { /* if txrx return zero sta cnt */ frame = (ge_frame_topo_resp_subfn5_t *)data_p; frame->type = type; frame->total_cnt = topo_info->cnt; frame->cur_cnt = topo_info->cnt; frame->seq = sm->seq; GE_FRM_HDR_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_TOPO_RESP_CMD, frm_len); tail = (ge_frm_tail_t *)(frame->info + topo_info_len); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, frm_len - sizeof(ge_frm_tail_t)); tail->tail = GE_FRM_TAIL_CODE; } if (cmd->index.current == cmd->index.total) { /* switch cmd handle state to idle state */ prototask_contxt.topo_resp_index = 0; iot_proto_cmd_handle_state_init(); } /* report topo to MCU */ iot_proto_send_to_mainboard(data_pkt); break; } /* go data down link path */ case CMD_REMOTE_DOWN_LINK: { ge_frame_topo_resp_subfn5_t *frame; uint16_t i; iot_pkt_t *resp_pkt = NULL; protpkt_tx_info_t txinfo = { 0 }; iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 3, 500, 1, prototask_contxt.local_dev.mac, sm->dev.mac); /* alloc packet for response frame */ resp_pkt = iot_pkt_alloc(frm_len, IOT_GREE_APP_MID); IOT_ASSERT(resp_pkt); iot_pkt_put(resp_pkt, frm_len); frame = (ge_frame_topo_resp_subfn5_t *)iot_pkt_data(resp_pkt); if (topo_info->cnt > 0) { for (i = 0; i < topo_info->cnt; i++) { os_mem_set(frame, 0, frm_len); frame->type = type; frame->seq = sm->seq; frame->total_cnt = (uint8_t)cmd->index.total; frame->cur_cnt = prototask_contxt.topo_resp_index + i + 1; switch (type) { case TOPO_INFO_TYPE_V0: { topo_info_v0_t *topo_info_v0 = (topo_info_v0_t *)frame->info; topo_info_v0->level = topo_info->topo[i].level; iot_mac_addr_cpy(topo_info_v0->mac, topo_info->topo[i].mac); break; } case TOPO_INFO_TYPE_V1: { topo_info_v1_t *topo_info_v1 = (topo_info_v1_t *)frame->info; topo_info_v1->level = topo_info->topo[i].level; topo_info_v1->logic_phase = topo_info->topo[i].logic_phase; topo_info_v1->phy_phase = topo_info->topo[i].phy_phase; iot_mac_addr_cpy(topo_info_v1->mac, topo_info->topo[i].mac); break; } default: iot_pkt_free(resp_pkt); return rpt2mcu; } GE_FRM_HDR_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_TOPO_RESP_CMD, frm_len); tail = (ge_frm_tail_t *)(frame->info + topo_info_len); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, frm_len - sizeof(ge_frm_tail_t)); tail->tail = GE_FRM_TAIL_CODE; /* send to remote */ iot_proto_remote_cmd_send_to_plctxrx((uint8_t *)frame, frm_len, &txinfo); } prototask_contxt.topo_resp_index += topo_info->cnt; } else { os_mem_set(frame, 0, frm_len); frame->type = type; frame->seq = sm->seq; frame->total_cnt = topo_info->cnt; frame->cur_cnt = topo_info->cnt; GE_FRM_HDR_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_TOPO_RESP_CMD, frm_len); tail = (ge_frm_tail_t *)(frame->info + topo_info_len); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, frm_len - sizeof(ge_frm_tail_t)); tail->tail = GE_FRM_TAIL_CODE; /* switch cmd handle state to idle state */ iot_proto_cmd_handle_state_init(); /* send to remote */ iot_proto_remote_cmd_send_to_plctxrx((uint8_t *)frame, frm_len, &txinfo); } if (cmd->index.current == cmd->index.total) { /* switch cmd handle state to idle state */ prototask_contxt.topo_resp_index = 0; iot_proto_cmd_handle_state_init(); } if (resp_pkt) { iot_pkt_free(resp_pkt); } break; } /* report to MCU */ case CMD_REMOTE_UP_LINK: { ge_frame_topo_resp_subfn5_t *frm = (ge_frame_topo_resp_subfn5_t*)data; /* check have respon over */ if (sm->state == PROTO_CMD_WAIT_TOPO_RESP && frm->total_cnt == frm->cur_cnt) sm->state = PROTO_CMD_IDLE; rpt2mcu = true; break; } default: break; } return rpt2mcu; } bool_t iot_proto_query_net_sts_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; uint8_t mac[IOT_MAC_ADDR_LEN] = { 0 }; ge_frame_net_stat_query_subfn6_t *query_cmd = (ge_frame_net_stat_query_subfn6_t *)data; ge_frame_net_stat_resp_subfn6_t *resp_frm; if (len != sizeof(ge_frame_net_stat_query_subfn6_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(ge_frame_net_stat_resp_subfn6_t), IOT_GREE_APP_MID); IOT_ASSERT(pkt); resp_frm = (ge_frame_net_stat_resp_subfn6_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_NET_STS_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); return rpt2mcu; } iot_mac_addr_cpy(mac, query_cmd->mac); proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); iot_pkt_t *cmd_pkt; plctxrx_cmd_arg_t cmd = { 0 }; cmd.cid.cid = PLCTXRX_CID_NET_STS; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = sizeof(mac); /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd) + cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); os_mem_cpy(iot_pkt_data(cmd_pkt) + sizeof(cmd), mac, sizeof(mac)); iot_pkt_put(cmd_pkt, sizeof(cmd) + cmd.dlen); /* if async cmd, we need to set a state for response */ sm->state = PROTO_CMD_WAIT_NET_STS_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } bool_t iot_proto_net_sts_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; iot_pkt_t *data_pkt = NULL; uint16_t i; iot_cus_printf("[glpr]resp net states to mcu\n"); ge_frame_net_stat_resp_subfn6_t *frame; uint16_t size; plctxrx_net_sts_data_info_t *net_sts = (plctxrx_net_sts_data_info_t*)cmd->data; if (cmd->resp == PLCTXRX_RESP_ERROR || net_sts == NULL) { size = sizeof(ge_frame_net_stat_resp_subfn6_t); data_pkt = iot_pkt_alloc(size, IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); frame = (ge_frame_net_stat_resp_subfn6_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, size); os_mem_set(frame, 0, size); frame->seq = sm->seq; EXT_FN_FRM_PREPARE((frame), PROTO_GE_PLC_RESP_CMD, PROTO_NET_STS_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)(frame), sizeof(*frame) - sizeof(ge_frm_tail_t)); } else { size = sizeof(ge_frame_net_stat_resp_subfn6_t)*net_sts->count; data_pkt = iot_pkt_alloc(size, IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); frame = (ge_frame_net_stat_resp_subfn6_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt,size); for (i = 0; i < net_sts->count; i++) { os_mem_set(frame + i, 0, sizeof(*frame)); (frame + i)->total_cnt = net_sts->count; (frame + i)->cur_cnt = i + 1; (frame + i)->snr = net_sts->net_sts_data[i].snr; (frame + i)->nf = net_sts->net_sts_data[i].nf; (frame + i)->tsf = net_sts->net_sts_data[i].dl_tf_sr; (frame + i)->rsf = net_sts->net_sts_data[i].ul_tf_sr; iot_mac_addr_cpy((frame + i)->mac, net_sts->net_sts_data[i].mac); (frame + i)->seq = sm->seq; EXT_FN_FRM_PREPARE((frame+i), PROTO_GE_PLC_RESP_CMD, PROTO_NET_STS_RESP_CMD); (frame + i)->tail.check_sum = ge_frm_checksum_calc((uint8_t *)(frame + i), sizeof(*(frame + i)) - sizeof(ge_frm_tail_t)); } } /* clean state */ iot_proto_cmd_handle_state_init(); /* report net states to MCU */ iot_proto_send_to_mainboard(data_pkt); return rpt2mcu; } bool_t iot_proto_query_node_info_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; iot_pkt_t *cmd_pkt; uint16_t pkt_len; plctxrx_cmd_arg_t *cmd; plctxrx_cmd_query_node_info_t *node_info; ge_frame_node_info_query_subfn23_t *query_cmd = (ge_frame_node_info_query_subfn23_t *)data; pkt_len = sizeof(plctxrx_cmd_arg_t) + sizeof(plctxrx_cmd_query_node_info_t); if (len != sizeof(ge_frame_node_info_query_subfn23_t)) { iot_cus_printf("query_node_info cmd length mismatch\n"); iot_proto_node_info_report(NULL, 0, 0, 0, query_cmd->type, 1); return rpt2mcu; } proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID); if (NULL == cmd_pkt) { iot_cus_printf("[glpr]query_node_info alloc pkt error\n"); return rpt2mcu; } cmd = (plctxrx_cmd_arg_t *)iot_pkt_put(cmd_pkt, pkt_len); cmd->cid.cid = PLCTXRX_CID_NODE_INFO; cmd->cid.opcode = PLCTXRX_OP_QUERY; cmd->need_ack = true; cmd->prio = 0; cmd->dlen = sizeof(plctxrx_cmd_query_node_info_t); node_info = (plctxrx_cmd_query_node_info_t *)cmd->arg; iot_mac_addr_cpy(node_info->mac, query_cmd->mac); node_info->type = query_cmd->type; /* if async cmd, we need to set a state for response */ sm->state = PROTO_CMD_WAIT_NODE_INFO_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } /** * @brief iot_proto_query_nw_info_handler() - query network information handler * @param data query network command data frame data. * @param len the data length. * @param dir the direction of command command from. * @retval: whether need report to mcu. */ bool_t iot_proto_query_nw_info_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; iot_pkt_t *cmd_pkt; plctxrx_cmd_arg_t *cmd; ge_frame_nw_info_query_subfn24_t *query_cmd = (ge_frame_nw_info_query_subfn24_t *)data; if (len != sizeof(ge_frame_nw_info_query_subfn24_t)) { iot_proto_nw_info_report(0, NULL, 0); return rpt2mcu; } proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(plctxrx_cmd_arg_t), IOT_GREE_APP_MID); if (NULL == cmd_pkt) { iot_cus_printf("[glpr]query_nw_info alloc pkt error\n"); return rpt2mcu; } cmd = (plctxrx_cmd_arg_t *)iot_pkt_put(cmd_pkt, sizeof(plctxrx_cmd_arg_t)); cmd->cid.cid = PLCTXRX_CID_NW_INFO; cmd->cid.opcode = PLCTXRX_OP_QUERY; cmd->need_ack = true; cmd->prio = 0; cmd->dlen = 0; /* if async cmd, we need to set a state for response */ sm->state = PROTO_CMD_WAIT_NW_INFO_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } bool_t iot_proto_query_local_ip4_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; iot_pkt_t *pkt = NULL; ge_frame_local_ip4_resp_subfn25_t *resp_cmd; ge_frame_local_ip4_query_subfn25_t *query_cmd = (ge_frame_local_ip4_query_subfn25_t *)data; uint8_t ip4_addr[IOT_IP4_ADDR_LEN] = {0}; uint8_t ip4_mask[IOT_IP4_ADDR_LEN] = {0}; if (len != sizeof(ge_frame_local_ip4_query_subfn25_t)) { iot_cus_printf("[glpr][err]qurey local ip4 info cmd len mismatch\n"); return rpt2mcu; } pkt = iot_pkt_alloc(sizeof(*resp_cmd), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_cmd = (ge_frame_local_ip4_resp_subfn25_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_cmd)); os_mem_set(resp_cmd, 0, sizeof(*resp_cmd)); EXT_FN_FRM_PREPARE(resp_cmd, PROTO_GE_PLC_RESP_CMD, PROTO_LOCAL_IP4_INFO_RESP_CMD); resp_cmd->seq = query_cmd->seq; iot_oem_get_local_ip4_addr(ip4_addr); iot_oem_get_local_ip4_netmask(ip4_mask); os_mem_cpy(resp_cmd->ip4_addr, ip4_addr, IOT_IP4_ADDR_LEN); os_mem_cpy(resp_cmd->ip4_mask, ip4_mask, IOT_IP4_ADDR_LEN); resp_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_cmd, sizeof(*resp_cmd)-sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); return rpt2mcu; } /** * @brief iot_proto_gpio_resp() - response gpio info. * @param data_pkt data which need to resp */ void iot_proto_gpio_resp(iot_pkt_t *data_pkt) { ge_frame_query_gpio_resp_subfn27_t *frame = (ge_frame_query_gpio_resp_subfn27_t *)iot_pkt_data(data_pkt); if (iot_mac_addr_cmp(frame->dest_mac, prototask_contxt.local_dev.mac)) { /* report topo to MCU */ iot_proto_send_to_mainboard(data_pkt); iot_proto_cmd_handle_state_init(); return; } protpkt_tx_info_t txinfo = { 0 }; iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, PROTO_UNICAST_RETRY_DEFAULT_CNT, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, frame->src_mac, frame->dest_mac); iot_proto_remote_cmd_send_to_plctxrx(iot_pkt_data(data_pkt), iot_pkt_data_len(data_pkt), &txinfo); iot_pkt_free(data_pkt); return; } /* * @brief iot_proto_delay_time_send() - send delay time info. * @param data_pkt data which need to send * @param src_mac source mac * @param dst_mac dst mac */ void iot_proto_delay_time_send(iot_pkt_t *data_pkt, uint8_t *src_mac, uint8_t *dst_mac) { uint8_t *data; uint8_t len; protpkt_tx_info_t txinfo = { 0 }; iot_proto_fill_txinfo(&txinfo, false, PLCTXRX_UNICAST, 0, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, src_mac, dst_mac); txinfo.force_noaggr = true; data = iot_pkt_data(data_pkt); len = (uint8_t)iot_pkt_data_len(data_pkt); iot_common_bin_dump(data, len); iot_proto_data_send_to_plctxrx(data, len, &txinfo); iot_pkt_free(data_pkt); return; } /** * @brief iot_proto_query_gpio_handler() - query gpio handler * @param data query gpio frame data. * @param len the data length. * @param dir the direction of command command from. * @retval: whether need report to mcu. */ bool_t iot_proto_query_gpio_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; bool_t rpt_cfm = false; ge_frame_gpio_query_subfn27_t *frm = (ge_frame_gpio_query_subfn27_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 }; uint8_t *local_mac = prototask_contxt.local_dev.mac; protpkt_tx_info_t txinfo = { 0 }; uint8_t reason = PROTO_REASON_OK; transmit_direction_e_t tmp_dir = 0; uint8_t gpio_index = 0; uint32_t gpio_value = 0; if (len != sizeof(ge_frame_gpio_query_subfn27_t)) { reason = PROTO_REASON_LEN_MISSMATCH; iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "query gpio"); rpt_cfm = true; goto cfm; } else if (iot_mac_addr_cmp(frm->dest_mac, dst_mac)) { reason = PROTO_REASON_MAC_ADDR_ZERO; iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "query gpio"); rpt_cfm = true; goto cfm; } else if (IOT_PROTO_INVALID_GPIO_INDEX == (gpio_index = iot_proto_get_gpio_index(frm->gpio_num))) { reason = PROTO_REASON_NOT_SUPPORT; iot_cus_printf("[glpr][err]%s cmd gpio num is invalid\n", "config gpio"); rpt_cfm = true; goto cfm; } iot_mac_addr_cpy(dst_mac, frm->dest_mac); if (iot_mac_addr_cmp(dst_mac, local_mac)) { tmp_dir = CMD_LOCAL_DOWN_LINK; } else { tmp_dir = CMD_REMOTE_DOWN_LINK; } switch (tmp_dir) { case CMD_LOCAL_DOWN_LINK: { ge_frame_query_gpio_resp_subfn27_t *resp_frame = NULL; iot_pkt_t *data_pkt = NULL; uint16_t frame_len = sizeof(ge_frame_query_gpio_resp_subfn27_t); if (IOT_GE_GPIO_OPEN != iot_ge_gpio_g[gpio_index].gpio_state) { reason = PROTO_REASON_NOT_READY; iot_cus_printf("[glpr][err]%s need to config the gpio before\n", "query gpio"); rpt_cfm = true; goto cfm; } if (IOT_GE_GPIO_DIR_INPUT == iot_ge_gpio_g[gpio_index].dir_mode) { gpio_value = iot_gpio_value_get(frm->gpio_num); } else if (IOT_GE_GPIO_DIR_OUTPUT == iot_ge_gpio_g[gpio_index].dir_mode) { iot_gpio_output_value_get(frm->gpio_num, (int *)&gpio_value); } gpio_value = gpio_value? 1:0; iot_cus_printf("%s gpio num = %d, value = %d\n", __FUNCTION__, frm->gpio_num, gpio_value); data_pkt = iot_pkt_alloc(frame_len, IOT_GREE_APP_MID); resp_frame = (ge_frame_query_gpio_resp_subfn27_t*)iot_pkt_put(data_pkt, frame_len); os_mem_set(resp_frame, 0, frame_len); iot_mac_addr_cpy(resp_frame->dest_mac, frm->src_mac); iot_mac_addr_cpy(resp_frame->src_mac, frm->dest_mac); resp_frame->seq = frm->seq; resp_frame->gpio_num = frm->gpio_num; resp_frame->gpio_dir = iot_ge_gpio_g[gpio_index].dir_mode; resp_frame->pull_mode = iot_ge_gpio_g[gpio_index].pull_mode; resp_frame->value = (uint8_t)gpio_value; EXT_FN_FRM_PREPARE(resp_frame, PROTO_GE_PLC_RESP_CMD, PROTO_QUERY_GPIO_RESP_CMD); resp_frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frame, frame_len - sizeof(ge_frm_tail_t)); iot_proto_gpio_resp(data_pkt); reason = PROTO_REASON_OK; return rpt2mcu; } case CMD_REMOTE_DOWN_LINK: { iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, PROTO_UNICAST_RETRY_DEFAULT_CNT, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, local_mac, dst_mac); iot_proto_remote_cmd_send_to_plctxrx(data, sizeof(ge_frame_gpio_query_subfn27_t), &txinfo); sm->dir = CMD_REMOTE_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; return rpt2mcu; } default: break; } cfm: if (rpt_cfm) { iot_proto_resp_cfm_frame(reason, dir, PROTO_GE_GPIO_QUERY_CMD, frm->seq, frm->src_mac); } return rpt2mcu; } /* * @brief iot_ntb_to_us() transform one value form ntb to us. * @param ntb the ntb value which need to transform to us. * @param current_type the current date type. * @retval:data_us the us value witch transformed form ntb value. */ uint32_t iot_ntb_to_us(uint32_t ntb, uint8_t current_type) { uint32_t data_us; /* current_type is not smaller than overflow_index means value is * overflow, the value should add a (0xFFFFFFFF / 25) */ if (overflow_index <= current_type) { data_us = (ntb + 0xFFFFFFFF % 25) / 25 + 0xFFFFFFFF / 25; } else { data_us = ntb / 25; } return data_us; } /* * @brief iot_delay_time_ntb_to_us() - change ntb to us * @param data addr of value need to change. */ void iot_delay_time_ntb_to_us(ge_delay_tm_test_t *data) { if (data->cco_tx_time > data->sta_rx_time) { overflow_index = STA_RX_TIME; } else if (data->sta_rx_time > data->sta_tx_time) { overflow_index = STA_TX_TIME; } else if (data->sta_tx_time > data->cco_rx_time) { overflow_index = CCO_RX_TIME; } data->cco_tx_time = iot_ntb_to_us(data->cco_tx_time, CCO_TX_TIME); data->sta_rx_time = iot_ntb_to_us(data->sta_rx_time, STA_RX_TIME); data->sta_tx_time = iot_ntb_to_us(data->sta_tx_time, STA_TX_TIME); data->cco_rx_time = iot_ntb_to_us(data->cco_rx_time, CCO_RX_TIME); /* clear the value of overflow_index to initialization value*/ overflow_index = CCO_RX_TIME + 1; } /** * @brief iot_proto_delay_time_handler() - test time delay * @param data test delay time frame data. * @param len the data length. * @param dir the direction of command command from. * @retval: whether need report to mcu. */ #if PLC_SUPPORT_STA_ROLE bool_t iot_proto_delay_time_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; ge_frame_delay_time_subfn166_t *frm = (ge_frame_delay_time_subfn166_t *)data; uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 }; uint8_t reason = PROTO_REASON_OK; uint16_t rsv_data_len = frm->tm_test.datalen; ge_frame_delay_time_subfn166_t *resp_frame = NULL; ge_frm_tail_t *tail_data; iot_pkt_t *data_pkt = NULL; if (iot_mac_addr_cmp(frm->dest_mac, dst_mac)) { reason = PROTO_REASON_MAC_MISSMATCH; iot_cus_printf("[glpr][err]%s dst_mac missmatch\n", "test delay time"); goto cfm; } /* sta don't support FE A6 from uart,we need response the unsupported reason included in the FE 14 frame */ if (dir != CMD_REMOTE_UP_LINK) { reason = PROTO_REASON_CMD_DIR_ERR; iot_cus_printf("[glpr][err]%s sta direction error\n", "test delay time"); goto cfm; } /* add fill data,need to alloc new pkt */ data_pkt = iot_pkt_alloc(len, IOT_GREE_APP_MID); if (data_pkt == NULL) { reason = PROTO_REASON_ALLOC_MEM_ERR; iot_cus_printf("[err]%s pkt alloc fail\n", __FUNCTION__); goto cfm; } resp_frame = (ge_frame_delay_time_subfn166_t *)iot_pkt_put(data_pkt, len); tail_data = (ge_frm_tail_t *)(iot_pkt_data(data_pkt) + sizeof(ge_frame_delay_time_subfn166_t) + rsv_data_len); os_mem_set(resp_frame, 0, len); resp_frame->seq = frm->seq; resp_frame->resv = frm->resv; iot_mac_addr_cpy(resp_frame->dest_mac, frm->dest_mac); os_mem_cpy((uint8_t *)&resp_frame->tm_test, (uint8_t *)&frm->tm_test, sizeof(frm->tm_test) + rsv_data_len); iot_common_bin_dump((uint8_t *)resp_frame, len); iot_delay_timer_get(&resp_frame->tm_test.mcu_tx_time, STA_RX_TIME, 0); iot_delay_timer_get(&resp_frame->tm_test.mcu_tx_time, STA_TX_TIME, 0); EXT_FN_TWO_PART_FRM_PREPARE(resp_frame, tail_data, rsv_data_len, PROTO_GE_PLC_SET_CMD, PROTO_GE_DELAY_TM_CMD); tail_data->check_sum = ge_frm_checksum_calc((uint8_t *)resp_frame, len - sizeof(ge_frm_tail_t)); iot_proto_delay_time_send(data_pkt, resp_frame->dest_mac, prototask_contxt.cco_dev.mac); return rpt2mcu; cfm: iot_proto_resp_cfm_frame(reason, dir, PROTO_GE_DELAY_TM_CMD, frm->seq, frm->dest_mac); return rpt2mcu; } #else /* PLC_SUPPORT_STA_ROLE */ /** * @brief iot_proto_delay_time_recv_subfn_handler() - compute cco recv time stamp. * @param data data which need to recv * @param len the data length * @param dir the data received direction * @retval: whether need report to mcu. */ static bool_t iot_proto_delay_time_recv_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { ge_frm_tail_t *tail_frm; (void)dir; ge_frame_delay_time_subfn166_t *frame = (ge_frame_delay_time_subfn166_t *)data; iot_delay_timer_get(&frame->tm_test.mcu_tx_time, CCO_RX_TIME, 0); iot_delay_time_ntb_to_us(&frame->tm_test); tail_frm = (ge_frm_tail_t *)(data + sizeof(ge_frame_delay_time_subfn166_t) + frame->tm_test.datalen); tail_frm->check_sum = ge_frm_checksum_calc(data, len - sizeof(ge_frm_tail_t)); tail_frm->tail = GE_FRM_TAIL_CODE; return true; } /** * @brief iot_proto_delay_time_send_subfn_handler() - cco send time stamp. * @param data data which need to send * @param len the data length * @param dir the data received direction * @retval: whether need report to mcu. */ static bool_t iot_proto_delay_time_send_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { uint16_t pkt_len; bool_t rpt2mcu = false; ge_frame_delay_time_subfn166_t *frm = (ge_frame_delay_time_subfn166_t *)data; uint8_t reason = PROTO_REASON_OK; uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 }; iot_pkt_t *data_pkt = NULL; uint8_t *local_mac = prototask_contxt.local_dev.mac; ge_delay_tm_test_t *time_data = &frm->tm_test; uint8_t *pkt_data; if (iot_mac_addr_cmp(frm->dest_mac, dst_mac)) { reason = PROTO_REASON_MAC_ADDR_ZERO; iot_cus_printf("[glpr][err]%s dst_mac is ivalid\n", "test delay time"); goto cfm; } iot_mac_addr_cpy(dst_mac, frm->dest_mac); if (iot_mac_addr_cmp(dst_mac, local_mac)) { reason = PROTO_REASON_MAC_ADDR_ZERO; iot_cus_printf("[glpr][err]%s the mac is local\n", "test delay time"); goto cfm; } pkt_len = len + time_data->datalen; if (pkt_len > 255) { reason = PROTO_REASON_PARAME_ERR; iot_cus_printf("[glpr][err]%s the fill data is too much\n", "test delay time"); goto cfm; } data_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID); if (data_pkt == NULL) { reason = PROTO_REASON_ALLOC_MEM_ERR; iot_cus_printf("[err]%s pkt alloc fail\n", __FUNCTION__); goto cfm; } iot_common_bin_dump(data, len); frm->hdr.hdr.data_len = frm->hdr.hdr.data_len + time_data->datalen; frm->resv = GE_TYPE; pkt_data = iot_pkt_put(data_pkt, pkt_len); frm->tm_test.level = iot_plctxrx_get_node_level(frm->dest_mac); if (frm->tm_test.level == -1) { iot_cus_printf("[glpr][err] query level failed\n"); } iot_delay_timer_get(&frm->tm_test.mcu_tx_time, CCO_TX_TIME, 0); os_mem_cpy(pkt_data, data, sizeof(ge_frame_delay_time_subfn166_t)); os_mem_cpy(pkt_data + sizeof(ge_frame_delay_time_subfn166_t) + time_data->datalen, data + sizeof(ge_frame_delay_time_subfn166_t), sizeof(ge_frm_tail_t)); iot_cus_printf("delaytime with fill pkt_len = %d\n", pkt_len); iot_proto_delay_time_send(data_pkt, local_mac, dst_mac); return rpt2mcu; cfm: iot_proto_resp_cfm_frame(reason, dir, PROTO_GE_DELAY_TM_CMD, frm->seq, frm->dest_mac); return rpt2mcu; } /** * @brief iot_proto_delay_time_handler() - test delay time. * @param data data which need to test * @param len the data length * @param dir the data received direction * @retval: whether need report to mcu. */ bool_t iot_proto_delay_time_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; if (CMD_LOCAL_DOWN_LINK == dir) { rpt2mcu = iot_proto_delay_time_send_subfn_handler(data, len, dir); } else { rpt2mcu = iot_proto_delay_time_recv_subfn_handler(data, len, dir); } return rpt2mcu; } #endif /* end PLC_SUPPORT_STA_ROLE */ void iot_proto_cfm_cmd_group(void *buf, uint8_t cmd, uint8_t result, uint8_t reason, uint8_t seq) { IOT_ASSERT(buf); ge_frame_cmd_cfm_set_subfn20_t *cfm = (ge_frame_cmd_cfm_set_subfn20_t *)buf; os_mem_set(cfm, 0, sizeof(*cfm)); cfm->cmd = cmd; cfm->reason = reason; cfm->result = result; cfm->seq = seq; EXT_FN_FRM_PREPARE(cfm, PROTO_GE_PLC_SET_CMD, PROTO_CMD_CFM_CMD); cfm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)cfm, sizeof(*cfm) - sizeof(ge_frm_tail_t)); return; } bool_t iot_proto_cmd_cfm_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu =false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); (void)dir; (void)len; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; uint8_t need_save_flash = 0; iot_cus_printf("[glpr] cmd_cfm: dir=%d, sm->dir=%d\n", dir, sm->dir); switch (sm->dir) { case CMD_LOCAL_UP_LINK: { plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; /* send to MCU */ iot_pkt_t *cmd_pkt = iot_pkt_alloc(sizeof(ge_frame_cmd_cfm_set_subfn20_t), IOT_GREE_APP_MID); uint8_t result = (0 == cmd->resp) ? 0 : 1; IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(ge_frame_cmd_cfm_set_subfn20_t)); /* group cfm frame */ iot_proto_cfm_cmd_group(iot_pkt_data(cmd_pkt), sm->cur_subfn, result, (uint8_t)cmd->resp, sm->seq); iot_proto_send_to_mainboard(cmd_pkt); if (result) { /* switch cmd handle state to idle */ iot_proto_cmd_handle_state_init(); break; } if (sm->cur_subfn == PROTO_LEAVE_NW_SET_CMD) { os_mem_set(prototask_contxt.cco_dev.mac, 0, IOT_MAC_ADDR_LEN); os_mem_set(p_flash->public.pub.cco_mac, 0, IOT_MAC_ADDR_LEN); need_save_flash = 1; } else if (sm->cur_subfn == PROTO_LOCAL_MAC_SET_CMD) { iot_mac_addr_cpy(p_flash->public.pub.local_mac, prototask_contxt.local_dev.mac); need_save_flash = 1; } /* switch cmd handle state to idle */ iot_proto_cmd_handle_state_init(); break; } case CMD_REMOTE_UP_LINK: { rpt2mcu = true; ge_frame_cmd_cfm_set_subfn20_t *cfm_cmd = (ge_frame_cmd_cfm_set_subfn20_t *)data; switch (cfm_cmd->cmd) { case PROTO_OP_WHITELIST_SET_CMD: //case PROTO_PAIR_CFM_SET_CMD: //case PROTO_CCO_START_GROUP_NET_CMD: //case PROTO_CCO_END_GROUP_NET_CMD: case PROTO_REBOOT_STA_CMD: //case PROTO_UNPAIR_DEVS_CMD: case PROTO_GE_GPIO_SET_CMD: { rpt2mcu = true; cfm_cmd->seq = sm->seq; /* switch cmd handle state to idle */ iot_proto_cmd_handle_state_init(); break; } #if 0 case PROTO_START_PAIR_CMD: case PROTO_END_PAIR_CMD: { uint8_t dev_role = prototask_contxt.local_dev.dev_role; rpt2mcu = prototask_contxt.pair_handler[dev_role](data, len, dir, PROTO_CMD_CFM_CMD); break; } #endif default: /* switch cmd handle state to idle */ iot_proto_cmd_handle_state_init(); break; } break; } case CMD_REMOTE_DOWN_LINK: { plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; protpkt_tx_info_t txinfo = { 0 }; iot_pkt_t *cfm_pkt = NULL; uint8_t result = (0 == cmd->resp)?0:1; cfm_pkt = iot_pkt_alloc(sizeof(ge_frame_cmd_cfm_set_subfn20_t), IOT_GREE_APP_MID); IOT_ASSERT(cfm_pkt); iot_pkt_put(cfm_pkt, sizeof(ge_frame_cmd_cfm_set_subfn20_t)); /* group cfm frame */ iot_proto_cfm_cmd_group(iot_pkt_data(cfm_pkt), sm->cur_subfn, result, (uint8_t)cmd->resp, sm->seq); /* CFM response to remote device */ iot_proto_fill_txinfo(&txinfo, 1, PLCTXRX_UNICAST, 3, 500, 1, prototask_contxt.local_dev.mac, sm->dev.mac); iot_proto_remote_cmd_send_to_plctxrx(iot_pkt_data(cfm_pkt), sizeof(ge_frame_cmd_cfm_set_subfn20_t), &txinfo); /* switch cmd handle state to idle */ iot_proto_cmd_handle_state_init(); if (cfm_pkt) { iot_pkt_free(cfm_pkt); } break; } default: break; } if (need_save_flash) { iot_proto_flashsave(p_flash); } return rpt2mcu; } bool_t iot_proto_query_swver_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); iot_pkt_t *cmd_pkt; ge_frame_fw_swver_query_subfn2_t *query_cmd = (ge_frame_fw_swver_query_subfn2_t *)data; plctxrx_cmd_arg_t cmd = { 0 }; ge_frame_fw_swver_resp_subfn2_t *resp_frm; if (len != sizeof(ge_frame_fw_swver_query_subfn2_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(ge_frame_fw_swver_resp_subfn2_t), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_frm = (ge_frame_fw_swver_resp_subfn2_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_FW_SWVER_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey software version"); return rpt2mcu; } cmd.cid.cid = PLCTXRX_CID_SWVER; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = 0; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd)+cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd)+cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); /* if async cmd, we need to set a state for response */ sm->state = PROTO_CMD_WAIT_SWVER_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } bool_t iot_proto_query_boot_info_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)data; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); iot_pkt_t *cmd_pkt; ge_frame_bootinfo_query_subfn3_t *query_cmd = (ge_frame_bootinfo_query_subfn3_t *)data; plctxrx_cmd_arg_t cmd = { 0 }; ge_frame_sysinfo_resp_subfn3_t *resp_frm; if (len != sizeof(ge_frame_bootinfo_query_subfn3_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(ge_frame_sysinfo_resp_subfn3_t), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_frm = (ge_frame_sysinfo_resp_subfn3_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_BOOT_INFO_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey boot info"); return rpt2mcu; } cmd.cid.cid = PLCTXRX_CID_BOOTINFO; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = 0; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd)+cmd.dlen,IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd)+cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); /* if async cmd, we need to set a state for response */ sm->state = PROTO_CMD_WAIT_BOOT_INFO_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } bool_t iot_proto_query_avail_nw_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); iot_pkt_t *cmd_pkt; ge_frame_avail_nw_query_subfn9_t *query_cmd = (ge_frame_avail_nw_query_subfn9_t *)data; ge_frame_avail_nw_resp_subfn9_t *resp_frm; if (len != sizeof(ge_frame_avail_nw_query_subfn9_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(ge_frame_avail_nw_resp_subfn9_t), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_frm = (ge_frame_avail_nw_resp_subfn9_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_AVAIL_NW_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm) - sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey avail network"); return rpt2mcu; } plctxrx_cmd_arg_t cmd = { 0 }; cmd.cid.cid = PLCTXRX_CID_FIND_NETWORK; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = 0; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd)+cmd.dlen,IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd)+cmd.dlen); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); /* if async cmd, we need to set a state for response */ sm->state = PROTO_CMD_WAIT_AVAIL_NETWORK_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); iot_cus_printf("[glpr]query avail nw send succ!\n"); return rpt2mcu; } bool_t iot_proto_query_tx_pwr_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; ge_frame_tx_pwr_query_subfn11_t *query_cmd = (ge_frame_tx_pwr_query_subfn11_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); iot_pkt_t *cmd_pkt; ge_frame_tx_pwr_resp_subfn11_t *resp_frm; if (len != sizeof(ge_frame_tx_pwr_query_subfn11_t)) { iot_pkt_t *pkt = iot_pkt_alloc(sizeof(ge_frame_tx_pwr_resp_subfn11_t), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_frm = (ge_frame_tx_pwr_resp_subfn11_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_frm)); os_mem_set(resp_frm, 0, sizeof(*resp_frm)); EXT_FN_FRM_PREPARE(resp_frm, PROTO_GE_PLC_RESP_CMD, PROTO_TX_PWR_RESP_CMD); resp_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_frm, sizeof(*resp_frm)-sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey tx power"); return rpt2mcu; } /* send topo response to remote device */ plctxrx_cmd_arg_t cmd = { 0 }; cmd.cid.cid = PLCTXRX_CID_TX_PWR; cmd.cid.opcode = PLCTXRX_OP_QUERY; cmd.need_ack = true; cmd.prio = 0; /* SEQ: one byte */ cmd.dlen = 0; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd), IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(cmd)); /* copy plctxrx_cmd_arg_t */ os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); sm->state = PROTO_CMD_WAIT_TX_PWR_RESP; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = query_cmd->seq; /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); iot_cus_printf("[glpr]query_tx_pwr:query tx power cmd send succ!\n"); return rpt2mcu; } bool_t iot_proto_query_uart_thrpt_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; ge_frame_uart_thpt_resp_subfn12_t *resp_cmd; ge_frame_uart0_thrpt_query_subfn12_t *query_cmd = (ge_frame_uart0_thrpt_query_subfn12_t *)data; iot_pkt_t *pkt = iot_pkt_alloc(sizeof(ge_frame_uart_thpt_resp_subfn12_t), IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[glpr][err]No Mem!\n"); return rpt2mcu; } resp_cmd = (ge_frame_uart_thpt_resp_subfn12_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp_cmd)); os_mem_set(resp_cmd, 0, sizeof(*resp_cmd)); EXT_FN_FRM_PREPARE(resp_cmd, PROTO_GE_PLC_RESP_CMD, PROTO_UART_THPT_RESP_CMD); if (len == sizeof(ge_frame_uart0_thrpt_query_subfn12_t)) { resp_cmd->seq = query_cmd->seq; resp_cmd->recv_rate[0] = (uint8_t)(uart_thpt.recv_rate&0xFF); resp_cmd->recv_rate[1] = (uint8_t)((uart_thpt.recv_rate>>8) & 0xFF ); resp_cmd->recv_rate[2] = (uint8_t)((uart_thpt.recv_rate>>16) & 0xFF ); resp_cmd->send_rate[0] = (uint8_t)(uart_thpt.send_rate&0xFF); resp_cmd->send_rate[1] = (uint8_t)((uart_thpt.send_rate>>8) & 0xFF ); resp_cmd->send_rate[2] = (uint8_t)((uart_thpt.send_rate>>16) & 0xFF ); } else { iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "qurey uart thoughput"); } resp_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp_cmd, sizeof(*resp_cmd)-sizeof(ge_frm_tail_t)); /* send to MCU */ iot_proto_send_to_mainboard(pkt); return rpt2mcu; } bool_t iot_proto_comm_fault_ind_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; bool_t rpt2mcu = false; plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; /* only indication can report this message */ IOT_ASSERT(cmd->cid.opcode == PLCTXRX_OP_INDICATION); switch (dir) { case CMD_LOCAL_UP_LINK: { /* send to MCU */ ge_frame_comm_fault_rpt_set_subfn8_t *rpt_cmd; plctxrx_cmd_comm_fault_ind_t *resp_cmd = (plctxrx_cmd_comm_fault_ind_t*)cmd->data; iot_pkt_t *cmd_pkt = iot_pkt_alloc(sizeof(ge_frame_comm_fault_rpt_set_subfn8_t), IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); rpt_cmd = (ge_frame_comm_fault_rpt_set_subfn8_t *)iot_pkt_data(cmd_pkt); iot_pkt_put(cmd_pkt, sizeof(*rpt_cmd)); os_mem_set(rpt_cmd, 0, sizeof(*rpt_cmd)); rpt_cmd->type = resp_cmd->type; rpt_cmd->seq = prototask_contxt.local_dev.ind_seq++; rpt_cmd->reason = resp_cmd->reason; EXT_FN_FRM_PREPARE(rpt_cmd, PROTO_GE_PLC_SET_CMD, PROTO_COMM_FAULT_RPT_CMD); rpt_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)rpt_cmd, sizeof(*rpt_cmd) - sizeof(ge_frm_tail_t)); iot_proto_send_to_mainboard(cmd_pkt); break; } default: break; } return rpt2mcu; } bool_t iot_proto_start_groupnet_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu =false; uint32_t reason = 0; sta_dev_t *local_dev = &prototask_contxt.local_dev; ge_frame_start_group_set_subfn13_t *frame = (ge_frame_start_group_set_subfn13_t*)data; if (len != sizeof(ge_frame_start_group_set_subfn13_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (IOT_PLC_DEV_ROLE_CCO != local_dev->nw_role) { reason = PROTO_REASON_NO_AUTHORITY; } else if (IOT_PLC_DEV_ROLE_CCO != local_dev->nw_role && !prototask_contxt.local_dev.dev_ready) { reason = PROTO_REASON_NOT_READY; } else if (local_dev->nid != frame->nid) { reason = PROTO_REASON_NID_MISSMATCH; } if (PROTO_REASON_OK != reason) { iot_proto_resp_cfm_frame(reason, dir, PROTO_CCO_START_GROUP_NET_CMD, frame->seq, prototask_contxt.rx_info.mac); iot_cus_printf("[glpr][err]Group start err:reason=%d\n", reason); return rpt2mcu; } if (IOT_PLC_DEV_ROLE_CCO == local_dev->nw_role) { iot_proto_cco_groupnet_sm(data, PROTO_CCO_START_GROUP_NET_CMD, dir, NULL); } return rpt2mcu; } bool_t iot_proto_end_groupnet_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu =false; uint32_t reason = 0; sta_dev_t *local_dev = &prototask_contxt.local_dev; ge_frame_end_group_set_subfn14_t *frame = (ge_frame_end_group_set_subfn14_t*)data; if (len != sizeof(ge_frame_end_group_set_subfn14_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (IOT_PLC_DEV_ROLE_CCO != local_dev->nw_role) { reason = PROTO_REASON_NO_AUTHORITY; } else if (IOT_PLC_DEV_ROLE_CCO != local_dev->nw_role && !prototask_contxt.local_dev.dev_ready) { reason = PROTO_REASON_NOT_READY; } else if (local_dev->nid != frame->nid) { reason = PROTO_REASON_NID_MISSMATCH; } if (PROTO_REASON_OK != reason) { iot_proto_resp_cfm_frame(reason, dir, PROTO_CCO_END_GROUP_NET_CMD, frame->seq, prototask_contxt.rx_info.mac); iot_cus_printf("[glpr][err]Group end err:reason=%d\n", reason); return rpt2mcu; } if (IOT_PLC_DEV_ROLE_CCO == local_dev->nw_role) { iot_proto_cco_groupnet_sm(data, PROTO_CCO_END_GROUP_NET_CMD, dir, NULL); } return rpt2mcu; } bool_t iot_proto_fw_swver_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; bool_t rpt2mcu = false; IOT_ASSERT(CMD_LOCAL_UP_LINK == dir); iot_pkt_t *datapkt; ge_frame_fw_swver_resp_subfn2_t *send_cmd; proto_cmd_hdl_state_t* sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_software_ver_resp_t *swver = (plctxrx_cmd_software_ver_resp_t *)cmd->data; /* group gree frame */ datapkt = iot_pkt_alloc(sizeof(ge_frame_fw_swver_resp_subfn2_t), IOT_GREE_APP_MID); IOT_ASSERT(datapkt); iot_pkt_put(datapkt, sizeof(ge_frame_fw_swver_resp_subfn2_t)); send_cmd = (ge_frame_fw_swver_resp_subfn2_t *)iot_pkt_data(datapkt); os_mem_set(send_cmd, 0 ,sizeof(*send_cmd)); send_cmd->seq = sm->seq; send_cmd->swver = swver->version; EXT_FN_FRM_PREPARE(send_cmd, PROTO_GE_PLC_RESP_CMD, PROTO_FW_SWVER_RESP_CMD); send_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)send_cmd, sizeof(*send_cmd)-sizeof(ge_frm_tail_t)); /* switch back state to idle state */ iot_proto_cmd_handle_state_init(); /* send to MCU */ iot_proto_send_to_mainboard(datapkt); return rpt2mcu; } bool_t iot_proto_boot_info_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; bool_t rpt2mcu = false; IOT_ASSERT(CMD_LOCAL_UP_LINK == dir); iot_pkt_t *datapkt; ge_frame_sysinfo_resp_subfn3_t *send_cmd; proto_cmd_hdl_state_t* sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_boot_info_resp_t *boot_info = (plctxrx_cmd_boot_info_resp_t *)cmd->data; /* group gree frame */ datapkt = iot_pkt_alloc(sizeof(*send_cmd), IOT_GREE_APP_MID); IOT_ASSERT(datapkt); iot_pkt_put(datapkt, sizeof(ge_frame_sysinfo_resp_subfn3_t)); send_cmd = (ge_frame_sysinfo_resp_subfn3_t *)iot_pkt_data(datapkt); os_mem_set(send_cmd, 0, sizeof(*send_cmd)); send_cmd->seq = sm->seq; send_cmd->boot_cnt = (uint16_t)boot_info->total_boot_cnt; send_cmd->last_boot_reason = boot_info->last_reboot_reason; send_cmd->run_time = boot_info->os_running_time; EXT_FN_FRM_PREPARE(send_cmd, PROTO_GE_PLC_RESP_CMD, PROTO_BOOT_INFO_RESP_CMD); send_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)send_cmd, sizeof(*send_cmd) - sizeof(ge_frm_tail_t)); /* switch back state to idle state ASAP */ iot_proto_cmd_handle_state_init(); /* send to MCU */ iot_proto_send_to_mainboard(datapkt); return rpt2mcu; } bool_t iot_proto_avail_nw_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; (void)dir; bool_t rpt2mcu = false; proto_cmd_hdl_state_t* sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_network_t *net_info = (plctxrx_cmd_network_t*)cmd->data; plctxrx_cmd_network_info_t *node = (plctxrx_cmd_network_info_t *)net_info->node; proto_neighbor_info_t *nb_node = prototask_contxt.neighbor_nw.node; uint16_t frame_cnt = (net_info->count > 0) ? net_info->count : 1; uint16_t size; uint8_t joined_flag = 0; uint16_t i; if (prototask_contxt.local_dev.dev_ready) { joined_flag = 1; if (net_info->count > 0) { frame_cnt++; } } size = sizeof(ge_frame_avail_nw_resp_subfn9_t) * frame_cnt; iot_pkt_t *data_pkt = iot_pkt_alloc(size, IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); ge_frame_avail_nw_resp_subfn9_t *frame = (ge_frame_avail_nw_resp_subfn9_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, size); if (net_info->count > 0 || joined_flag == 1) { prototask_contxt.neighbor_nw.count = net_info->count; os_mem_set(prototask_contxt.neighbor_nw.node, 0, sizeof(*nb_node) * PROTO_SUPPORT_MAX_NEIGHBOR_NET); if (joined_flag) { os_mem_set(frame, 0, sizeof(*frame)); frame->nid = prototask_contxt.local_dev.nid; frame->seq = sm->seq; frame->total_cnt = (uint8_t)frame_cnt; frame->cur_cnt = 1; frame->snr = 0; if (IOT_PLC_DEV_ROLE_CCO == prototask_contxt.local_dev.nw_role) { iot_mac_addr_cpy(frame->mac, prototask_contxt.local_dev.mac); } else { iot_mac_addr_cpy(frame->mac, prototask_contxt.cco_dev.mac); } EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_AVAIL_NW_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)(frame), sizeof(*frame) - sizeof(ge_frm_tail_t)); } for (i = 0; i < net_info->count; i++) { /* update the neighbor network info in local */ iot_mac_addr_cpy((nb_node + i)->mac, (node + i)->mac); (nb_node + i)->nid = (uint8_t)((node + i)->nid & 0xFF); (nb_node + i)->best_snr = (uint8_t)(node + i)->snr; iot_cus_printf("[glpr]avail_nw_resp_subfn_handler:nw[%d]" "report mac[%2x:%2x:%2x:%2x:%2x:%2x]\n", (nb_node+i)->nid, (nb_node+i)->mac[0], (nb_node+i)->mac[1], (nb_node+i)->mac[2], (nb_node+i)->mac[3], (nb_node+i)->mac[4], (nb_node+i)->mac[5]); os_mem_set(frame + i + joined_flag, 0, sizeof(*frame)); (frame + i + joined_flag)->nid = (uint8_t)((node + i)->nid & 0xFF); (frame + i + joined_flag)->seq = sm->seq; (frame + i + joined_flag)->total_cnt = (uint8_t)frame_cnt; (frame + i + joined_flag)->cur_cnt = (uint8_t)(i + 1 + joined_flag); (frame + i + joined_flag)->snr = (uint8_t)(node + i)->snr; iot_mac_addr_cpy((frame + i + joined_flag)->mac, (node + i)->mac); EXT_FN_FRM_PREPARE((frame + i + joined_flag), PROTO_GE_PLC_RESP_CMD, PROTO_AVAIL_NW_RESP_CMD); (frame + i + joined_flag)->tail.check_sum = ge_frm_checksum_calc((uint8_t *)(frame + i + joined_flag), sizeof(*(frame + i + joined_flag)) - sizeof(ge_frm_tail_t)); } } else { os_mem_set(frame, 0, sizeof(*frame)); frame->seq = sm->seq; EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_AVAIL_NW_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); } /* report topo to MCU */ iot_proto_send_to_mainboard(data_pkt); /* switch back state to idle state */ iot_proto_cmd_handle_state_init(); return rpt2mcu; } bool_t iot_proto_tx_power_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; (void)dir; bool_t rpt2mcu = false; uint16_t size; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_tx_pwr_t *tx_pwr_info = (plctxrx_cmd_tx_pwr_t*)cmd->data; ge_frame_tx_pwr_resp_subfn11_t *frame; size = sizeof(ge_frame_tx_pwr_resp_subfn11_t); iot_pkt_t *data_pkt = iot_pkt_alloc(size, IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); frame = (ge_frame_tx_pwr_resp_subfn11_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt,size); os_mem_set(frame, 0, sizeof(*frame)); frame->seq = sm->seq; if (cmd->resp == PLCTXRX_RESP_ERROR) { frame->tx_pwr = 0; } else { frame->tx_pwr = tx_pwr_info->tx_pwr; } EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_TX_PWR_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame)-sizeof(ge_frm_tail_t)); /* report topo to MCU */ iot_proto_send_to_mainboard(data_pkt); /* switch back state to idle state */ iot_proto_cmd_handle_state_init(); return rpt2mcu; } bool_t iot_proto_ntb_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_ntb_resp_t *ntb_info = (plctxrx_cmd_ntb_resp_t*)cmd->data; ge_frame_ntb_resp_subfn19_t *frame; iot_pkt_t *data_pkt = iot_pkt_alloc(sizeof(*frame), IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); frame = (ge_frame_ntb_resp_subfn19_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, sizeof(*frame)); os_mem_set(frame, 0, sizeof(*frame)); frame->seq = sm->seq; frame->ntb = ntb_info->ntb; EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_NTB_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); /* report ntb to MCU */ iot_proto_send_to_mainboard(data_pkt); /* switch back state to idle state */ iot_proto_cmd_handle_state_init(); return rpt2mcu; } /** * @brief iot_proto_node_info_report() - report node information * handler * @param data data which need to report * @param dlen the data length * @param total_cnt report information total count * @param cur_cnt current time report information count * @param type the node information type report * @param done the node information report done */ void iot_proto_node_info_report(uint8_t *data, uint16_t dlen, uint16_t total_cnt, uint16_t cur_cnt, uint8_t type, uint8_t done) { proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); ge_frame_node_info_resp_subfn23_t *frame; ge_frm_tail_t *tail; uint8_t resp_len = (uint8_t)(sizeof(ge_frame_node_info_resp_subfn23_t) + dlen + sizeof(ge_frm_tail_t)); iot_pkt_t *data_pkt = iot_pkt_alloc(resp_len, IOT_GREE_APP_MID); if (NULL == data_pkt) { iot_cus_printf("[glpr] alloc pkt error\n"); IOT_ASSERT(0); return; } frame = (ge_frame_node_info_resp_subfn23_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, resp_len); os_mem_set(frame, 0, sizeof(ge_frame_node_info_resp_subfn23_t)); frame->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE; frame->hdr.hdr.data_len = resp_len - GE_FRM_MIN_LEN; frame->hdr.hdr.fn = PROTO_GE_PLC_RESP_CMD; frame->hdr.subfn = PROTO_NODE_INFO_RESP_CMD; frame->seq = sm->seq; frame->type = type; if (data && dlen > 0) { frame->total_cnt = total_cnt; frame->cur_cnt = (uint8_t)cur_cnt; frame->index = (uint8_t)((prototask_contxt.topo_resp_index + QUERY_NODE_INFO_MAX_CNT_ONCE - 1) / QUERY_NODE_INFO_MAX_CNT_ONCE); os_mem_cpy(frame->info, data, dlen); } prototask_contxt.topo_resp_index += cur_cnt; tail = (ge_frm_tail_t *)(frame->info + dlen); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(ge_frame_node_info_resp_subfn23_t) + dlen); tail->tail = GE_FRM_TAIL_CODE; /* switch back state to idle state */ if (done) { prototask_contxt.topo_resp_index = 0; iot_proto_cmd_handle_state_init(); } /* report node info to MCU */ iot_proto_send_to_mainboard(data_pkt); } /** * @brief iot_proto_nw_info_report() - report network information * @param max_level network max level * @param data network level information data which need to report * @param dlen the data length */ void iot_proto_nw_info_report(uint8_t max_level, uint8_t *data, uint8_t length) { proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); ge_frame_nw_info_resp_subfn24_t *frame; ge_frm_tail_t *tail; uint8_t resp_len = sizeof(ge_frame_nw_info_resp_subfn24_t) + length + sizeof(ge_frm_tail_t); iot_pkt_t * data_pkt = iot_pkt_alloc(resp_len, IOT_GREE_APP_MID); if (NULL == data_pkt) { iot_cus_printf("[glpr] alloc pkt error\n"); return; } frame = (ge_frame_nw_info_resp_subfn24_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, resp_len); os_mem_set(frame, 0, sizeof(ge_frame_nw_info_resp_subfn24_t)); frame->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE; frame->hdr.hdr.data_len = resp_len - GE_FRM_MIN_LEN; frame->hdr.hdr.fn = PROTO_GE_PLC_RESP_CMD; frame->hdr.subfn = PROTO_NW_INFO_RESP_CMD; frame->seq = sm->seq; if (data && length > 0) { frame->max_level = max_level; os_mem_cpy(frame->level_info, data, length); } tail = (ge_frm_tail_t *)(frame->level_info + length); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(ge_frame_nw_info_resp_subfn24_t) + length); tail->tail = GE_FRM_TAIL_CODE; /* report network info to MCU */ iot_proto_send_to_mainboard(data_pkt); /* switch back state to idle state */ iot_proto_cmd_handle_state_init(); } /** * @brief iot_proto_node_info_resp_subfn_handler() - report node infomation * handler * @param data data which need to report * @param len the data length * @param dir the data received direction * @retval: whether need report to mcu. */ bool_t iot_proto_node_info_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; iot_proto_node_info_report(cmd->data, cmd->dlen, cmd->index.total, cmd->index.current, (uint8_t)cmd->resv, cmd->done); return true; } /** * @brief iot_proto_nw_info_resp_subfn_handler() - report network infomation * handler * @param data data which need to report * @param len the data length * @param dir the data received direction * @retval: whether need report to mcu. */ bool_t iot_proto_nw_info_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; iot_plc_nw_info_query_rpt_t *nw_info = (iot_plc_nw_info_query_rpt_t*)cmd->data; uint8_t data_len = sizeof(iot_plc_nw_level_info_t) * nw_info->max_level; iot_proto_nw_info_report(nw_info->max_level, (uint8_t*)nw_info->nw_level_info, data_len); return rpt2mcu; } /** * @brief iot_proto_gpio_resp_subfn_handler() - response gpio info. * @param data data which need to resp * @param len the data length * @param dir the data received direction * @retval: whether need report to mcu. */ bool_t iot_proto_gpio_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; (void)dir; bool_t rpt2mcu = false; ge_frame_query_gpio_resp_subfn27_t *frame = (ge_frame_query_gpio_resp_subfn27_t *)data; if (iot_mac_addr_cmp(frame->dest_mac, prototask_contxt.local_dev.mac)) { /* resp gpio info to uart */ iot_pkt_t *pkt = NULL; uint8_t *data_ptr = NULL; uint16_t data_len = sizeof(*frame); pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID); data_ptr = (uint8_t*)iot_pkt_put(pkt, data_len); os_mem_cpy(data_ptr, (uint8_t*)frame, data_len); iot_proto_send_to_mainboard(pkt); iot_proto_cmd_handle_state_init(); } return rpt2mcu; } bool_t iot_proto_fb_bitmap_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; uint8_t row = 0, col = 0; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_fb_bitmap_resp_t *bitmap_info = (plctxrx_cmd_fb_bitmap_resp_t*)cmd->data; ge_frame_fb_bitmap_resp_subfn20_t *frame; iot_pkt_t *data_pkt = iot_pkt_alloc(sizeof(*frame), IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); frame = (ge_frame_fb_bitmap_resp_subfn20_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, sizeof(*frame)); os_mem_set(frame, 0, sizeof(*frame)); frame->seq = sm->seq; /* band id idx is less than 16 */ #define IOT_GE_BITMAP_COL_MAX 8 for (row = 0; row < sizeof(uint16_t); row++) { for (col = 0; col < IOT_GE_BITMAP_COL_MAX; col++) { if (((bitmap_info->fb_bitmap[row] & (1 << col)) >> col != 0)) { frame->bitmap |= 1 << (row*IOT_GE_BITMAP_COL_MAX+col); } } } frame->is_scan_bitmap = bitmap_info->is_scan_bitmap; EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_FB_BITMAP_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); /* report bitmap to MCU */ iot_proto_send_to_mainboard(data_pkt); /* switch back state to idle state */ iot_proto_cmd_handle_state_init(); return rpt2mcu; } bool_t iot_proto_fix_rate_mode_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_fix_rate_mode_resp_t *fix_rate_mode = (plctxrx_cmd_fix_rate_mode_resp_t*)cmd->data; ge_frame_fix_rate_mode_resp_subfn21_t *frame; iot_pkt_t *data_pkt = iot_pkt_alloc(sizeof(*frame), IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); frame = (ge_frame_fix_rate_mode_resp_subfn21_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, sizeof(*frame)); os_mem_set(frame, 0, sizeof(*frame)); frame->seq = sm->seq; frame->enable = fix_rate_mode->enable; EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_FIX_RATE_MODE_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); /* report fix rate to MCU */ iot_proto_send_to_mainboard(data_pkt); /* switch back state to idle state */ iot_proto_cmd_handle_state_init(); return rpt2mcu; } bool_t iot_proto_work_band_resp_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_band_info_t *resp_band_info = (plctxrx_cmd_band_info_t*)cmd->data; ge_frame_work_band_resp_subfn22_t *frame; iot_pkt_t *data_pkt = iot_pkt_alloc(sizeof(*frame), IOT_GREE_APP_MID); IOT_ASSERT(data_pkt); frame = (ge_frame_work_band_resp_subfn22_t *)iot_pkt_data(data_pkt); iot_pkt_put(data_pkt, sizeof(*frame)); os_mem_set(frame, 0, sizeof(*frame)); frame->seq = sm->seq; frame->band = resp_band_info->band_id; EXT_FN_FRM_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_WORK_BAND_RESP_CMD); frame->tail.check_sum = ge_frm_checksum_calc((uint8_t *)frame, sizeof(*frame) - sizeof(ge_frm_tail_t)); /* report work band to MCU */ iot_proto_send_to_mainboard(data_pkt); /* switch back state to idle state */ iot_proto_cmd_handle_state_init(); return rpt2mcu; } /* Timout handler for querying white list or pair table. */ void iot_proto_wl_pt_remote_query_timeout_from_mcu(uint32_t state) { ge_frame_wl_resp_subfn7_t *p_whitelist_resp; iot_pkt_t *p_pkt; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); iot_cus_printf("[glpr]wlist ptable rmt %s timeout.\n", "query"); if (PROTO_CMD_WAIT_RMT_WHITELIST_RESP == state) { p_pkt = iot_pkt_alloc(sizeof(*p_whitelist_resp), IOT_GREE_APP_MID); if (!p_pkt) return; p_whitelist_resp = (ge_frame_wl_resp_subfn7_t *)iot_pkt_put (p_pkt, sizeof(*p_whitelist_resp)); os_mem_set(p_whitelist_resp, 0x00, sizeof(*p_whitelist_resp)); EXT_FN_FRM_PREPARE(p_whitelist_resp, PROTO_GE_PLC_RESP_CMD, PROTO_WHITELIST_RESP_CMD); p_whitelist_resp->cco_flag = 0x01; p_whitelist_resp->seq = sm->seq; p_whitelist_resp->tail.check_sum = ge_frm_checksum_calc ((uint8_t *)p_whitelist_resp, sizeof(*p_whitelist_resp) - sizeof(ge_frm_tail_t)); iot_proto_send_to_mainboard(p_pkt); } return; } /* send topo resp timeout to mcu */ void iot_proto_wait_rmt_topo_resp_timeout(proto_cmd_hdl_state_t *sm) { ge_frame_topo_resp_subfn5_t *frame; uint16_t resp_len = 0; ge_frm_tail_t *tail = NULL; uint16_t topo_info_len = 0; iot_pkt_t *rsp_data; (void)sm; switch (prototask_contxt.topo_info_type) { case TOPO_INFO_TYPE_V0: topo_info_len = sizeof(topo_info_v0_t); break; case TOPO_INFO_TYPE_V1: topo_info_len = sizeof(topo_info_v1_t); break; default: iot_cus_printf("[glpr][err]topo resp timeout error with type[%d]\n", prototask_contxt.topo_info_type); return; } resp_len = sizeof(ge_frame_topo_resp_subfn5_t) + topo_info_len + sizeof(ge_frm_tail_t); rsp_data = iot_pkt_alloc(resp_len, IOT_GREE_APP_MID); IOT_ASSERT(rsp_data); frame = (ge_frame_topo_resp_subfn5_t *)iot_pkt_data(rsp_data); iot_pkt_put(rsp_data, resp_len); os_mem_set(frame, 0, resp_len); frame->type = prototask_contxt.topo_info_type; GE_FRM_HDR_PREPARE(frame, PROTO_GE_PLC_RESP_CMD, PROTO_TOPO_RESP_CMD, resp_len); tail = (ge_frm_tail_t *)(frame->info + topo_info_len); tail->check_sum = ge_frm_checksum_calc((uint8_t *)frame, resp_len - sizeof(ge_frm_tail_t)); tail->tail = GE_FRM_TAIL_CODE; iot_proto_send_to_mainboard(rsp_data); } bool_t iot_proto_cco_state_ind_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; (void)len; bool_t rpt2mcu = false; iot_pkt_t *datapkt = NULL; ge_frame_cco_stat_ind_set_subfn21_t* ind_frm; plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_cco_sta_ind_t *state = (plctxrx_cmd_cco_sta_ind_t *)cmd->data; /* modify local device ready state */ prototask_contxt.local_dev.dev_ready = state->dev_ready; /* save local nid in cco role */ prototask_contxt.local_dev.nid = state->nid; iot_cus_printf("[glpr]state_ind:ready=%d\n", state->dev_ready); datapkt = iot_pkt_alloc(sizeof(ge_frame_cco_stat_ind_set_subfn21_t), IOT_GREE_APP_MID); IOT_ASSERT(datapkt); iot_pkt_put(datapkt, sizeof(ge_frame_cco_stat_ind_set_subfn21_t)); ind_frm = (ge_frame_cco_stat_ind_set_subfn21_t *)iot_pkt_data(datapkt); os_mem_set(ind_frm, 0 ,sizeof(ge_frame_cco_stat_ind_set_subfn21_t)); EXT_FN_FRM_PREPARE(ind_frm, PROTO_GE_PLC_SET_CMD, PROTO_CMD_CCO_STAT_IND_CMD); ind_frm->ready = state->dev_ready; ind_frm->nid = state->nid; ind_frm->seq = prototask_contxt.local_dev.ind_seq++; ind_frm->tail.check_sum = ge_frm_checksum_calc((uint8_t *)ind_frm, sizeof(*ind_frm)-sizeof(ge_frm_tail_t)); /* report cco stated network event to MCU */ iot_proto_send_to_mainboard(datapkt); #if IOT_GE_PAGING_ENABLE if (!os_is_timer_active(prototask_contxt.paging_timer)) { os_start_timer(prototask_contxt.paging_timer, PROTO_TMR_PAGING_TIMEOUT_INTVL); } #endif return rpt2mcu; } bool_t iot_proto_set_join_nw_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu = false; iot_pkt_t *cmd_pkt; uint8_t i; uint32_t reason = PROTO_REASON_OK; plctxrx_cmd_arg_t cmd = { 0 }; plctxrx_cmd_join_network_t *join_info; ge_frame_join_nw_set_subfn3_t *frm = (ge_frame_join_nw_set_subfn3_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); iot_cus_printf("[glpr]set_join_nw_subfn_handler nb_cnt=%d\n", prototask_contxt.neighbor_nw.count); sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = frm->seq; sm->cur_subfn = frm->hdr.subfn; /* all machine, except outdoor machine can set join network */ if (IOT_PLC_DEV_ROLE_CCO == prototask_contxt.local_dev.nw_role) { reason = PROTO_REASON_NO_AUTHORITY; } else if (len != sizeof(ge_frame_join_nw_set_subfn3_t)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (prototask_contxt.local_dev.dev_ready) { reason = PROTO_REASON_JOINED; } else if (prototask_contxt.neighbor_nw.count == 0) { reason = PROTO_REASON_NO_NB_NW_FOUND; } if (reason != PROTO_REASON_OK) { goto err_cfm; } for (i = 0; i < prototask_contxt.neighbor_nw.count; i++) { if (frm->nid == prototask_contxt.neighbor_nw.node[i].nid) { iot_cus_printf("[glpr]set nid %d vs nod nid: %d\n", frm->nid, prototask_contxt.neighbor_nw.node[i].nid); cmd.cid.cid = PLCTXRX_CID_JOIN_NETWORK; cmd.cid.opcode = PLCTXRX_OP_CONFIG; cmd.prio = 0; cmd.need_ack = true; cmd.dlen = sizeof(plctxrx_cmd_join_network_t); /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(cmd) + cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); join_info = (plctxrx_cmd_join_network_t *) \ (iot_pkt_data(cmd_pkt) + sizeof(cmd)); join_info->nid= frm->nid;//add iot_mac_addr_cpy(join_info->mac, prototask_contxt.neighbor_nw.node[i].mac); iot_cus_printf("[glpr]join_nid=%d mac:%2x:%2x:%2x:%2x:%2x:%2x\n", join_info->nid, join_info->mac[0], join_info->mac[1], join_info->mac[2], join_info->mac[3], join_info->mac[4], join_info->mac[5]); iot_pkt_put(cmd_pkt, sizeof(cmd) + cmd.dlen); os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); iot_proto_cmd_send_to_plctxrx(cmd_pkt); return rpt2mcu; } else { reason = PROTO_REASON_NID_MISSMATCH; } } err_cfm: iot_cus_printf("[glpr]join nw failed, reason:%d\n", reason); iot_proto_resp_cfm_frame(reason, dir, PROTO_JOIN_NW_SET_CMD, frm->seq, NULL); /* switch cmd handle state to idle */ iot_proto_cmd_handle_state_init(); return rpt2mcu; } /* translate from txrx cid to gree fn, subfn */ uint8_t iot_proto_plctxtx_fn_subfn_get(plctxrx_cmd_resp_t *cmd, uint8_t *fn, uint8_t *subfn) { IOT_ASSERT(cmd && fn && subfn); uint8_t ret = ERR_FAIL; switch (cmd->cid.cid) { case PLCTXRX_CID_MAC: { switch (cmd->cid.opcode) { case PLCTXRX_OP_RESPONSE: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_LOCAL_MAC_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_OP_CFM: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_TOPO: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_TOPO_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_CID_WHITELIST: { switch (cmd->cid.opcode) { case PLCTXRX_OP_RESPONSE: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_WHITELIST_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_OP_CFM: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_FIND_NETWORK: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_AVAIL_NW_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_CID_JOIN_NETWORK: { switch (cmd->cid.opcode) { case PLCTXRX_OP_CFM: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; ret = ERR_OK; break; } case PLCTXRX_OP_INDICATION: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CONN_IND_RPT_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_LEAVE_NETWORK: { if (PLCTXRX_OP_CFM == cmd->cid.opcode) { *subfn = PROTO_CMD_CFM_CMD; } else { /* PLCTXRX_OP_INDICATION */ *subfn = PROTO_DISCONN_IND_RPT_CMD; } *fn = PROTO_GE_PLC_SET_CMD; ret = ERR_OK; break; } case PLCTXRX_CID_REJECT_STA: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_REJECT_IND_RPT_CMD; ret = ERR_OK; break; } case PLCTXRX_CID_CCO_STATE: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CCO_STAT_IND_CMD; ret = ERR_OK; break; } case PLCTXRX_CID_VENDOR_INFO: { if (PLCTXRX_OP_CFM == cmd->cid.opcode) { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; } ret = ERR_OK; break; } case PLCTXRX_CID_SWVER: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_FW_SWVER_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_CID_BOOTINFO: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_BOOT_INFO_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_CID_NET_STS: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_NET_STS_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_CID_NID: { switch (cmd->cid.opcode) { case PLCTXRX_OP_CFM: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_COMM_FAULT: { switch (cmd->cid.opcode) { case PLCTXRX_OP_INDICATION: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_COMM_FAULT_RPT_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_TX_PWR: { switch (cmd->cid.opcode) { case PLCTXRX_OP_RESPONSE: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_TX_PWR_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_OP_CFM: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_GRAPP_REG_CONF: { switch (cmd->cid.opcode) { case PLCTXRX_OP_INDICATION: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_APP_REG_CONF_IND; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_BAND_ID: { switch (cmd->cid.opcode) { case PLCTXRX_OP_CFM: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; ret = ERR_OK; break; } case PLCTXRX_OP_RESPONSE: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_WORK_BAND_RESP_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_VENDOR_DATA: { if (PLCTXRX_OP_CFM == cmd->cid.opcode) { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; } ret = ERR_OK; break; } case PLCTXRX_CID_NTB: { if (PLCTXRX_OP_RESPONSE == cmd->cid.opcode) { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_NTB_RESP_CMD; } ret = ERR_OK; break; } case PLCTXRX_CID_FB_BITMAP: { switch (cmd->cid.opcode) { case PLCTXRX_OP_RESPONSE: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_FB_BITMAP_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_OP_CFM: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_FIXED_RATE: { switch (cmd->cid.opcode) { case PLCTXRX_OP_RESPONSE: { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_FIX_RATE_MODE_RESP_CMD; ret = ERR_OK; break; } case PLCTXRX_OP_CFM: { *fn = PROTO_GE_PLC_SET_CMD; *subfn = PROTO_CMD_CFM_CMD; ret = ERR_OK; break; } default: break; } break; } case PLCTXRX_CID_NODE_INFO: { if (PLCTXRX_OP_RESPONSE == cmd->cid.opcode) { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_NODE_INFO_RESP_CMD; } ret = ERR_OK; break; } case PLCTXRX_CID_NW_INFO: { if (PLCTXRX_OP_RESPONSE == cmd->cid.opcode) { *fn = PROTO_GE_PLC_RESP_CMD; *subfn = PROTO_NW_INFO_RESP_CMD; } ret = ERR_OK; break; } default: break; } return ret; } /* update beacon vendor info */ uint8_t iot_proto_update_vendr(iot_pkt_t *pkt) { proto_vendor_info_t *vendr_info = (proto_vendor_info_t *)iot_pkt_data(pkt); iot_pkt_t *ind_pkt; ge_frame_bc_data_send_subfn162_t *data_cmd; if (!os_mem_cmp(vendr_info->data, prototask_contxt.rxbc_data.data, IOT_PLC_BEACON_DATA_MAX)) { goto out; } ind_pkt = iot_pkt_alloc(sizeof(*data_cmd), IOT_GREE_APP_MID); IOT_ASSERT(ind_pkt); data_cmd = (ge_frame_bc_data_send_subfn162_t *)iot_pkt_data(ind_pkt); os_mem_set(data_cmd, 0, sizeof(*data_cmd)); iot_pkt_put(ind_pkt, sizeof(*data_cmd)); EXT_FN_FRM_PREPARE(data_cmd, PROTO_GE_PLC_SET_CMD, PROTO_GE_BC_DATA_CMD); os_mem_cpy(data_cmd->data, vendr_info->data, sizeof(*vendr_info)); os_mem_cpy(prototask_contxt.rxbc_data.data, vendr_info->data, sizeof(*vendr_info)); data_cmd->tail.check_sum = ge_frm_checksum_calc((uint8_t *)data_cmd, sizeof(*data_cmd)-sizeof(ge_frm_tail_t)); /* report data info to MCU */ iot_proto_send_to_mainboard(ind_pkt); out: iot_pkt_free(pkt); return ERR_OK; } bool_t iot_proto_clr_flashinfo_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { IOT_ASSERT(CMD_LOCAL_DOWN_LINK == dir); ge_frame_clr_cust_flash_set_subfn25_t *set_cmd = (ge_frame_clr_cust_flash_set_subfn25_t *)data; uint32_t reason = 0; bool_t rpt2mcu = false; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; if (len != sizeof(ge_frame_clr_cust_flash_set_subfn25_t)) { reason = PROTO_REASON_LEN_MISSMATCH; goto out; } os_mem_set(p_flash->public.pub.local_mac, 0, IOT_MAC_ADDR_LEN); p_flash->public.pub.local_type = 0; os_mem_set(p_flash->public.pub.cco_mac, 0, IOT_MAC_ADDR_LEN); #if PLC_SUPPORT_CCO_ROLE os_mem_set(p_flash->public.pub.dev_tbl, 0, sizeof(proto_dev_t)*STA_DEV_MAX); p_flash->public.pub.dev_cnt = 0; #endif iot_proto_flashsave(p_flash); goto out; out: iot_cus_printf("[glpr]Clear flash info:reason=%d\n", reason); iot_proto_resp_cfm_frame(reason, dir, PROTO_CLR_CUST_FLASH_CMD, set_cmd->seq, NULL); return rpt2mcu; } void iot_proto_wl_save2flash(void) { #if PLC_SUPPORT_CCO_ROLE ge_app_pib_info_t *p_flash = &(prototask_contxt.flashinfo); proto_dev_t *p_table = prototask_contxt.dev_lst.dev; uint16_t i, dev_cnt; dev_cnt = prototask_contxt.dev_lst.valid_dev_cnt; for (i = 0; i < dev_cnt; i++) { /* Copy formal white list onto config from flash */ p_flash->public.pub.dev_tbl[i] = p_table[i]; } p_flash->public.pub.dev_cnt = i; /* Write flash. */ iot_proto_flashsave(p_flash); iot_cus_printf("[glpr]whitelist save to flash!\n"); #endif } /* Enable/disable white list in CVG level. action : 2 - disable; 3 - enable. need_ack_cfm : true - plctxrx will ack cfm; false - No ack cfm. */ void iot_proto_whitelist_en_disable(uint8_t action, bool_t need_ack_cfm) { ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; iot_pkt_t *p_pkt; plctxrx_cmd_whitelist_t *p_wlist; plctxrx_cmd_arg_t *p_arg; p_pkt = iot_pkt_alloc(sizeof(*p_wlist) + sizeof(*p_arg), IOT_GREE_APP_MID); IOT_ASSERT(p_pkt); iot_pkt_put(p_pkt, sizeof(*p_wlist)+sizeof(*p_arg)); p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt); p_arg->cid.cid = PLCTXRX_CID_WHITELIST; p_arg->cid.opcode = PLCTXRX_OP_CONFIG; p_arg->prio = 0; p_arg->need_ack = need_ack_cfm; p_arg->dlen = sizeof(*p_wlist); p_wlist = (plctxrx_cmd_whitelist_t *)p_arg->arg; p_wlist->action = action; p_wlist->listcnt = 0; /* save whitelist state to flash */ if (p_flash->public.pub.wl_state != (action == GE_PROTO_WL_ENABLE)) { p_flash->public.pub.wl_state = (action == GE_PROTO_WL_ENABLE); iot_proto_flashsave(p_flash); } iot_proto_cmd_send_to_plctxrx(p_pkt); } /* Load config from customor flash. */ uint32_t iot_proto_flashload(ge_app_pib_info_t *p_info) { #if (HW_PLATFORM == HW_PLATFORM_SIMU) (void)p_info; iot_mac_addr_cpy(prototask_contxt.local_dev.mac, g_ucMACAddress); #else uint8_t *rw = NULL; uint8_t temp_pt = MAX_PIB_TYPE; (void)iot_pib_get_app_section(&rw, &temp_pt, IOT_PIB_APP_GET_WRITE_SECTION); IOT_ASSERT(rw); BUILD_BUG_ON(sizeof(ge_app_pib_info_t) == sizeof(app_pib_rw_t)); #if PLC_SUPPORT_CCO_ROLE IOT_ASSERT(temp_pt == CCO_PIB_TYPE); #else IOT_ASSERT(temp_pt == STA_PIB_TYPE); #endif prototask_contxt.pib_rw = (app_pib_rw_t *)rw; os_mem_cpy(&prototask_contxt.flashinfo, prototask_contxt.pib_rw, sizeof(ge_app_pib_info_t)); #endif return ERR_OK; } /* To dump our config info on flash. */ void iot_proto_dumpflash(ge_app_pib_info_t* p_info) { iot_cus_printf("\nMagic1 : 0x%02x%02x%02x%02x.", p_info->magic1[0], p_info->magic1[1], p_info->magic1[2], p_info->magic1[3]); iot_cus_printf("\nLocal_dev:%d Mac: %02x-%02x-%02x-%02x-%02x-%02x.", p_info->public.pub.local_type, p_info->public.pub.local_mac[0], p_info->public.pub.local_mac[1], p_info->public.pub.local_mac[2], p_info->public.pub.local_mac[3], p_info->public.pub.local_mac[4], p_info->public.pub.local_mac[5]); iot_cus_printf("\ncco Mac: %02x-%02x-%02x-%02x-%02x-%02x.", p_info->public.pub.cco_mac[0], p_info->public.pub.cco_mac[1], p_info->public.pub.cco_mac[2], p_info->public.pub.cco_mac[3], p_info->public.pub.cco_mac[4], p_info->public.pub.cco_mac[5]); iot_cus_printf("\nbaudidx=%d-wl_state=%d.",p_info->public.pub.baudidx, p_info->public.pub.wl_state); #if PLC_SUPPORT_CCO_ROLE uint16_t i; proto_dev_t *p_dev; p_dev = p_info->public.pub.dev_tbl; for (i = 0; i < p_info->public.pub.dev_cnt; i++) { iot_cus_printf("\nDEV#%02d:", i); iot_cus_printf("\n IP:%d.", p_dev->ip); iot_cus_printf("\n Role:%d.", p_dev->dev_role); iot_cus_printf("\n MAC:%02x-%02x-%02x-%02x-%02x-%02x.", p_dev->mac[0], p_dev->mac[1], p_dev->mac[2], p_dev->mac[3], p_dev->mac[4], p_dev->mac[5]); p_dev++; } #endif iot_cus_printf("\nMagic2 : 0x%02x%02x%02x%02x.", p_info->magic2[0], p_info->magic2[1], p_info->magic2[2], p_info->magic2[3]); return; } /* Check the magic code to tell if our config damaged. */ uint32_t iot_proto_cust_flashinfo_check(ge_app_pib_info_t *p_info) { int32_t magic1, magic2; magic1 = (p_info->magic1[0] << 24) | (p_info->magic1[1] << 16) | (p_info->magic1[2] << 8) | p_info->magic1[3]; magic2 = (p_info->magic2[0] << 24) | (p_info->magic2[1] << 16) | (p_info->magic2[2] << 8) | p_info->magic2[3]; iot_cus_printf("[glpr]Magic = 0x%08x, 0x%08x!\n", magic1, magic2); if ((IOT_PROTO_CUST_FLASHINFO_MAGIC1 != magic1) ||(IOT_PROTO_CUST_FLASHINFO_MAGIC2 != magic2)) { return ERR_FAIL; } return ERR_OK; } /* Repair this config when it is damaged. */ void iot_proto_cust_flashinfo_repair(ge_app_pib_info_t *p_info) { p_info->magic1[0] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 24) & 0xFF; p_info->magic1[1] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 16) & 0xFF; p_info->magic1[2] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 8) & 0xFF; p_info->magic1[3] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1) & 0xFF; p_info->magic2[0] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 24) & 0xFF; p_info->magic2[1] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 16) & 0xFF; p_info->magic2[2] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 8) & 0xFF; p_info->magic2[3] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2) & 0xFF; return; } /* This will store config onto customor flash area. */ uint32_t iot_proto_flashsave(ge_app_pib_info_t *p_info) { #if (HW_PLATFORM == HW_PLATFORM_SIMU) (void)p_info; #else uint8_t ref; uint16_t ticket; // update info to pib iot_pib_acquire_app_commit_ref(&ref); os_mem_cpy(prototask_contxt.pib_rw, p_info, sizeof(*p_info)); iot_pib_release_app_commit_ref(&ref); iot_pib_app_commit(&ticket); #endif return ERR_OK; } /* upgrade pib info from old pib section, in case that pib info lost * after remote upgrade successfully */ void iot_proto_upgrade_app_pib_info(void) { #if HW_PLATFORM != HW_PLATFORM_SIMU ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; if (ERR_OK != iot_pib_upgrade_app_cfg()) { iot_cus_printf("%s: failed to upgrade app pib section\n", __FUNCTION__); } if (ERR_OK == iot_proto_flashload(p_flash)) { iot_proto_flashsave(p_flash); } else { iot_cus_printf("%s: failed to load app pib cfg\n", __FUNCTION__); } #endif return; } uint8_t uart_baud_find_index(uint32_t baudrate) { uint8_t idx; uint32_t uart_baud[] = PROTO_GE_UART_BAUD_VALUE; for(idx = 0; idx < PROTO_GE_UART_BAUD_IDX_MAX; idx++) { if(baudrate == uart_baud[idx]) { break; } } return idx; } /* check uart param */ bool_t iot_proto_uart_param_check(uint32_t baudrate, uint8_t parity, uint8_t data_bits, uint8_t stop_bits) { switch (baudrate) { case PROTO_GE_UART_BAUD_3000000: case PROTO_GE_UART_BAUD_256000: case PROTO_GE_UART_BAUD_115200: case PROTO_GE_UART_BAUD_19200: case PROTO_GE_UART_BAUD_9600: case PROTO_GE_UART_BAUD_4800: case PROTO_GE_UART_BAUD_2400: break; default: return false; } switch (parity) { case IOT_UART_PARITY_NONE: case IOT_UART_PARITY_ODD: case IOT_UART_PARITY_EVEN: case IOT_UART_PARITY_MARK: case IOT_UART_PARITY_SPACE: break; default: return false; } switch (data_bits) { case IOT_UART_DLEN_5_BITS: case IOT_UART_DLEN_6_BITS: case IOT_UART_DLEN_7_BITS: case IOT_UART_DLEN_8_BITS: break; default: return false; } switch (stop_bits) { case IOT_UART_STOP_1_BITS: case IOT_UART_STOP_1_5_BITS: case IOT_UART_STOP_2_BITS: break; default: return false; } return true; } /* load flash info into dev wl and pair tbl */ void iot_proto_flashinfo_init(void) { uint32_t uart_baud[] = PROTO_GE_UART_BAUD_VALUE; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; /* do flash used check */ BUILD_BUG_ON(sizeof(public_use_t) <= IOT_APP_PUBLIC_SIZE); BUILD_BUG_ON(sizeof(at_private_use_t) <= IOT_APP_AT_PRIVATE_SIZE); BUILD_BUG_ON(sizeof(proto_private_use_t) <= IOT_APP_PROTO_PRIVATE_SIZE); if (ERR_FAIL == iot_proto_flashload(p_flash) || ERR_FAIL == iot_proto_cust_flashinfo_check(p_flash)) { iot_cus_printf("[glpr][err]Cannot get custom flash info!!"); os_mem_set(p_flash, 0x0, sizeof(*p_flash)); /* enable whitelist as default state */ #if HW_PLATFORM == HW_PLATFORM_SIMU /* used the mac address defined in RTOSConfig.ini */ iot_mac_addr_cpy(p_flash->public.pub.local_mac, g_ucMACAddress); if (prototask_contxt.local_dev.nw_role != IOT_PLC_DEV_ROLE_CCO) { p_flash->public.pub.wl_state = 0; } else { p_flash->public.pub.wl_state = 1; } /* config uart baud to default index - 115200bit/s */ p_flash->public.pub.baudidx = 0; #else #if PLC_SUPPORT_STA_ROLE /* default disable whitelist for sta */ p_flash->public.pub.wl_state = 0; /* config uart param - 9600bit/s-EVEN-8-1 */ p_flash->public.pub.baudidx = 1; /* for solar mppt: config uart param - 115200bit/s-EVEN-8-1 */ if (CUS_BOARD_ID_SOLRMPPT_V1_0 == iot_board_get_board_id()) { p_flash->public.pub.baudidx = 0; } p_flash->public.pub.parity = IOT_UART_PARITY_EVEN; p_flash->public.pub.data = IOT_UART_DLEN_8_BITS; p_flash->public.pub.stop = IOT_UART_STOP_1_BITS; #else p_flash->public.pub.wl_state = 1; /* config uart param - 115200bit/s-NONE-8-1 */ p_flash->public.pub.baudidx = 0; p_flash->public.pub.parity = IOT_UART_PARITY_NONE; p_flash->public.pub.data = IOT_UART_DLEN_8_BITS; p_flash->public.pub.stop = IOT_UART_STOP_1_BITS; #endif #endif iot_proto_cust_flashinfo_repair(&(prototask_contxt.flashinfo)); iot_proto_flashsave(p_flash); } else { #if PLC_SUPPORT_CCO_ROLE uint16_t cnt; proto_dev_t *p_dev = prototask_contxt.dev_lst.dev_tmp; /* whitelist load */ p_flash->public.pub.dev_cnt = (STA_DEV_MAX >= p_flash->public.pub.dev_cnt) ? p_flash->public.pub.dev_cnt : 0; for (cnt = 0; cnt < p_flash->public.pub.dev_cnt; cnt++) { p_dev[cnt] = p_flash->public.pub.dev_tbl[cnt]; } prototask_contxt.dev_lst.valid_dev_tmp_cnt = p_flash->public.pub.dev_cnt; iot_proto_add_wl_tmp2formal(); #endif /* config uart param */ if (p_flash->public.pub.baudidx >= PROTO_GE_UART_BAUD_IDX_MAX) { p_flash->public.pub.baudidx = 0; } if (iot_proto_uart_param_check(uart_baud[p_flash->public.pub.baudidx], p_flash->public.pub.parity, p_flash->public.pub.data, p_flash->public.pub.stop) == false) { p_flash->public.pub.baudidx = 0; p_flash->public.pub.parity = DEF_UART_PARITY; p_flash->public.pub.data = IOT_UART_DLEN_8_BITS; p_flash->public.pub.stop = IOT_UART_STOP_1_BITS; iot_proto_flashsave(p_flash); } } /* config uart param */ iot_grapp_modify_uart_param(p_flash->public.pub.baudidx, p_flash->public.pub.parity, p_flash->public.pub.data, p_flash->public.pub.stop); /* dump flash info */ iot_proto_dumpflash(&(prototask_contxt.flashinfo)); if ((p_flash->public.pub.edge_start_tm < UART_MONITOR_START_MIN) || (p_flash->public.pub.edge_start_tm > UART_MONITOR_START_MAX)) { p_flash->public.pub.edge_start_tm = UART_MONITOR_START_TIMEOUT; } return; } #endif // IOT_GR_APP_ENABLE