/**************************************************************************** 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_cli_sg_api.h" #include "iot_board_api.h" #include "iot_plc_led_api.h" #include "iot_grapp.h" #include "iot_plctxrx.h" #include "iot_proto_common.h" #include "iot_proto_ge.h" #include "iot_gr_upgrade.h" #include "iot_pib_api.h" #include "iot_ntoh_api.h" #include "iot_adc_api.h" #include "iot_gpio_api.h" #include "iot_proto_dl645.h" #include "iot_proto_cctt.h" #include "iot_proto_modbus.h" #include "iot_edge_compute.h" #if IOT_GR_APP_ENABLE #if GE_CRC_ENABLE /* CRC table for the CRC-16. */ /* The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */ const uint16_t iot_crc16_tab[256] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 }; #endif enum proto_cmd_protocol_type_e { NO_FRAME, GE_FRAME, MODBUS_FRAME, DL645_FRAME, }; /* sta detected mac max count, interval 3 seconds */ #define STA_DETECTED_MAC_MAX_CNT (4) void iot_proto_wl_pt_remote_set_timeout (uint32_t type, uint32_t dir, uint8_t seq, uint8_t *dst_mac); uint8_t ge_bcast_addr[IOT_MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /****************************************************************************** *****************************function define ********************************* ******************************************************************************/ void iot_proto_task_post_msg(uint16_t msg_type, uint16_t msg_id, void* data, transmit_direction_e_t dir, uint8_t prio); static proto_savedmsg_node_t *iot_proto_msgnode_alloc(iot_mem_pool_t *pool); static uint32_t iot_proto_msgnode_free(iot_mem_pool_t *pool, proto_savedmsg_node_t *msgnode); static void iot_proto_savedmsg_list_push_backend(proto_msg_saved_list_t *list, list_node_t *node); static proto_savedmsg_node_t * iot_proto_savedmsg_list_pop_front(proto_msg_saved_list_t *list); static void iot_proto_saved_msg_handle(void); static uint16_t iot_proto_plc_data_group_frame(uint8_t *dst, uint8_t *src, uint16_t src_len); static void iot_proto_cus_app_msg_handle(iot_task_msg_t *msg); void iot_proto_handle_save_cus_app_info_to_pib(iot_pkt_t *data); static void post_monitor_start_timer(timer_id_t timer_id, void * arg); static void post_monitor_start_timer_msg_handler(void); /****************************************************************************** *****************************global variable define ************************** ******************************************************************************/ /* debug macro for whitelist and pairtable */ #define WHITELIST_PAIR_DEBUG 0 /* global buffer to hold uart input frame. */ mcu_data_handle_t mcu_data; /* buf, contain complete data, post to proto msg pool */ uint8_t ge_buf[MCU_DATA_RECV_MAX]; prototask_contxt_t prototask_contxt; /* msg pool for saved msg */ static iot_mem_pool_t *saved_msg_q; /* gathering buffer for sending to MCU */ uint8_t glb_ul_tmp_buf[UL_TMP_BUF_LEN]; /* record the length of the data received from plc */ uint16_t glb_ul_data_len = 0; /* function may gather the frames, up to 200 bytes */ #define IOT_PROTO_LOG_BUF_LEN 384 char proto_log_buf[IOT_PROTO_LOG_BUF_LEN]; /* uart0 t-put statistic infor */ uart_thpt_t uart_thpt; /* operable global gpio */ iot_ge_gpio_config_t iot_ge_gpio_g[IOT_GE_VALID_GPIO_MAX]; /* LEDC01 module operable gpio pin number limit */ uint8_t iot_ledc01_ge_gpio_valid[IOT_GE_LEDC01_VALID_GPIO_MAX] = { 10, 28, 36}; #define ARRAY_CNT(a) (sizeof(a) / sizeof((a)[0])) #if (HW_PLATFORM == HW_PLATFORM_SIMU) extern uint8_t ucIsClientMode; #endif #define PARSE_FRM_MAX_LEN (GE_FRM_MAX_LEN + GE_FRM_PLD_MAX_LEN) bool_t mac_addr_is_bcast_addr(uint8_t *mac) { if (iot_mac_addr_cmp(bcast_mac, mac)) { return true; } else { return false; } } bool_t mac_addr_is_valid_addr(uint8_t *mac) { uint8_t tmp_mac[IOT_MAC_ADDR_LEN] = { 0 }; if (iot_mac_addr_cmp(mac, tmp_mac)) { return false; } else { return true; } } bool_t mac_addr_in_flash_is_valid_addr(uint8_t *mac) { uint8_t all_zero_mac[IOT_MAC_ADDR_LEN] = { 0 }; if (iot_mac_addr_cmp(mac, all_zero_mac) || iot_mac_addr_cmp(mac, bcast_mac)) { return false; } else { return true; } } void iot_common_bin_dump(uint8_t *data, uint32_t dlen) { os_acquire_mutex(prototask_contxt.common_bin_dump_mutex); uint32_t i = 0; uint32_t offset = 0; offset = iot_sprintf(proto_log_buf, "dump pkt[len:%d]",dlen); for (i = 0; i < dlen; ++i) { offset += iot_sprintf(proto_log_buf + offset, "%02X ", data[i]); if (IOT_PROTO_LOG_BUF_LEN <= offset + 4) { break; } } proto_log_buf[offset] = 0; iot_cus_printf("%s\n", proto_log_buf); os_release_mutex(prototask_contxt.common_bin_dump_mutex); return; } /****************************************************************************** **********************************function realize***************************** ******************************************************************************/ void iot_proto_fill_txinfo(protpkt_tx_info_t* txinfo, bool_t need_ack, txrx_type_e send_type, uint8_t retry_cnt, uint16_t retry_intvl, uint16_t sta_cnt, uint8_t *src_mac, uint8_t *dst_mac) { uint8_t i; txinfo->send_type = send_type; txinfo->src_module = IOT_PLCTXRX_MSDU_SRCMODULE_PROTO; /* initilize mac */ os_mem_set(txinfo->src_mac, 0, IOT_MAC_ADDR_LEN); os_mem_set(txinfo->org_mac, 0, IOT_MAC_ADDR_LEN); os_mem_set(txinfo->dst_mac, 0, IOT_MAC_ADDR_LEN); /* why zero, because copy only 3 bytes */ os_mem_cpy(txinfo->src_mac, src_mac, IOT_MAC_ADDR_LEN); os_mem_cpy(txinfo->org_mac, src_mac, IOT_MAC_ADDR_LEN); txinfo->sta_cnt = sta_cnt; txinfo->retry_cnt = retry_cnt; txinfo->retry_intvl = retry_intvl; txinfo->need_ack = need_ack; if (dst_mac) { for ( i = 0; i < txinfo->sta_cnt; i++) { iot_mac_addr_cpy(txinfo->dst_mac + i * IOT_MAC_ADDR_LEN, dst_mac + i * IOT_MAC_ADDR_LEN); } } else { iot_mac_addr_cpy(txinfo->dst_mac, ge_bcast_addr); } } proto_cmd_hdl_state_t* iot_proto_cmd_handle_state_get() { return &prototask_contxt.sm; } void iot_proto_cmd_handle_state_init() { os_mem_set(&prototask_contxt.sm, 0, sizeof(proto_cmd_hdl_state_t)); } void iot_proto_gpio_tab_init() { uint8_t board_id = iot_board_get_board_id(); if ((CUS_BOARD_ID_LEDCSTA01 == board_id) || (CUS_BOARD_ID_LEDCCCO01 == board_id)) { for(int i = 0; i < IOT_GE_LEDC01_VALID_GPIO_MAX; i++) { iot_ge_gpio_g[i].gpio_num = iot_ledc01_ge_gpio_valid[i]; iot_ge_gpio_g[i].dir_mode = IOT_GE_GPIO_DIR_INPUT; iot_ge_gpio_g[i].pull_mode = IOT_GE_GPIO_PULL_NONE; iot_ge_gpio_g[i].gpio_state = IOT_GE_GPIO_CLOSE; iot_gpio_open_as_input(iot_ge_gpio_g[i].gpio_num); iot_gpio_set_pull_mode(iot_ge_gpio_g[i].gpio_num, GPIO_PULL_NONE); } } #if PLC_SUPPORT_STA_ROLE if (CUS_BOARD_ID_LEDC_V3_0 == board_id && iot_hwver_is_ledc_v3_0_jy()) { iot_gpio_open_as_output(HPLC_3P0_JY_EN_OUT3V3_PIN); iot_gpio_open_as_output(HPLC_3P0_JY_EN_OUT12V_PIN); iot_gpio_open_as_input(HPLC_3P0_JY_MONITOR_PIN); iot_gpio_set_pull_mode(HPLC_3P0_JY_MONITOR_PIN, GPIO_PULL_UP); iot_gpio_open_as_output(HPLC_3P0_JY_HW_WDG_PIN); prototask_contxt.hw_watchdog_en = 1; iot_adc_init(); } #endif return; } /* To clear command state for temporary white list & pair table operation. */ void iot_proto_whitelist_state_init(void) { os_mem_set(prototask_contxt.dev_lst.dev_tmp, 0, sizeof(proto_dev_t) * STA_DEV_MAX); prototask_contxt.dev_lst.valid_dev_tmp_cnt = 0; prototask_contxt.dev_lst.wl_ccofrag_cnt = 0; } /* Timout handler for setting white list or pair table. */ void iot_proto_wl_pt_remote_set_timeout(uint32_t state, uint32_t dir, uint8_t seq, uint8_t *dst_mac) { uint32_t tmp_dir = 0; iot_cus_printf("[glpr]" \ "wlist ptable rmt %s timeout.\n", "set"); /* To switch async sm dir to sync dir to send response */ /* sm->dir means hope response from */ if (CMD_LOCAL_UP_LINK == dir || CMD_REMOTE_UP_LINK == dir) { /* tmp dir means org cmd from local down. just for unit cfm func */ tmp_dir = CMD_LOCAL_DOWN_LINK; } else if (CMD_LOCAL_DOWN_LINK == dir || CMD_REMOTE_DOWN_LINK == dir) { /* means send to remote by plc */ tmp_dir = CMD_REMOTE_UP_LINK; } if (PROTO_CMD_WAIT_WHITE_LIST_SET == state) { /* Timeout, so send command conform frame to uplayer. */ iot_proto_resp_cfm_frame(PROTO_REASON_TIME_OUT, tmp_dir, PROTO_OP_WHITELIST_SET_CMD, seq, dst_mac); } return; } void iot_proto_wait_cmd_cfm_timeout(proto_cmd_hdl_state_t *sm) { uint32_t tmp_dir = 0; switch (sm->cur_subfn) { case PROTO_OP_WHITELIST_SET_CMD: case PROTO_CCO_START_GROUP_NET_CMD: case PROTO_CCO_END_GROUP_NET_CMD: case PROTO_REBOOT_STA_CMD: case PROTO_GE_GPIO_SET_CMD: case PROTO_GE_GPIO_CONFIG_CMD: case PROTO_GE_GPIO_QUERY_CMD: { tmp_dir = CMD_LOCAL_DOWN_LINK; iot_proto_resp_cfm_frame(PROTO_REASON_TIME_OUT, tmp_dir, sm->cur_subfn, sm->seq, sm->dev.mac); break; } default : iot_cus_printf("[glpr][err]Wait cmd cfm TO,subfn=%d!\n", sm->cur_subfn); IOT_ASSERT(0); break; } } void iot_proto_mainboard_data_pend(iot_pkt_t *data) { if (prototask_contxt.cache_pkt != NULL) { iot_pkt_free(prototask_contxt.cache_pkt); } iot_cus_printf("cache pkt for send uart\n"); prototask_contxt.cache_pkt = data; } void iot_proto_resume_pkt_2_mainboard(void) { if (prototask_contxt.cache_pkt != NULL) { iot_proto_send_to_mainboard(prototask_contxt.cache_pkt); } prototask_contxt.cache_pkt = NULL; } /* This will send a iot_pkt_t of data to UART connected to mainboard. */ void iot_proto_send_to_mainboard(iot_pkt_t *p_pkt) { iot_cus_printf("[glpr]iot_proto_send_to_mainboard:\n"); iot_common_bin_dump(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt)); uart_thpt.send_len += iot_pkt_data_len(p_pkt); if (prototask_contxt.proto_sendto_mainboard_fn) { prototask_contxt.proto_sendto_mainboard_fn(p_pkt); } else { iot_pkt_free(p_pkt); } return; } void iot_proto_cmd_send_to_plctxrx(iot_pkt_t *p_pkt) { if (prototask_contxt.gree_cmd_send_cb) { prototask_contxt.gree_cmd_send_cb(p_pkt); } else { iot_pkt_free(p_pkt); } return; } void iot_proto_resp_cfm_frame(uint32_t resp, uint32_t dir, uint32_t cmd, uint8_t seq, uint8_t *dst_mac) { ge_frame_cmd_cfm_set_subfn20_t *p_cfm; iot_pkt_t *p_pkt; protpkt_tx_info_t info = { 0 }; iot_cus_printf("\n[glpr]cfm frame resp=%d, " \ "dir=%d, cmd=%d\n", resp, dir, cmd); p_pkt = iot_pkt_alloc(sizeof(*p_cfm), IOT_GREE_APP_MID); if (!p_pkt) { iot_cus_printf("[glpr][err]No Mem!\n"); return; } p_cfm = (ge_frame_cmd_cfm_set_subfn20_t *)iot_pkt_data(p_pkt); iot_proto_cfm_cmd_group(iot_pkt_put(p_pkt, sizeof(*p_cfm)), (uint8_t)cmd, (PLCTXRX_RESP_OK == resp?0:1), (uint8_t)resp, seq); if (CMD_LOCAL_DOWN_LINK == dir) { iot_proto_send_to_mainboard(p_pkt); } else if (CMD_REMOTE_UP_LINK == dir) { iot_proto_fill_txinfo(&info, 1, PLCTXRX_UNICAST, 2, 200, 1, prototask_contxt.local_dev.mac, dst_mac); iot_proto_remote_cmd_send_to_plctxrx ((uint8_t *)p_cfm, sizeof(*p_cfm), &info); iot_pkt_free(p_pkt); } else { iot_cus_printf("[glpr]Invalid dir!\n"); iot_pkt_free(p_pkt); } return; } void iot_proto_boot_ready_ind(uint8_t *local_mac) { iot_pkt_t *rpt2mcu_pkt = NULL; ge_frame_boot_ready_id_set_subfn24_t *boot_rdy_ind; rpt2mcu_pkt = iot_pkt_alloc(sizeof(*boot_rdy_ind), IOT_GREE_APP_MID); if (rpt2mcu_pkt == NULL) { return; } boot_rdy_ind = (ge_frame_boot_ready_id_set_subfn24_t *)iot_pkt_data(rpt2mcu_pkt); iot_pkt_put(rpt2mcu_pkt, sizeof(*boot_rdy_ind)); os_mem_set(boot_rdy_ind, 0, sizeof(*boot_rdy_ind)); EXT_FN_FRM_PREPARE(boot_rdy_ind, PROTO_GE_PLC_SET_CMD, PROTO_BOOT_READY_ID_CMD); iot_mac_addr_cpy(boot_rdy_ind->local_mac, local_mac); iot_proto_get_cco_mac(boot_rdy_ind->cco_mac); boot_rdy_ind->seq = prototask_contxt.local_dev.ind_seq; boot_rdy_ind->tail.check_sum = ge_frm_checksum_calc((uint8_t *)boot_rdy_ind, sizeof(*boot_rdy_ind) - sizeof(ge_frm_tail_t)); iot_proto_send_to_mainboard(rpt2mcu_pkt); } static void iot_proto_save_cmd(proto_msg_saved_list_t *list, uint8_t *data, uint16_t len, plctxrx_rx_data_info_t *rx_info, transmit_direction_e_t dir, uint16_t msg_id, uint16_t msg_type) { proto_savedmsg_node_t *msg_node = iot_proto_msgnode_alloc(saved_msg_q); iot_pkt_t *cmd_data; uint8_t rxinfo_len = 0; if (!msg_node) { iot_cus_printf("[glpr][err]save cmd:msg pool is empty!\n"); return; } if (rx_info) { /* add rx_info and remove preamble,checksum and tail code */ rxinfo_len = sizeof(*rx_info); len -= (GE_FRM_PREAMBLE_FIELD_LEN + GE_FRM_CHECKSUM_FIELD_LEN + GE_FRM_TAIL_FILED_LEN); data += GE_FRM_PREAMBLE_FIELD_LEN; } cmd_data = iot_pkt_alloc(len + rxinfo_len, IOT_GREE_APP_MID); IOT_ASSERT(cmd_data); if (rxinfo_len > 0) { os_mem_cpy(iot_pkt_data(cmd_data), rx_info, sizeof(*rx_info)); } os_mem_cpy(iot_pkt_data(cmd_data) + rxinfo_len, data, len); iot_pkt_put(cmd_data, len + rxinfo_len); msg_node->data = cmd_data; msg_node->dir = dir; msg_node->msg_id = msg_id; msg_node->msg_type = msg_type; iot_cus_printf("[glpr]save cmd:msg node=0x%x, node=0x%x\n", msg_node, &msg_node->node); iot_proto_savedmsg_list_push_backend(list, &msg_node->node); } /* Return the index of mac in this dev_tb if found. */ int32_t iot_proto_check_mac_exists(uint8_t *mac, proto_dev_t *dev_tb, uint16_t valid_cnt) { uint16_t i; IOT_ASSERT(mac && dev_tb); for (i = 0; i < valid_cnt; i++) { if (iot_mac_addr_cmp(dev_tb[i].mac, mac)) return i; } return -1; } /* Return the index of new_wl in this dev_tb if aaded. */ void iot_proto_add_wl_to_tmp(proto_dev_t *dev) { proto_dev_t free_dev = { 0 }; proto_dev_list_t *dev_list = &prototask_contxt.dev_lst; uint16_t cnt; IOT_ASSERT(dev); /* check if temporary list of whitelist is full */ if (dev_list->valid_dev_tmp_cnt >= STA_DEV_MAX) return; /* Get a free place to store */ for (cnt = 0; cnt < STA_DEV_MAX; cnt++) { if (iot_mac_addr_cmp(free_dev.mac, dev_list->dev_tmp[cnt].mac)) { os_mem_cpy(&dev_list->dev_tmp[cnt], dev, sizeof(proto_dev_t)); break; } } /* device added */ if (cnt < STA_DEV_MAX) { dev_list->valid_dev_tmp_cnt++; } } static void iot_proto_reboot_delay_timeout_timer(timer_id_t timer_id, void * arg) { (void)arg; (void)timer_id; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_REBOOT_STA_TIMEOUT, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } static void iot_proto_reboot_delay_timeout_handler(void) { uint8_t reason = prototask_contxt.reboot_reason; switch (reason) { case REBOOT_ASSERT: { /* creat assert */ iot_cus_printf("[glpr]recv assert cmd\n"); IOT_ASSERT(0); break; } case REBOOT_WRITE_ZERO_ADDR: { /* recv test cmd to write 0 address */ iot_cus_printf("[glpr]test write zero address\n"); *((int *)(NULL)) = 0x7e7e7e7e; break; } case REBOOT_NORMAL: default: iot_cus_printf("[glpr] reboot cmd excuted\n"); iot_system_restart(IOT_SYS_RST_REASON_APP_REQ); break; } } static void iot_proto_sta_leave_delay_timeout_timer(timer_id_t timer_id, void * arg) { (void)arg; (void)timer_id; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_STA_LEAVE_TIMEOUT, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } static void iot_proto_sta_leave_delay_timeout_handler(void) { proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); plctxrx_cmd_arg_t *p_arg; plctxrx_cmd_leave_net_t *p_leave; iot_pkt_t *p_pkt; uint32_t pkt_len; pkt_len = sizeof(*p_arg) + sizeof(*p_leave) + IOT_MAC_ADDR_LEN; if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID))) { iot_cus_printf("[glpr][err]No Mem!\n"); } p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len); p_leave = (plctxrx_cmd_leave_net_t *)p_arg->arg; p_arg->cid.cid = PLCTXRX_CID_LEAVE_NETWORK; p_arg->cid.opcode = PLCTXRX_OP_CONFIG; p_arg->prio = 0; p_arg->need_ack = true; p_arg->dlen = sizeof(*p_leave); p_leave->cnt = 1; iot_mac_addr_cpy(p_leave->mac[0], prototask_contxt.cco_dev.mac); /* set sm state */ sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->dir = CMD_LOCAL_UP_LINK; sm->seq = 0;//p_frame->seq; sm->cur_subfn = PROTO_LEAVE_NW_SET_CMD; iot_cus_printf("[glpr]sta leaving network\n"); iot_proto_cmd_send_to_plctxrx(p_pkt); } static void iot_proto_statistic_timer(timer_id_t timer_id, void * arg) { (void)arg; (void)timer_id; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_STATISTIC, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } static void iot_proto_statistic_infor_update(void) { proto_dev_list_t *dev_lst = &prototask_contxt.dev_lst; prototask_contxt.statistic_cnt++; if (prototask_contxt.statistic_cnt % PROTO_STASTIC_UPDATE_INTVL_CNT == 0) { uart_thpt.recv_rate = (uart_thpt.recv_len * 2) / PROTO_STASTIC_UPDATE_INTVL_CNT; uart_thpt.send_rate = (uart_thpt.send_len * 2) / PROTO_STASTIC_UPDATE_INTVL_CNT; uart_thpt.recv_len = 0; uart_thpt.send_len = 0; prototask_contxt.statistic_cnt = 0; iot_cus_printf("[glpr]software version:%d.%d.%d.%d\n", iot_version_major(), iot_version_minor(), iot_version_micro(), iot_version_build()); } /* change cco network done state */ if (IOT_PLC_DEV_ROLE_CCO == prototask_contxt.local_dev.nw_role) { if (prototask_contxt.flashinfo.public.pub.wl_state && (dev_lst->online_dev_cnt > 0) && (dev_lst->online_dev_cnt == dev_lst->valid_dev_cnt)) { if (prototask_contxt.cco_net_done == 0) { prototask_contxt.cco_net_done = 1; iot_plc_led_request(IOT_PLC_LED_NET_FORMAT_DONE); } } else { if (prototask_contxt.cco_net_done == 1) { prototask_contxt.cco_net_done = 0; iot_plc_led_request(IOT_PLC_LED_DIS_ASSOCIATED); } } } if (prototask_contxt.statistic_cnt % PROTO_TIMER_GY_FEED_WDG_INTVL_CNT == 0) { if ((IOT_PLC_DEV_ROLE_STA == prototask_contxt.local_dev.nw_role) && (CUS_BOARD_ID_LEDC_V3_0 == iot_board_get_board_id()) && iot_hwver_is_ledc_v3_0_jy() && prototask_contxt.hw_watchdog_en) { iot_gpio_value_set(HPLC_3P0_JY_HW_WDG_PIN, prototask_contxt.hw_watchdog_out); prototask_contxt.hw_watchdog_out = !prototask_contxt.hw_watchdog_out; } } } /** * @brief iot_proto_check_trial_run_pass(): do trial run check, if trial run * fail and not join the network, need roll back software, * only sta need to do this check. */ static void iot_proto_check_trial_run_pass(void) { ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; iot_cus_printf("[glpr]check trial_run_pass = %d\n", p_flash->public.pub.trial_run_pass); if (prototask_contxt.local_dev.nw_role == IOT_PLC_DEV_ROLE_STA && p_flash->public.pub.trial_run_pass == false) { /* not join netwrok will switch boot part */ if (prototask_contxt.local_dev.dev_ready) { p_flash->public.pub.trial_run_pass = true; iot_cus_printf("[glpr]change trial_run_pass to true\n"); iot_proto_flashsave(p_flash); } else { iot_cus_printf("[glpr]switch boot part because trial run fail\n"); iot_switch_boot_part(); iot_system_restart(IOT_SYS_RST_REASON_APP_REQ); } } } static void iot_proto_statistic_timer_timeout_handler(void) { iot_proto_statistic_infor_update(); } static void iot_proto_brd_data_rpt_window_timer(timer_id_t timer_id, void * arg) { (void)arg; (void)timer_id; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_BRD_PKT_WINDOW_RPT, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } #if IOT_GE_PAGING_ENABLE static void iot_proto_paging_timer(timer_id_t timer_id, void * arg) { (void)arg; (void)timer_id; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_PAGING_TIMEOUT, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } #endif static void iot_proto_trial_run_check_timer(timer_id_t timer_id, void * arg) { (void)arg; (void)timer_id; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_TRIAL_RUN_CHECK, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } #if PLC_SUPPORT_STA_ROLE static void iot_proto_645_local_mode_timer(timer_id_t timer_id, void * arg) { (void)arg; (void)timer_id; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_645_LOCAL_MODE, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } #endif static void iot_proto_brd_data_rpt_window_timer_handler(void) { uint8_t *ptr = NULL; iot_pkt_t *pkt =NULL; uint16_t len = prototask_contxt.rpt_cache.data_len; if (len != 0) { pkt = iot_pkt_alloc(len, IOT_GREE_APP_MID); if (pkt == NULL) { iot_cus_printf("[grpr]NO memery, sending cached pkt failed\n"); return; } ptr = iot_pkt_data(pkt); iot_pkt_put(pkt, len); os_mem_cpy(ptr, prototask_contxt.rpt_cache.data, len); iot_proto_send_to_mainboard(pkt); os_mem_set(&prototask_contxt.rpt_cache, 0, sizeof(proto_rpt_cache_t)); } } #if PLC_SUPPORT_CCO_ROLE static void iot_proto_sta_paging_timer_handler(void) { iot_proto_sta_paging_mac(); } #else static void iot_proto_sta_paging_timer_handler(void) { /* for sta do nothing*/ } #endif void iot_proto_add_wl_tmp2formal(void) { uint32_t i, j; proto_dev_t *p_tmp_table, *p_formal_table; uint16_t tmp_cnt, valid_cnt; proto_dev_t free_dev = { 0 }; proto_dev_list_t *p_dev_list = &prototask_contxt.dev_lst; tmp_cnt = p_dev_list->valid_dev_tmp_cnt; valid_cnt = p_dev_list->valid_dev_cnt; p_tmp_table = p_dev_list->dev_tmp; p_formal_table = p_dev_list->dev; if ((tmp_cnt + valid_cnt) > STA_DEV_MAX) tmp_cnt = STA_DEV_MAX - valid_cnt; p_dev_list->valid_dev_cnt = tmp_cnt + valid_cnt; for (i = 0, j = 0; (i < STA_DEV_MAX) && (j < tmp_cnt); i++) { if (iot_mac_addr_cmp(free_dev.mac, p_formal_table[i].mac)) { p_formal_table[i] = p_tmp_table[j++]; } } return; } void iot_proto_del_wl_from_formal(void) { uint32_t i, j; proto_dev_t *p_tmp_table, *p_formal_table; uint16_t tmp_cnt, valid_cnt; proto_dev_t free_dev = { 0 }; tmp_cnt = prototask_contxt.dev_lst.valid_dev_tmp_cnt; valid_cnt = prototask_contxt.dev_lst.valid_dev_cnt; p_tmp_table = prototask_contxt.dev_lst.dev_tmp; p_formal_table = prototask_contxt.dev_lst.dev; if (tmp_cnt > valid_cnt) { iot_cus_printf("[gepr]tmp cnt=%d > valid cnt=%d\n", tmp_cnt, valid_cnt); IOT_ASSERT(0); return; } prototask_contxt.dev_lst.valid_dev_cnt -= tmp_cnt; /* delete device that need to be deleted in valid pair list */ for (i = 0; i < tmp_cnt; i++) { for (j = 0; j < STA_DEV_MAX; j++) { if (iot_mac_addr_cmp(p_formal_table[j].mac, p_tmp_table[i].mac)) { os_mem_set(&p_formal_table[j], 0, sizeof(proto_dev_t)); if (prototask_contxt.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 */ prototask_contxt.dev_lst.online_flag[j] = false; } break; } } } /* clear temporary source buffer */ os_mem_set(p_tmp_table, 0, sizeof(proto_dev_t) * STA_DEV_MAX); /* re-org formal tbl. move empty, cached in tmp */ for (i = 0, j = 0; i < STA_DEV_MAX && j < STA_DEV_MAX; i++) { /** * if device in dest table is not a free device * then copy it to source tmporary buffer one by one. */ if (!iot_mac_addr_cmp(free_dev.mac, p_formal_table[i].mac)) { p_tmp_table[j] = p_formal_table[i]; j++; } } /* make the result back to normal tbl */ os_mem_cpy(p_formal_table, p_tmp_table, sizeof(proto_dev_t) * STA_DEV_MAX); return; } /* Add/Delete white list to/from CVG level. action : 0 - delete; 1 - add. need_ack_cfm : true - plctxrx will ack cfm; false - No ack cfm. */ void iot_proto_whitelist_add_remove(uint8_t action, uint8_t *mac, bool_t need_ack_cfm) { uint16_t cnt, frag_cnt, i = 0, j = 0; iot_pkt_t *p_pkt; plctxrx_cmd_whitelist_t *p_wlist; plctxrx_cmd_arg_t *p_arg; uint16_t loop_cnt = 0; uint16_t index = 0; /* one mac op or full table */ if (mac) { cnt = 1; } else { cnt = prototask_contxt.dev_lst.valid_dev_tmp_cnt; if (0 == cnt) return; } loop_cnt = (cnt <= PROTO_SET_CVG_WL_FRAG_CNT)? 1:(cnt/PROTO_SET_CVG_WL_FRAG_CNT + (((cnt%PROTO_SET_CVG_WL_FRAG_CNT) == 0)?0:1)); iot_cus_printf("[glpr]loop_cnt=%d,total_cnt=%d!\n", loop_cnt, prototask_contxt.dev_lst.valid_dev_tmp_cnt); for (i = 1; i <= loop_cnt; i++) { if (i*PROTO_SET_CVG_WL_FRAG_CNT > cnt) { frag_cnt = cnt - (i - 1)*PROTO_SET_CVG_WL_FRAG_CNT; } else { frag_cnt = PROTO_SET_CVG_WL_FRAG_CNT; } p_pkt = iot_pkt_alloc(sizeof(*p_wlist) + sizeof(*p_arg) + frag_cnt * IOT_MAC_ADDR_LEN, IOT_GREE_APP_MID); if (!p_pkt) { iot_cus_printf("[glpr][err]No Mem!\n"); return; } p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, sizeof(*p_wlist) + sizeof(*p_arg) + frag_cnt * IOT_MAC_ADDR_LEN); p_arg->cid.cid = PLCTXRX_CID_WHITELIST; p_arg->cid.opcode = PLCTXRX_OP_CONFIG; p_arg->prio = 0; /* if proto layer need a confirm from plctxrx, * then we make the last packet to response * confirm cmd. */ if (i + 1 > loop_cnt && true == need_ack_cfm) { p_arg->need_ack = need_ack_cfm; } else { p_arg->need_ack = false; } p_arg->dlen = sizeof(*p_wlist) + frag_cnt * IOT_MAC_ADDR_LEN; p_wlist = (plctxrx_cmd_whitelist_t *)p_arg->arg; /* TODO need refine magic num */ p_wlist->action = action; for (j = 0; j < frag_cnt; j++) { index = (i - 1) * PROTO_SET_CVG_WL_FRAG_CNT + j; if (mac) { iot_mac_addr_cpy(p_wlist->maclist[j], mac); } else { iot_mac_addr_cpy(p_wlist->maclist[j], prototask_contxt.dev_lst.dev_tmp[index].mac); } } p_wlist->listcnt = frag_cnt; iot_proto_cmd_send_to_plctxrx(p_pkt); } return; } /* Clear white list from CVG layer. need_ack_cfm : true - plctxrx will ack cfm; false - No ack cfm. */ void iot_proto_whitelist_remove_all(bool_t need_ack_cfm) { 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 = GE_PROTO_ACTION_DEL_ALL; p_wlist->listcnt = 0; iot_proto_cmd_send_to_plctxrx(p_pkt); } /* This function will forword these frames that SET/QUERY white list. */ bool_t iot_proto_wl_or_pt_remote_set_or_query_to_cco (uint8_t *data, uint16_t len, transmit_direction_e_t dir, uint8_t wait_type) { (void)dir; uint32_t cur_index = 0, total_index = 0; protpkt_tx_info_t info = { 0 }; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); uint8_t wait_resp = 0; if (PROTO_CMD_WAIT_RMT_WHITELIST_CFM == wait_type) { iot_cus_printf("[glpr]set whitelist to CCO.\n"); wait_resp = PROTO_CMD_WAIT_CMD_CFM; /* AA AA 0B FE 05 ACTION 00 SEQ TOTAL_L TOTAL_H CUR_L CUR_H MAC0~5 SUM FF */ cur_index = 10; total_index = 8; } else if (PROTO_CMD_WAIT_RMT_WHITELIST_RESP == wait_type) { iot_cus_printf("[glpr]query whitelist from CCO.\n"); wait_resp = PROTO_CMD_WAIT_RMT_WHITELIST_RESP; } iot_proto_fill_txinfo(&info, 1, PLCTXRX_UNICAST, 2, 200, 1, prototask_contxt.local_dev.mac, prototask_contxt.cco_dev.mac); if (PROTO_CMD_WAIT_RMT_WHITELIST_RESP == wait_resp) { /* The 1st frame to start waiting resp tmr. */ sm->state = wait_resp; sm->dir = CMD_REMOTE_UP_LINK; /* CFM up to mcu */ } else { /* The last frame to switch waiting event as CFM. */ if ((data[cur_index] == data[total_index]) && (data[cur_index + 1] == data[total_index + 1])) { sm->state = wait_resp; sm->dir = CMD_REMOTE_UP_LINK; /* CFM up to mcu */ } } iot_proto_remote_cmd_send_to_plctxrx(data, len, &info); return 0; } #if ENABLE_GE_DATA_SEND_TO_BEACON void iot_proto_vendor_info_set(uint8_t *p_passd, bool_t need_ack, uint8_t net_start_flag) { (void)p_passd; (void)need_ack; (void)net_start_flag; } #endif void iot_proto_set_tx_power(uint8_t tx_power, uint8_t need_ack) { iot_pkt_t *cmd_pkt; plctxrx_cmd_arg_t cmd = { 0 }; plctxrx_cmd_tx_pwr_t tx_pwr; cmd.cid.cid = PLCTXRX_CID_TX_PWR; cmd.cid.opcode = PLCTXRX_OP_CONFIG; cmd.prio = 0; cmd.need_ack = need_ack; cmd.dlen = sizeof(plctxrx_cmd_tx_pwr_t); /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(sizeof(plctxrx_cmd_arg_t) + cmd.dlen, IOT_GREE_APP_MID); IOT_ASSERT(cmd_pkt); tx_pwr.tx_pwr = tx_power; 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), &tx_pwr, cmd.dlen); /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); } void iot_proto_set_mac(uint8_t *mac, uint8_t dev_type, uint8_t need_ack) { plctxrx_cmd_arg_t *plctxrx_cmd; plctxrx_handle_mac_t *hd_mac; iot_pkt_t *cmd_pkt = NULL; uint16_t data_len = sizeof(*plctxrx_cmd) + sizeof(*hd_mac); ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; /* alloc packet for sending cmd */ cmd_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID); if (cmd_pkt == NULL) { return; } prototask_contxt.macaddr_set = 1; iot_mac_addr_cpy(prototask_contxt.local_dev.mac, mac); plctxrx_cmd = (plctxrx_cmd_arg_t*)iot_pkt_put(cmd_pkt, data_len); plctxrx_cmd->cid.cid = PLCTXRX_CID_MAC; plctxrx_cmd->cid.opcode = PLCTXRX_OP_CONFIG; plctxrx_cmd->prio = 0; plctxrx_cmd->need_ack = need_ack; plctxrx_cmd->dlen = sizeof(plctxrx_handle_mac_t); hd_mac = (plctxrx_handle_mac_t*)plctxrx_cmd->arg; if (dev_type) { hd_mac->dev_type = dev_type; } else { #if PLC_SUPPORT_CCO_ROLE hd_mac->dev_type = IOT_PLC_DEV_TYPE_CONCENTRATOR; #else hd_mac->dev_type = IOT_PLC_DEV_TYPE_POWER_METER; #endif } iot_mac_addr_cpy(hd_mac->mac, mac); iot_cus_printf("[glpr]set mac addr downto plctxrx!\n"); /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); /* 不需要回复ack且mac地址和存储地址不一样时需要存储flash */ if (!need_ack) { iot_proto_cmd_handle_state_init(); if (!iot_mac_addr_cmp(p_flash->public.pub.local_mac, mac)) { /* save new mac */ iot_mac_addr_cpy(p_flash->public.pub.local_mac, mac); iot_proto_flashsave(p_flash); } } } /* set flash mac or oem mac */ void iot_proto_set_local_mac(void) { uint8_t mac[IOT_MAC_ADDR_LEN] = { 0 }; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; if (iot_mac_addr_valid(p_flash->public.pub.local_mac)) { /* set saved flash mac */ iot_mac_addr_cpy(mac, p_flash->public.pub.local_mac); } else { /* use oem mac */ iot_oem_get_module_mac(mac); } iot_proto_set_mac(mac, 0, false); /* report boot ready */ iot_proto_boot_ready_ind(mac); } #if IOT_PSRAM_ENABLE static bool_t iot_proto_sw_uart_mode_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu =false; uint8_t reason = PROTO_REASON_OK; uint8_t uart_mode = 0; iot_pkt_t *pkt; ge_frame_cmd_cfm_set_subfn20_t *cfm_cmd; ge_frame_sw_uart_mode_set_subfn27_t *set_cmd = (ge_frame_sw_uart_mode_set_subfn27_t *)data; iot_oem_base_cfg_t *oem_base_cfg; /* check param */ if (len != sizeof(*set_cmd)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (uart_mode == GR_AT_OP_MODE) { reason = PROTO_REASON_DUP_SETTING; } iot_cus_printf("[glpr]iot_proto_sw_uart_mode_handler\n"); if (PROTO_REASON_OK == reason) { /* save uart mnode to oem */ iot_oem_get_base_cfg(&oem_base_cfg); oem_base_cfg->iotapp_mode = GR_AT_OP_MODE; if (ERR_OK != iot_oem_set_base_cfg(oem_base_cfg)) { iot_cus_printf("[glpr]set oem cfg uart mode error\n"); reason = PROTO_REASON_SWITCH_UART_MODE_ERR; } else{ iot_cus_printf("[glpr]system will reboot after 3 seconds\n"); os_start_timer(prototask_contxt.reboot_tmr, PROTO_TMR_SW_UART_MODE_DELAY_INTVL); } } /* 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; } #else static bool_t iot_proto_sw_uart_mode_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; (void)dir; bool_t rpt2mcu =false; iot_pkt_t *pkt; ge_frame_cmd_cfm_set_subfn20_t *cfm_cmd; ge_frame_sw_uart_mode_set_subfn27_t *set_cmd = (ge_frame_sw_uart_mode_set_subfn27_t *)data; iot_cus_printf("[glpr][err]not support switch to GE mode\n"); /* 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 = PROTO_REASON_NOT_SUPPORT; cfm_cmd->result = 1; 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; } #endif static bool_t iot_proto_set_band_id_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; plctxrx_cmd_arg_t cmd = { 0 }; uint8_t role = prototask_contxt.local_dev.nw_role; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); ge_frame_band_id_set_subfn28_t *set_cmd = (ge_frame_band_id_set_subfn28_t *)data; plctxrx_cmd_band_info_t band_info; /* check param */ if (len != sizeof(*set_cmd)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if (role != IOT_PLC_DEV_ROLE_CCO) { reason = PROTO_REASON_NO_AUTHORITY; } iot_cus_printf("[glpr]iot_proto_set_band_id_handler\n"); if (PROTO_REASON_OK == reason) { cmd.cid.cid = PLCTXRX_CID_BAND_ID; cmd.cid.opcode = PLCTXRX_OP_CONFIG; cmd.need_ack = true; cmd.prio = 0; cmd.dlen = sizeof(plctxrx_cmd_band_info_t); /* 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 */ band_info.band_id = set_cmd->band_id; os_mem_cpy(iot_pkt_data(cmd_pkt), &cmd, sizeof(cmd)); os_mem_cpy(iot_pkt_data(cmd_pkt) + sizeof(cmd), &band_info, sizeof(plctxrx_cmd_band_info_t)); iot_pkt_put(cmd_pkt, sizeof(cmd) + cmd.dlen); /* send cmd to plctxrx layer */ iot_proto_cmd_send_to_plctxrx(cmd_pkt); sm->dir = CMD_LOCAL_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = set_cmd->seq; sm->cur_subfn = set_cmd->hdr.subfn; }else { iot_proto_resp_cfm_frame(reason, dir, PROTO_SET_BAND_ID_CMD, set_cmd->seq, NULL); } return rpt2mcu; } static bool_t iot_proto_set_host_port_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)dir; bool_t rpt2mcu =false; uint8_t reason = PROTO_REASON_OK; iot_pkt_t *pkt; ge_frame_cmd_cfm_set_subfn20_t *cfm_cmd; ge_frame_host_port_set_subfn29_t *set_cmd = (ge_frame_host_port_set_subfn29_t *)data; iot_oem_base_cfg_t *oem_base_cfg; iot_oem_get_base_cfg(&oem_base_cfg); #if SUPPORT_HOST_PORT_ETH /* check param */ if (len != sizeof(*set_cmd)) { reason = PROTO_REASON_LEN_MISSMATCH; } else if ((set_cmd->host_port != HOST_PORT_UART) && (set_cmd->host_port != HOST_PORT_ETH)) { reason = PROTO_REASON_PARAME_ERR; } else if (oem_base_cfg->host_port == set_cmd->host_port) { reason = PROTO_REASON_DUP_SETTING; } #else reason = PROTO_REASON_NOT_SUPPORT; #endif /* end SUPPORT_HOST_PORT_ETH */ iot_cus_printf("[glpr]iot_proto_set_host_port_handler\n"); if (PROTO_REASON_OK == reason) { /* save host port to oem */ oem_base_cfg->host_port = set_cmd->host_port; if (ERR_OK != iot_oem_set_base_cfg(oem_base_cfg)) { iot_cus_printf("[glpr]set oem cfg host port error\n"); reason = PROTO_REASON_SET_HOST_PORT_ERR; } else { iot_cus_printf("[glpr]system will reboot after 3 seconds\n"); os_start_timer(prototask_contxt.reboot_tmr, PROTO_TMR_SET_HOST_PORT_DELAY_INTVL); } } /* 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; } static bool_t iot_proto_disconn_ind_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)len; uint8_t role = prototask_contxt.local_dev.nw_role; 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_leave_net_t *info; info = (plctxrx_cmd_leave_net_t *)cmd->data; IOT_ASSERT(info->cnt > 0); if (IOT_PLC_DEV_ROLE_CCO == role) { iot_proto_cco_groupnet_sm(NULL, PROTO_DISCONN_IND_RPT_CMD, dir, info); } else { /* switch ready state to not ready */ prototask_contxt.local_dev.dev_ready = false; /* report disconnect event to MCU */ iot_proto_report_disconn_event2mcu(info->mac[0]); } iot_cus_printf("[glpr]disconn_ind:" "disconnect ind,valid_cnt=%d,online_cnt=%d\n", dev_lst->valid_dev_cnt,dev_lst->online_dev_cnt); return rpt2mcu; } static bool_t iot_proto_reject_ind_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; iot_pkt_t *pkt; ge_frame_reject_ind_rpt_set_subfn36_t *ind_frm; plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)data; plctxrx_cmd_reject_info_t *info = (plctxrx_cmd_reject_info_t *)cmd->data; pkt = iot_pkt_alloc(sizeof(*ind_frm), IOT_GREE_APP_MID); if (pkt == NULL) { return rpt2mcu; } ind_frm = (ge_frame_reject_ind_rpt_set_subfn36_t *)iot_pkt_put(pkt, sizeof(*ind_frm)); /* fill reject indication frame field */ EXT_FN_FRM_PREPARE(ind_frm, PROTO_GE_PLC_SET_CMD, PROTO_REJECT_IND_RPT_CMD); iot_mac_addr_cpy(ind_frm->mac, info->mac); ind_frm->reason = info->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)); iot_proto_send_to_mainboard(pkt); return rpt2mcu; } static bool_t iot_proto_set_tx_power_subfn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; ge_frame_tx_pwr_set_subfn22_t *set_cmd = (ge_frame_tx_pwr_set_subfn22_t *)data; proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); if (len != sizeof(ge_frame_tx_pwr_set_subfn22_t)) { iot_proto_resp_cfm_frame(PROTO_REASON_LEN_MISSMATCH, dir, PROTO_CMD_TX_PWR_CMD, set_cmd->seq, NULL); iot_cus_printf("[glpr][err]%s cmd len mismatch\n", "set tx power"); return rpt2mcu; } else if (set_cmd->txpwr > PROTO_TX_POWER_VALUE_MAX || set_cmd->txpwr < PROTO_TX_POWER_VALUE_MIN) { iot_cus_printf("[glpr][err]set tx power value error\n"); iot_proto_resp_cfm_frame(PROTO_REASON_PARAME_ERR, dir, PROTO_CMD_TX_PWR_CMD, set_cmd->seq, NULL); return rpt2mcu; } iot_proto_set_tx_power(set_cmd->txpwr, true); sm->dir = CMD_LOCAL_UP_LINK; sm->state = PROTO_CMD_WAIT_CMD_CFM; sm->seq = set_cmd->seq; sm->cur_subfn = set_cmd->hdr.subfn; /* send cmd to plctxrx layer */ iot_cus_printf("[glpr]set tx power succ!\n"); return rpt2mcu; } static iot_pkt_t *iot_proto_pack_dev_info() { ge_frame_rpt_dev_verinfo_ind_subfn155_t *resp; iot_pkt_t *pkt = iot_pkt_alloc(sizeof(*resp), IOT_GREE_APP_MID); if (!pkt) { IOT_ASSERT(0); return NULL; } resp = (ge_frame_rpt_dev_verinfo_ind_subfn155_t *)iot_pkt_data(pkt); iot_pkt_put(pkt, sizeof(*resp)); os_mem_set(resp, 0, sizeof(*resp)); EXT_FN_FRM_PREPARE(resp, PROTO_GE_PLC_SET_CMD, PROTO_RPT_DEV_VERINFO_IND_CMD); resp->verinfo= iot_htonl(iot_version_hex()); resp->ver_type = iot_version_type(); iot_oem_get_chip_mmid(resp->chip_mmid, IOT_CHIP_MMID_LEN); resp->hw_ver = iot_board_hw_version_hex(); resp->seq = prototask_contxt.local_dev.ind_seq++; iot_mac_addr_cpy(resp->dev_mac, prototask_contxt.local_dev.mac); resp->tail.check_sum = ge_frm_checksum_calc((uint8_t *)resp, sizeof(*resp) - sizeof(ge_frm_tail_t)); return pkt; } bool_t iot_proto_set_dev_verinfo_rpt_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { uint32_t reason = PROTO_REASON_OK; bool_t rpt2mcu = false; iot_pkt_t *rpt_rsp_pkt; protpkt_tx_info_t txinfo = { 0 }; ge_frame_set_dev_verinfo_rpt_subfn33_t *set_rpt_cmd = (ge_frame_set_dev_verinfo_rpt_subfn33_t *)data; switch (dir) { case CMD_LOCAL_DOWN_LINK: { if (len != sizeof(*set_rpt_cmd)) { reason = PROTO_REASON_LEN_MISSMATCH; } iot_proto_resp_cfm_frame(reason, dir, PROTO_SET_RPT_DEV_VERINFO_CMD, set_rpt_cmd->seq, NULL); if (PROTO_REASON_OK != reason) goto out; /* if target device is local or target mac is broadcast mac, * then report local version info to MCU/PC. */ if (iot_mac_addr_cmp(prototask_contxt.local_dev.mac, set_rpt_cmd->dest_mac) || iot_mac_is_bcast(set_rpt_cmd->dest_mac)) { rpt_rsp_pkt = iot_proto_pack_dev_info(); if (!rpt_rsp_pkt) { iot_cus_printf("%s:rpt rsp no memory!\n", __FUNCTION__); goto out; } iot_proto_send_to_mainboard(rpt_rsp_pkt); goto out; } /* send requst report indication cmd to target device */ iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, prototask_contxt.local_dev.mac, set_rpt_cmd->dest_mac); iot_proto_remote_cmd_send_to_plctxrx(data, len, &txinfo); break; } case CMD_REMOTE_UP_LINK: { if (!iot_mac_addr_cmp(prototask_contxt.local_dev.mac, set_rpt_cmd->dest_mac) || iot_mac_is_bcast(set_rpt_cmd->dest_mac)) { goto out; } rpt_rsp_pkt = iot_proto_pack_dev_info(); if (!rpt_rsp_pkt) { iot_cus_printf("%s:rpt rsp no memory!\n", __FUNCTION__); goto out; } /* report device version info to the device which requested */ iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1, prototask_contxt.local_dev.mac, prototask_contxt.rx_info.mac); /* report ver info in the way recived set report cmd */ txinfo.force_tx_connless = prototask_contxt.rx_info.rx_type; iot_proto_remote_cmd_send_to_plctxrx(iot_pkt_data(rpt_rsp_pkt), (uint8_t)iot_pkt_data_len(rpt_rsp_pkt), &txinfo); iot_pkt_free(rpt_rsp_pkt); break; } default: break; } out: return rpt2mcu; } void iot_proto_set_fb_bitmap(uint16_t *p_set_bitmap, bool_t need_ack) { uint8_t i; uint8_t row = 0, col = 0; ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; iot_pkt_t *p_pkt; plctxrx_cmd_fb_bitmap_t *p_bitmap; plctxrx_cmd_arg_t *p_arg; uint16_t fb_bitmap = 0; p_pkt = iot_pkt_alloc(sizeof(*p_arg) + sizeof(*p_bitmap), IOT_GREE_APP_MID); IOT_ASSERT(p_pkt); iot_pkt_put(p_pkt, sizeof(*p_arg) + sizeof(*p_bitmap)); p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt); p_arg->cid.cid = PLCTXRX_CID_FB_BITMAP; p_arg->cid.opcode = PLCTXRX_OP_CONFIG; p_arg->need_ack = need_ack; p_arg->dlen = sizeof(plctxrx_cmd_fb_bitmap_t); if (p_set_bitmap) { fb_bitmap = *p_set_bitmap; } else { if (p_flash->public.pub.fb_bitmap != 0) { fb_bitmap = p_flash->public.pub.fb_bitmap; } else { /* default bitmap 8~11 * assign to mac band in customer range: * PLC_LIB_FREQ_BAND_0 = 0, //2M to 12M * PLC_LIB_FREQ_BAND_1 = 1, //2.4M to 5.6M * PLC_LIB_FREQ_BAND_2 = 2, //700K to 3M * PLC_LIB_FREQ_BAND_3 = 3, //1.7M to 3M * PLC_LIB_FREQ_BAND_4 = 4, //5.6M to 12M * PLC_LIB_FREQ_BAND_8 = 8, //5.8M to 9M * PLC_LIB_FREQ_BAND_9 = 9, //4.9M to 24.4M * PLC_LIB_FREQ_BAND_10 = 10,//28.3M to 34.5M * PLC_LIB_FREQ_BAND_11 = 11,//4.9M to 12.2M */ fb_bitmap |= 1 << PLC_LIB_FREQ_BAND_1; fb_bitmap |= 1 << PLC_LIB_FREQ_BAND_2; fb_bitmap |= 1 << PLC_LIB_FREQ_BAND_9; } } p_bitmap = (plctxrx_cmd_fb_bitmap_t *)p_arg->arg; for (i = 0; i < sizeof(uint16_t)*8; i++) { if (((fb_bitmap & (0x1 << i)) >> i) != 0) { row = i >> 3; col = i % 8; p_bitmap->fb_bitmap[row] |= (1 << col); } } /* save default band bitmap to app pib */ p_flash->public.pub.fb_bitmap = fb_bitmap; iot_proto_flashsave(p_flash); iot_proto_cmd_send_to_plctxrx(p_pkt); } static proto_fnhdl_tbl_t proto_set_subfnhdl_tbl[] = { {PROTO_LOCAL_MAC_SET_CMD, iot_proto_set_local_mac_subfn_handler, 0}, {PROTO_JOIN_NW_SET_CMD, iot_proto_set_join_nw_subfn_handler,0}, {PROTO_OP_WHITELIST_SET_CMD, iot_proto_whitelist_set_handler, 0}, {PROTO_CONN_IND_RPT_CMD, iot_proto_conn_ind_subfn_handler, 0}, {PROTO_DISCONN_IND_RPT_CMD, iot_proto_disconn_ind_subfn_handler, 0}, {PROTO_CCO_START_GROUP_NET_CMD, iot_proto_start_groupnet_subfn_handler, 0}, {PROTO_CCO_END_GROUP_NET_CMD, iot_proto_end_groupnet_subfn_handler, 0}, {PROTO_REBOOT_STA_CMD, iot_proto_reboot_sta_handler, 0}, {PROTO_CMD_CFM_CMD, iot_proto_cmd_cfm_subfn_handler, 0}, {PROTO_CMD_CCO_STAT_IND_CMD, iot_proto_cco_state_ind_subfn_handler, 0}, {PROTO_CMD_TX_PWR_CMD , iot_proto_set_tx_power_subfn_handler, 0}, {PROTO_CCO_NID_SET_CMD, iot_proto_set_nid_subfn_handler, 0}, {PROTO_LEAVE_NW_SET_CMD, iot_proto_set_sta_leave_handler, 0}, {PROTO_COMM_FAULT_RPT_CMD, iot_proto_comm_fault_ind_subfn_handler, 0}, {PROTO_APP_REG_CONF_IND, iot_proto_grapp_reg_conf_ind_subfn_handler, 0}, {PROTO_CLR_CUST_FLASH_CMD, iot_proto_clr_flashinfo_handler, 0}, {PROTO_GE_DATA_CMD, iot_proto_data_handler, 0}, {PROTO_GE_UART_PARAM_SET_CMD, iot_proto_set_uart_param_handler, 0}, {PROTO_SW_UART_MODE_CMD, iot_proto_sw_uart_mode_handler, 0}, {PROTO_SET_BAND_ID_CMD, iot_proto_set_band_id_handler, 0}, {PROTO_SET_HOST_PORT_CMD, iot_proto_set_host_port_handler, 0}, {PROTO_GE_BC_DATA_CMD, iot_proto_bc_data_handler, 0}, {PROTO_SET_FB_BITMAP_CMD, iot_proto_set_fb_bitmap_handler, 0}, {PROTO_SET_FIX_RATE_MODE_CMD, iot_proto_set_fix_rate_mode_handler, 0}, {PROTO_SEND_STA_PAGING_CMD, iot_proto_sta_paging_handler, 0}, {PROTO_SET_RPT_DEV_VERINFO_CMD, iot_proto_set_dev_verinfo_rpt_handler, 0}, {PROTO_SET_SWITCH_BOOT_PART_CMD, iot_proto_switch_boot_part_handler, 0}, {PROTO_LOCAL_IP4_INFO_SET_CMD, iot_proto_set_local_ip4_subfn_handler, 0}, {PROTO_AES_SET_CMD, iot_proto_set_aes_handler, 0}, {PROTO_GE_GPIO_CONFIG_CMD, iot_proto_config_gpio_handler, 0}, {PROTO_GE_GPIO_SET_CMD, iot_proto_set_gpio_handler, 0}, {PROTO_GE_DELAY_TM_CMD, iot_proto_delay_time_handler, 0}, {PROTO_REJECT_IND_RPT_CMD, iot_proto_reject_ind_subfn_handler, 0}, }; static bool_t iot_proto_set_fn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; bool_t need_save = false; bool_t need_handle = false; plctxrx_cmd_resp_t *cmd = NULL; uint8_t ret; uint8_t fn = 0, subfn = 0; ge_extend_fn_hdr_t *frm_hdr; proto_cmd_hdl_state_t *sm_state = iot_proto_cmd_handle_state_get(); uint8_t state = sm_state->state; uint32_t i; PROTO_FN_HANDLE handler = NULL; if (CMD_LOCAL_UP_LINK == dir) { cmd = (plctxrx_cmd_resp_t *)data; ret = iot_proto_plctxtx_fn_subfn_get(cmd, &fn, &subfn); if (ret) { iot_cus_printf("[glpr][err]set_fn_handler:cid=0x%x,opcode=0x%x\n", cmd->cid.cid, cmd->cid.opcode); return rpt2mcu; } /* else ,it means it is a intact gree cmd frame */ } else { frm_hdr = (ge_extend_fn_hdr_t *)data; subfn = frm_hdr->subfn; } iot_cus_printf("[glpr]set_fn_handler:subfn=%d,dir=%d,cur_state=%d\n", subfn, dir, state); if (PROTO_GE_DATA_CMD == subfn && state == PROTO_CMD_WAIT_MAC_RESP) { ge_frame_data_send_set_subfn160_t *s160_data = (ge_frame_data_send_set_subfn160_t*)data; iot_cus_printf("recv mac:%02X %02x %02X %02x %02X %02x\n", s160_data->dest_mac[0], s160_data->dest_mac[1], s160_data->dest_mac[2], s160_data->dest_mac[3], s160_data->dest_mac[4], s160_data->dest_mac[5]); if (!iot_mac_addr_cmp(prototask_contxt.local_dev.mac, s160_data->dest_mac)) { if (!prototask_contxt.macaddr_set) { /* set mac and type to CVG layer */ iot_proto_set_mac(s160_data->dest_mac, 0, false); /* detect mac, set mac and report boot ready*/ iot_proto_boot_ready_ind(s160_data->dest_mac); } return rpt2mcu; } } if (prototask_contxt.macaddr_set == 0 && PROTO_APP_REG_CONF_IND != subfn && PROTO_LOCAL_MAC_SET_CMD != subfn && PROTO_GE_UART_PARAM_SET_CMD != subfn) { iot_cus_printf("[glpr]no mac received! not handle\n"); return rpt2mcu; } /* check if subfn is data cmd for general or uart param or indication */ if (PROTO_GE_DATA_CMD == subfn || PROTO_GE_UART_PARAM_SET_CMD == subfn || PROTO_SEND_STA_PAGING_CMD == subfn || PROTO_GE_DELAY_TM_CMD == subfn || (cmd && cmd->cid.opcode == PLCTXRX_OP_INDICATION)) { for (i = 0; i < ARRAY_CNT(proto_set_subfnhdl_tbl); i++) { if (proto_set_subfnhdl_tbl[i].cmdid == subfn) { handler = proto_set_subfnhdl_tbl[i].cmd_handle_fn; break; } } if (handler) { return handler(data, len, dir); } else { return rpt2mcu; } } switch (dir) { case CMD_LOCAL_DOWN_LINK: { switch (state) { case PROTO_CMD_IDLE: { /* not handle indication frame message which received from mcu */ if (subfn == PROTO_BOOT_READY_ID_CMD || subfn == PROTO_CONN_IND_RPT_CMD || subfn == PROTO_DISCONN_IND_RPT_CMD || subfn == PROTO_WHITELIST_IND_CMD || subfn == PROTO_PAIRTABLE_IND_CMD || subfn == PROTO_APP_REG_CONF_IND || subfn == PROTO_STA_LEAVE_IND || subfn == PROTO_MONITR_ONLINE_IND || subfn == PROTO_CMD_CCO_STAT_IND_CMD) { iot_cus_printf("[glpr][war]subfn=%X,no need to handle\n",subfn); } else { need_handle = true; } break; } case PROTO_CMD_WAIT_MAC_RESP: { if (subfn == PROTO_LOCAL_MAC_SET_CMD) { need_handle = true; } break; } case PROTO_CMD_WAIT_WHITE_LIST_SET: { if (subfn == PROTO_OP_WHITELIST_SET_CMD) { need_handle = true; } else { need_save = true; } break; } default: need_save = true; break; } break; } case CMD_LOCAL_UP_LINK: { switch (state) { case PROTO_CMD_IDLE: { switch (subfn) { case PROTO_COMM_FAULT_RPT_CMD: case PROTO_CONN_IND_RPT_CMD: case PROTO_DISCONN_IND_RPT_CMD: case PROTO_CMD_CCO_STAT_IND_CMD: case PROTO_APP_REG_CONF_IND: { need_handle = true; break; } default: break; } break; } case PROTO_CMD_WAIT_CMD_CFM: { if (PROTO_CMD_CFM_CMD == subfn) { need_handle = true; } else { need_save = true; } break; } case PROTO_CMD_WAIT_WHITE_LIST_SET: { if (PROTO_CMD_CFM_CMD == subfn) { need_handle = true; } break; } default: { if (PROTO_CMD_CFM_CMD != subfn) { need_save = true; } else { // drop it } break; } } break; } case CMD_REMOTE_UP_LINK: { /** * if remote cmd whitelist ind or pairtable indication, * handle it as the highest priority. */ if (PROTO_WHITELIST_IND_CMD == subfn || PROTO_PAIRTABLE_IND_CMD == subfn) { need_handle = true; break; } /* swicth boot part indication command need report to uart */ if (PROTO_SWITCH_BOOT_PART_IND_CMD == subfn) { rpt2mcu = true; break; } switch (state) { case PROTO_CMD_IDLE: { if (PROTO_CMD_CFM_CMD != subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_CMD_CFM: { if (PROTO_CMD_CFM_CMD == subfn) { need_handle = true; } else { need_save = true; } break; } case PROTO_CMD_WAIT_WHITE_LIST_SET: { if (subfn == PROTO_OP_WHITELIST_SET_CMD) { need_handle = true; } else { need_save = true; } break; } /* if in other waiting state, save all cmd except * PROTO_CMD_CFM_CMD. */ default: { if (PROTO_CMD_CFM_CMD != subfn) { need_save = true; } else { // drop it } break; } } break; } default: break; } iot_cus_printf("[glpr]subfn:%d handle:%d need_save:%d\n", subfn, need_handle,need_save); if (need_handle) { for (i = 0; i < ARRAY_CNT(proto_set_subfnhdl_tbl); i++) { if (proto_set_subfnhdl_tbl[i].cmdid == subfn) { handler = proto_set_subfnhdl_tbl[i].cmd_handle_fn; break; } } if (NULL != handler) { rpt2mcu = handler(data, len, dir); if (PROTO_CMD_IDLE == sm_state->state) { /* clear wait response timer if it's active. */ if (os_is_timer_active(prototask_contxt.wait_resp_timer)) { os_stop_timer(prototask_contxt.wait_resp_timer); iot_task_clean_msg(prototask_contxt.task_handle, PROTO_TIMER_MSG, PROTO_TIMER_WAIT_RESP_TIMEOUT); } /* push saved msg to task queue */ iot_proto_saved_msg_handle(); } else { /* restart timer */ if (os_is_timer_active(prototask_contxt.wait_resp_timer)) { os_stop_timer(prototask_contxt.wait_resp_timer); iot_task_clean_msg(prototask_contxt.task_handle, PROTO_TIMER_MSG, PROTO_TIMER_WAIT_RESP_TIMEOUT); } os_start_timer(prototask_contxt.wait_resp_timer, PROTO_TIMER_WAIT_RESPONSE_TIMEOUT_INTVL); } } else { iot_cus_printf("\n[glpr][error]No handler found!\n"); } } if (need_save) { proto_msg_saved_list_t *list = &prototask_contxt.saved_msg_list; transmit_direction_e_t tmp_dir = 0; uint16_t msg_type = 0; uint16_t msg_id = 0; plctxrx_rx_data_info_t *rxinfo = NULL; switch (dir) { case CMD_LOCAL_UP_LINK: { tmp_dir = CMD_LOCAL_UP_LINK; msg_type = PROTO_PLC_RX_MSG; msg_id = PROTO_PLCTXRX_RX_CMD_MSG; break; } case CMD_LOCAL_DOWN_LINK: { tmp_dir = DATA_DOWN_LINK; msg_type = PROTO_MCU_RX_MSG; msg_id = 0; break; } case CMD_REMOTE_UP_LINK: { tmp_dir = DATA_UP_LINK; msg_type = PROTO_PLC_RX_MSG; msg_id = PROTO_PLC_RX_DATA_MSG; rxinfo = &prototask_contxt.rx_info; break; } default: break; } iot_cus_printf("[glpr]" "Save this cmd msg!tmp_dir=%d,msg_id=%d,msg_type=%d\n", tmp_dir,msg_id,msg_type); iot_proto_save_cmd(list, data, len, rxinfo, tmp_dir, msg_id, msg_type); } return rpt2mcu; } static proto_fnhdl_tbl_t proto_query_subfnhdl_tbl[] = { {PROTO_LOCAL_MAC_QUERY_CMD, iot_proto_query_local_mac_handler, 0}, {PROTO_FW_SWVER_QUERY_CMD, iot_proto_query_swver_handler, 0}, {PROTO_BOOTINFO_QUERY_CMD, iot_proto_query_boot_info_handler, 0}, {PROTO_TOPO_QUERY_CMD, iot_proto_query_topo_handler, 0}, {PROTO_NET_STS_QUERY_CMD, iot_proto_query_net_sts_handler, 0}, {PROTO_WHITELIST_QUERY_CMD, iot_proto_query_whitelist_handler, 0}, {PROTO_AVAIL_NW_QUERY_CMD, iot_proto_query_avail_nw_handler, 0}, {PROTO_TX_PWR_QUERY_CMD, iot_proto_query_tx_pwr_handler, 0}, {PROTO_UART_THRPT_QUERY_CMD, iot_proto_query_uart_thrpt_handler, 0}, {PROTO_NW_DETAILINFO_QUERY_CMD, iot_proto_query_nw_detailinfo_handler, 0}, {PROTO_GE_UART_PARAM_QUERY_CMD, iot_proto_query_uart_param_handler, 0}, {PROTO_GE_EXT_WL_QUERY_CMD, iot_proto_ext_query_wl_handler, 0}, {PROTO_NID_QUERY_CMD, iot_proto_query_nid_handler, 0}, {PROTO_WHITELIST_STATE_QUERY_CMD, iot_proto_query_wl_state_handler, 0}, {PROTO_MODULE_INFO_QUERY_CMD, iot_proto_query_module_info_handler, 0}, {PROTO_NTB_QUERY_CMD, iot_proto_query_ntb_handler, 0}, {PROTO_FB_BITMAP_QUERY_CMD, iot_proto_query_fb_bitmap_handler, 0}, {PROTO_FIX_RATE_QUERY_CMD, iot_proto_query_fix_rate_mode_handler, 0}, {PROTO_WORK_BAND_QUERY_CMD, iot_proto_query_work_band_handler, 0}, {PROTO_NODE_INFO_QUERY_CMD, iot_proto_query_node_info_handler, 0}, {PROTO_NW_INFO_QUERY_CMD, iot_proto_query_nw_info_handler, 0}, {PROTO_LOCAL_IP4_INFO_QUERY_CMD, iot_proto_query_local_ip4_handler, 0}, {PROTO_AES_QUERY_CMD, iot_proto_query_aes_handler, 0}, {PROTO_GE_GPIO_QUERY_CMD, iot_proto_query_gpio_handler, 0}, }; static bool_t iot_proto_query_fn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; bool_t need_save = false; bool_t need_handle = false; uint8_t subfn = 0; ge_extend_fn_hdr_t *frm_hdr; proto_cmd_hdl_state_t *sm_state = iot_proto_cmd_handle_state_get(); uint8_t state = sm_state->state; uint32_t i; PROTO_FN_HANDLE handler = NULL; frm_hdr = (ge_extend_fn_hdr_t *)data; subfn = frm_hdr->subfn; iot_cus_printf("[glpr]query_fn_handler:subfn=%d,dir=%d,cur_state=%d\n", subfn, dir, state); /* uart param setting is highest priority */ if (PROTO_GE_UART_PARAM_QUERY_CMD == subfn) { for (i = 0; i < ARRAY_CNT(proto_query_subfnhdl_tbl); i++) { if (proto_query_subfnhdl_tbl[i].cmdid == subfn) { handler = proto_query_subfnhdl_tbl[i].cmd_handle_fn; break; } } if (handler) { return handler(data, len, dir); } else { return rpt2mcu; } } if ((prototask_contxt.macaddr_set == 0)) { iot_cus_printf("[glpr]no mac received! not handle]"); return rpt2mcu; } switch (dir) { case CMD_LOCAL_DOWN_LINK: case CMD_REMOTE_UP_LINK: { switch (state) { case PROTO_CMD_IDLE: { need_handle = true; break; } default: need_save = true; break; } break; } default: IOT_ASSERT(0); break; } iot_cus_printf("[glpr]subfn:%d handle:%d need_save:%d\n", subfn, need_handle,need_save); if (need_handle) { handler = NULL; for (i = 0; i < ARRAY_CNT(proto_query_subfnhdl_tbl); i++) { if (proto_query_subfnhdl_tbl[i].cmdid == subfn) { handler = proto_query_subfnhdl_tbl[i].cmd_handle_fn; break; } } if (NULL != handler) { rpt2mcu = handler(data, len, dir); if (PROTO_CMD_IDLE != sm_state->state) { /* start wait response timer */ os_start_timer(prototask_contxt.wait_resp_timer, PROTO_TIMER_WAIT_RESPONSE_TIMEOUT_INTVL); } } else { iot_cus_printf("\n[glpr]No handler found!"); } } if (need_save) { proto_msg_saved_list_t *list = &prototask_contxt.saved_msg_list; transmit_direction_e_t tmp_dir = 0; uint16_t msg_type = 0; uint16_t msg_id = 0; plctxrx_rx_data_info_t *rxinfo = NULL; switch (dir) { case CMD_LOCAL_DOWN_LINK: { tmp_dir = DATA_DOWN_LINK; msg_type = PROTO_MCU_RX_MSG; msg_id = 0; break; } case CMD_REMOTE_UP_LINK: { tmp_dir = DATA_UP_LINK; msg_type = PROTO_PLC_RX_MSG; msg_id = PROTO_PLC_RX_DATA_MSG; rxinfo = &prototask_contxt.rx_info; break; } default: IOT_ASSERT(0); break; } iot_cus_printf("[glpr]" "Save this cmd msg!tmp_dir=%d,msg_id=%d,msg_type=%d\n", tmp_dir,msg_id,msg_type); iot_proto_save_cmd(list, data, len, rxinfo, tmp_dir, msg_id, msg_type); } return rpt2mcu; } static proto_fnhdl_tbl_t proto_query_resp_subfnhdl_tbl[] = { {PROTO_LOCAL_MAC_RESP_CMD, iot_proto_local_mac_resp_handler, 0}, {PROTO_FW_SWVER_RESP_CMD, iot_proto_fw_swver_resp_subfn_handler, 0}, {PROTO_BOOT_INFO_RESP_CMD, iot_proto_boot_info_resp_subfn_handler, 0}, {PROTO_TOPO_RESP_CMD, iot_proto_topo_resp_subfn_handler, 0}, {PROTO_NET_STS_RESP_CMD, iot_proto_net_sts_resp_subfn_handler, 0}, {PROTO_WHITELIST_RESP_CMD, iot_proto_whitelist_resp_handler, 0}, {PROTO_AVAIL_NW_RESP_CMD, iot_proto_avail_nw_resp_subfn_handler, 0}, {PROTO_TX_PWR_RESP_CMD, iot_proto_tx_power_resp_subfn_handler, 0}, {PROTO_NTB_RESP_CMD, iot_proto_ntb_resp_subfn_handler, 0}, {PROTO_FB_BITMAP_RESP_CMD, iot_proto_fb_bitmap_resp_subfn_handler, 0}, {PROTO_FIX_RATE_MODE_RESP_CMD, iot_proto_fix_rate_mode_resp_subfn_handler, 0}, {PROTO_WORK_BAND_RESP_CMD, iot_proto_work_band_resp_subfn_handler, 0}, {PROTO_NODE_INFO_RESP_CMD, iot_proto_node_info_resp_subfn_handler, 0}, {PROTO_NW_INFO_RESP_CMD, iot_proto_nw_info_resp_subfn_handler, 0}, {PROTO_AES_RESP_CMD, iot_proto_resp_aes_handler, 0}, {PROTO_QUERY_GPIO_RESP_CMD, iot_proto_gpio_resp_subfn_handler, 0}, }; static bool_t iot_proto_query_resp_fn_handler(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { bool_t rpt2mcu = false; bool_t need_handle = false; plctxrx_cmd_resp_t *cmd; uint8_t ret; uint8_t state; uint8_t fn = 0, subfn = 0; ge_extend_fn_hdr_t *frm_hdr; proto_cmd_hdl_state_t *sm_state = iot_proto_cmd_handle_state_get(); uint32_t i; PROTO_FN_HANDLE handler; if (CMD_LOCAL_UP_LINK == dir) { cmd = (plctxrx_cmd_resp_t *)data; ret = iot_proto_plctxtx_fn_subfn_get(cmd, &fn, &subfn); if (ret) { iot_cus_printf("[glpr][err]query_resp_fn_handler:cid=0x%x,opcode=0x%x\n", cmd->cid.cid, cmd->cid.opcode); return rpt2mcu; } /* else ,it means it is a intact gree cmd frame */ } else { frm_hdr = (ge_extend_fn_hdr_t *)data; subfn = frm_hdr->subfn; } iot_cus_printf("[glpr]query_resp_fn_handler:subfn=%d,dir=%d,cur_state=%d\n", subfn, dir, sm_state->state); state = sm_state->state; /* no mac, doesn't handle cmd */ if ((prototask_contxt.macaddr_set == 0) && (subfn != PROTO_LOCAL_MAC_RESP_CMD)) { iot_cus_printf("[glpr]no mac received! not handle]"); return rpt2mcu; } switch (dir) { case CMD_LOCAL_DOWN_LINK: { switch (state) { case PROTO_CMD_WAIT_MAC_RESP: { if (PROTO_LOCAL_MAC_RESP_CMD == subfn) { need_handle = true; } break; } default: break; } break; } case CMD_LOCAL_UP_LINK: { switch (state) { case PROTO_CMD_WAIT_SWVER_RESP: { if (PROTO_FW_SWVER_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_BOOT_INFO_RESP: { if (PROTO_BOOT_INFO_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_TOPO_RESP: { if (PROTO_TOPO_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_NET_STS_RESP: { if (PROTO_NET_STS_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_RMT_WHITELIST_RESP: { if (PROTO_WHITELIST_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_AVAIL_NETWORK_RESP: { if (PROTO_AVAIL_NW_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_TX_PWR_RESP: { if (PROTO_TX_PWR_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_NTB_RESP: { if (PROTO_NTB_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_FB_BITMAP_RESP: { if (PROTO_FB_BITMAP_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_FIX_RATE_MODE_RESP: { if (PROTO_FIX_RATE_MODE_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_WORK_BAND_RESP: { if (PROTO_WORK_BAND_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_NODE_INFO_RESP: { if (PROTO_NODE_INFO_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_NW_INFO_RESP: { if (PROTO_NW_INFO_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_DL645_WAIT_TOPO_INFO_RESP: { if (PROTO_TOPO_RESP_CMD == subfn) { need_handle = true; } break; } default: break; } break; } case CMD_REMOTE_UP_LINK: { switch (state) { case PROTO_CMD_WAIT_TOPO_RESP: { if (PROTO_TOPO_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_RMT_WHITELIST_RESP: { if (PROTO_WHITELIST_RESP_CMD == subfn) { need_handle = true; } break; } case PROTO_CMD_WAIT_CMD_CFM: { if (PROTO_QUERY_GPIO_RESP_CMD == subfn) { need_handle = true; } break; } default: break; } break; } case CMD_REMOTE_DOWN_LINK: // do nothing break; default: break; } iot_cus_printf("[glpr]subfn:%d handle:%d\n", subfn, need_handle); if (need_handle) { handler = NULL; for(i = 0; i < ARRAY_CNT(proto_query_resp_subfnhdl_tbl); i++) { if (proto_query_resp_subfnhdl_tbl[i].cmdid == subfn) { handler = proto_query_resp_subfnhdl_tbl[i].cmd_handle_fn; break; } } if (NULL != handler) { rpt2mcu = handler(data, len, dir); } else { iot_cus_printf("\n[glpr][err]No handler found!"); } iot_cus_printf("[glpr]query_resp_fn:handled_state=%d\n", sm_state->state); if (PROTO_CMD_IDLE == sm_state->state) { /* clear wait response timer if it's active. */ if (os_is_timer_active(prototask_contxt.wait_resp_timer)) { os_stop_timer(prototask_contxt.wait_resp_timer); iot_task_clean_msg(prototask_contxt.task_handle, PROTO_TIMER_MSG, PROTO_TIMER_WAIT_RESP_TIMEOUT); } /* get next cmd execute */ iot_proto_saved_msg_handle(); } else { if (os_is_timer_active(prototask_contxt.wait_resp_timer)) { os_stop_timer(prototask_contxt.wait_resp_timer); iot_task_clean_msg(prototask_contxt.task_handle, PROTO_TIMER_MSG, PROTO_TIMER_WAIT_RESP_TIMEOUT); } os_start_timer(prototask_contxt.wait_resp_timer, PROTO_TIMER_WAIT_RESPONSE_TIMEOUT_INTVL); } } return rpt2mcu; } /* fncode handler table */ static proto_fnhdl_tbl_t proto_subfn_hdl_tbl[] = { {PROTO_GE_PLC_RESP_CMD, iot_proto_query_resp_fn_handler, 0 }, {PROTO_GE_PLC_SET_CMD, iot_proto_set_fn_handler, 0 }, {PROTO_GE_PLC_QUERY_CMD, iot_proto_query_fn_handler, 0 }, /* for gree cmd number statistic */ {0, NULL, 0 } }; #if PLC_SUPPORT_CCO_ROLE && ENABLE_GREE_UPGRADE static proto_upgrade_fnhdl_tbl_t proto_upgrade_fnhdl_tbl[] = { { PROTO_UPGRADE_DL, iot_proto_upgrade_fn_handler }, { 0, NULL }, }; #endif uint8_t iot_proto_plctxrx_register(PLCXMIT_CMD_CB cmd_cb, PLCXMIT_DATA_CB data_cb) { IOT_ASSERT(cmd_cb && data_cb); int8_t ret = ERR_FAIL; if (cmd_cb && data_cb) { prototask_contxt.gree_cmd_send_cb = cmd_cb; prototask_contxt.gree_data_send_cb = data_cb; #if HW_PLATFORM != HW_PLATFORM_SIMU /* if app pib upgrade flag is set, copy old app pib info into new app * pib section */ if (iot_pib_app_upgrade_flag()) { iot_cus_printf("%s: need to copy pib\n", __FUNCTION__); iot_proto_upgrade_app_pib_info(); } #endif iot_proto_flashinfo_init(); ret = ERR_OK; } return ret; } /* get data from the crc pos in gree frame */ uint16_t iot_gree_get_crc_byte(uint8_t *data) { uint16_t crc_data= 0; #if GE_CRC_ENABLE crc_data = (data[1] << 8) | data[0]; #else crc_data = data[0]; #endif return crc_data; } #if GE_CRC_ENABLE /* calculate frame checksum or crc */ uint16_t ge_frm_checksum_calc(uint8_t *data, uint16_t len) { register uint16_t crc = 0xFFFF; IOT_ASSERT(data && len); while (len--) { crc = (crc>>8) ^ iot_crc16_tab[(crc ^ *data++) & 0xff]; } return crc; } #else uint8_t ge_frm_checksum_calc(uint8_t *data, uint16_t len) { uint16_t i; uint8_t checksum = data[0]; IOT_ASSERT(data && len); for (i = 1; i < len; i++) { checksum ^= data[i]; } return checksum; } #endif uint8_t ge_frame_data_len(uint8_t *data, uint16_t data_len, uint16_t *frame_data_len) { uint8_t error_code = ERR_OK; ge_extend_fn_hdr_t *p_hdr = NULL; IOT_ASSERT(data && frame_data_len); *frame_data_len = 0; if (data_len < GE_FRM_DATA_CNT_FIELD_POS + 1) { /* not a complete frame */ error_code = 1; goto error; } p_hdr = (ge_extend_fn_hdr_t *)data; if ((p_hdr->hdr.fn == PROTO_UPGRADE_DL) && (p_hdr->subfn == PROTO_UPGRADE_DATA)) { /* for gree upgrade cmds the data length is 0x91-0x98 or 0x9A */ if (GREE_CHECK_UPGRADE_CMD(p_hdr->hdr.data_len)) { if (p_hdr->hdr.data_len == GREE_UPGRADE_DATA_CONTROL) { if (data_len < GREE_UPGRADE_DATA_FRM_MIN_LEN) { /* not a complete frame */ error_code = 1; goto error; } /* calc gree upgrade data len */ *frame_data_len = GREE_UPGRADE_DATA_FRM_CTL_LEN + data[GREE_UPGRADE_DATA_FRM_LEN_LOW_BYTE] + (data[GREE_UPGRADE_DATA_FRM_LEN_HIG_BYTE] << 8); } else { *frame_data_len = GREE_ACQUIRE_UPGRADE_CMD_LEN(p_hdr->hdr.data_len); } } } else if ((p_hdr->hdr.fn == PROTO_GE_PLC_SET_CMD) && (p_hdr->subfn == PROTO_GE_DATA_CMD)) { *frame_data_len = ACQUIRE_DATA_LEN(p_hdr->hdr.data_len); if(data[GE_FRM_DATA_EXT_LEN_POS] & GE_FRM_DATA_EXT_FLAG) { *frame_data_len += GE_EXT_DATA_LEN; } } else if (GE_CHECK_FRM_CMD(p_hdr->hdr.data_len)) { *frame_data_len = ACQUIRE_DATA_LEN(p_hdr->hdr.data_len); } else { /* detec frame control length error */ error_code = 2; *frame_data_len = 0; goto error; } /* check the frame is complete */ if (data_len >= (*frame_data_len + GE_FRM_MIN_LEN)) { return ERR_OK; } else { /* not a complete frame */ error_code = 1; goto error; } error: iot_cus_printf("[glpr][war %d] ctl=%X flen=%d dlen=%d\n", error_code, p_hdr->hdr.data_len, *frame_data_len, data_len); return error_code; } /* * iot_proto_ge_frame_check - parser a ge frame * @recv_data: descript of receive buffer. * @p_gepool: point to the pool whitch save the ge frame witch checked out from the uart buffer * @gepool_size: point to the data length in the p_gepool * @ge_pkt_len: point to the ge length if there is a frame can be checked out * @retval: - check result, GET_NO_FRAME, GET_ONE_FRAME or GET_HALF_FRAME */ static uint8_t iot_proto_ge_frame_check(mcu_data_handle_t *recv_data, uint8_t *p_gepool, uint16_t *gepool_size, uint16_t *ge_pkt_len) { uint8_t check_result = GET_NO_FRAME; uint8_t ret = 0; uint8_t *buf = &recv_data->data[recv_data->data_pos]; uint16_t gefrm_len = 0; uint16_t crc_data = 0; /* find the 1st preamble 0xAA. if not, the checking is fail */ if (0xAA == buf[0]) { /* half frame, return */ if (GE_FRM_MIN_LEN > recv_data->total_len - recv_data->data_pos) { check_result = GET_HALF_FRAME; goto result; } /* check second 0xAA. if not, return */ if (0xAA == buf[1]) { ret = ge_frame_data_len(&buf[0], recv_data->total_len - recv_data->data_pos , &gefrm_len); if (ret == 2) { /* frame control check error,drop */ goto result; } else if (ret == 1) { /* half frame, return */ check_result = GET_HALF_FRAME; goto result; } /* step to check end code 0xFF */ if (buf[gefrm_len + GE_FRM_TAIL_CODE_FIELD_POS] != GE_FRM_TAIL_CODE) { /* not right, drop */ iot_cus_printf("[glpr][war]not end with FF\n"); goto result; } /* crc check here */ crc_data = iot_gree_get_crc_byte( &buf[gefrm_len + GE_FRM_CHECK_SUM_FIELD_POS]); if (crc_data != ge_frm_checksum_calc(&buf[0], gefrm_len + GE_FRM_CHECK_SUM_FIELD_POS)) { /*crc not right, drop*/ iot_cus_printf("[glpr][war]detec pkt crc wrong\n"); goto result; } /* finally, we got one pkt, so luckly */ if (*gepool_size + GE_FRM_MIN_LEN + gefrm_len > MCU_DATA_RECV_MAX) { check_result = GET_OVERFLOW; goto result; } /* prepare output */ os_mem_cpy(&p_gepool[*gepool_size], &buf[0], GE_FRM_MIN_LEN + gefrm_len); *gepool_size += (GE_FRM_MIN_LEN + gefrm_len); *ge_pkt_len = (GE_FRM_MIN_LEN + gefrm_len); check_result = GET_ONE_FRAME; } } result: return check_result; } /* * iot_proto_data_parse_and_post - parser command and post to task. * @buf: input buf need to parser * @len: buf len * @post_func: the function will post parsered command to task * @param: param passed to the post_func. * @return: parser result */ uint8_t iot_proto_data_parse_and_post(uint8_t *buf, uint16_t len, POST_RECV_DATA post_func, uint32_t param) { uint8_t* pdata; uint8_t* pbuf; uint8_t check_result = GET_NO_FRAME; uint16_t total; uint16_t ge_buflen; mcu_data_handle_t* p_mcudata; uint16_t ge_len; /* record the position modbus firstly check out a half frame each loop */ static uint16_t modbus_half_predict; if (NULL == buf || len == 0) { return ERR_FAIL; } total = len; pbuf = buf; p_mcudata = &mcu_data; uart_thpt.recv_len += len; /* uart drv may report len > UART_RECV_SIZE_MAX, so we handle it in times */ do { /* data_pos indicate possible gree frame start from. if it is larger than max gree size, means pmcudata[0] ~ p_mcudata[GE_FRM_MAX_LEN] not valide gree frame. however, it should not happen. paser function should alreay remove garbage bytes.*/ if (p_mcudata->data_pos >= PARSE_FRM_MAX_LEN) { iot_cus_printf("[glpr][err] data_pos:%d total:%d\n", p_mcudata->data_pos, total); goto error; } pdata = &p_mcudata->data[p_mcudata->data_pos]; iot_cus_printf("[glpr]break frame pos= %d new_len=%d\n", p_mcudata->data_pos, len); if (total > UART_RECV_SIZE_MAX) { os_mem_cpy(pdata, pbuf, UART_RECV_SIZE_MAX); pbuf += UART_RECV_SIZE_MAX; total -= UART_RECV_SIZE_MAX; p_mcudata->total_len = UART_RECV_SIZE_MAX + p_mcudata->data_pos; } else { os_mem_cpy(pdata, pbuf, total); pbuf += total; p_mcudata->total_len = total + p_mcudata->data_pos; total = 0; } /* now position should be 0, one new paser cycle starts */ p_mcudata->data_pos = 0; /* clean ge_buf */ ge_buflen = 0; os_mem_set(ge_buf, 0, MCU_DATA_RECV_MAX); check_result = GET_NO_FRAME; /* do frame check from mcudata offset 0, and the function will return full gree frame buffer, ge_buf, and ge_buflen. Also, wrong packet in middle removed. remain half packet moved to head of p_mucdata. */ while (p_mcudata->data_pos < p_mcudata->total_len) { ge_len = 0; /* if the function iot_proto_ge_frame_check() get a ge frame, the frame should be copy to the ge_buf closely in the function. ge_buflen is all data length in the ge_buf, it should add the length of the frame in the function. ge_len is the length of the ge frame, the p_mcudata->data_pos should jump the whole length of the frame then check the next positon if do not find a ge frame. the value of ge_buf, ge_buflen, ge_len will not changed */ check_result = iot_proto_ge_frame_check(p_mcudata, ge_buf, &ge_buflen, &ge_len); if (check_result == GET_ONE_FRAME) { p_mcudata->data_pos += ge_len; modbus_half_predict = 0; continue; } else if (check_result == GET_HALF_FRAME) { break; } else if (check_result == GET_OVERFLOW) { modbus_half_predict = 0; break; } /* if the function iot_proto_645_format_check() get a dl645 frame, the frame should be handled then become a ge frame to copy to the ge_buf closely in the function. ge_buflen is all data length in the ge_buf, it should add the length of the frame in thefunction. ge_len is the length of the dl645 frame, the p_mcudata->data_pos should jump the whole length of the dl645 frame then check the next positon if do not find a ge frame. the value of ge_buf, ge_buflen, ge_len will not changed */ check_result = iot_proto_645_format_check(p_mcudata, ge_buf, &ge_buflen, &ge_len); if (check_result == GET_ONE_FRAME) { p_mcudata->data_pos += ge_len; modbus_half_predict = 0; continue; } else if (check_result == GET_HALF_FRAME) { break; } else if (check_result == GET_OVERFLOW) { modbus_half_predict = 0; break; } #if PLC_SUPPORT_STA_ROLE /* if the function iot_proto_modbus_format_check() get a modbus frame, the frame should be handled then become a ge frame to copy to the ge_buf closely in the function. ge_buflen is all data length in the ge_buf, it should add the length of the frame in the function. ge_len is the length of the modbus frame, the p_mcudata->data_pos should jump the whole length of the modbus frame then check the next positon if do not find a ge frame. the value of ge_buf, ge_buflen, ge_len will not changed */ check_result = iot_proto_modbus_format_check(p_mcudata, ge_buf, &ge_buflen, &ge_len); if (check_result == GET_ONE_FRAME) { p_mcudata->data_pos += ge_len; modbus_half_predict = 0; continue; } else if (check_result == GET_HALF_FRAME) { /* only the first half position should be record */ if (!modbus_half_predict) { /* add 1 to let the position '0' can be record too. when copy the half frame to front of p_mcudata->data_pos, it should minus 1 */ modbus_half_predict = p_mcudata->data_pos + 1; } check_result = GET_NO_FRAME; } else if (check_result == GET_OVERFLOW) { iot_cus_printf("overflow data pos=%d\n", p_mcudata->data_pos); iot_cus_printf("overflow left length =%d\n", total + p_mcudata->total_len - p_mcudata->data_pos); modbus_half_predict = 0; break; } #endif p_mcudata->data_pos++; } if (modbus_half_predict) { modbus_half_predict -= 1; os_mem_cpy(p_mcudata->data, &p_mcudata->data[modbus_half_predict], p_mcudata->total_len - modbus_half_predict); p_mcudata->data_pos = p_mcudata->total_len - modbus_half_predict; modbus_half_predict = 0; } else if ((check_result == GET_HALF_FRAME) || (check_result == GET_OVERFLOW)) { /* if half frame or overflow exist, save the rest of data */ os_mem_cpy(p_mcudata->data, &p_mcudata->data[p_mcudata->data_pos], p_mcudata->total_len - p_mcudata->data_pos); p_mcudata->data_pos = p_mcudata->total_len - p_mcudata->data_pos; } else { p_mcudata->total_len = 0; p_mcudata->data_pos = 0; } /* put filtered packeted in message queue */ if (ge_buflen > 0) { if (post_func(ge_buf, ge_buflen, param)) { goto error; } } } while ((total > 0) || (check_result == GET_OVERFLOW)); return ERR_OK; error: p_mcudata->data_pos = 0; return ERR_FAIL; } /* post uart received command to task */ uint8_t iot_proto_task_post_uart_cmd(uint8_t * data, uint16_t len, uint32_t param) { uint8_t msg = PROTO_MCU_RX_MSG; uint8_t msg_id = 0; iot_pkt_t* send_pkt = NULL; (void)param; send_pkt = iot_pkt_alloc(len, IOT_GREE_APP_MID); if (send_pkt) { /* copy data from buf to data packet */ os_mem_cpy(iot_pkt_put(send_pkt, len), data, len); /* alloc message to insert proto task msg queue */ if (iot_hwver_is_ledc_v3_0_jy() && (iot_board_get_board_id() == CUS_BOARD_ID_LEDC_V3_0) && (IOT_PLC_DEV_ROLE_STA == prototask_contxt.local_dev.nw_role)) { if (prototask_contxt.edge_obj.uart_hdl != NULL) { msg = EDGE_UART_RX_MSG; } } iot_proto_task_post_msg(msg, msg_id, send_pkt, DATA_DOWN_LINK, IOT_PROTO_TASK_QUEUE_LP); return ERR_OK; } else { iot_cus_printf("[glpr][err]no mem, frame len:%d\n", len); return ERR_FAIL; } } #if IOT_GE_EXT_SDK_ENABLE /* * uart drver calls, running in uart driver task. * @buf: input data pointer * @len: data len */ uint8_t iot_proto_uplayer_data_recv_func(uint8_t *buf, uint16_t len) { /* extern sdk need parser uart data when recved */ return iot_proto_task_post_uart_cmd(buf, len, 0); } #else /* * uart drver calls, running in uart driver task. * @buf: input data pointer * @len: data len */ uint8_t iot_proto_uplayer_data_recv_func(uint8_t *buf, uint16_t len) { return iot_proto_data_parse_and_post(buf, len, iot_proto_task_post_uart_cmd, 0); } #endif /* hook */ static uint8_t iot_proto_parse_fn(uint8_t *data) { IOT_ASSERT(data); ge_frm_hdr_t *hdr = (ge_frm_hdr_t *)data; return hdr->fn; } /* hook */ uint8_t iot_proto_register_response_to_uplayer(PROTO_SENDTO_UPLAYER fn) { uint8_t ret = ERR_FAIL; if (fn) { prototask_contxt.proto_sendto_mainboard_fn = fn; ret = ERR_FAIL; } return ret; } /* hook */ uint8_t iot_proto_register_update_cco_mac_to_uplayer(PROTO_UPDATA_CCO_MAC fn) { uint8_t ret = ERR_FAIL; if (fn) { prototask_contxt.update_cco_mac = fn; ret = ERR_FAIL; } return ret; } uint8_t iot_proto_is_ready(void) { return prototask_contxt.local_dev.dev_ready ? 1 : 0; } /* handle mcu message */ static void iot_proto_mcu_msg_handle(iot_pkt_t *data, transmit_direction_e_t dir) { uint8_t fn; uint16_t cur_pos = 0; uint16_t total_len = (uint16_t)iot_pkt_data_len(data); uint8_t *data_buf = iot_pkt_data(data); uint8_t *tmp_buf; /* data cnt in each gree frame */ uint16_t data_len; uint8_t i; uint8_t ret = 0; transmit_direction_e_t tmp_dir; uint8_t fncode_hdlr_cnt = ARRAY_CNT(proto_subfn_hdl_tbl) - 1; #if PLC_SUPPORT_CCO_ROLE && ENABLE_GREE_UPGRADE uint8_t upgrade_fncode_hdlr_cnt = ARRAY_CNT(proto_upgrade_fnhdl_tbl) - 1; #endif /* handle each intact frame extracted from uart data buffer */ do { data_len = 0; tmp_buf = data_buf + cur_pos; if (cur_pos >= (total_len - 1)) { iot_cus_printf("[grpr][err] pos=%d >= %d - 1\n", cur_pos, total_len); break; } ret = ge_frame_data_len(tmp_buf, total_len - cur_pos, &data_len); if (ret != ERR_OK) { /* not get a complete frame */ iot_cus_printf("[grpr][err] incomplete frame\n"); break; } /* increase current pos to reach next intact frame */ cur_pos += data_len + GE_FRM_MIN_LEN; /* get fncode from gree frame */ fn = prototask_contxt.proto_pase_fn(tmp_buf); /* * if fn is extended fn,then direction must be * CMD_LOCAL_DOWN_LINK. */ if (PROTO_UPGRADE_DL == fn) { #if PLC_SUPPORT_CCO_ROLE && ENABLE_GREE_UPGRADE for (i = 0; i < upgrade_fncode_hdlr_cnt; i++) { if (fn == proto_upgrade_fnhdl_tbl[i].cmdid) { if (proto_upgrade_fnhdl_tbl[i].cmd_handle_fn) { proto_upgrade_fnhdl_tbl[i].cmd_handle_fn(tmp_buf, data_len + GE_FRM_MIN_LEN); } break; } } /* find no fncode in fncode table */ if (i == upgrade_fncode_hdlr_cnt) { iot_cus_printf("[glpr][err]not find %x in fncode table\n", fn); } #else iot_cus_printf("[glpr][info]upgrade %x not support\n",fn); #endif } else if (PROTO_GE_PLC_QUERY_CMD == fn || PROTO_GE_PLC_RESP_CMD == fn || PROTO_GE_PLC_SET_CMD == fn) { /* tag for direction send */ tmp_dir = CMD_LOCAL_DOWN_LINK; /* look for fncode handler to handle rx data from MCU */ for (i = 0; i < fncode_hdlr_cnt; i++) { if (fn == proto_subfn_hdl_tbl[i].cmdid) { if (proto_subfn_hdl_tbl[i].cmd_handle_fn) { proto_subfn_hdl_tbl[i].cmd_handle_fn(tmp_buf, data_len + GE_FRM_MIN_LEN, tmp_dir); } break; } } /* find no fncode in fncode table */ if (i == fncode_hdlr_cnt) { iot_cus_printf("[glpr][err] gree fn=0x%x not support\n", fn); } } } while (cur_pos < total_len); iot_pkt_free(data); } /* aggr received gree frame, cached to report mcu once */ static void iot_proto_monitor_timeout_trigger_send(void) { if (glb_ul_data_len > 0) { iot_pkt_t *data = iot_pkt_alloc(glb_ul_data_len, IOT_GREE_APP_MID); IOT_ASSERT(data); iot_pkt_put(data, glb_ul_data_len); /* copy data from glb_ul_tmp_buf to packet */ os_mem_cpy(iot_pkt_data(data), glb_ul_tmp_buf, glb_ul_data_len); /* to pick up DL645 frame and modbus frame in the FEA0 frame in data */ iot_handle_ge_from_plc(data); /* report gree frame to MCU */ iot_proto_send_to_mainboard(data); /* clear data buffer */ os_mem_set(glb_ul_tmp_buf, 0, glb_ul_data_len); glb_ul_data_len = 0; } } static void iot_proto_query_mac_timeout_trigger_send(void) { /* baud_index 1:9600, baud_index 2:2400 */ uint8_t baud_inx[]= {2, 1}; if (prototask_contxt.macaddr_set) { /* mac setted */ return; } if (prototask_contxt.detect_devmac_cnt < STA_DETECTED_MAC_MAX_CNT) { /* set baud */ iot_grapp_modify_uart_param( baud_inx[prototask_contxt.detect_devmac_cnt % 2], IOT_UART_PARITY_EVEN, IOT_UART_DLEN_8_BITS, IOT_UART_STOP_1_BITS); prototask_contxt.detect_devmac_cnt++; iot_grapp_set_uart_config(greeapp->uart_com); /* send cmd query mac */ iot_proto_query_mcu_mac(); /* restart timer */ os_start_timer(prototask_contxt.detect_timer, PROTO_TIMER_QUERY_MAC_TIMEOUT_INTVL); return; } /*timeout set mac */ iot_proto_set_local_mac(); } /* cmd response time out */ static void iot_proto_wait_response_timeout_trigger_send(void) { proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get(); uint32_t do_clean; switch (sm->state) { case PROTO_CMD_WAIT_WHITE_LIST_SET: case PROTO_CMD_WAIT_PAIR_TABLE_SET: { iot_proto_wl_pt_remote_set_timeout(sm->state, sm->dir, sm->seq, sm->dev.mac); /* fail do clean */ iot_proto_whitelist_state_init(); iot_proto_pairtable_state_init(); do_clean = 1; break; } case PROTO_CMD_WAIT_RMT_WHITELIST_RESP: { IOT_ASSERT(CMD_REMOTE_UP_LINK == sm->dir); iot_proto_wl_pt_remote_query_timeout_from_mcu(sm->state); do_clean = 1; break; } case PROTO_CMD_WAIT_TOPO_RESP: { IOT_ASSERT(CMD_REMOTE_UP_LINK == sm->dir); iot_proto_wait_rmt_topo_resp_timeout(sm); do_clean = 1; break; } case PROTO_CMD_WAIT_MAC_RESP: case PROTO_CMD_WAIT_IP_RESP: case PROTO_CMD_WAIT_SWVER_RESP: case PROTO_CMD_WAIT_BOOT_INFO_RESP: case PROTO_CMD_WAIT_PLCTXRX_CONFIG_RESP: case PROTO_CMD_WAIT_PASSD_RESP: case PROTO_CMD_WAIT_NET_STS_RESP: case PROTO_CMD_WAIT_PLC_STS_RESP: case PROTO_CMD_WAIT_AVAIL_NETWORK_RESP: case PROTO_CMD_WAIT_GREE_STS_RESP: case PROTO_CMD_WAIT_NTB_RESP: case PROTO_CMD_WAIT_FB_BITMAP_RESP: case PROTO_CMD_WAIT_FIX_RATE_MODE_RESP: case PROTO_CMD_WAIT_WORK_BAND_RESP: case PROTO_CMD_DL645_WAIT_TOPO_INFO_RESP: { /* we believe local not timeout */ do_clean = 1; break; } case PROTO_CMD_WAIT_CMD_CFM: { IOT_ASSERT(CMD_REMOTE_UP_LINK == sm->dir); iot_proto_wait_cmd_cfm_timeout(sm); do_clean = 1; break; } default: do_clean = 0; break; } if (do_clean) { /* reinit cmd handle state */ iot_proto_cmd_handle_state_init(); /* handle next saved cmd, if we have */ iot_proto_saved_msg_handle(); } } static void iot_proto_timer_msg_handle(iot_task_msg_t *msg) { iot_proto_msg_t *task_msg; IOT_ASSERT(msg); task_msg = (iot_proto_msg_t*)msg; switch (task_msg->msg.id) { case PROTO_TIMER_MONITOR_TIMEOUT: { /* ul data aggr timer */ iot_proto_monitor_timeout_trigger_send(); break; } case PROTO_TIMER_QUERY_MAC_TIMEOUT: { /* ask mcu for mac addr timer */ iot_proto_query_mac_timeout_trigger_send(); break; } case PROTO_TIMER_WAIT_RESP_TIMEOUT: { /* mcu cmd response timeout */ iot_proto_wait_response_timeout_trigger_send(); break; } case PROTO_TIMER_REBOOT_STA_TIMEOUT: { /* delay reboot */ iot_proto_reboot_delay_timeout_handler(); break; } case PROTO_TIMER_STATISTIC: { iot_proto_statistic_timer_timeout_handler(); break; } case PROTO_TIMER_STA_LEAVE_TIMEOUT: { /* monitor leave net, need indicate to cco active. */ iot_proto_sta_leave_delay_timeout_handler(); break; } case PROTO_TIMER_UPDATE_STATE_TIMEOUT: { #if PLC_SUPPORT_CCO_ROLE && ENABLE_GREE_UPGRADE /* update upgrade state timer */ iot_proto_update_sta_upgrade_status(); #endif break; } case PROTO_TIMER_BRD_PKT_WINDOW_RPT: { iot_proto_brd_data_rpt_window_timer_handler(); break; } case PROTO_TIMER_PAGING_TIMEOUT: { iot_proto_sta_paging_timer_handler(); break; } case PROTO_TIMER_TRIAL_RUN_CHECK: { iot_proto_check_trial_run_pass(); break; } case PROTO_TIMER_645_LOCAL_MODE: { #if PLC_SUPPORT_STA_ROLE iot_proto_645_local_mode_timer_handler(); #endif break; } case PROTO_START_EDGE_TMR_ID: { post_monitor_start_timer_msg_handler(); break; } default: break; } } uint16_t iot_proto_get_plc_data_len(uint8_t *src_data, uint16_t data_len) { uint16_t frm_len = 0; if((data_len >= GE_FRM_DATA_CNT_FIELD_LEN + GE_FRM_ID_FIELD_LEN) && (src_data != NULL)) { IOT_ASSERT(src_data[0] <= GE_FRM_PLD_MAX_LEN); frm_len = ACQUIRE_DATA_LEN(src_data[0]) + GE_FRM_DATA_CNT_FIELD_LEN + GE_FRM_ID_FIELD_LEN; if (src_data[1] == PROTO_GE_PLC_SET_CMD && src_data[2] == PROTO_GE_DATA_CMD) { /* if data extend,frame len is need to add GE_EXT_DATA_LEN */ if (src_data[4] & GE_FRM_DATA_EXT_FLAG) { frm_len += GE_EXT_DATA_LEN; } } } return frm_len; } static uint16_t iot_proto_plc_data_group_frame(uint8_t *dst, uint8_t *src, uint16_t src_len) { /** * payload of gree frame * field:| data cnt | id | data | * oct :| 1 B | 4B | data cnt B | */ uint16_t src_frm_len = 0; IOT_ASSERT(src && dst); uint8_t *tmp_buf = dst; uint16_t check_sum = 0; ge_extend_fn_hdr_t *dst_hdr; /* add preamble */ *((uint16_t *)tmp_buf) = GE_FRM_PREAMBLE_CODE; tmp_buf += GE_FRM_PREAMBLE_FIELD_LEN; /* get net payload len */ src_frm_len = iot_proto_get_plc_data_len(src, src_len); /* add payload */ if (src_frm_len) { os_mem_cpy(tmp_buf, src, src_frm_len); dst_hdr = (ge_extend_fn_hdr_t*)dst; /* set received connless type */ if (dst_hdr->hdr.fn == PROTO_GE_PLC_SET_CMD && dst_hdr->subfn == PROTO_GE_DATA_CMD && prototask_contxt.rx_info.rx_type) { /* recv data frame, change receive connless type */ ge_frame_data_send_set_subfn160_t *data_frame = (ge_frame_data_send_set_subfn160_t *)dst; data_frame->recv_connless |= 1; } tmp_buf += src_frm_len; /* add check sum */ check_sum = ge_frm_checksum_calc(dst, src_frm_len + GE_FRM_PREAMBLE_FIELD_LEN); *tmp_buf = (uint8_t)(check_sum & 0xFF); #if GE_CRC_ENABLE *(tmp_buf + 1) = (uint8_t)(check_sum >> 8); #endif tmp_buf += GE_FRM_CHECKSUM_FIELD_LEN; /* add tail */ *tmp_buf = 0xFF; } return src_frm_len; } /* local txrx response handle */ static void iot_proto_plctxrx_cmd_handle(iot_pkt_t *data, transmit_direction_e_t dir) { uint16_t buf_len = (uint16_t)iot_pkt_data_len(data); uint8_t *buf = iot_pkt_data(data); uint8_t fn = 0, subfn = 0; uint8_t ret; plctxrx_cmd_resp_t *cmd = (plctxrx_cmd_resp_t *)buf; iot_cus_printf("[glpr]cid==%d, opcode=%d dlen=%d\n", cmd->cid.cid, cmd->cid.opcode, cmd->dlen); ret = iot_proto_plctxtx_fn_subfn_get(cmd, &fn, &subfn); IOT_ASSERT(!ret); uint8_t fncode_hdlr_cnt = sizeof(proto_subfn_hdl_tbl)/sizeof(proto_fnhdl_tbl_t) - 1; uint8_t i; iot_cus_printf("[glpr]plctxrx cmd fn=%x, subfn=%d\n",fn, subfn); for (i = 0; i < fncode_hdlr_cnt; i++) { if (proto_subfn_hdl_tbl[i].cmdid == fn) { proto_subfn_hdl_tbl[i].cmd_handle_fn(buf, buf_len, dir); break; } } IOT_ASSERT(i < fncode_hdlr_cnt); iot_pkt_free(data); } static void iot_proto_plc_data_handle(iot_pkt_t *data, transmit_direction_e_t dir) { uint16_t pos = 0; uint16_t buf_len = (uint16_t)iot_pkt_data_len(data); uint8_t *buf = iot_pkt_data(data); uint8_t *ptr = glb_ul_tmp_buf; bool_t need_report = false; bool_t is_win_cached = false; uint8_t i; transmit_direction_e_t tmp_dir; uint8_t fncode_hdlr_cnt = sizeof(proto_subfn_hdl_tbl)/sizeof(proto_fnhdl_tbl_t) - 1; iot_pkt_t *tmp_pkt = NULL; uint8_t *tmp_buf; tmp_pkt = iot_pkt_alloc(GE_EXT_DATA_FRM_MAX_LEN, IOT_GREE_APP_MID); IOT_ASSERT(tmp_pkt); iot_pkt_put(tmp_pkt, GE_EXT_DATA_FRM_MAX_LEN); tmp_buf = iot_pkt_data(tmp_pkt); os_mem_set(tmp_buf, 0, GE_EXT_DATA_FRM_MAX_LEN); /* get rxinfo */ plctxrx_rx_data_info_t *rxinfo = (plctxrx_rx_data_info_t *)buf; /* point to data & get data len */ buf = (uint8_t *)(rxinfo + 1); buf_len -= sizeof(*rxinfo); /* save remote device info */ os_mem_cpy(&prototask_contxt.rx_info, rxinfo, sizeof(*rxinfo)); /* disable up uart cache timer */ if (os_is_timer_active(prototask_contxt.uart_monitor_timer)) { os_stop_timer(prototask_contxt.uart_monitor_timer); iot_task_clean_msg(prototask_contxt.task_handle, PROTO_TIMER_MSG, PROTO_TIMER_MONITOR_TIMEOUT); } /* maybe a big buffer,need to extract each intact gree frame */ while (pos < buf_len) { uint8_t fn; uint16_t src_frame_len; /* TODO once gree enlarge pkt size, the local vair is not suitable */ uint16_t tmp_buf_len = GE_FRM_PREAMBLE_FIELD_LEN + GE_FRM_CHECKSUM_FIELD_LEN + GE_FRM_TAIL_FILED_LEN; /* pure payload len */ src_frame_len = iot_proto_plc_data_group_frame(tmp_buf, &buf[pos], buf_len - pos); /* full pkt len */ tmp_buf_len += src_frame_len; /* move analysis mark ahead */ pos += src_frame_len; /* get fn handler */ fn = prototask_contxt.proto_pase_fn(tmp_buf); prototask_contxt.num_fn_received++; iot_cus_printf("[glpr]plc_data_handle:fn=0x%x,dir=%d,src_frame_len:%d," "total:%d,\n", fn, dir, src_frame_len, prototask_contxt.num_fn_received); /* * if fn is extended fn,then direction must be * CMD_REMOTE_UP_LINK. since this is plc data receive path. * if FE A0 extend data frame received, it can't be handled here, * uart_monitor_timer will dump this frame. */ if (PROTO_GE_PLC_QUERY_CMD == fn || PROTO_GE_PLC_RESP_CMD == fn || PROTO_GE_PLC_SET_CMD == fn) { tmp_dir = CMD_REMOTE_UP_LINK; iot_common_bin_dump(tmp_buf, tmp_buf_len); /* look for fncode handler to handle frame from plc */ for (i = 0; i < fncode_hdlr_cnt; i++) { if (fn == proto_subfn_hdl_tbl[i].cmdid) { /* increase each fn counter */ proto_subfn_hdl_tbl[i].cmd_num++; /* check if this frame should be reported to MCU. */ need_report = proto_subfn_hdl_tbl[i].cmd_handle_fn(tmp_buf, tmp_buf_len, tmp_dir); is_win_cached = iot_proto_cache_data_for_window_rpt(tmp_buf, tmp_buf_len, tmp_dir); break; } } IOT_ASSERT(i < fncode_hdlr_cnt); } if (!need_report) continue; /* each time report one fn to MCU */ prototask_contxt.num_fn_send++; iot_cus_printf("[glpr] report mcu fnnum:%d,fn=0x%x\n", prototask_contxt.num_fn_send, fn); if (is_win_cached == false) { /* group a big packet to report to MCU */ if (glb_ul_data_len + tmp_buf_len <= UL_TMP_BUF_LEN) { ptr += glb_ul_data_len; os_mem_cpy(ptr, tmp_buf, tmp_buf_len); glb_ul_data_len += tmp_buf_len; } else { iot_pkt_t *pkt_data = iot_pkt_alloc(glb_ul_data_len,IOT_GREE_APP_MID); IOT_ASSERT(pkt_data); /* make tail pointer of packet ponit to data tail */ iot_pkt_put(pkt_data, glb_ul_data_len); /* copy data to packet data field */ os_mem_cpy(iot_pkt_data(pkt_data), glb_ul_tmp_buf, glb_ul_data_len); /* to pick up DL645 frame and modbus frame in the FEA0 frame in data */ iot_handle_ge_from_plc(pkt_data); /* report gree frame to MCU */ iot_proto_send_to_mainboard(pkt_data); os_mem_set(glb_ul_tmp_buf, 0, glb_ul_data_len); /* don't forget current handle pkt */ glb_ul_data_len = tmp_buf_len; os_mem_cpy(glb_ul_tmp_buf, tmp_buf, glb_ul_data_len); } } /* point ptr to head everytime. since re-point ptr every time used */ ptr = glb_ul_tmp_buf; } /* arm uplink uart timer */ if (glb_ul_data_len > 0) { os_start_timer(prototask_contxt.uart_monitor_timer, PROTO_TIMER_MONITOR_TIMEOUT_INTVL); } if (tmp_pkt) { iot_pkt_free(tmp_pkt); } iot_pkt_free(data); return; } static void iot_proto_plc_msg_handle(iot_task_msg_t *msg) { iot_proto_msg_t *task_msg; IOT_ASSERT(msg); task_msg = (iot_proto_msg_t*)msg; switch (task_msg->msg.id) { case PROTO_PLC_RX_DATA_MSG: { iot_proto_plc_data_handle(task_msg->data1, (transmit_direction_e_t)task_msg->data2); break; } case PROTO_PLCTXRX_RX_CMD_MSG: { iot_proto_plctxrx_cmd_handle(task_msg->data1, (transmit_direction_e_t)task_msg->data2); break; } default: if (task_msg->data1) iot_pkt_free(task_msg->data1); break; } } #if PLC_SUPPORT_CCO_ROLE static void iot_proto_cco_cli_rpt_wl_state(uint8_t req_id) { iot_pkt_t *buf_pkt; iot_cli_sg_rpt_wl_state_t *rsp; buf_pkt = iot_pkt_alloc(iot_cli_sg_get_headroom_req() + sizeof(*rsp), IOT_GREE_APP_MID); IOT_ASSERT(buf_pkt); rsp = (iot_cli_sg_rpt_wl_state_t*)iot_pkt_reserve(buf_pkt, iot_cli_sg_get_headroom_req()); rsp->state = prototask_contxt.flashinfo.public.pub.wl_state; iot_cli_sg_send_data_to_cli_interface(buf_pkt, IOT_CLI_SG_MSG_RPT_WL_STATE, req_id); } static void iot_proto_cco_cli_rpt_wl(uint8_t req_id, uint16_t start_index, uint16_t count) { iot_cli_sg_rpt_wl_t* rsp; uint16_t rsp_len; iot_pkt_t *buf_pkt; uint16_t i; if (start_index > prototask_contxt.dev_lst.valid_dev_cnt) { count = 0; } else if (start_index + count - 1 > prototask_contxt.dev_lst.valid_dev_cnt) { count = prototask_contxt.dev_lst.valid_dev_cnt - start_index + 1; } /* allocate buffer for response */ rsp_len = sizeof(iot_cli_sg_rpt_wl_t); rsp_len += count * sizeof(rsp->node_info[0]); rsp_len += iot_cli_sg_get_headroom_req(); buf_pkt = iot_pkt_alloc(rsp_len, IOT_GREE_APP_MID); IOT_ASSERT(buf_pkt); /* fill response info */ rsp = (iot_cli_sg_rpt_wl_t*)iot_pkt_reserve(buf_pkt, iot_cli_sg_get_headroom_req()); rsp->total_count = prototask_contxt.dev_lst.valid_dev_cnt; rsp->rsp_count = (uint8_t)count; for (i = 0; i < rsp->rsp_count; ++i) { rsp->node_info[i].proto_type = IOT_CLI_SG_PROTO_TYPE_RAW_DATA; iot_mac_addr_cpy(rsp->node_info[i].mac, prototask_contxt.dev_lst.dev[start_index+i-1].mac); iot_mac_addr_reverse(rsp->node_info[i].mac); } iot_cli_sg_send_data_to_cli_interface(buf_pkt, IOT_CLI_SG_MSG_RPT_WL, req_id); } static void iot_proto_cco_cli_add_wl(uint8_t req_id, iot_cli_sg_add_wl_t *req) { iot_pkt_t *buf_pkt; iot_cli_sg_result_t *rsp; proto_dev_t wlist; uint16_t i; buf_pkt = iot_pkt_alloc(iot_cli_sg_get_headroom_req() + sizeof(*rsp), IOT_GREE_APP_MID); IOT_ASSERT(buf_pkt); iot_proto_whitelist_state_init(); for (i = 0; i < req->count; i++) { iot_mac_addr_reverse(req->node_info[i].mac); if ((0 > iot_proto_check_mac_exists(req->node_info[i].mac, prototask_contxt.dev_lst.dev, prototask_contxt.dev_lst.valid_dev_cnt)) && (0 > iot_proto_check_mac_exists(req->node_info[i].mac, prototask_contxt.dev_lst.dev_tmp, prototask_contxt.dev_lst.valid_dev_tmp_cnt))) { /* mac not in dev_tmp and dev, need add */ os_mem_set(&wlist, 0x00, sizeof(wlist)); iot_mac_addr_cpy(wlist.mac, req->node_info[i].mac); iot_proto_add_wl_to_tmp(&wlist); } } if (prototask_contxt.dev_lst.valid_dev_tmp_cnt > 0) { iot_proto_add_wl_tmp2formal(); iot_proto_whitelist_add_remove(GE_PROTO_ACTION_ADD, NULL, false); iot_proto_wl_save2flash(); iot_proto_whitelist_state_init(); } rsp = (iot_cli_sg_result_t*)iot_pkt_reserve(buf_pkt, iot_cli_sg_get_headroom_req()); rsp->result = ERR_OK; iot_cli_sg_send_data_to_cli_interface(buf_pkt, IOT_CLI_SG_MSG_RPT_ADD_WL, req_id); } static void iot_proto_cco_cli_rm_wl(uint8_t req_id, iot_cli_sg_rm_wl_t *req) { iot_pkt_t *buf_pkt; iot_cli_sg_result_t *rsp; proto_dev_t wlist; uint16_t i; buf_pkt = iot_pkt_alloc(iot_cli_sg_get_headroom_req() + sizeof(*rsp), IOT_GREE_APP_MID); IOT_ASSERT(buf_pkt); rsp = (iot_cli_sg_result_t*)iot_pkt_reserve(buf_pkt, iot_cli_sg_get_headroom_req()); iot_proto_whitelist_state_init(); for (i = 0; i < req->count; i++) { iot_mac_addr_reverse(req->mac_addr[i]); os_mem_set(&wlist, 0x00, sizeof(wlist)); iot_mac_addr_cpy(wlist.mac, req->mac_addr[i]); iot_proto_add_wl_to_tmp(&wlist); } iot_proto_whitelist_add_remove(GE_PROTO_ACTION_DEL, NULL, false); iot_proto_del_wl_from_formal(); iot_proto_wl_save2flash(); iot_proto_whitelist_state_init(); rsp->result = ERR_OK; iot_cli_sg_send_data_to_cli_interface(buf_pkt, IOT_CLI_SG_MSG_RPT_RM_WL, req_id); } static void iot_proto_cco_cli_set_wl_state(uint8_t req_id, iot_cli_sg_set_wl_state_t *req) { iot_pkt_t *buf_pkt; iot_cli_sg_result_t *rsp; buf_pkt = iot_pkt_alloc(iot_cli_sg_get_headroom_req() + sizeof(*rsp), IOT_GREE_APP_MID); IOT_ASSERT(buf_pkt); rsp = (iot_cli_sg_result_t*)iot_pkt_reserve(buf_pkt, iot_cli_sg_get_headroom_req()); rsp->result = ERR_OK; if (req->state != prototask_contxt.flashinfo.public.pub.wl_state) { if (req->state) { iot_proto_whitelist_en_disable(GE_PROTO_WL_ENABLE, false); } else { iot_proto_whitelist_en_disable(GE_PROTO_WL_DISABLE, false); } rsp->result = ERR_OK; } iot_cli_sg_send_data_to_cli_interface(buf_pkt, IOT_CLI_SG_MSG_RPT_SET_WL_STATE, req_id); } static void iot_proto_cco_cli_msg_handle(iot_proto_msg_t *msg) { iot_pkt_t *pkt = (iot_pkt_t *)msg->data1; iot_cli_sg_msg_header_t *hdr; if (NULL == pkt) { return; } hdr = (iot_cli_sg_msg_header_t *)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD); switch (hdr->msg_id) { case IOT_CLI_SG_MSG_QUERY_WL_STATE: { iot_proto_cco_cli_rpt_wl_state(hdr->req_id); break; } case IOT_CLI_SG_MSG_QUERY_WL: { iot_cli_sg_query_wl_t *req; req = (iot_cli_sg_query_wl_t *)iot_pkt_data(pkt); iot_proto_cco_cli_rpt_wl(hdr->req_id, req->start_index, req->count); break; } case IOT_CLI_SG_MSG_ADD_WL: { iot_cli_sg_add_wl_t *req; req = (iot_cli_sg_add_wl_t *)iot_pkt_data(pkt); iot_proto_cco_cli_add_wl(hdr->req_id, req); break; } case IOT_CLI_SG_MSG_RM_WL: { iot_cli_sg_rm_wl_t *req; req = (iot_cli_sg_rm_wl_t *)iot_pkt_data(pkt); iot_proto_cco_cli_rm_wl(hdr->req_id, req); break; } case IOT_CLI_SG_MSG_SET_WL_STATE: { iot_cli_sg_set_wl_state_t *req; req = (iot_cli_sg_set_wl_state_t *)iot_pkt_data(pkt); iot_proto_cco_cli_set_wl_state(hdr->req_id, req); break; } default: { iot_cus_printf("[gepr]cco_cli_msg, unknown msg_id=%d\n", hdr->msg_id); break; } } iot_pkt_free(pkt); } static void iot_proto_cco_cctt_msg_handle(iot_proto_msg_t *msg) { IOT_ASSERT(msg); uint8_t *data; uint8_t data_len; iot_pkt_t *pkt; iot_proto_msg_t *task_msg = (iot_proto_msg_t*)msg; pkt = task_msg->data1; if (pkt == NULL) { return; } data = iot_pkt_data(pkt); data_len = iot_pkt_data_len(pkt); switch (task_msg->msg.id) { case CCTT_REBOOT_CCO: { iot_cctt_reboot_cco(data, data_len); break; } case CCTT_REBOOT_STA: { iot_cctt_reboot_sta(data, data_len); break; } case CCTT_QUERY_TOPO: { iot_cctt_query_topo(data, data_len); break; } case CCTT_ADD_WHITELIST: { iot_cctt_set_whitelist(data, data_len, GE_PROTO_ACTION_ADD); break; } case CCTT_DEL_WHITELIST: { iot_cctt_set_whitelist(data, data_len, GE_PROTO_ACTION_DEL); break; } case CCTT_QUERY_WHITELIST: { iot_cctt_read_whitelist(data, data_len); break; } case CCTT_SET_WL_STATE: { iot_cctt_set_wl_state(data, data_len); break; } case CCTT_CLR_WHITELIST: { iot_cctt_clear_whitelist(data, data_len); break; } case CCTT_CHECK_WL_MAC: { iot_cctt_check_whitelist_mac(data, data_len); break; } case CCTT_SET_PLC_NW: { iot_cctt_set_plc_nw(data, data_len); break; } case CCTT_READ_PLC_NW: { iot_cctt_get_plc_nw(); break; } case CCTT_REBOOT_MAC_LIST_PCO: { iot_cctt_reboot_mac_list_pco(data, data_len); break; } case CCTT_DELAYTIME: { iot_cctt_delaytime(data, data_len); break; } case CCTT_SET_RS485_CONFIG: { iot_cctt_set_rs485_config(data, data_len); break; } case CCTT_READ_RS485_CONFIG: { iot_cctt_read_rs485_config(data, data_len); break; } case CCTT_RS485_TRANS_DL645: { iot_cctt_rs485_trans_dl645(data, data_len); break; } case CCTT_RS485_TRANS_MODBUS: { iot_cctt_rs485_trans_modbus(data, data_len); break; } default: break; } iot_pkt_free(pkt); } /* handle dl645 topo resp */ bool_t iot_proto_cctt_dl645_topo_resp(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { plctxrx_cmd_resp_t *cmd; plctxrx_handle_topo_v2_t *topo_info; (void)dir; if (len > sizeof(plctxrx_cmd_resp_t) + sizeof(plctxrx_handle_topo_v2_t)) { cmd = (plctxrx_cmd_resp_t *)data; topo_info = (plctxrx_handle_topo_v2_t *)cmd->data; iot_cco_resp_topo_to_cctt(topo_info->node, cmd->index.total, topo_info->cnt, !cmd->done); iot_cco_resp_topo_set_query_info(cmd->done, topo_info->cnt); } iot_proto_cmd_handle_state_init(); return 0; } /** * @brief iot_cco_handle_local_dl645_cmd() - handle the local cmd * data is del 0x33 * @param pkt: point to the dl645 pkt data */ void iot_cco_handle_local_dl645_cmd(iot_pkt_t *pkt) { iot_cctt_handle_local_dl645_cmd(pkt); } /** * @brief iot_handle_cco_delay_tm_ge_rm_pad_data() - cco handle the delay time message from plc * @param data_input: data in ptr * @param data_output: data out ptr * @return: ge frm len */ uint8_t iot_handle_cco_delay_tm_ge_rm_pad_data(uint8_t *data_input, uint8_t *data_output) { uint8_t tmp_len = sizeof(ge_frame_delay_time_subfn166_t); uint8_t tail_len = sizeof(ge_frm_tail_t); ge_frm_tail_t *tail; ge_frame_delay_time_subfn166_t *frame = (ge_frame_delay_time_subfn166_t *)data_output; if (data_input == NULL || data_output == NULL) { iot_cus_printf("[err]%s data ptr is null\n", "delay tm"); return 0; } /* when FE A6 frame remove pad data, copy data_input to data_output, and recalculate data len and crc in data_output */ os_mem_cpy(data_output, data_input, tmp_len); frame->hdr.hdr.data_len = tmp_len + tail_len - GE_FRM_MIN_LEN; tail = (ge_frm_tail_t *)(data_output + tmp_len); tail->check_sum = ge_frm_checksum_calc(data_output, tmp_len); tail->tail = GE_FRM_TAIL_CODE; tmp_len += tail_len; return tmp_len; } #else /* PLC_SUPPORT_CCO_ROLE */ static void iot_proto_cco_cli_msg_handle(iot_proto_msg_t *msg) { if (msg->data1) iot_pkt_free(msg->data1); } static void iot_proto_cco_cctt_msg_handle(iot_proto_msg_t *msg) { if (msg->data1) iot_pkt_free(msg->data1); } bool_t iot_proto_cctt_dl645_topo_resp(uint8_t *data, uint16_t len, transmit_direction_e_t dir) { (void)data; (void)len; (void)dir; return 0; } #endif /* end PLC_SUPPORT_CCO_ROLE */ static void iot_proto_task_handle_msg(iot_task_h task_h, iot_task_msg_t *msg) { iot_proto_msg_t *task_msg; IOT_ASSERT(task_h == prototask_contxt.task_handle); IOT_ASSERT(msg); task_msg = (iot_proto_msg_t*)msg; switch (task_msg->msg.type) { /* handle msg from uart */ case PROTO_MCU_RX_MSG: { if (task_msg->msg.id == PROTO_MCU_RX_DL645_MSG) { #if PLC_SUPPORT_CCO_ROLE iot_cco_handle_local_dl645_cmd(task_msg->data1); #endif if (task_msg->data1) { iot_pkt_free(task_msg->data1); } } else { iot_proto_mcu_msg_handle(task_msg->data1, (transmit_direction_e_t)task_msg->data2); } break; } /* handle msg from plctxrx layer */ case PROTO_PLC_RX_MSG: { iot_proto_plc_msg_handle(&task_msg->msg); break; } /* handle msg from timer */ case PROTO_TIMER_MSG: { iot_proto_timer_msg_handle(&task_msg->msg); break; } case PROTO_CUS_APP_MSG: { iot_proto_cus_app_msg_handle(&task_msg->msg); break; } case PROTO_CLI_MSG: { iot_proto_cco_cli_msg_handle(task_msg); break; } case PROTO_CCTT_MSG: { iot_proto_cco_cctt_msg_handle(task_msg); break; } case EDGE_UART_RX_MSG: case EDGE_INPUT_MSG: case EDGE_TIMER_MSG: case EDGE_INTERNAL_MSG: { iot_edge_state_machine(task_msg->msg.type, task_msg->msg.id, task_msg->data1); break; } case EDGE_OUTPUT_MSG: { iot_proto_edge_msg_output_msg_handler(task_msg->msg.id, task_msg->data1); break; } default: break; } iot_task_free_msg(prototask_contxt.task_handle, &task_msg->msg); } static void iot_proto_task_handle_msg_cancel(iot_task_h task_h, iot_task_msg_t *msg) { iot_proto_msg_t *task_msg; IOT_ASSERT(task_h == prototask_contxt.task_handle); IOT_ASSERT(msg); task_msg = (iot_proto_msg_t*)msg; switch (task_msg->msg.type) { case PROTO_MCU_RX_MSG: { if (task_msg->data1) iot_pkt_free(task_msg->data1); break; } case PROTO_PLC_RX_MSG: { if (task_msg->data1) iot_pkt_free(task_msg->data1); break; } case PROTO_TIMER_MSG: { break; } case PROTO_CLI_MSG: { if (task_msg->data1) iot_pkt_free(task_msg->data1); break; } default: break; } iot_task_free_msg(prototask_contxt.task_handle, &task_msg->msg); } /* cut preamble, checksum and tail field of a inract frame */ /* send data to plctxrx */ void iot_proto_data_send_to_plctxrx(uint8_t *data, uint16_t len, protpkt_tx_info_t *txinfo) { iot_pkt_t *send_pkt; uint8_t *ptr; uint16_t org_frm_len; uint16_t cur_frm_len; uint16_t i; uint8_t role = prototask_contxt.local_dev.nw_role; bool_t is_ready = prototask_contxt.local_dev.dev_ready; uint16_t total_frm_len = 0; switch (role) { case IOT_PLC_DEV_ROLE_STA: case IOT_PLC_DEV_ROLE_PCO: { if (!is_ready) { /* send connless packet */ txinfo->force_tx_connless = 1; txinfo->need_ack = false; iot_cus_printf("[glpr][info]STA is not ready,send connless pkt!\n"); } break; } case IOT_PLC_DEV_ROLE_CCO: { if (!is_ready) { iot_cus_printf("[glpr][err]CCO not ready!\n"); return; } break; } default: IOT_ASSERT(0); break; } send_pkt = iot_pkt_alloc(len, IOT_GREE_APP_MID); if (!send_pkt) { IOT_ASSERT(send_pkt); return; } ptr = data; /** del preamble code,checksum code and tail * code of each gree frame */ for (i = 0; i < len;) { org_frm_len = ACQUIRE_DATA_LEN(ptr[GE_FRM_DATA_LEN_POS]) + GE_FRM_MIN_LEN; if(ptr[GE_FRM_DATA_EXT_LEN_POS] & GE_FRM_DATA_EXT_FLAG) { org_frm_len += GE_EXT_DATA_LEN; } IOT_ASSERT(org_frm_len >= GE_FRM_MIN_LEN && org_frm_len <= GE_EXT_DATA_FRM_MAX_LEN); cur_frm_len = org_frm_len - GE_FRM_PREAMBLE_FIELD_LEN - GE_FRM_CHECKSUM_FIELD_LEN - GE_FRM_TAIL_FILED_LEN; os_mem_cpy(iot_pkt_data(send_pkt) + total_frm_len, ptr + GE_FRM_PREAMBLE_FIELD_LEN, cur_frm_len); total_frm_len += cur_frm_len; iot_pkt_put(send_pkt, cur_frm_len); /*+1 means move one byte forward */ i += org_frm_len + 1; ptr += org_frm_len; } if (prototask_contxt.gree_data_send_cb) { /* here send data to remote peer */ prototask_contxt.gree_data_send_cb(iot_pkt_data(send_pkt), (uint16_t)iot_pkt_data_len(send_pkt), txinfo); } iot_pkt_free(send_pkt); } void iot_proto_remote_cmd_send_to_plctxrx (uint8_t *data, uint16_t len, protpkt_tx_info_t *txinfo) { iot_cus_printf("[glpr]cmd_send_to_plctxrx:\n"); iot_common_bin_dump(data, len); iot_proto_data_send_to_plctxrx(data, len, txinfo); } /* prot layer copy txrx msdu agin in one buffer. txrx split effort no used. TODO, remove txrx layer split effort. make it more general */ uint8_t iot_proto_plc_data_recv_func(protpkt_list_t *report_framelist, plctxrx_rx_data_info_t *rxinfo) { IOT_ASSERT(report_framelist && rxinfo && (report_framelist->frame_cnt > 0) && (report_framelist->total_len > 0)); uint8_t *buf, *tmp; list_node_t* node = report_framelist->list_head; /* alloc pkt */ iot_pkt_t *pkt = iot_pkt_alloc(report_framelist->total_len+sizeof(*rxinfo), \ IOT_GREE_APP_MID); IOT_ASSERT(pkt); buf = iot_pkt_data(pkt); os_mem_cpy(buf, rxinfo, sizeof(*rxinfo)); iot_pkt_put(pkt, sizeof(*rxinfo)); /* copy data from each node */ tmp = iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL); while (report_framelist->frame_cnt--) { IOT_ASSERT(node); os_mem_cpy(tmp, node->data, node->len); iot_pkt_put(pkt, node->len); tmp += node->len; node = node->next; } IOT_ASSERT(!node && (buf+report_framelist->total_len+sizeof(*rxinfo) == tmp)); iot_proto_task_post_msg(PROTO_PLC_RX_MSG, PROTO_PLC_RX_DATA_MSG, pkt, DATA_UP_LINK, IOT_PROTO_TASK_QUEUE_LP); return ERR_OK; } /* local txrx cmd response */ uint8_t iot_proto_plctxrx_cmd_resp_recv_func(iot_pkt_t *data) { IOT_ASSERT(data); iot_proto_task_post_msg(PROTO_PLC_RX_MSG, PROTO_PLCTXRX_RX_CMD_MSG, data, CMD_LOCAL_UP_LINK, IOT_PROTO_TASK_QUEUE_LP); return ERR_OK; } /* callback for uart recv timeout checking timer */ static void iot_proto_uart_monitor_timeout_timer( timer_id_t timer_id, void * arg) { (void)timer_id; (void)arg; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_MONITOR_TIMEOUT, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } /* callback for querying MCU mac timeout checking timer */ static void iot_proto_query_mac_timeout_timer( timer_id_t timer_id, void * arg) { (void)timer_id; (void)arg; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_QUERY_MAC_TIMEOUT, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } /* callback for update upgrade state timeout checking timer */ static void iot_proto_update_upgrade_state_timeout_timer( timer_id_t timer_id, void * arg) { (void)timer_id; (void)arg; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_UPDATE_STATE_TIMEOUT, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } /* callback for waiting response timeout checking timer */ static void iot_proto_wait_resp_cmd_timeout_timer( timer_id_t timer_id, void * arg) { (void)timer_id; (void)arg; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_TIMER_WAIT_RESP_TIMEOUT, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } /* post dl645 command msg for handle */ uint8_t iot_proto_post_dl645_cmd_msg(uint8_t *data, uint16_t len) { iot_pkt_t *pkt; pkt = iot_pkt_alloc(len, IOT_GREE_APP_MID); if (pkt == NULL) { return ERR_NOMEM; } os_mem_cpy(iot_pkt_put(pkt, len), data, len); iot_proto_task_post_msg(PROTO_MCU_RX_MSG, PROTO_MCU_RX_DL645_MSG, pkt, DATA_DOWN_LINK, IOT_PROTO_TASK_QUEUE_LP); return ERR_OK; } /* below msg pool operation */ static proto_savedmsg_node_t *iot_proto_msgnode_alloc(iot_mem_pool_t *pool) { IOT_ASSERT(pool); proto_savedmsg_node_t *msgnode; msgnode = (proto_savedmsg_node_t *)iot_mem_pool_alloc(pool); return msgnode; } static uint32_t iot_proto_msgnode_free(iot_mem_pool_t *pool, proto_savedmsg_node_t *msgnode) { IOT_ASSERT(pool && msgnode); return iot_mem_pool_free(pool, msgnode); } static void iot_proto_savedmsg_list_push_backend(proto_msg_saved_list_t *list, list_node_t *node) { IOT_ASSERT(list && node); if (!list->head) { IOT_ASSERT(0 == list->depth); list->head = list->tail = node; } else { list->tail->next = node; list->tail = node; } list->depth++; node->next = NULL; return; } static proto_savedmsg_node_t * iot_proto_savedmsg_list_pop_front(proto_msg_saved_list_t *list) { IOT_ASSERT(list); list_node_t *link; proto_savedmsg_node_t *savedmsg_node; if (list->depth <= 0) return NULL; link = list->head; list->head = list->head->next; list->depth--; if (0 == list->depth) list->tail = NULL; savedmsg_node = container_of(link, proto_savedmsg_node_t, node); return savedmsg_node; } static void iot_proto_saved_msg_handle(void) { proto_savedmsg_node_t *savedmsg_node; proto_msg_saved_list_t *list = &prototask_contxt.saved_msg_list; uint16_t depth = list->depth; /* check if there are messages in msg saved list */ if (list->depth <= 0) return; while (depth--) { /* get fist cmd */ savedmsg_node = iot_proto_savedmsg_list_pop_front(list); IOT_ASSERT(savedmsg_node); /* post messgae and bring info with msg */ iot_proto_task_post_msg(savedmsg_node->msg_type, savedmsg_node->msg_id, savedmsg_node->data, (transmit_direction_e_t)savedmsg_node->dir, IOT_PROTO_TASK_QUEUE_LP); /* return handled cmd into cmd_q */ iot_proto_msgnode_free(saved_msg_q, savedmsg_node); } return; } void iot_proto_task_post_msg(uint16_t msg_type, uint16_t msg_id, void* data, transmit_direction_e_t dir, uint8_t prio) { iot_task_msg_t *msg; iot_proto_msg_t *task_msg; msg = iot_task_alloc_msg_with_reserved(prototask_contxt.task_handle, 0); if (!msg) { IOT_ASSERT(0); return; } task_msg = (iot_proto_msg_t*)msg; task_msg->msg.type = msg_type; task_msg->msg.id = msg_id; task_msg->data1 = data; task_msg->data2 = dir; iot_task_queue_msg(prototask_contxt.task_handle, &task_msg->msg, prio); } static void iot_proto_cus_app_msg_handle(iot_task_msg_t *msg) { iot_proto_msg_t *task_msg; IOT_ASSERT(msg); task_msg = (iot_proto_msg_t*)msg; switch (task_msg->msg.id) { case PROTO_CUS_APP_SAVE_PIB_MSG: iot_proto_handle_save_cus_app_info_to_pib(task_msg->data1); break; default: IOT_ASSERT(0); break; } } #if PLC_SUPPORT_CCO_ROLE /* for cli task register */ static void iot_proto_task_cli_callback(void *param, iot_pkt_t *pkt) { (void)param; iot_proto_task_post_msg(PROTO_CLI_MSG, 0, pkt, 0, IOT_PROTO_TASK_QUEUE_LP); } #endif /** * @brief iot_proto_custom_pib_info_load() - To load custom pib info * @param cus_pib_info: - point to custom pib info * @param size: - load custom pib info size need smaller than defined */ void iot_proto_custom_pib_info_load(void *cus_pib_info, uint8_t size) { if (size > 0 && size <= IOT_PROTO_CUST_APP_FLASH_SIZE) { os_mem_cpy(cus_pib_info, prototask_contxt.flashinfo.proto_prv.proto.custom_pib_info, size); } else { iot_cus_printf("[glpr][err]pib_info_load size=%d need <= %d!\n", size, IOT_PROTO_CUST_APP_FLASH_SIZE); } } /** * @brief iot_proto_custom_pib_info_save() - To save custom pib information * @param cus_pib_info: - point to custom pib info which recv from custom app * @param size: - save custom pib info size, need smaller than defined */ void iot_proto_custom_pib_info_save(void *cus_pib_info, uint8_t size) { iot_pkt_t *p_pkt; uint8_t *data; if (size > 0 && size <= IOT_PROTO_CUST_APP_FLASH_SIZE) { p_pkt = iot_pkt_alloc(size, IOT_GREE_APP_MID); if (!p_pkt) { iot_cus_printf("[glpr][err]No Mem!\n"); return; } data = iot_pkt_put(p_pkt, size); os_mem_cpy(data, cus_pib_info, size); iot_proto_task_post_msg(PROTO_CUS_APP_MSG, PROTO_CUS_APP_SAVE_PIB_MSG, p_pkt, 0, IOT_PROTO_TASK_QUEUE_LP); } else { iot_cus_printf("[glpr][err]pib_info_save size=%d need <= %d!\n", size, IOT_PROTO_CUST_APP_FLASH_SIZE); } } /** * @brief iot_proto_handle_save_cus_app_info_to_pib() - handle msg to save * custom app information to pib * @param data: pkt inlude led_info */ void iot_proto_handle_save_cus_app_info_to_pib(iot_pkt_t *data) { ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo; os_mem_cpy(p_flash->proto_prv.proto.custom_pib_info, iot_pkt_data(data), iot_pkt_data_len(data)); iot_proto_flashsave(p_flash); iot_pkt_free(data); return; } void iot_handle_ge_from_plc(iot_pkt_t *p_pkt) { /* the index of the input data */ uint16_t index = 0; /* the data length of the input pkt */ uint16_t input_data_len; /* the data length of the frame unpacked from ge frame */ uint16_t data_len_after_handle = 0; /* the data length of each data frame */ uint16_t frame_data_len; uint8_t* buf; ge_frame_data_send_set_subfn160_t *p_buf; ge_frame_delay_time_subfn166_t *p_tm_buf; ge_extend_fn_hdr_t *p_buf_hdr; buf = iot_pkt_data(p_pkt); input_data_len = iot_pkt_data_len(p_pkt); if (buf == NULL) { IOT_ASSERT(0); return; } while (index < input_data_len) { p_buf = (ge_frame_data_send_set_subfn160_t *)&buf[index]; p_tm_buf = (ge_frame_delay_time_subfn166_t *)&buf[index]; IOT_ASSERT(p_buf); IOT_ASSERT(p_tm_buf); if ((p_buf->hdr.hdr.fn == PROTO_GE_PLC_SET_CMD) && (p_buf->hdr.subfn == PROTO_GE_DATA_CMD) && (p_buf->resv == DL645_07_RESV0_RESV)) { frame_data_len = p_buf->hdr.hdr.data_len; #if PLC_SUPPORT_STA_ROLE /* If a dl645 frame is included in a FEA0 ge frame, the handling of frame may be three conditions: 1 get the dl645 frame and send it to the uart 2 get the extend frame and send it to the uart 3 handle it in local model the 3 condition won't send any data the uart, the data should be take away. the 1 and 2 condition should send data to uart, when those frames are being checked out, the function iot_handle_ge_to_dl645() will get the frames witch need to send to the uart and copy them to the front of buf closely. finally, the length of the frame in the buf is shorter than original length of buf, the data length of pkt should be shrinked to the finally length */ data_len_after_handle += iot_handle_ge_to_dl645(&buf[index], &buf[data_len_after_handle]); index += frame_data_len + sizeof(ge_frame_data_send_set_subfn160_t) + sizeof(ge_frm_tail_t) - IOT_MAC_ADDR_LEN; #else /* PLC_SUPPORT_STA_ROLE */ /* get other frame datas */ os_mem_cpy(&buf[data_len_after_handle], &buf[index + GE_FEA0_HEAD_LEN], frame_data_len - IOT_MAC_ADDR_LEN); data_len_after_handle += frame_data_len - IOT_MAC_ADDR_LEN; index += frame_data_len + sizeof(ge_frame_data_send_set_subfn160_t) + sizeof(ge_frm_tail_t) - IOT_MAC_ADDR_LEN; } else if ((p_tm_buf->hdr.hdr.fn == PROTO_GE_PLC_SET_CMD) && (p_tm_buf->hdr.subfn == PROTO_GE_DELAY_TM_CMD)) { if (p_tm_buf->resv == DL645_07_RESV0_RESV) { /* If the type pose of the FE A6 frame is DL645_TYPE, we need to reconstruct dl645 frame from ge frame */ frame_data_len = p_tm_buf->hdr.hdr.data_len; data_len_after_handle += iot_handle_cco_delay_tm_pack_ge_to_dl645 (&buf[index], &buf[data_len_after_handle]); index += frame_data_len + GE_FRM_MIN_LEN; } else if (p_tm_buf->resv == GE_TYPE) { /* If the type pose of the FE A6 frame is GE_TYPE, we need to remove pad data from ge frame */ frame_data_len = p_tm_buf->hdr.hdr.data_len; data_len_after_handle += iot_handle_cco_delay_tm_ge_rm_pad_data (&buf[index], &buf[data_len_after_handle]); index += frame_data_len + GE_FRM_MIN_LEN; } #endif /* end PLC_SUPPORT_STA_ROLE */ } else { p_buf_hdr = (ge_extend_fn_hdr_t *)&buf[index]; frame_data_len = p_buf_hdr->hdr.data_len; if (p_buf->data_ext_flag) { frame_data_len += GE_EXT_DATA_LEN; } os_mem_cpy(&buf[data_len_after_handle], &buf[index], GE_FRM_MIN_LEN + frame_data_len); index += GE_FRM_MIN_LEN + frame_data_len; data_len_after_handle += GE_FRM_MIN_LEN + frame_data_len; } } if (input_data_len > data_len_after_handle) { iot_pkt_shrink(p_pkt, input_data_len - data_len_after_handle); } } uint8_t is_edge_running(void) { return (prototask_contxt.edge_obj.uart_hdl != NULL); } void iot_edge_delay_start(void) { if (os_is_timer_active(prototask_contxt.edge_monitor_start_tmr)) { os_stop_timer(prototask_contxt.edge_monitor_start_tmr); iot_task_clean_msg(prototask_contxt.task_handle, PROTO_TIMER_MSG, PROTO_START_EDGE_TMR_ID); } os_start_timer(prototask_contxt.edge_monitor_start_tmr, prototask_contxt.flashinfo.public.pub.edge_start_tm); } /* edge out msg */ void iot_edge_post_to_proto_msg_handle(void *p_data, uint8_t msg_id) { iot_proto_task_post_msg(EDGE_OUTPUT_MSG, msg_id, p_data, 0, IOT_PROTO_TASK_QUEUE_LP); } /** * @brief post_monitor_start_timer() - call back function of prototask_contxt.edge_monitor_start_tmr * @param timer_id timer id * @param arg data */ static void post_monitor_start_timer(timer_id_t timer_id, void * arg) { (void)arg; (void)timer_id; iot_proto_task_post_msg(PROTO_TIMER_MSG, PROTO_START_EDGE_TMR_ID, NULL, 0, IOT_PROTO_TASK_QUEUE_LP); } /** * @brief post_monitor_start_timer_msg_handler() - handle function of prototask_contxt.edge_monitor_start_tmr */ static void post_monitor_start_timer_msg_handler(void) { void **pp_output_data; iot_pkt_t *p_pkt; p_pkt = iot_pkt_alloc(sizeof(uint32_t), IOT_GREE_APP_MID); if (!p_pkt) { iot_cus_printf("[glpr][err]No Mem!\n"); return; } pp_output_data = (void **)iot_pkt_put(p_pkt, sizeof(uint32_t)); *pp_output_data = greeapp->uart_com; greeapp->uart_com = NULL; proto_post_data_to_edge_msg_handle(EDGE_INPUT_REQ_START_ID, pp_output_data, sizeof(uint32_t)); iot_pkt_free(p_pkt); } /* iot_plcuart_pl_task_init - plc uart protocol handle task initialize */ uint32_t iot_proto_task_init() { uint32_t ret = ERR_OK; os_mem_set(&prototask_contxt, 0, sizeof(prototask_contxt_t)); prototask_contxt.task_cfg.stack_size = 0; prototask_contxt.task_cfg.task_prio = IOT_GRAPP_PROTO_TASK_PRIO; prototask_contxt.task_cfg.msg_size = sizeof(iot_proto_msg_t); prototask_contxt.task_cfg.msg_cnt = IOT_PROTO_TASK_POOL_SIZE; prototask_contxt.task_cfg.queue_cnt = IOT_PROTO_TASK_QUEUE_MAX_PRIO; prototask_contxt.task_cfg.queue_cfg[IOT_PROTO_TASK_QUEUE_LP].quota = 0; prototask_contxt.task_cfg.msg_exe_func = iot_proto_task_handle_msg; prototask_contxt.task_cfg.msg_cancel_func = iot_proto_task_handle_msg_cancel; /* create task */ prototask_contxt.task_handle = iot_task_create(IOT_GREE_APP_MID, &prototask_contxt.task_cfg); if (prototask_contxt.task_handle == NULL) { ret = ERR_FAIL; goto error_0; } /* init prototask_contxt protocol hanler process*/ prototask_contxt.proto_pase_fn = iot_proto_parse_fn; prototask_contxt.proto_cmd_hdl_tbl = proto_subfn_hdl_tbl; /* com0 drv period check timer */ prototask_contxt.uart_monitor_timer = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_uart_monitor_timeout_timer, &prototask_contxt); if (prototask_contxt.uart_monitor_timer == 0) { ret = ERR_FAIL; goto error_1; } /* init command handle state */ iot_proto_cmd_handle_state_init(); /* init gpio tab */ iot_proto_gpio_tab_init(); /* init local device */ #if (HW_PLATFORM == HW_PLATFORM_SIMU) if (ucIsClientMode == 0) { prototask_contxt.local_dev.nw_role = IOT_PLC_DEV_ROLE_CCO; } else { prototask_contxt.local_dev.nw_role = IOT_PLC_DEV_ROLE_STA; } #else #if PLC_SUPPORT_CCO_ROLE prototask_contxt.local_dev.nw_role = IOT_PLC_DEV_ROLE_CCO; #else prototask_contxt.local_dev.nw_role = IOT_PLC_DEV_ROLE_STA; #endif #endif if (iot_hwver_is_ledc_v3_0_jy() && (iot_board_get_board_id() == CUS_BOARD_ID_LEDC_V3_0) && (IOT_PLC_DEV_ROLE_STA == prototask_contxt.local_dev.nw_role)) { iot_edge_init(); } /* init saved message queue pool */ ret = iot_mem_pool_new(IOT_GREE_APP_MID, PROTO_SAVED_MSG_NODE_NUM, sizeof(proto_savedmsg_node_t), &saved_msg_q, 1); if (ret) { goto error_2; } if (prototask_contxt.local_dev.nw_role != IOT_PLC_DEV_ROLE_CCO && !iot_hwver_is_ledc_v3_0_jy()) { /* init proto timer to retry to query mac from MCU */ prototask_contxt.detect_timer = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_query_mac_timeout_timer, NULL); if (prototask_contxt.detect_timer == 0) { ret = ERR_FAIL; goto error_3; } } /* init wait response timer for async cmd handle */ prototask_contxt.wait_resp_timer = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_wait_resp_cmd_timeout_timer, &prototask_contxt); if (prototask_contxt.wait_resp_timer == 0) { ret = ERR_FAIL; goto error_4; } prototask_contxt.reboot_tmr = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_reboot_delay_timeout_timer, &prototask_contxt); if (prototask_contxt.reboot_tmr == 0) { ret = ERR_FAIL; goto error_5; } prototask_contxt.statisc_tmr = os_create_timer(IOT_GREE_APP_MID, true, iot_proto_statistic_timer, &prototask_contxt); if (prototask_contxt.statisc_tmr == 0) { ret = ERR_FAIL; goto error_6; } os_start_timer(prototask_contxt.statisc_tmr, PROTO_TIMER_STATIST_INTVL); prototask_contxt.leave_tmr = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_sta_leave_delay_timeout_timer, &prototask_contxt); if (prototask_contxt.leave_tmr == 0) { ret = ERR_FAIL; goto error_7; } /* init update upgrade state timer */ prototask_contxt.upgrade_tmr = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_update_upgrade_state_timeout_timer, NULL); if (prototask_contxt.upgrade_tmr == 0) { ret = ERR_FAIL; goto error_8; } prototask_contxt.rpt_window_tmr = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_brd_data_rpt_window_timer, &prototask_contxt); if (prototask_contxt.rpt_window_tmr == 0) { ret = ERR_FAIL; goto error_9; } #if IOT_GE_PAGING_ENABLE if (IOT_PLC_DEV_ROLE_CCO == prototask_contxt.local_dev.nw_role) { prototask_contxt.paging_timer = os_create_timer(IOT_GREE_APP_MID, true, iot_proto_paging_timer, &prototask_contxt); if (prototask_contxt.paging_timer == 0) { ret = ERR_FAIL; goto error_10; } } #endif if (IOT_PLC_DEV_ROLE_STA == prototask_contxt.local_dev.nw_role && TRIAL_RUN_CHECK_ENABLE) { prototask_contxt.trial_run_tmr = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_trial_run_check_timer, NULL); if (prototask_contxt.trial_run_tmr == 0) { ret = ERR_FAIL; goto error_11; } os_start_timer(prototask_contxt.trial_run_tmr, IOT_APP_FW_RECOVER_TIME); } #if PLC_SUPPORT_STA_ROLE prototask_contxt.dl645_localmode_tmr = os_create_timer(IOT_GREE_APP_MID, false, iot_proto_645_local_mode_timer, NULL); if (prototask_contxt.dl645_localmode_tmr == 0) { ret = ERR_FAIL; goto error_12; } #endif /* Create global timer end. */ #if PLC_SUPPORT_CCO_ROLE prototask_contxt.cli_interface.recv = iot_proto_task_cli_callback; prototask_contxt.cli_interface.param = NULL; ret = iot_cli_sg_interface_register(&prototask_contxt.cli_interface); #endif if (ret) { goto error_13; } prototask_contxt.common_bin_dump_mutex = os_create_mutex(0); if (prototask_contxt.common_bin_dump_mutex == NULL) { iot_cus_printf("common_bin_dump mutex create failed \n"); goto error_13; } prototask_contxt.edge_monitor_start_tmr = os_create_timer(IOT_GREE_APP_MID, false, post_monitor_start_timer, NULL); if (prototask_contxt.edge_monitor_start_tmr == 0) { ret = ERR_FAIL; goto error_13; } if (iot_hwver_is_ledc_v3_0_jy() && (iot_board_get_board_id() == CUS_BOARD_ID_LEDC_V3_0) && (IOT_PLC_DEV_ROLE_STA == prototask_contxt.local_dev.nw_role)) { if (iot_edge_tmr_init()) { goto error_14; } } #if PLC_SUPPORT_CCO_ROLE cctt_init(); #endif goto success; error_14: os_delete_timer(prototask_contxt.edge_monitor_start_tmr); error_13: #if PLC_SUPPORT_STA_ROLE if (prototask_contxt.dl645_localmode_tmr > 0) { os_delete_timer(prototask_contxt.dl645_localmode_tmr); } error_12: #endif if (prototask_contxt.trial_run_tmr > 0) { os_delete_timer(prototask_contxt.trial_run_tmr); } error_11: #if IOT_GE_PAGING_ENABLE if (prototask_contxt.paging_timer > 0) { os_delete_timer(prototask_contxt.paging_timer); } error_10: #endif os_delete_timer(prototask_contxt.rpt_window_tmr); error_9: os_delete_timer(prototask_contxt.upgrade_tmr); error_8: os_delete_timer(prototask_contxt.leave_tmr); error_7: os_delete_timer(prototask_contxt.statisc_tmr); error_6: os_delete_timer(prototask_contxt.reboot_tmr); error_5: os_delete_timer(prototask_contxt.wait_resp_timer); error_4: if (prototask_contxt.detect_timer > 0) { os_delete_timer(prototask_contxt.detect_timer); } error_3: iot_mem_pool_destroy(saved_msg_q); error_2: os_delete_timer(prototask_contxt.uart_monitor_timer); error_1: iot_task_delete(prototask_contxt.task_handle); error_0: os_mem_set(&prototask_contxt, 0, sizeof(prototask_contxt_t)); success: iot_cus_printf("[glpr]:proto_task_init %s!\n", ret ? "fail" : "success"); return ret; } void iot_proto_task_deinit() { os_delete_timer(prototask_contxt.uart_monitor_timer); os_delete_timer(prototask_contxt.detect_timer); os_delete_timer(prototask_contxt.wait_resp_timer); os_delete_timer(prototask_contxt.reboot_tmr); os_delete_timer(prototask_contxt.statisc_tmr); os_delete_timer(prototask_contxt.leave_tmr); if (saved_msg_q) { iot_mem_pool_destroy(saved_msg_q); saved_msg_q = NULL; } if (prototask_contxt.task_handle) { os_delete_task(prototask_contxt.task_handle); } os_mem_set(&prototask_contxt, 0, sizeof(prototask_contxt_t)); } uint8_t iot_proto_get_cco_mac(uint8_t* mac) { IOT_ASSERT(mac); #if PLC_SUPPORT_STA_ROLE if (!iot_mac_addr_valid(prototask_contxt.cco_dev.mac)) { return ERR_FAIL; } os_mem_cpy(mac, prototask_contxt.cco_dev.mac, IOT_MAC_ADDR_LEN); #endif #if PLC_SUPPORT_CCO_ROLE if (!iot_mac_addr_valid(prototask_contxt.local_dev.mac)) { return ERR_FAIL; } os_mem_cpy(mac, prototask_contxt.local_dev.mac, IOT_MAC_ADDR_LEN); #endif return ERR_OK; } uint8_t iot_proto_cli_uart_gpio_reassign(uint8_t rxpin, uint8_t txpin) { uint8_t cli_port = iot_board_get_uart(UART_CLI_PORT); if (cli_port >= IOT_UART_PORT_SUPP_MAX) { return 0; } return iot_uart_reassign_pin(cli_port, rxpin, txpin); } #endif