917 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			917 lines
		
	
	
		
			27 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. | ||
|  | 
 | ||
|  | ****************************************************************************/ | ||
|  | 
 | ||
|  | #include "iot_errno_api.h"
 | ||
|  | #include "os_utils_api.h"
 | ||
|  | #include "iot_uart_api.h"
 | ||
|  | #include "iot_version_api.h"
 | ||
|  | #include "iot_system_api.h"
 | ||
|  | #include "proto_spg_cco.h"
 | ||
|  | #include "iot_sg_ctrl_api.h"
 | ||
|  | #include "proto_645.h"
 | ||
|  | 
 | ||
|  | #if (IOT_SG_CONTROLLER_ENABLE)
 | ||
|  | 
 | ||
|  | /* report max scan node count */ | ||
|  | #define IOT_CTRL_SCAN_NODE_MAX_CNT      (200)
 | ||
|  | 
 | ||
|  | /* command from contrl application */ | ||
|  | typedef struct _ctrl_spg_frame_pkt_t { | ||
|  |     /* main application function code */ | ||
|  |     uint8_t     afn; | ||
|  |     /* seccondary application function code */ | ||
|  |     uint8_t     fn; | ||
|  |     /* sequence number of ctrl command */ | ||
|  |     uint8_t     app_sn; | ||
|  |     /* length of the applied data (unit: byte)*/ | ||
|  |     uint16_t    app_data_len; | ||
|  |     /* applied data */ | ||
|  |     uint8_t     *app_data; | ||
|  | }ctrl_spg_frame_pkt_t; | ||
|  | 
 | ||
|  | typedef struct _spg_cctt_drv_data { | ||
|  |     /* seq number */ | ||
|  |     uint8_t     sn; | ||
|  |     /* requested meter mac */ | ||
|  |     uint8_t     req_mac[IOT_MAC_ADDR_LEN]; | ||
|  |     /* destination mac in address field */ | ||
|  |     uint8_t     dest_mac[IOT_MAC_ADDR_LEN]; | ||
|  | } spg_cctt_drv_data; | ||
|  | 
 | ||
|  | static spg_cctt_drv_data *drv_data = NULL; | ||
|  | 
 | ||
|  | static uint32_t iot_spg_ctrl_send_uart_sn_ext(uint8_t role, uint8_t afn, | ||
|  |     uint8_t fn, iot_pkt_t *pkt, uint8_t sn, uint8_t mac_used, uint8_t *req_mac, | ||
|  |     uint8_t *dec_mac, uint8_t di2) | ||
|  | { | ||
|  |     uint8_t *data = NULL; | ||
|  |     proto_spg_hdr_t *pkt_hdr = NULL; | ||
|  |     proto_spg_addr_field_t *spg_addr_ptr = NULL; | ||
|  |     proto_spg_app_data_t *spg_app_ptr = NULL; | ||
|  |     uint8_t *cs_ptr = NULL;     //pointer to checksum
 | ||
|  |     uint16_t index = 0; | ||
|  |     uint16_t app_data_len = (uint16_t)iot_pkt_data_len(pkt); | ||
|  | 
 | ||
|  |     data = iot_pkt_push(pkt, proto_spg_get_header_len(mac_used)); | ||
|  |     IOT_ASSERT(data); | ||
|  | 
 | ||
|  |     if ((iot_pkt_block_len(pkt, IOT_PKT_BLOCK_DATA) + PROTO_SPG_CS_BCODE_LEN) != | ||
|  |         proto_spg_get_proto_pkt_len(mac_used, app_data_len)) { | ||
|  |         iot_pkt_free(pkt); | ||
|  |         return ERR_NOMEM; | ||
|  |     } | ||
|  |     pkt_hdr = (proto_spg_hdr_t*)data; | ||
|  |     pkt_hdr->sof_byte = PROTO_SPG_SOF_BYTE; | ||
|  | 
 | ||
|  |     pkt_hdr->ctrl_byte.dir = PROTO_SPG_DIR_UP_LINK; | ||
|  |     if (role == PROTO_SPG_PRM_SLAVE) { | ||
|  |         /* response Message */ | ||
|  |         pkt_hdr->ctrl_byte.prm = PROTO_SPG_PRM_SLAVE; | ||
|  |     } else { | ||
|  |         /* report message */ | ||
|  |         pkt_hdr->ctrl_byte.prm = PROTO_SPG_PRM_MASTER; | ||
|  |     } | ||
|  |     pkt_hdr->ctrl_byte.addr = PROTO_SPG_NO_ADDRESS; | ||
|  |     pkt_hdr->ctrl_byte.ver = PROTO_SPG_DEFAULT_VERSION; | ||
|  |     pkt_hdr->ctrl_byte.rsvd = 0; | ||
|  | 
 | ||
|  |     index += sizeof(proto_spg_hdr_t); | ||
|  | 
 | ||
|  |     if (mac_used && req_mac && dec_mac) { | ||
|  |         spg_addr_ptr = (proto_spg_addr_field_t *)(data+index); | ||
|  |         pkt_hdr->ctrl_byte.addr = PROTO_SPG_WITH_ADDRESS; | ||
|  | 
 | ||
|  |         /* only src mac and dest mac for up link */ | ||
|  |         os_mem_cpy(spg_addr_ptr->src_mac, req_mac, PROTO_SPG_MAC_ADDR_LEN); | ||
|  |         index += PROTO_SPG_MAC_ADDR_LEN; | ||
|  |         os_mem_cpy(spg_addr_ptr->dest_mac, dec_mac, PROTO_SPG_MAC_ADDR_LEN); | ||
|  |         index += PROTO_SPG_MAC_ADDR_LEN; | ||
|  |     } | ||
|  | 
 | ||
|  |     spg_app_ptr = (proto_spg_app_data_t *)(data+index); | ||
|  |     spg_app_ptr->afn = afn; | ||
|  |     spg_app_ptr->seq = sn; | ||
|  |     spg_app_ptr->di[0] = fn; | ||
|  |     spg_app_ptr->di[1] = afn; | ||
|  |     spg_app_ptr->di[2] = di2; | ||
|  |     spg_app_ptr->di[3] = (uint8_t)PROTO_SPG_APP_CTRL_DI3; | ||
|  |     index += sizeof(proto_spg_app_data_t); | ||
|  | 
 | ||
|  |     /* skip app data as app data is already in iot_pkt */ | ||
|  |     index += app_data_len; | ||
|  | 
 | ||
|  |     /* check sum field */ | ||
|  |     cs_ptr = (data +index); | ||
|  |     index++; | ||
|  | 
 | ||
|  |     /* tail of the frame */ | ||
|  |     data[index] = PROTO_SPG_EOF_BYTE; | ||
|  |     index++; | ||
|  |     pkt_hdr->len = index; | ||
|  | 
 | ||
|  |     *cs_ptr = proto_spg_get_checksum(data + PROTO_SPG_CTRL_OFFSET, | ||
|  |         index - PROTO_SPG_CTRL_OFFSET - PROTO_SPG_CHECKSUM_LEN - | ||
|  |         PROTO_SPG_BACKCODE_LEN); | ||
|  | 
 | ||
|  |     // put checksum and back code. 2 byte.
 | ||
|  |     iot_pkt_put(pkt, PROTO_SPG_CS_BCODE_LEN); | ||
|  |     iot_ctrl_uart_send(pkt); | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | static uint32_t iot_spg_ctrl_send_uart_sn(uint8_t role, uint8_t afn, | ||
|  |     uint8_t fn, iot_pkt_t *pkt, uint8_t di2, uint8_t mac_used, uint8_t sn) | ||
|  | { | ||
|  |     if (mac_used) { | ||
|  |         return iot_spg_ctrl_send_uart_sn_ext(role, afn, fn, pkt, sn, | ||
|  |             SPG_USED_ADDR, drv_data->dest_mac, drv_data->req_mac, di2); | ||
|  |     } else { | ||
|  |         return iot_spg_ctrl_send_uart_sn_ext(role, afn, fn, pkt, sn, | ||
|  |             SPG_NO_USED_ADDR, NULL, NULL, di2); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static uint32_t iot_spg_ctrl_send_uart(uint8_t role, uint8_t afn, uint8_t fn, | ||
|  |     const uint8_t *app_data, uint16_t len, uint8_t di2, uint8_t mac_used, | ||
|  |     uint8_t sn) | ||
|  | { | ||
|  |     iot_pkt_t *pkt = NULL; | ||
|  |     uint8_t *pkt_data = NULL; | ||
|  | 
 | ||
|  |     pkt = iot_pkt_alloc(proto_spg_get_pkt_len(mac_used, len), | ||
|  |         IOT_SMART_GRID_MID); | ||
|  |     IOT_ASSERT(pkt); | ||
|  | 
 | ||
|  |     pkt_data = iot_pkt_reserve(pkt, proto_spg_get_rsvd_len(mac_used)); | ||
|  | 
 | ||
|  |     if (app_data && len) { | ||
|  |         os_mem_cpy(pkt_data, app_data, len); | ||
|  |         iot_pkt_put(pkt, len); | ||
|  |     } | ||
|  | 
 | ||
|  |     return iot_spg_ctrl_send_uart_sn(role, afn, fn, pkt, di2, mac_used, sn); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static uint32_t iot_spg_ctrl_drv_init() | ||
|  | { | ||
|  |     uint32_t ret = 0; | ||
|  |     uint32_t result = ERR_OK; | ||
|  |     iot_frame_fmt fmt = { 0 }; | ||
|  | 
 | ||
|  |     if (!drv_data) { | ||
|  |         drv_data = os_mem_malloc(IOT_SMART_GRID_MID, | ||
|  |             sizeof(*drv_data)); | ||
|  |         if (!drv_data) { | ||
|  |             return ERR_NOMEM; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     /* config the UART port settings */ | ||
|  |     fmt.preamble_code[0] = PROTO_SPG_SOF_BYTE; | ||
|  |     fmt.preamble_codelen = PROTO_SPG_PRECODE_LEN; | ||
|  |     fmt.datalen_offset = 0; | ||
|  |     fmt.datalen_size = PROTO_SPG_LENGTH_SIZE; | ||
|  |     fmt.backcode_offset = 0; | ||
|  |     fmt.backcode_len = PROTO_SPG_BACKCODE_LEN; | ||
|  |     /* in uart data parsing, datalen means raw data to be send,
 | ||
|  |      * excluding preamble/datalen/backcode. For datalen field in | ||
|  |      * spg datagram means the length of the whole datagram, we shall | ||
|  |      * set the datalen_fix as below. | ||
|  |      */ | ||
|  |     fmt.datalen_fix = fmt.preamble_codelen + | ||
|  |         fmt.datalen_size + fmt.backcode_len; | ||
|  |     fmt.backcode[0] = PROTO_SPG_EOF_BYTE; | ||
|  |     fmt.frame_timeout = CTRL_FRAME_PARSE_TIMEOUT; | ||
|  |     fmt.timeout_mode = TIMEOUT_PERDATA; | ||
|  |     fmt.check_frame_func = proto_spg_check_frame_handler; | ||
|  |     ret = iot_sg_ctrl_config_uart(PROTO_SPG_DEFAULT_BAUD, | ||
|  |         (uint8_t)IOT_UART_PARITY_EVEN, (uint8_t)IOT_UART_DLEN_8_BITS, | ||
|  |         (uint8_t)IOT_UART_STOP_1_BITS, &fmt); | ||
|  |     if (!ret) { | ||
|  |         result = ERR_FAIL; | ||
|  |     } | ||
|  |     return result; | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_drv_deinit() | ||
|  | { | ||
|  |     if (drv_data) { | ||
|  |         os_mem_free(drv_data); | ||
|  |         drv_data = NULL; | ||
|  |     } | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_freq_band_handler( | ||
|  |     iot_plc_freq_band_info_query_rpt_t *rpt) | ||
|  | { | ||
|  |     spg_query_freq_band_t rsp = { 0 }; | ||
|  |     rsp.freq_band = rpt->freq_band; | ||
|  |     /* report this response to UART/APP */ | ||
|  |     iot_spg_ctrl_send_uart(PROTO_SPG_PRM_SLAVE, PROTO_SPG_AFN_03, | ||
|  |         PROTO_SPG_F90, (uint8_t *)&rsp, (uint16_t)sizeof(rsp), | ||
|  |         PROTO_SPG_APP_DI2_00, SPG_NO_USED_ADDR, drv_data->sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_send_00h02_nack(uint8_t reason, uint8_t sn) | ||
|  | { | ||
|  |     spg_afn00_fn02_reject_t reject = { 0 }; | ||
|  |     reject.err_no = reason; | ||
|  |     iot_spg_ctrl_send_uart(PROTO_SPG_PRM_SLAVE, PROTO_SPG_AFN_00, PROTO_SPG_F2, | ||
|  |         (uint8_t*)&reject, sizeof(reject), PROTO_SPG_APP_DI2_01, | ||
|  |         SPG_NO_USED_ADDR, sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_send_00h01_ack(uint8_t sn) | ||
|  | { | ||
|  |     spg_afn00_fn01_conf_t conf = { 0 }; | ||
|  | 
 | ||
|  |     conf.wait_duration = PROTO_SPG_DEFAULT_WAIT_TIME; | ||
|  |     iot_spg_ctrl_send_uart(PROTO_SPG_PRM_SLAVE, PROTO_SPG_AFN_00, PROTO_SPG_F1, | ||
|  |         (uint8_t*)&conf, sizeof(conf), PROTO_SPG_APP_DI2_01, | ||
|  |         SPG_NO_USED_ADDR, sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_set_freq_band_result(uint8_t result) | ||
|  | { | ||
|  |     if (!result) { | ||
|  |         iot_spg_ctrl_send_00h01_ack(drv_data->sn); | ||
|  |     } else { | ||
|  |         iot_spg_ctrl_send_00h02_nack(PROTO_SPG_ERR_COMM_TIMEOUT, drv_data->sn); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_01h_f01(ctrl_spg_frame_pkt_t *frm) | ||
|  | { | ||
|  |     iot_spg_ctrl_send_00h01_ack(frm->app_sn); | ||
|  |     os_delay(1000); | ||
|  |     iot_system_restart(IOT_SYS_RST_REASON_CCTT_REQ); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_rpt_data_transfer_handle(uint8_t sn, | ||
|  |     uint8_t *data, uint16_t len, uint8_t data_type) | ||
|  | { | ||
|  |     spg_afn22_fn01_data_send_ul_t *rsp; | ||
|  |     iot_pkt_t *rpt_pkt; | ||
|  |     uint16_t rpt_pkt_len; | ||
|  | 
 | ||
|  |     rpt_pkt_len = len + sizeof(*rsp); | ||
|  |     rpt_pkt = iot_pkt_alloc(proto_spg_get_pkt_len(SPG_NO_USED_ADDR, | ||
|  |         rpt_pkt_len), IOT_SMART_GRID_MID); | ||
|  |     IOT_ASSERT(rpt_pkt); | ||
|  | 
 | ||
|  |     rsp = (spg_afn22_fn01_data_send_ul_t *)iot_pkt_reserve(rpt_pkt, | ||
|  |         proto_spg_get_rsvd_len(SPG_NO_USED_ADDR)); | ||
|  | 
 | ||
|  |     rsp->data_type = data_type; | ||
|  |     rsp->data_len = len; | ||
|  |     os_mem_cpy(rsp->data, data, len); | ||
|  |     proto_645_add33_handle(rsp->data, len); | ||
|  |     iot_pkt_put(rpt_pkt, rpt_pkt_len); | ||
|  | 
 | ||
|  |     iot_spg_ctrl_send_uart_sn(PROTO_SPG_PRM_SLAVE, PROTO_SPG_AFN_22, | ||
|  |         PROTO_SPG_F1, rpt_pkt, PROTO_SPG_APP_DI2_05, SPG_NO_USED_ADDR, sn); | ||
|  | } | ||
|  | 
 | ||
|  | static uint32_t iot_spg_ctrl_event_report_handle(uint8_t sn, | ||
|  |     uint8_t *addr, uint8_t dev_type, uint32_t proto_type, uint8_t evt_type, | ||
|  |     uint8_t *data, uint16_t len) | ||
|  | { | ||
|  |     (void)addr; | ||
|  |     (void)dev_type; | ||
|  |     (void)proto_type; | ||
|  | 
 | ||
|  |     switch (evt_type) { | ||
|  |     case IOT_CTRL_EVENT_DEVICE_CONNECT_CONF: | ||
|  |         iot_sg_ctrl_printf("%s connect conf\n", __FUNCTION__); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_DEVICE_CONNECT_FAIL: | ||
|  |         iot_spg_ctrl_send_00h02_nack(PROTO_SPG_ERR_COMM_TIMEOUT, sn); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_DEVICE_CONNECTED: | ||
|  |         iot_spg_ctrl_send_00h01_ack(sn); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_DEVICE_DISCONNECTED: | ||
|  |         iot_sg_ctrl_printf("%s disconnected\n", __FUNCTION__); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_CCO_DATA_RPT: | ||
|  |         iot_spg_ctrl_rpt_data_transfer_handle(sn, data, len, | ||
|  |             PROTO_SPG_CTRL_DATA_TYPE_CCO_CTRL); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_PASSTHROUGH_RPT: | ||
|  |         iot_spg_ctrl_rpt_data_transfer_handle(sn, data, len, | ||
|  |             PROTO_SPG_CTRL_DATA_TYPE_PASSTHROUGH); | ||
|  |         break; | ||
|  |     default: | ||
|  |         iot_sg_ctrl_printf("%s event:%d invalid\n", __FUNCTION__, evt_type); | ||
|  |         break; | ||
|  |     } | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_01h_init(ctrl_spg_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint32_t reason= PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  | 
 | ||
|  |     if (PROTO_SPG_F1 == frm->fn) { | ||
|  |         iot_spg_ctrl_01h_f01(frm); | ||
|  |     } else { | ||
|  |         iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x," | ||
|  |             "fn : %x\n", __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |     } | ||
|  |     iot_pkt_free(pkt); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_03h_f01() | ||
|  | { | ||
|  |     spg_afn03_fn01_hw_info_ul_t rsp_data; | ||
|  |     iot_build_info_t ts_info; | ||
|  | 
 | ||
|  |     /* hw info */ | ||
|  |     uint16_t sw_version = (iot_version_packed() & 0xFFFF); | ||
|  | 
 | ||
|  |     rsp_data.info.vendor_id = iot_sg_ctrl_get_vendor_id(); | ||
|  |     rsp_data.info.chip_code = iot_sg_ctrl_get_chip_code(); | ||
|  |     iot_version_get_user_build_info(&ts_info); | ||
|  |     rsp_data.info.day = iot_byte_to_bcd(ts_info.day); | ||
|  |     rsp_data.info.month = iot_byte_to_bcd(ts_info.month); | ||
|  |     rsp_data.info.year = iot_byte_to_bcd(ts_info.year); | ||
|  |     rsp_data.info.version[0] = (sw_version & 0xFF); | ||
|  |     rsp_data.info.version[1] = (sw_version >> 8); | ||
|  | 
 | ||
|  |     iot_spg_ctrl_send_uart(PROTO_SPG_PRM_SLAVE, PROTO_SPG_AFN_03, PROTO_SPG_F1, | ||
|  |         (const uint8_t *)&rsp_data, sizeof(rsp_data), PROTO_SPG_APP_DI2_00, | ||
|  |         SPG_NO_USED_ADDR, drv_data->sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_03h_read_param(ctrl_spg_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint32_t reason; | ||
|  | 
 | ||
|  |     switch (frm->fn) { | ||
|  |     case PROTO_SPG_F1: | ||
|  |         iot_spg_ctrl_03h_f01(); | ||
|  |         break; | ||
|  |     case PROTO_SPG_F90: | ||
|  |         iot_sg_ctrl_get_freq_band_msg(); | ||
|  |         break; | ||
|  |     default: | ||
|  |         reason = PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  |         iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x," | ||
|  |             "fn : %x\n", __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |         break; | ||
|  |     } | ||
|  |     iot_pkt_free(pkt); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_04h_f90(ctrl_spg_frame_pkt_t *frm) | ||
|  | { | ||
|  |     uint8_t reason = PROTO_SPG_ERR_OTHER; | ||
|  |     uint32_t result = ERR_FAIL; | ||
|  |     spg_set_freq_band_t *app_data = | ||
|  |         (spg_set_freq_band_t *)frm->app_data; | ||
|  |     uint16_t len = frm->app_data_len; | ||
|  | 
 | ||
|  |     if (!app_data) { | ||
|  |         reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |         goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (len < sizeof(*app_data)) { | ||
|  |         reason = PROTO_SPG_ERR_INVALID_DATA_LEN; | ||
|  |         goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |     iot_sg_ctrl_set_freq_band_msg(app_data->freq_band); | ||
|  |     result = ERR_OK; | ||
|  | out: | ||
|  |     if (ERR_FAIL == result) { | ||
|  |         iot_spg_ctrl_send_00h02_nack(reason, frm->app_sn); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_04h_set_param(ctrl_spg_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint32_t reason; | ||
|  | 
 | ||
|  |     switch (frm->fn) { | ||
|  |     case PROTO_SPG_F90: | ||
|  |         iot_spg_ctrl_04h_f90(frm); | ||
|  |         break; | ||
|  |     default: | ||
|  |         reason = PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  |         iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x," | ||
|  |             "fn : %x\n", __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |         break; | ||
|  |     } | ||
|  |     iot_pkt_free(pkt); | ||
|  | } | ||
|  | 
 | ||
|  | uint8_t iot_spg_ctrl_get_proto_data_sn(uint8_t *data, uint16_t data_len, | ||
|  |     uint8_t *app_sn) | ||
|  | { | ||
|  |     uint8_t result = ERR_FAIL, *spg_hdr; | ||
|  |     proto_spg_hdr_t *headr_data = NULL; | ||
|  |     proto_spg_addr_field_t *addr_data = NULL; | ||
|  |     proto_spg_app_data_t *app_data = NULL; | ||
|  | 
 | ||
|  |     spg_hdr = proto_spg_sanity_check(data, data_len, &result, | ||
|  |         PROTO_SPG_APP_CTRL_DI3); | ||
|  |     if (spg_hdr) { | ||
|  |         headr_data = (proto_spg_hdr_t*)spg_hdr; | ||
|  |         if (headr_data->ctrl_byte.addr) { | ||
|  |             addr_data = (proto_spg_addr_field_t*)(spg_hdr + | ||
|  |                 PROTO_SPG_DATA_OFFSET); | ||
|  |             app_data = (proto_spg_app_data_t*)(spg_hdr + PROTO_SPG_DATA_OFFSET + | ||
|  |                 sizeof(*addr_data)); | ||
|  |         } else { | ||
|  |             app_data = (proto_spg_app_data_t*)(spg_hdr + PROTO_SPG_DATA_OFFSET); | ||
|  |         } | ||
|  |         *app_sn = app_data->seq; | ||
|  |         return ERR_OK; | ||
|  |     } | ||
|  |     return result; | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_cco_ctrl_data_send(uint8_t *data, uint16_t data_len, | ||
|  |     uint8_t app_sn, iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint8_t reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |     uint32_t result = ERR_OK; | ||
|  |     uint8_t sn; | ||
|  | 
 | ||
|  |     proto_645_sub33_handle(data, data_len); | ||
|  |     if (iot_spg_ctrl_get_proto_data_sn(data, data_len, &sn) != ERR_OK) { | ||
|  |         iot_sg_ctrl_data_print("error data", data, data_len); | ||
|  |         reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |         result = ERR_FAIL; | ||
|  |         goto out; | ||
|  |     } | ||
|  |     iot_pkt_set_data(pkt, data); | ||
|  |     iot_pkt_set_tail(pkt, data + data_len); | ||
|  |     if (iot_sg_ctrl_send_data(PROTO_CTRL_CMD_TYPE_MR_CCO, sn, pkt)) { | ||
|  |         reason = PROTO_SPG_ERR_OTHER; | ||
|  |         result = ERR_FAIL; | ||
|  |     } | ||
|  | 
 | ||
|  | out: | ||
|  |     if (ERR_OK != result) { | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, app_sn); | ||
|  |         iot_pkt_free(pkt); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_passthrough_data_send(uint8_t *data, uint16_t data_len, | ||
|  |     uint8_t app_sn, iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint8_t reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |     uint8_t sn = 0; | ||
|  |     uint32_t result = ERR_OK; | ||
|  | 
 | ||
|  |     proto_645_sub33_handle(data, data_len); | ||
|  |     switch (iot_sg_ctrl_get_connect_role()) { | ||
|  |     case IOT_PLC_DEV_ROLE_CCO: | ||
|  |     { | ||
|  |         if (iot_spg_ctrl_get_proto_data_sn(data, data_len, &sn) != ERR_OK) { | ||
|  |             reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |             result = ERR_FAIL; | ||
|  |             goto out; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     case IOT_PLC_DEV_ROLE_STA: | ||
|  |     case IOT_PLC_DEV_ROLE_PCO: | ||
|  |     { | ||
|  |         if (iot_sg_ctrl_get_sta_passthrough_state()) { | ||
|  |             reason = PROTO_SPG_ERR_MASTER_IS_BUSY; | ||
|  |             result = ERR_FAIL; | ||
|  |             goto out; | ||
|  |         } | ||
|  | 
 | ||
|  |         if (proto_645_format_check(data, data_len, PROTO_645_DIR_MASTER) | ||
|  |             == NULL) { | ||
|  |             reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |             result = ERR_FAIL; | ||
|  |             goto out; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         reason = PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  |         result = ERR_FAIL; | ||
|  |         goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |     iot_pkt_set_data(pkt, data); | ||
|  |     iot_pkt_set_tail(pkt, data + data_len); | ||
|  |     if (sn) { | ||
|  |         result = iot_sg_ctrl_send_data(PROTO_CTRL_CMD_TYPE_PASSTHROUGH, sn, | ||
|  |             pkt); | ||
|  |     } else { | ||
|  |         result = iot_sg_ctrl_send_data(PROTO_CTRL_CMD_TYPE_PASSTHROUGH, | ||
|  |             IOT_CTRL_PASSTHROUGH_SN, pkt); | ||
|  |     } | ||
|  |     if (result != ERR_OK) { | ||
|  |         reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |     } | ||
|  | 
 | ||
|  | out: | ||
|  |     if (ERR_OK != result) { | ||
|  |         iot_sg_ctrl_data_print("error data", data, data_len); | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, app_sn); | ||
|  |         iot_pkt_free(pkt); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_data_send_handle(ctrl_spg_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint32_t reason= PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  |     uint8_t consumed = 0; | ||
|  |     spg_afn22_fn01_data_send_dl_t *req; | ||
|  | 
 | ||
|  |     req = (spg_afn22_fn01_data_send_dl_t *)frm->app_data; | ||
|  |     switch (req->data_type) { | ||
|  |     case PROTO_SPG_CTRL_DATA_TYPE_CCO_CTRL: | ||
|  |     { | ||
|  |         iot_sg_ctrl_cco_ctrl_data_send(req->data, req->data_len, frm->app_sn, | ||
|  |             pkt); | ||
|  |         consumed = 1; | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_SPG_CTRL_DATA_TYPE_PASSTHROUGH: | ||
|  |     { | ||
|  |         iot_sg_ctrl_passthrough_data_send(req->data, req->data_len, frm->app_sn, | ||
|  |             pkt); | ||
|  |         consumed = 1; | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         iot_sg_ctrl_printf("%s:data type error,reason is %lu, data type is %lu", | ||
|  |             __FUNCTION__, reason, req->data_type); | ||
|  |             iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |         break; | ||
|  |     } | ||
|  |     if (!consumed) { | ||
|  |         iot_pkt_free(pkt); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_22h_data_send(ctrl_spg_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint32_t reason= PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  |     uint8_t consumed = 0; | ||
|  | 
 | ||
|  |     switch (frm->fn) { | ||
|  |     case PROTO_SPG_F1: | ||
|  |     { | ||
|  |         iot_sg_ctrl_data_send_handle(frm, pkt); | ||
|  |         consumed = 1; | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x," | ||
|  |             "fn : %x\n", __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |             iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |         break; | ||
|  |     } | ||
|  |     if (!consumed) { | ||
|  |         iot_pkt_free(pkt); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_41h_f01(ctrl_spg_frame_pkt_t *frm) | ||
|  | { | ||
|  |     uint8_t cnt; | ||
|  |     uint8_t i; | ||
|  |     uint16_t rsp_len; | ||
|  |     spg_afn41_fn01_rpt_node_info_ul *rsp_data = NULL; | ||
|  |     ctrl_node_info_t *node_info = NULL; | ||
|  |     iot_pkt_t *tmp_pkt; | ||
|  |     iot_pkt_t *tmp2_pkt = NULL; | ||
|  | 
 | ||
|  |     cnt = iot_sg_ctrl_get_scan_node_cnt(); | ||
|  |     if (cnt > IOT_CTRL_SCAN_NODE_MAX_CNT) { | ||
|  |         iot_sg_ctrl_printf("WARNING: %s scan count: %d exceed \n", cnt); | ||
|  |         cnt = IOT_CTRL_SCAN_NODE_MAX_CNT; | ||
|  |     } else if (!cnt) { | ||
|  |         goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |     tmp2_pkt = iot_pkt_alloc(cnt * sizeof(ctrl_node_info_t), | ||
|  |         IOT_SMART_GRID_MID); | ||
|  |     IOT_ASSERT(tmp2_pkt); | ||
|  | 
 | ||
|  |     node_info = (ctrl_node_info_t *)iot_pkt_data(tmp2_pkt); | ||
|  |     cnt = iot_sg_ctrl_get_scan_node_info(node_info, 1, cnt); | ||
|  | out: | ||
|  |     rsp_len = sizeof(*rsp_data) + cnt * sizeof(spg_ctrl_node_info_t); | ||
|  |     tmp_pkt = iot_pkt_alloc(proto_spg_get_pkt_len(SPG_NO_USED_ADDR, | ||
|  |         rsp_len), IOT_SMART_GRID_MID); | ||
|  |     IOT_ASSERT(tmp_pkt); | ||
|  | 
 | ||
|  |     rsp_data = (spg_afn41_fn01_rpt_node_info_ul*)iot_pkt_reserve(tmp_pkt, | ||
|  |         proto_spg_get_rsvd_len(SPG_NO_USED_ADDR)); | ||
|  |     rsp_data->total_cnt = cnt; | ||
|  |     for (i = 0; i < cnt; i++, node_info++) { | ||
|  |         rsp_data->node_info[i].nid = node_info->nid; | ||
|  |         rsp_data->node_info[i].band_id = node_info->band_id; | ||
|  |         iot_mac_addr_cpy(rsp_data->node_info[i].addr, node_info->addr); | ||
|  |     } | ||
|  |     if (tmp2_pkt) { | ||
|  |         iot_pkt_free(tmp2_pkt); | ||
|  |     } | ||
|  |     iot_pkt_put(tmp_pkt, rsp_len); | ||
|  |     iot_spg_ctrl_send_uart_sn(PROTO_SPG_PRM_SLAVE, PROTO_SPG_AFN_41, | ||
|  |         PROTO_SPG_F1, tmp_pkt, PROTO_SPG_APP_DI2_00, SPG_NO_USED_ADDR, | ||
|  |         frm->app_sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_41h_f02(ctrl_spg_frame_pkt_t *frm) | ||
|  | { | ||
|  |     uint32_t reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |     uint32_t result = ERR_OK; | ||
|  |     spg_afn41_fn02_req_connect_node_dl_t *req = | ||
|  |         (spg_afn41_fn02_req_connect_node_dl_t *)frm->app_data; | ||
|  |     uint16_t len = frm->app_data_len; | ||
|  | 
 | ||
|  |     if (len < sizeof(spg_afn41_fn02_req_connect_node_dl_t)) { | ||
|  |         /* invalid data length */ | ||
|  |         reason = PROTO_SPG_ERR_INVALID_DATA_LEN; | ||
|  |         result = ERR_FAIL; | ||
|  |         goto out; | ||
|  |     } | ||
|  |     if (ERR_OK != iot_sg_ctrl_proto_connect_from_scan_node(req->addr, | ||
|  |         frm->app_sn)) { | ||
|  |         reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |         result = ERR_FAIL; | ||
|  |     } | ||
|  | out: | ||
|  |     if (ERR_OK != result) { | ||
|  |         iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x," | ||
|  |             "fn : %x\n", __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_41h_scan_node_mgr(ctrl_spg_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint32_t reason= PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  | 
 | ||
|  |     switch (frm->fn) { | ||
|  |     case PROTO_SPG_F1: | ||
|  |     { | ||
|  |         iot_spg_ctrl_41h_f01(frm); | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_SPG_F2: | ||
|  |     { | ||
|  |         iot_spg_ctrl_41h_f02(frm); | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x," | ||
|  |             "fn : %x\n", __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |         break; | ||
|  |     } | ||
|  |     iot_pkt_free(pkt); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_f0h_f01(ctrl_spg_frame_pkt_t *frm) | ||
|  | { | ||
|  |     spg_afnf0_fn01_req_connect_node_dl_t *cmd = NULL; | ||
|  | 
 | ||
|  |     uint32_t result = ERR_OK; | ||
|  |     uint8_t reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  | 
 | ||
|  |     cmd = (spg_afnf0_fn01_req_connect_node_dl_t*)frm->app_data; | ||
|  |     uint16_t len = frm->app_data_len; | ||
|  | 
 | ||
|  |     if (len < sizeof(spg_afnf0_fn01_req_connect_node_dl_t)) { | ||
|  |         reason = PROTO_SPG_ERR_INVALID_DATA_LEN; | ||
|  |         result = ERR_FAIL; | ||
|  |         goto out; | ||
|  |     } | ||
|  |     if (ERR_OK != iot_sg_ctrl_proto_connect(cmd->addr, | ||
|  |         (uint8_t)frm->app_sn)) { | ||
|  |         reason = PROTO_SPG_ERR_INVALID_DATA; | ||
|  |         result = ERR_FAIL; | ||
|  |     } | ||
|  | out: | ||
|  |     if (ERR_OK != result) { | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_f0h_f02(ctrl_spg_frame_pkt_t *frm) | ||
|  | { | ||
|  |     iot_sg_ctrl_reset_connet_status(); | ||
|  |     iot_spg_ctrl_send_00h01_ack(frm->app_sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_f0h_cmd(ctrl_spg_frame_pkt_t *frm, iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint32_t reason= PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  |     uint8_t consumed = 0; | ||
|  | 
 | ||
|  |     switch (frm->fn) { | ||
|  |     case PROTO_SPG_F1: | ||
|  |     { | ||
|  |         iot_spg_ctrl_f0h_f01(frm); | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_SPG_F2: | ||
|  |     { | ||
|  |         iot_spg_ctrl_f0h_f02(frm); | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : 0x%02X," | ||
|  |             "fn : 0x%02X\n", __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |         break; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (!consumed) { | ||
|  |         iot_pkt_free(pkt); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_spg_ctrl_send_data_handle(ctrl_spg_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint32_t reason= PROTO_SPG_ERR_MASTER_UNSUPPORTED_CMD; | ||
|  |     uint32_t result = ERR_OK; | ||
|  | 
 | ||
|  |     iot_sg_ctrl_printf("%s: afn = 0x%02X, fn = 0n%lu, sn: %d \n", __FUNCTION__, | ||
|  |         frm->afn, frm->fn, frm->app_sn); | ||
|  |     switch (frm->afn) { | ||
|  |     case PROTO_SPG_AFN_01: | ||
|  |     { | ||
|  |         iot_spg_ctrl_01h_init(frm, pkt); | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_SPG_AFN_03: | ||
|  |     { | ||
|  |         iot_spg_ctrl_03h_read_param(frm, pkt); | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_SPG_AFN_04: | ||
|  |     { | ||
|  |         iot_spg_ctrl_04h_set_param(frm, pkt); | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_SPG_AFN_22: | ||
|  |     { | ||
|  |         iot_spg_ctrl_22h_data_send(frm, pkt); | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_SPG_AFN_41: | ||
|  |     { | ||
|  |         iot_spg_ctrl_41h_scan_node_mgr(frm, pkt); | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_SPG_AFN_F0: | ||
|  |     { | ||
|  |         iot_spg_ctrl_f0h_cmd(frm, pkt); | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         result = ERR_FAIL; | ||
|  |         break; | ||
|  |     } | ||
|  |     if (ERR_OK != result) { | ||
|  |         iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x," | ||
|  |             "fn : %x\n", __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |         iot_spg_ctrl_send_00h02_nack((uint8_t)reason, frm->app_sn); | ||
|  |         iot_pkt_free(pkt); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @brief iot_sg_ctrl_uart_data_recv_handle - receive uart data | ||
|  |  * @param pkt: include full 3762 frame, the pkt whill be free | ||
|  |  */ | ||
|  | static uint32_t iot_spg_ctrl_uart_data_recv_handle(iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint8_t *spg_hdr; | ||
|  |     uint16_t len = (uint16_t)iot_pkt_data_len(pkt); | ||
|  |     proto_spg_hdr_t *headr_data = NULL; | ||
|  |     proto_spg_addr_field_t *addr_data = NULL; | ||
|  |     proto_spg_app_data_t *app_data = NULL; | ||
|  |     ctrl_spg_frame_pkt_t spg_cmd; | ||
|  |     uint32_t result = ERR_OK; | ||
|  | 
 | ||
|  |     if(len < sizeof(proto_spg_hdr_t)){ | ||
|  |         goto err; | ||
|  |     } | ||
|  | 
 | ||
|  |     spg_hdr = proto_spg_sanity_check(iot_pkt_data(pkt), len, | ||
|  |         (uint8_t *)&result, PROTO_SPG_APP_CTRL_DI3); | ||
|  |     if (!spg_hdr) { | ||
|  |         goto err; | ||
|  |     } | ||
|  | 
 | ||
|  |     headr_data = (proto_spg_hdr_t*)spg_hdr; | ||
|  |     if (headr_data->ctrl_byte.addr) { | ||
|  |         addr_data = (proto_spg_addr_field_t*)(spg_hdr + PROTO_SPG_DATA_OFFSET); | ||
|  |         app_data = (proto_spg_app_data_t*)(spg_hdr + PROTO_SPG_DATA_OFFSET + | ||
|  |             sizeof(*addr_data)); | ||
|  |         /* record mac msg */ | ||
|  |         os_mem_cpy(drv_data->dest_mac, addr_data->dest_mac, | ||
|  |             PROTO_SPG_MAC_ADDR_LEN); | ||
|  |         os_mem_cpy(drv_data->req_mac, addr_data->src_mac, | ||
|  |             PROTO_SPG_MAC_ADDR_LEN); | ||
|  |         /* offset address length */ | ||
|  |         headr_data->len -= PROTO_SPG_MAC_ADDR_LEN; | ||
|  |         headr_data->len -= PROTO_SPG_MAC_ADDR_LEN; | ||
|  |     } else { | ||
|  |         os_mem_set(drv_data->dest_mac, 0, PROTO_SPG_MAC_ADDR_LEN); | ||
|  |         os_mem_set(drv_data->req_mac, 0, PROTO_SPG_MAC_ADDR_LEN); | ||
|  |         app_data = (proto_spg_app_data_t*)(spg_hdr + PROTO_SPG_DATA_OFFSET); | ||
|  |     } | ||
|  |     /* check di data */ | ||
|  |     if ((app_data->di[3] != PROTO_SPG_APP_CTRL_DI3) || | ||
|  |         (app_data->di[1] != app_data->afn)) { | ||
|  |         goto err; | ||
|  |     } | ||
|  |     /* record seq msg */ | ||
|  |     drv_data->sn = app_data->seq; | ||
|  |     spg_cmd.app_sn = app_data->seq; | ||
|  |     spg_cmd.afn = app_data->afn; | ||
|  |     spg_cmd.fn = app_data->di[0]; | ||
|  |     spg_cmd.app_data_len = headr_data->len - PROTO_SPG_FIX_FIELD_LEN - | ||
|  |         sizeof(proto_spg_app_data_t); | ||
|  |     if (!spg_cmd.app_data_len) { | ||
|  |         spg_cmd.app_data = NULL; | ||
|  |     } else { | ||
|  |         spg_cmd.app_data = app_data->data; | ||
|  |     } | ||
|  |     iot_spg_ctrl_send_data_handle(&spg_cmd, pkt); | ||
|  |     goto out; | ||
|  | err: | ||
|  |     iot_pkt_free(pkt); | ||
|  |     result = ERR_FAIL; | ||
|  | out: | ||
|  |     return result; | ||
|  | } | ||
|  | 
 | ||
|  | static uint32_t iot_spg_ctrl_check_data_handle(iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint8_t *spg_hdr; | ||
|  |     uint16_t len = (uint16_t)iot_pkt_data_len(pkt); | ||
|  |     uint8_t ctrl = 0; | ||
|  |     uint32_t result = ERR_FAIL; | ||
|  | 
 | ||
|  |     if(len < sizeof(proto_spg_hdr_t)){ | ||
|  |         return result; | ||
|  |     } | ||
|  | 
 | ||
|  |     spg_hdr = proto_spg_sanity_check(iot_pkt_data(pkt), len, | ||
|  |         (uint8_t *)&result, PROTO_SPG_APP_CTRL_DI3); | ||
|  |     if (!spg_hdr) { | ||
|  |         return result; | ||
|  |     } | ||
|  | 
 | ||
|  |     ctrl = spg_hdr[PROTO_SPG_CTRL_OFFSET]; | ||
|  |     if ((ctrl & 0x07) == PROTO_CTRL_COMMUNICAT_RSVD) { | ||
|  |         result = ERR_OK; | ||
|  |     } | ||
|  |     return result; | ||
|  | } | ||
|  | 
 | ||
|  | iot_ctrl_drv_t g_spg_ctrl_drv = { | ||
|  |     .drv_id = IOT_CTRL_DRV_ID_SPG, | ||
|  |     .init = iot_spg_ctrl_drv_init, | ||
|  |     .deinit = iot_spg_ctrl_drv_deinit, | ||
|  |     .event_report_handle = iot_spg_ctrl_event_report_handle, | ||
|  |     .ctrl_drv_data_handle = iot_spg_ctrl_uart_data_recv_handle, | ||
|  |     .check_data_handle = iot_spg_ctrl_check_data_handle, | ||
|  |     .freq_band_report_cb = iot_spg_ctrl_freq_band_handler, | ||
|  |     .freq_band_set_result_cb = iot_spg_ctrl_set_freq_band_result, | ||
|  | }; | ||
|  | 
 | ||
|  | #endif /* IOT_SG_CONTROLLER_ENABLE */
 |