739 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			739 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /****************************************************************************
 | ||
|  | 
 | ||
|  | Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. | ||
|  | 
 | ||
|  | This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT | ||
|  | be copied by any method or incorporated into another program without | ||
|  | the express written consent of Aerospace C.Power. This Information or any portion | ||
|  | thereof remains the property of Aerospace C.Power. The Information contained herein | ||
|  | is believed to be accurate and Aerospace C.Power assumes no responsibility or | ||
|  | liability for its use in any way and conveys no license or title under | ||
|  | any patent or copyright and makes no representation or warranty that this | ||
|  | Information is free from patent or copyright infringement. | ||
|  | 
 | ||
|  | ****************************************************************************/ | ||
|  | /* os_ship header files */ | ||
|  | #include "os_timer_api.h"
 | ||
|  | #include "os_utils_api.h"
 | ||
|  | 
 | ||
|  | /* iot common header files */ | ||
|  | #include "iot_io_api.h"
 | ||
|  | #include "iot_module_api.h"
 | ||
|  | #include "iot_errno_api.h"
 | ||
|  | #include "iot_task_api.h"
 | ||
|  | #include "iot_pkt_api.h"
 | ||
|  | #include "iot_ipc_api.h"
 | ||
|  | #include "iot_sg_ext_api.h"
 | ||
|  | #include "iot_board_api.h"
 | ||
|  | #include "iot_oem_api.h"
 | ||
|  | #include "iot_plc_api.h"
 | ||
|  | #include "iot_mem_pool_api.h"
 | ||
|  | 
 | ||
|  | #include "iot_pkt_api.h"
 | ||
|  | #include "iot_proto_common.h"
 | ||
|  | #include "iot_proto_ge.h"
 | ||
|  | #include "iot_modbus_task.h"
 | ||
|  | #include "iot_modbus_ext.h"
 | ||
|  | #include "iot_gpio_api.h"
 | ||
|  | 
 | ||
|  | #define IOT_MODBUS_EXT_DATA_DUMP      1
 | ||
|  | 
 | ||
|  | #define IOT_MB_EXT_RESP_TIMER_PERIOD       (2000) /* units:ms */
 | ||
|  | 
 | ||
|  | extern iot_mb_task_t mb_task; | ||
|  | 
 | ||
|  | mb_ext_cmd_current_t current_handle_cmd; | ||
|  | 
 | ||
|  | uint8_t mb_ext_gpio_config_flag = 0; | ||
|  | 
 | ||
|  | void iot_mb_ext_data_dump(uint8_t * buf, uint32_t len, uint32_t line) | ||
|  | { | ||
|  | #if IOT_MODBUS_EXT_DATA_DUMP
 | ||
|  |     uint32_t i; | ||
|  | 
 | ||
|  |     iot_printf("[mb_task]DUMP(%03d)@line:%d", len, line); | ||
|  |     for (i = 0; i < len; i++) { | ||
|  |         iot_printf(" %02X", buf[i]); | ||
|  |     } | ||
|  |     iot_printf("\n"); | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | mb_extend_fn_hdr_t * iot_mb_ext_get_current_cmd_head() | ||
|  | { | ||
|  |     return &(current_handle_cmd.hdr); | ||
|  | } | ||
|  | 
 | ||
|  | static uint8_t iot_mb_ext_resp_transmit(uint8_t * data, uint32_t len, mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     iot_pkt_t *p_pkt = NULL; | ||
|  | 
 | ||
|  |     iot_mb_ext_data_dump(data, len, __LINE__); | ||
|  | 
 | ||
|  |     /* response */ | ||
|  |     if (dir == MODBUS_CMD_FROM_UART) { | ||
|  |         p_pkt = iot_pkt_alloc(len, IOT_MODBUS_MID); | ||
|  |         if (NULL == p_pkt) { | ||
|  |             iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__); | ||
|  |             IOT_ASSERT(0); | ||
|  |             return false; | ||
|  |         } | ||
|  | 
 | ||
|  |         os_mem_cpy(iot_pkt_put(p_pkt, len), data, len); | ||
|  | 
 | ||
|  |         iot_mb_task_msg_post_to_uart(mb_task.uart_h, p_pkt); | ||
|  | 
 | ||
|  |     } else if (dir == MODBUS_CMD_FROM_PLC) { | ||
|  |         p_pkt = iot_modbus_fn160_appdata_pack(data, len, 0, 1); | ||
|  |         if (NULL == p_pkt) { | ||
|  |             iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__); | ||
|  |             IOT_ASSERT(0); | ||
|  |             return ERR_FAIL; | ||
|  |         } | ||
|  | 
 | ||
|  |         /* parser ge command and post to task */ | ||
|  |         iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt), | ||
|  |             iot_mb_task_post_uart_cmd, 0); | ||
|  |         iot_pkt_free(p_pkt); | ||
|  |     } | ||
|  | 
 | ||
|  |     os_mem_set(¤t_handle_cmd, 0, sizeof(current_handle_cmd)); | ||
|  | 
 | ||
|  |     if (os_is_timer_active(mb_task.mb_ext_resp_timer)) { | ||
|  |         os_stop_timer(mb_task.mb_ext_resp_timer); | ||
|  |     } | ||
|  | 
 | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | uint8_t modbus_ext_set_resp_handler(iot_pkt_t *p_pkt_frame) | ||
|  | { | ||
|  |     uint8_t ret = ERR_FAIL; | ||
|  |     uint16_t crc16 = 0; | ||
|  |     uint32_t data_len = 0; | ||
|  |     ge_frame_cmd_cfm_set_subfn20_t *cfm = (ge_frame_cmd_cfm_set_subfn20_t *) | ||
|  |         iot_pkt_data(p_pkt_frame); | ||
|  |     mb_ext_frame_set_resp_t *mb_resp_frm = NULL; | ||
|  |     iot_pkt_t *mb_resp_pkt = NULL; | ||
|  | 
 | ||
|  |     if (mb_ext_gpio_config_flag) { | ||
|  |         mb_ext_gpio_config_flag = 0; | ||
|  |         goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |     mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head(); | ||
|  |     if ((cfm->result == ERR_OK) && ((cur_cmd->fn == MODBUS_EXT_SET_SINGLE_REG_FN) | ||
|  |         || (cur_cmd->fn == MODBUS_EXT_SET_MULTI_REG_FN))) { | ||
|  |         data_len = sizeof(mb_ext_frame_set_resp_t); | ||
|  |         mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID); | ||
|  |         IOT_ASSERT(mb_resp_pkt); | ||
|  |         mb_resp_frm = (mb_ext_frame_set_resp_t*)iot_pkt_put(mb_resp_pkt, | ||
|  |             sizeof(mb_ext_frame_set_resp_t)); | ||
|  |         os_mem_cpy(&(mb_resp_frm->hdr), &(current_handle_cmd.hdr), | ||
|  |             sizeof(mb_extend_fn_hdr_t)); | ||
|  |         mb_resp_frm->data = current_handle_cmd.data; | ||
|  |         crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2); | ||
|  |         mb_resp_frm->tail.check_sum = crc16; | ||
|  |         iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len, | ||
|  |             current_handle_cmd.dir); | ||
|  | 
 | ||
|  |         iot_pkt_free(mb_resp_pkt); | ||
|  |         ret = ERR_OK; | ||
|  |     } | ||
|  | 
 | ||
|  |     return ret; | ||
|  | out: | ||
|  | 
 | ||
|  |     return ERR_OK; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | uint8_t modbus_ext_aid_query_resp_handler(iot_pkt_t *p_pkt_frame) | ||
|  | { | ||
|  |     uint8_t ret = ERR_FAIL; | ||
|  |     uint16_t crc16 = 0; | ||
|  |     uint32_t data_len = 0; | ||
|  |     ge_frame_nid_resp_subfn16_t *resp_cmd = (ge_frame_nid_resp_subfn16_t *) | ||
|  |         iot_pkt_data(p_pkt_frame); | ||
|  |     iot_pkt_t *mb_resp_pkt = NULL; | ||
|  |     mb_ext_frame_aid_query_resp_t* mb_resp_frm = NULL; | ||
|  | 
 | ||
|  |     mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head(); | ||
|  |     if ((cur_cmd->fn == MODBUS_EXT_QUERY_FN) && | ||
|  |         (big_little_swap16(cur_cmd->reg_addr) == AID_QUERY_RA)) { | ||
|  |         data_len = sizeof(mb_ext_frame_aid_query_resp_t); | ||
|  |         mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID); | ||
|  |         IOT_ASSERT(mb_resp_pkt); | ||
|  |         mb_resp_frm = (mb_ext_frame_aid_query_resp_t*)iot_pkt_put(mb_resp_pkt, | ||
|  |             sizeof(mb_ext_frame_aid_query_resp_t)); | ||
|  |         mb_resp_frm->adapt_id = big_little_swap16(resp_cmd->nid); | ||
|  | 
 | ||
|  |         mb_resp_frm->sa = current_handle_cmd.hdr.sa; | ||
|  |         mb_resp_frm->fn = current_handle_cmd.hdr.fn; | ||
|  |         mb_resp_frm->data_len = sizeof(*mb_resp_frm) - 5; | ||
|  |         crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2); | ||
|  |         mb_resp_frm->tail.check_sum = crc16; | ||
|  |         iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len, | ||
|  |             current_handle_cmd.dir); | ||
|  | 
 | ||
|  |         iot_pkt_free(mb_resp_pkt); | ||
|  |         ret = ERR_OK; | ||
|  |     } | ||
|  | 
 | ||
|  |     return ret; | ||
|  | } | ||
|  | 
 | ||
|  | uint8_t modbus_ext_gpio_query_resp_handler(iot_pkt_t *p_pkt_frame) | ||
|  | { | ||
|  |     uint8_t ret = ERR_FAIL; | ||
|  |     uint16_t crc16 = 0; | ||
|  |     uint32_t data_len = 0; | ||
|  |     ge_frame_query_gpio_resp_subfn27_t *resp_cmd = | ||
|  |         (ge_frame_query_gpio_resp_subfn27_t *)iot_pkt_data(p_pkt_frame); | ||
|  |     mb_ext_frame_gpio_query_resp_t* mb_resp_frm = NULL; | ||
|  |     data_len = sizeof(mb_ext_frame_gpio_query_resp_t); | ||
|  | 
 | ||
|  |     mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head(); | ||
|  |     if ((cur_cmd->fn == MODBUS_EXT_QUERY_FN) && | ||
|  |         (big_little_swap16(cur_cmd->reg_addr) >= GPIO_QUERY_BASE_RA)) { | ||
|  |         iot_pkt_t *mb_resp_pkt = NULL; | ||
|  |         mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID); | ||
|  |         IOT_ASSERT(mb_resp_pkt); | ||
|  |         mb_resp_frm = (mb_ext_frame_gpio_query_resp_t*)iot_pkt_put(mb_resp_pkt, | ||
|  |             sizeof(mb_ext_frame_gpio_query_resp_t)); | ||
|  |         mb_resp_frm->gpio_value = big_little_swap16(resp_cmd->value); | ||
|  | 
 | ||
|  |         mb_resp_frm->sa = current_handle_cmd.hdr.sa; | ||
|  |         mb_resp_frm->fn = current_handle_cmd.hdr.fn; | ||
|  |         mb_resp_frm->data_len = sizeof(*mb_resp_frm) - 5; | ||
|  |         crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2); | ||
|  |         mb_resp_frm->tail.check_sum = crc16; | ||
|  |         iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len, | ||
|  |             current_handle_cmd.dir); | ||
|  | 
 | ||
|  |         iot_pkt_free(mb_resp_pkt); | ||
|  |         ret = ERR_OK; | ||
|  |     } | ||
|  | 
 | ||
|  |     return ret; | ||
|  | } | ||
|  | 
 | ||
|  | uint8_t iot_mb_ext_handle_resp_from_ge(iot_pkt_t *p_pkt_frame) | ||
|  | { | ||
|  |     ge_extend_fn_hdr_t *hdr = (ge_extend_fn_hdr_t *)iot_pkt_data(p_pkt_frame); | ||
|  | 
 | ||
|  |     if ((hdr->hdr.fn == PROTO_GE_PLC_SET_CMD) && | ||
|  |         (hdr->subfn == PROTO_CMD_CFM_CMD)) { | ||
|  |         if (ERR_OK == modbus_ext_set_resp_handler(p_pkt_frame)) { | ||
|  |             goto out; | ||
|  |         } | ||
|  |     } else if ((hdr->hdr.fn == PROTO_GE_PLC_RESP_CMD) && | ||
|  |         (hdr->subfn == PROTO_NID_QUERY_CMD)) { | ||
|  |         if (ERR_OK == modbus_ext_aid_query_resp_handler(p_pkt_frame)) { | ||
|  |             goto out; | ||
|  |         } | ||
|  |     } else if ((hdr->hdr.fn == PROTO_GE_PLC_RESP_CMD) && | ||
|  |         (hdr->subfn == PROTO_GE_GPIO_QUERY_CMD)) { | ||
|  |         if (ERR_OK == modbus_ext_gpio_query_resp_handler(p_pkt_frame)) { | ||
|  |             goto out; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     return ERR_FAIL; | ||
|  | out: | ||
|  | 
 | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | void iot_mb_ext_resp_cmd_timeout_or_failed() | ||
|  | { | ||
|  |     if (os_is_timer_active(mb_task.mb_ext_resp_timer)) { | ||
|  |         os_stop_timer(mb_task.mb_ext_resp_timer); | ||
|  |     } | ||
|  |     os_mem_set(¤t_handle_cmd, 0, sizeof(current_handle_cmd)); | ||
|  | 
 | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | static uint8_t modbus_ext_gpio_config(uint8_t gpio_num, uint8_t dir_mode, | ||
|  |     uint8_t pull_mode, uint8_t default_value) | ||
|  | { | ||
|  |     ge_frame_gpio_config_subfn164_t *pack_frm = NULL; | ||
|  |     uint32_t pack_frm_len = sizeof(ge_frame_gpio_config_subfn164_t); | ||
|  |     iot_pkt_t *p_pkt = NULL; | ||
|  |     uint16_t crc16 = 0; | ||
|  | 
 | ||
|  |     p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID); | ||
|  |     if (NULL == p_pkt) { | ||
|  |         iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__); | ||
|  |         IOT_ASSERT(0); | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     /* pack ge frame. */ | ||
|  |     pack_frm = (ge_frame_gpio_config_subfn164_t *)iot_pkt_put(p_pkt, pack_frm_len); | ||
|  |     pack_frm->hdr.hdr.preamble = 0xAAAA; | ||
|  |     pack_frm->hdr.hdr.data_len = 0x11; | ||
|  |     pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD; | ||
|  |     pack_frm->hdr.subfn = PROTO_GE_GPIO_CONFIG_CMD; | ||
|  | 
 | ||
|  |     pack_frm->seq = 0; | ||
|  |     iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac); | ||
|  |     iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac); | ||
|  |     pack_frm->gpio_num = gpio_num; | ||
|  |     pack_frm->dir_mode = dir_mode; | ||
|  |     pack_frm->pull_mode = pull_mode; | ||
|  |     pack_frm->output_value = default_value; | ||
|  | 
 | ||
|  |     crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3); | ||
|  |     pack_frm->tail.check_sum = crc16; | ||
|  |     pack_frm->tail.tail = GE_FRM_TAIL_CODE; | ||
|  | 
 | ||
|  |     /* post ge command to ge task */ | ||
|  |     iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt), | ||
|  |         iot_mb_task_post_uart_cmd, 0); | ||
|  |     iot_pkt_free(p_pkt); | ||
|  | 
 | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | bool_t modbus_ext_aid_query_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     ge_frame_nid_query_subfn16_t *pack_frm = NULL; | ||
|  |     uint32_t pack_frm_len = sizeof(ge_frame_nid_query_subfn16_t); | ||
|  |     iot_pkt_t *p_pkt = NULL; | ||
|  |     mb_ext_frame_aid_query_t *frm = (mb_ext_frame_aid_query_t *)data; | ||
|  |     uint16_t crc16 = 0; | ||
|  | 
 | ||
|  |     p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID); | ||
|  |     if (NULL == p_pkt) { | ||
|  |         iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__); | ||
|  |         IOT_ASSERT(0); | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t)); | ||
|  |     current_handle_cmd.data = frm->reg_count; | ||
|  |     current_handle_cmd.dir = dir; | ||
|  | 
 | ||
|  |     /* pack ge frame. */ | ||
|  |     pack_frm = (ge_frame_nid_query_subfn16_t *)iot_pkt_put(p_pkt, pack_frm_len); | ||
|  |     pack_frm->hdr.hdr.preamble = 0xAAAA; | ||
|  |     pack_frm->hdr.hdr.data_len = 0x01; | ||
|  |     pack_frm->hdr.hdr.fn = PROTO_GE_PLC_QUERY_CMD; | ||
|  |     pack_frm->hdr.subfn = PROTO_NID_QUERY_CMD; | ||
|  | 
 | ||
|  |     pack_frm->seq = 0; | ||
|  | 
 | ||
|  |     crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3); | ||
|  |     pack_frm->tail.check_sum = crc16; | ||
|  |     pack_frm->tail.tail = GE_FRM_TAIL_CODE; | ||
|  | 
 | ||
|  |     /* post ge command to ge task */ | ||
|  |     iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt), | ||
|  |         iot_mb_task_post_uart_cmd, 0); | ||
|  |     iot_pkt_free(p_pkt); | ||
|  | 
 | ||
|  |     os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD); | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | static bool_t modbus_ext_sa_query_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     iot_pkt_t *p_pkt = NULL; | ||
|  |     mb_ext_frame_sa_query_resp_t *resp_frm = NULL; | ||
|  |     uint32_t resp_frm_len = sizeof(mb_ext_frame_sa_query_resp_t); | ||
|  |     uint16_t crc16 = 0; | ||
|  | 
 | ||
|  |     mb_ext_frame_sa_query_t *frm = (mb_ext_frame_sa_query_t *)data; | ||
|  | 
 | ||
|  |     p_pkt = iot_pkt_alloc(resp_frm_len, IOT_MODBUS_MID); | ||
|  |     if (NULL == p_pkt) { | ||
|  |         iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__); | ||
|  |         IOT_ASSERT(0); | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     resp_frm = (mb_ext_frame_sa_query_resp_t *)iot_pkt_put(p_pkt, resp_frm_len); | ||
|  |     resp_frm->sa = frm->hdr.sa; | ||
|  |     resp_frm->fn = frm->hdr.fn; | ||
|  |     resp_frm->data_len = 2; | ||
|  |     resp_frm->slaver_addr = big_little_swap16(mb_task.slave_addr); | ||
|  |     crc16 = iot_modbus_rtu_crc16((uint8_t*)resp_frm, resp_frm_len - 2); | ||
|  |     resp_frm->tail.check_sum = crc16; | ||
|  |     iot_mb_ext_resp_transmit((uint8_t*)resp_frm, resp_frm_len, dir); | ||
|  | 
 | ||
|  |     iot_pkt_free(p_pkt); | ||
|  | 
 | ||
|  |     return true; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | bool_t modbus_ext_wl_item_count_query_handler(uint8_t *data, | ||
|  |     uint8_t len, mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     (void)data; | ||
|  |     (void)len; | ||
|  |     (void)dir; | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | bool_t modbus_ext_wl_item_query_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     (void)data; | ||
|  |     (void)len; | ||
|  |     (void)dir; | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | static bool_t modbus_ext_gpio_query_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     ge_frame_gpio_query_subfn27_t *pack_frm = NULL; | ||
|  |     uint32_t pack_frm_len = sizeof(ge_frame_gpio_query_subfn27_t); | ||
|  |     iot_pkt_t *p_pkt = NULL; | ||
|  |     mb_ext_frame_gpio_query_t *frm = (mb_ext_frame_gpio_query_t *)data; | ||
|  |     uint16_t crc16 = 0, reg_addr = 0; | ||
|  |     uint8_t gpio_num = 0xff; | ||
|  | 
 | ||
|  |     reg_addr = big_little_swap16(frm->hdr.reg_addr); | ||
|  |     if ((reg_addr - GPIO_QUERY_BASE_RA) % 8 != 0) { | ||
|  |        goto param_err; | ||
|  |     } else { | ||
|  |         gpio_num = (reg_addr - GPIO_QUERY_BASE_RA) / 8; | ||
|  |         //if (gpio_num >= GPIO_PIN_COUNT) {
 | ||
|  |         //    goto param_err;
 | ||
|  |         //}
 | ||
|  |     } | ||
|  | 
 | ||
|  |     p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID); | ||
|  |     if (NULL == p_pkt) { | ||
|  |         iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__); | ||
|  |         IOT_ASSERT(0); | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t)); | ||
|  |     current_handle_cmd.data = frm->reg_count; | ||
|  |     current_handle_cmd.dir = dir; | ||
|  | 
 | ||
|  |     mb_ext_gpio_config_flag = 1; | ||
|  |     modbus_ext_gpio_config(gpio_num, IOT_GE_GPIO_DIR_INPUT, IOT_GE_GPIO_PULL_NONE, 0); | ||
|  | 
 | ||
|  |     /* pack ge frame. */ | ||
|  |     pack_frm = (ge_frame_gpio_query_subfn27_t *)iot_pkt_put(p_pkt, pack_frm_len); | ||
|  |     pack_frm->hdr.hdr.preamble = 0xAAAA; | ||
|  |     pack_frm->hdr.hdr.data_len = 0x0E; | ||
|  |     pack_frm->hdr.hdr.fn = PROTO_GE_PLC_QUERY_CMD; | ||
|  |     pack_frm->hdr.subfn = PROTO_GE_GPIO_QUERY_CMD; | ||
|  | 
 | ||
|  |     pack_frm->seq = 0; | ||
|  |     iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac); | ||
|  |     iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac); | ||
|  |     pack_frm->gpio_num = gpio_num; | ||
|  | 
 | ||
|  |     crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3); | ||
|  |     pack_frm->tail.check_sum = crc16; | ||
|  |     pack_frm->tail.tail = GE_FRM_TAIL_CODE; | ||
|  | 
 | ||
|  |     /* post ge command to ge task */ | ||
|  |     iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt), | ||
|  |         iot_mb_task_post_uart_cmd, 0); | ||
|  |     iot_pkt_free(p_pkt); | ||
|  | 
 | ||
|  |     os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD); | ||
|  | 
 | ||
|  |     return true; | ||
|  | 
 | ||
|  | param_err: | ||
|  |     iot_printf("[%s][err]param err @line %d\n", __FUNCTION__, __LINE__); | ||
|  |     return false; | ||
|  | } | ||
|  | 
 | ||
|  | static mb_fnhdl_tbl_t modbus_query_ra_tbl[] = { | ||
|  | #if PLC_SUPPORT_CCO_ROLE
 | ||
|  |     {AID_QUERY_RA,   modbus_ext_aid_query_handler, 0}, | ||
|  |     {WL_ITEM_COUNT_QUERY_RA, modbus_ext_wl_item_count_query_handler, 0}, | ||
|  |     {WL_ITEM_QUERY_BASE_RA, modbus_ext_wl_item_query_handler, 0}, | ||
|  | #endif
 | ||
|  |     {SA_QUERY_RA, modbus_ext_sa_query_handler, 0}, | ||
|  |     {GPIO_QUERY_BASE_RA,   modbus_ext_gpio_query_handler, 0}, | ||
|  | }; | ||
|  | 
 | ||
|  | static bool_t iot_mb_ext_cmd_query_fn_handler(uint8_t *data, | ||
|  |     uint8_t len, mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     uint8_t i, ret = ERR_FAIL; | ||
|  |     uint16_t reg_addr = 0; | ||
|  |     mb_extend_fn_hdr_t *mb_head = (mb_extend_fn_hdr_t *)data; | ||
|  |     uint8_t fncode_hdlr_cnt = | ||
|  |                 sizeof(modbus_query_ra_tbl)/sizeof(mb_fnhdl_tbl_t); | ||
|  |     MODBUS_FN_HANDLE handler = NULL; | ||
|  | 
 | ||
|  |     reg_addr = big_little_swap16(mb_head->reg_addr); | ||
|  | 
 | ||
|  |     for (i = 0; i < fncode_hdlr_cnt; i++) { | ||
|  |         if (modbus_query_ra_tbl[i].cmdid == reg_addr) { | ||
|  |             handler = modbus_query_ra_tbl[i].cmd_handle_fn; | ||
|  |             break; | ||
|  |         } | ||
|  |      } | ||
|  | 
 | ||
|  | #if PLC_SUPPORT_CCO_ROLE
 | ||
|  |     if (reg_addr > WL_ITEM_QUERY_BASE_RA) { | ||
|  |         handler = modbus_ext_wl_item_query_handler; | ||
|  |     } | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     if (reg_addr > GPIO_QUERY_BASE_RA) { | ||
|  |         handler = modbus_ext_gpio_query_handler; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (handler) { | ||
|  |         ret = handler(data, len, dir); | ||
|  |         ret = (ret == true)? ERR_OK: ERR_FAIL; | ||
|  |     } | ||
|  | 
 | ||
|  |     return ret; | ||
|  | } | ||
|  | 
 | ||
|  | bool_t modbus_ext_aid_set_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     ge_frame_cco_nid_set_subfn17_t *pack_frm = NULL; | ||
|  |     uint32_t pack_frm_len = sizeof(ge_frame_cco_nid_set_subfn17_t); | ||
|  |     iot_pkt_t *p_pkt = NULL; | ||
|  |     mb_ext_frame_aid_set_t *frm = (mb_ext_frame_aid_set_t *)data; | ||
|  |     uint16_t crc16 = 0; | ||
|  | 
 | ||
|  |     p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID); | ||
|  |     if (NULL == p_pkt) { | ||
|  |         iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__); | ||
|  |         IOT_ASSERT(0); | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t)); | ||
|  |     current_handle_cmd.data = frm->adapt_id; | ||
|  |     current_handle_cmd.dir = dir; | ||
|  | 
 | ||
|  |     /* pack ge frame. */ | ||
|  |     pack_frm = (ge_frame_cco_nid_set_subfn17_t *)iot_pkt_put(p_pkt, pack_frm_len); | ||
|  |     pack_frm->hdr.hdr.preamble = 0xAAAA; | ||
|  |     pack_frm->hdr.hdr.data_len = 0X07; | ||
|  |     pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD; | ||
|  |     pack_frm->hdr.subfn = PROTO_CCO_NID_SET_CMD; | ||
|  | 
 | ||
|  |     pack_frm->nid = (frm->adapt_id) >> 8; | ||
|  |     pack_frm->seq = 0; | ||
|  |     iot_mac_addr_cpy(pack_frm->mac, mb_task.local_mac); | ||
|  | 
 | ||
|  |     crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3); | ||
|  |     pack_frm->tail.check_sum = crc16; | ||
|  |     pack_frm->tail.tail = GE_FRM_TAIL_CODE; | ||
|  | 
 | ||
|  |     /* post ge command to ge task */ | ||
|  |     iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt), | ||
|  |         iot_mb_task_post_uart_cmd, 0); | ||
|  |     iot_pkt_free(p_pkt); | ||
|  | 
 | ||
|  |     os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD); | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | static bool_t modbus_ext_sa_set_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     mb_ext_frame_sa_set_t *frm = (mb_ext_frame_sa_set_t *)data; | ||
|  |     uint8_t new_sa = (frm->slaver_addr) >> 8; | ||
|  | 
 | ||
|  |     if (mb_task.slave_addr != new_sa) { | ||
|  |         mb_task.slave_addr = new_sa; | ||
|  |     } | ||
|  | 
 | ||
|  |     iot_mb_ext_resp_transmit(data, len, dir); | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | bool_t modbus_ext_wl_set_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     (void)data; | ||
|  |     (void)len; | ||
|  |     (void)dir; | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | static bool_t modbus_ext_gpio_set_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     ge_frame_gpio_set_subfn165_t *pack_frm = NULL; | ||
|  |     uint32_t pack_frm_len = sizeof(ge_frame_gpio_set_subfn165_t); | ||
|  |     iot_pkt_t *p_pkt = NULL; | ||
|  |     mb_ext_frame_gpio_set_t *frm = (mb_ext_frame_gpio_set_t *)data; | ||
|  |     uint16_t crc16 = 0, reg_addr = 0; | ||
|  |     uint8_t gpio_num = 0xff; | ||
|  | 
 | ||
|  |     reg_addr = big_little_swap16(frm->hdr.reg_addr); | ||
|  | 
 | ||
|  |     if ((reg_addr - GPIO_SET_BASE_RA) % 8 != 0) { | ||
|  |        goto param_err; | ||
|  |     } else { | ||
|  |         gpio_num = (reg_addr - GPIO_SET_BASE_RA) / 8; | ||
|  |         //if (gpio_num >= GPIO_PIN_COUNT) {
 | ||
|  |         //    goto param_err;
 | ||
|  |         //}
 | ||
|  |     } | ||
|  | 
 | ||
|  |     p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID); | ||
|  |     if (NULL == p_pkt) { | ||
|  |         iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__); | ||
|  |         IOT_ASSERT(0); | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t)); | ||
|  |     current_handle_cmd.data = frm->gpio_value; | ||
|  |     current_handle_cmd.dir = dir; | ||
|  | 
 | ||
|  |     mb_ext_gpio_config_flag = 1; | ||
|  |     modbus_ext_gpio_config(gpio_num, IOT_GE_GPIO_DIR_OUTPUT, IOT_GE_GPIO_PULL_NONE, 0); | ||
|  | 
 | ||
|  |     /* pack ge frame. */ | ||
|  |     pack_frm = (ge_frame_gpio_set_subfn165_t *)iot_pkt_put(p_pkt, pack_frm_len); | ||
|  |     pack_frm->hdr.hdr.preamble = 0xAAAA; | ||
|  |     pack_frm->hdr.hdr.data_len = 0x0F; | ||
|  |     pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD; | ||
|  |     pack_frm->hdr.subfn = PROTO_GE_GPIO_SET_CMD; | ||
|  | 
 | ||
|  |     pack_frm->seq = 0; | ||
|  |     iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac); | ||
|  |     iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac); | ||
|  |     pack_frm->gpio_num = gpio_num; | ||
|  |     pack_frm->value = (frm->gpio_value) >> 8; | ||
|  | 
 | ||
|  |     crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3); | ||
|  |     pack_frm->tail.check_sum = crc16; | ||
|  |     pack_frm->tail.tail = GE_FRM_TAIL_CODE; | ||
|  | 
 | ||
|  |     /* post ge command to ge task */ | ||
|  |     iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt), | ||
|  |         iot_mb_task_post_uart_cmd, 0); | ||
|  |     iot_pkt_free(p_pkt); | ||
|  | 
 | ||
|  |     os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD); | ||
|  | 
 | ||
|  |     return true; | ||
|  | 
 | ||
|  | param_err: | ||
|  |     iot_printf("[%s][err]param err @line %d\n", __FUNCTION__, __LINE__); | ||
|  |     return false; | ||
|  | } | ||
|  | 
 | ||
|  | bool_t modbus_ext_wl_add_item_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     (void)data; | ||
|  |     (void)len; | ||
|  |     (void)dir; | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | bool_t modbus_ext_wl_remove_item_handler(uint8_t *data, uint8_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     (void)data; | ||
|  |     (void)len; | ||
|  |     (void)dir; | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | static mb_fnhdl_tbl_t modbus_set_ra_tbl[] = { | ||
|  | #if PLC_SUPPORT_CCO_ROLE
 | ||
|  |     {AID_SET_RA, modbus_ext_aid_set_handler, 0}, | ||
|  |     {WL_SET_RA, modbus_ext_wl_set_handler,0}, | ||
|  |     {WL_ADD_ITEM_SET_RA,   modbus_ext_wl_add_item_handler, 0}, | ||
|  |     {WL_RM_ITEM_SET_RA, modbus_ext_wl_remove_item_handler, 0}, | ||
|  | #endif
 | ||
|  |     {SA_SET_RA, modbus_ext_sa_set_handler,0}, | ||
|  |     {GPIO_SET_BASE_RA, modbus_ext_gpio_set_handler, 0}, | ||
|  | }; | ||
|  | 
 | ||
|  | static bool_t iot_mb_ext_cmd_set_handler(uint8_t *data, | ||
|  |     uint8_t len, mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     uint8_t i, ret = ERR_FAIL; | ||
|  |     mb_extend_fn_hdr_t *mb_head = (mb_extend_fn_hdr_t *)data;; | ||
|  |     uint8_t fncode_hdlr_cnt = | ||
|  |                 sizeof(modbus_set_ra_tbl)/sizeof(mb_fnhdl_tbl_t); | ||
|  |     MODBUS_FN_HANDLE handler = NULL; | ||
|  |     uint16_t reg_addr = big_little_swap16(mb_head->reg_addr); | ||
|  | 
 | ||
|  |     for (i = 0; i < fncode_hdlr_cnt; i++) { | ||
|  |         if (modbus_set_ra_tbl[i].cmdid == reg_addr) { | ||
|  |             handler = modbus_set_ra_tbl[i].cmd_handle_fn; | ||
|  |             break; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     if (reg_addr > GPIO_SET_BASE_RA) { | ||
|  |         handler = modbus_ext_gpio_set_handler; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (handler) { | ||
|  |         ret = handler(data, len, dir); | ||
|  |         ret = (ret == true)? ERR_OK: ERR_FAIL; | ||
|  |     } | ||
|  | 
 | ||
|  |     return ret; | ||
|  | } | ||
|  | 
 | ||
|  | /* fncode handler table */ | ||
|  | static mb_fnhdl_tbl_t mb_fn_hdl_tbl[] = { | ||
|  |     {MODBUS_EXT_QUERY_FN,           iot_mb_ext_cmd_query_fn_handler,    0 }, | ||
|  |     {MODBUS_EXT_SET_SINGLE_REG_FN,  iot_mb_ext_cmd_set_handler,         0 }, | ||
|  |     {MODBUS_EXT_SET_MULTI_REG_FN,   iot_mb_ext_cmd_set_handler,         0 }, | ||
|  | }; | ||
|  | 
 | ||
|  | uint8_t iot_mb_ext_cmd_handler(uint8_t * data, uint16_t len, | ||
|  |     mb_transmit_direction_e dir) | ||
|  | { | ||
|  |     uint8_t i, ret = ERR_FAIL; | ||
|  |     mb_extend_fn_hdr_t *mb_head = NULL; | ||
|  |     uint8_t fncode_hdlr_cnt = | ||
|  |                 sizeof(mb_fn_hdl_tbl)/sizeof(mb_fnhdl_tbl_t); | ||
|  | 
 | ||
|  |     if ((data == NULL) || (len == 0)) { | ||
|  |         iot_printf("[%s][err] invalid data, data:%p, len:%d\n", __FUNCTION__, data, len); | ||
|  |         goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |     iot_mb_ext_data_dump(data, len, __LINE__); | ||
|  |     mb_head = (mb_extend_fn_hdr_t *)data; | ||
|  | 
 | ||
|  |     /* look for fncode handler to handle modbus cmd frame */ | ||
|  |     for (i = 0; i < fncode_hdlr_cnt; i++) { | ||
|  |         if (mb_head->fn == mb_fn_hdl_tbl[i].cmdid) { | ||
|  |             /* increase each fn counter */ | ||
|  |             mb_fn_hdl_tbl[i].cmd_num++; | ||
|  |             mb_fn_hdl_tbl[i].cmd_handle_fn(data, len, dir); | ||
|  |             break; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     ret = ERR_OK; | ||
|  | out: | ||
|  |     return ret; | ||
|  | } |