608 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			608 lines
		
	
	
		
			17 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 "iot_board_api.h"
 | ||
|  | #include "iot_plc_msg_api.h"
 | ||
|  | #include "proto_3762.h"
 | ||
|  | #include "proto_3762_vendor.h"
 | ||
|  | #include "iot_sg_ctrl_api.h"
 | ||
|  | 
 | ||
|  | #if (IOT_SG_CONTROLLER_ENABLE)
 | ||
|  | 
 | ||
|  | static uint16_t app_sn = 0; | ||
|  | static uint8_t connect_state = 0; | ||
|  | 
 | ||
|  | /* command from app */ | ||
|  | typedef struct _ctrl_frame_pkt_t { | ||
|  |     /* msdu sequence number */ | ||
|  |     uint16_t        app_sn; | ||
|  |     /* app function number definition */ | ||
|  |     uint8_t         afn; | ||
|  |     /* function code for each command */ | ||
|  |     uint8_t         fn; | ||
|  |     /* app_data */ | ||
|  |     uint8_t        *app_data; | ||
|  |     /* 3762 data len */ | ||
|  |     uint16_t        app_data_len; | ||
|  | } ctrl_frame_pkt_t; | ||
|  | 
 | ||
|  | static uint8_t iot_sg_ctrl_send_uart(uint8_t afn, uint8_t fn, | ||
|  |     uint8_t *app_data, uint16_t len, uint8_t *mac_buf, uint32_t mac_cnt, | ||
|  |     uint8_t sn) | ||
|  | { | ||
|  |     pkt_3762_hdr_t *pkt_hdr; | ||
|  |     iot_pkt_t *pkt; | ||
|  |     uint8_t *data, *cs_ptr = NULL, ret = ERR_OK; | ||
|  |     uint16_t index = 0; | ||
|  |     pkt = iot_pkt_alloc(proto_3762_get_pkt_len(mac_cnt, len), | ||
|  |         IOT_SMART_GRID_MID); | ||
|  |     if (!pkt) { | ||
|  |         ret = ERR_NOMEM; | ||
|  |         goto out; | ||
|  |     } | ||
|  |     data = iot_pkt_data(pkt); | ||
|  |     pkt_hdr = (pkt_3762_hdr_t*)data; | ||
|  |     pkt_hdr->sof_byte = PROTO_3762_SOF_BYTE; | ||
|  |     pkt_hdr->ctrl_byte.dir = PROTO_3762_DIR_UP_LINK; | ||
|  |     pkt_hdr->ctrl_byte.prm = PROTO_3762_PRM_SLAVE; | ||
|  |     pkt_hdr->ctrl_byte.phy_type = PROTO_3762_PHY_TYPE_PLC; | ||
|  |     /* user_data = &data[index]; */ | ||
|  |     os_mem_set(&pkt_hdr->user_data.res.ul_info, 0, sizeof(pkt_hdr->user_data)); | ||
|  |     pkt_hdr->user_data.res.ul_info.route_flag = 0; | ||
|  |     pkt_hdr->user_data.res.ul_info.phy_phase = 0; | ||
|  |     pkt_hdr->user_data.res.ul_info.sn = sn; | ||
|  |     pkt_hdr->user_data.res.ul_info.channel_id = 0; | ||
|  |     pkt_hdr->user_data.res.ul_info.event_flag = 0; | ||
|  |     pkt_hdr->user_data.res.ul_info.line_flag = 0; | ||
|  |     pkt_hdr->user_data.res.ul_info.tsfm_status = 0; | ||
|  |     index += sizeof(pkt_3762_hdr_t); | ||
|  |     if (mac_cnt) { | ||
|  |         pkt_hdr->user_data.res.ul_info.comm_module = 1; | ||
|  |         /* only src mac and dest mac for up link */ | ||
|  |         os_mem_cpy(data + index, mac_buf, mac_cnt * PROTO_3762_MAC_ADDR_LEN); | ||
|  |         index += (uint16_t)mac_cnt * PROTO_3762_MAC_ADDR_LEN; | ||
|  |     } | ||
|  |     /* set AFN */ | ||
|  |     data[index] = afn; | ||
|  |     index++; | ||
|  |     /* set Fn */ | ||
|  |     data[index] = 1 << ((fn - 1) % 8);      /* DT1 */ | ||
|  |     index++; | ||
|  |     data[index] = (fn - 1) / 8;             /* DT2 */ | ||
|  |     index++; | ||
|  |     os_mem_cpy(data + index, app_data, len); | ||
|  |     index += len; | ||
|  |     cs_ptr = &data[index++];              /* set the checksum byte pointer */ | ||
|  |     data[index] = PROTO_3762_EOF_BYTE; | ||
|  |     index++; | ||
|  |     pkt_hdr->len = index; | ||
|  |     *cs_ptr = proto_3762_get_checksum(data[PROTO_3762_CTRL_OFFSET], | ||
|  |         data + PROTO_3762_DATA_OFFSET, | ||
|  |         index - PROTO_3762_DATA_OFFSET - 2); | ||
|  |     // put checksum and back code. 2 byte.
 | ||
|  |     iot_pkt_put(pkt, index); | ||
|  |     iot_ctrl_uart_send(pkt); | ||
|  | out: | ||
|  |     return ret; | ||
|  | } | ||
|  | 
 | ||
|  | static uint32_t iot_sg_ctrl_drv_init() | ||
|  | { | ||
|  |     uint32_t ret = 0; | ||
|  |     uint32_t result = ERR_OK; | ||
|  |     iot_frame_fmt fmt = { 0 }; | ||
|  | 
 | ||
|  |     /* config the UART port settings */ | ||
|  |     fmt.preamble_code[0] = PROTO_3762_2013_START_CHAR; | ||
|  |     fmt.preamble_codelen = 1; | ||
|  |     fmt.datalen_offset = 0; | ||
|  |     fmt.datalen_size = 2; | ||
|  |     fmt.backcode_offset = 0; | ||
|  |     fmt.backcode_len = 1; | ||
|  |     /* in uart data parsing, datalen means raw data to be send,
 | ||
|  |      * excluding preamble/datalen/backcode. For datalen field in | ||
|  |      * 3762 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_3762_2013_END_CHAR; | ||
|  |     fmt.frame_timeout = CTRL_FRAME_PARSE_TIMEOUT; | ||
|  |     fmt.timeout_mode = TIMEOUT_PERDATA; | ||
|  |     fmt.check_frame_func = proto_3762_check_frame_handler; | ||
|  |     ret = iot_sg_ctrl_config_uart(IOT_SG_CTRL_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_sg_ctrl_drv_deinit() | ||
|  | { | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_send_00h01_ack(uint8_t sn) | ||
|  | { | ||
|  |     afn00_fn01_conf_13_t reject = { 0 }; | ||
|  |     reject.cmd_state = 1; | ||
|  |     iot_sg_ctrl_send_uart(PROTO_3762_AFN_00, PROTO_3762_F1, (uint8_t*)&reject, | ||
|  |         sizeof(reject), NULL, 0, sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_send_00h02_nack(uint8_t reason, uint8_t sn) | ||
|  | { | ||
|  |     afn00_fn02_reject_t reject = { 0 }; | ||
|  |     reject.err_no = reason; | ||
|  |     iot_sg_ctrl_send_uart(PROTO_3762_AFN_00, PROTO_3762_F2, (uint8_t*)&reject, | ||
|  |         sizeof(reject), NULL, 0, sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_send_f0_f250_status_rpt(uint8_t connect, | ||
|  |     uint8_t role, uint8_t *addr, uint8_t sn) | ||
|  | { | ||
|  |     afnf0_fn250_status_rpt_ul_t uart_rpt; | ||
|  | 
 | ||
|  |     os_mem_set(&uart_rpt, 0, sizeof(uart_rpt)); | ||
|  |     if (connect) { | ||
|  |         uart_rpt.ready = PROTO_3762_STATE_CONNECTED; | ||
|  |         if (role == PROTO_CTRL_DEV_ROLE_CCO) { | ||
|  |             uart_rpt.connect_role = PROTO_3762_DEV_ROLE_CCO; | ||
|  |         } else { | ||
|  |             uart_rpt.connect_role = PROTO_3762_DEV_ROLE_STA; | ||
|  |         } | ||
|  |         iot_mac_addr_cpy(uart_rpt.addr, addr); | ||
|  |     } else { | ||
|  |         uart_rpt.ready = PROTO_3762_STATE_DISCONNECTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     iot_sg_ctrl_send_uart(PROTO_3762_AFN_F0, PROTO_3762_F250, | ||
|  |         (uint8_t *)&uart_rpt, sizeof(uart_rpt), NULL, 0, sn); | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_rpt_id_info(uint8_t *data, uint16_t len, uint8_t sn) | ||
|  | { | ||
|  |     uint32_t pkt_len; | ||
|  |     iot_pkt_t *pkt = NULL; | ||
|  |     afn10h_fn40_query_node_id_ul_t *rsp; | ||
|  |     iot_sg_ctrl_id_info_t *id_info = (iot_sg_ctrl_id_info_t *)data; | ||
|  | 
 | ||
|  |     (void)len; | ||
|  |     pkt_len = id_info->id_len + sizeof(afn10h_fn40_query_node_id_ul_t); | ||
|  |     pkt = (iot_pkt_t *)iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID); | ||
|  |     IOT_ASSERT(pkt); | ||
|  | 
 | ||
|  |     rsp = (afn10h_fn40_query_node_id_ul_t *)iot_pkt_data(pkt); | ||
|  |     rsp->dev_type = id_info->dev_type; | ||
|  |     iot_mac_addr_cpy(rsp->mac, id_info->addr); | ||
|  |     rsp->id_type = id_info->id_type; | ||
|  |     rsp->id_len = id_info->id_len; | ||
|  |     rsp->dev_type = id_info->dev_type; | ||
|  |     os_mem_cpy(rsp->id_info, id_info->info, id_info->id_len); | ||
|  |     iot_pkt_put(pkt, pkt_len); | ||
|  | 
 | ||
|  |     iot_sg_ctrl_send_uart(PROTO_3762_AFN_10, PROTO_3762_F40, iot_pkt_data(pkt), | ||
|  |         (uint16_t)pkt_len, NULL, 0, sn); | ||
|  |     iot_pkt_free(pkt); | ||
|  | } | ||
|  | 
 | ||
|  | static uint32_t iot_sg_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)proto_type; | ||
|  | 
 | ||
|  |     switch (evt_type) { | ||
|  |     case IOT_CTRL_EVENT_DEVICE_CONNECT_CONF: | ||
|  |         iot_sg_ctrl_send_00h01_ack(sn); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_DEVICE_CONNECT_FAIL: | ||
|  |         iot_sg_ctrl_send_00h02_nack(COMM_TIMEOUT, sn); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_DEVICE_CONNECTED: | ||
|  |         connect_state = 1; | ||
|  |         iot_sg_ctrl_send_f0_f250_status_rpt(1, dev_type, addr, sn); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_DEVICE_DISCONNECTED: | ||
|  |         connect_state = 0; | ||
|  |         iot_sg_ctrl_send_f0_f250_status_rpt(0, dev_type, addr, sn); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_METER_DATA: | ||
|  |         iot_sg_ctrl_send_uart(PROTO_3762_AFN_13, PROTO_3762_F1, data, len, | ||
|  |             NULL, 0, sn); | ||
|  |         break; | ||
|  |     case IOT_CTRL_EVENT_ID_INFO: | ||
|  |         iot_sg_ctrl_rpt_id_info(data, len, sn); | ||
|  |         break; | ||
|  |     default: | ||
|  |         break; | ||
|  |     } | ||
|  |     return ERR_OK; | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_f0h_f249(ctrl_frame_pkt_t *frm) | ||
|  | { | ||
|  |     uint32_t result = ERR_FAIL; | ||
|  |     uint8_t reason = MASTER_UNSUPPORTED_CMD; | ||
|  | 
 | ||
|  |     afnf0_fn249_connect_conf_dl_t *cmd = | ||
|  |         (afnf0_fn249_connect_conf_dl_t*)frm->app_data; | ||
|  |     uint16_t len = frm->app_data_len; | ||
|  | 
 | ||
|  |     if (len < sizeof(afnf0_fn249_connect_conf_dl_t)) { | ||
|  |         reason = INVALID_DATA_LEN; | ||
|  |         goto out; | ||
|  |     } | ||
|  |     if (iot_board_check_magic_no(cmd->magic_no) == 0) { | ||
|  |         iot_sg_ctrl_printf("%s : magic_no check fail \n", __FUNCTION__); | ||
|  |         goto out; | ||
|  |     } | ||
|  |     if (ERR_OK == iot_sg_ctrl_proto_connect(cmd->dst_mac, | ||
|  |         (uint8_t)frm->app_sn)) { | ||
|  |         result = ERR_OK; | ||
|  |     } | ||
|  | out: | ||
|  |     if (ERR_OK != result) { | ||
|  |         iot_sg_ctrl_send_00h02_nack(reason, (uint8_t)frm->app_sn); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_f0h_debug(ctrl_frame_pkt_t *frm) | ||
|  | { | ||
|  |     uint32_t result = ERR_FAIL; | ||
|  |     uint8_t reason = MASTER_UNSUPPORTED_CMD; | ||
|  | 
 | ||
|  |     switch (frm->fn) { | ||
|  |     case PROTO_3762_F249: | ||
|  |     { | ||
|  |         iot_sg_ctrl_f0h_f249(frm); | ||
|  |         result = ERR_OK; | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         break; | ||
|  |     } | ||
|  |     if (ERR_OK !=result) { | ||
|  |         iot_sg_ctrl_send_00h02_nack(reason, (uint8_t)frm->app_sn); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_send_data_handle_cco(ctrl_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint8_t reason; | ||
|  |     uint8_t consumed = 0; | ||
|  | 
 | ||
|  |     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_3762_AFN_F0: | ||
|  |     { | ||
|  |         switch (frm->fn) { | ||
|  |         case PROTO_3762_F249: | ||
|  |         { | ||
|  |             iot_sg_ctrl_f0h_debug(frm); | ||
|  |             goto out; | ||
|  |         } | ||
|  |         case PROTO_3762_F233: | ||
|  |         case PROTO_3762_F234: | ||
|  |         { | ||
|  |             break; | ||
|  |         } | ||
|  |         default: | ||
|  |             reason = MASTER_UNSUPPORTED_CMD; | ||
|  |             goto err; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_3762_AFN_05: | ||
|  |     { | ||
|  |         switch (frm->fn) { | ||
|  |         case PROTO_3762_F131: | ||
|  |         { | ||
|  |             break; | ||
|  |         } | ||
|  |         default: | ||
|  |             reason = MASTER_UNSUPPORTED_CMD; | ||
|  |             goto err; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_3762_AFN_10: | ||
|  |     { | ||
|  |         switch (frm->fn) { | ||
|  |         case PROTO_3762_F2: | ||
|  |         case PROTO_3762_F21: | ||
|  |         { | ||
|  |             break; | ||
|  |         } | ||
|  |         default: | ||
|  |             reason = MASTER_UNSUPPORTED_CMD; | ||
|  |             goto err; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_3762_AFN_11: | ||
|  |     { | ||
|  |         switch (frm->fn) { | ||
|  |         case PROTO_3762_F126: | ||
|  |         case PROTO_3762_F127: | ||
|  |         { | ||
|  |             break; | ||
|  |         } | ||
|  |         default: | ||
|  |             reason = MASTER_UNSUPPORTED_CMD; | ||
|  |             goto err; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_3762_AFN_13: | ||
|  |     { | ||
|  |         switch (frm->fn) { | ||
|  |         case PROTO_3762_F1: | ||
|  |         { | ||
|  |             break; | ||
|  |         } | ||
|  |         default: | ||
|  |             reason = MASTER_UNSUPPORTED_CMD; | ||
|  |             goto err; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         reason = MASTER_UNSUPPORTED_CMD; | ||
|  |         goto err; | ||
|  |     } | ||
|  | 
 | ||
|  |     consumed = 1; | ||
|  |     if (iot_sg_ctrl_send_data(PROTO_CTRL_CMD_TYPE_MR_CCO, | ||
|  |         (uint8_t)frm->app_sn, pkt)) { | ||
|  |         reason = INVALID_DATA; | ||
|  |         goto err; | ||
|  |     } | ||
|  |     goto out; | ||
|  | err: | ||
|  |     iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x,fn : %x\n", | ||
|  |         __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |     iot_sg_ctrl_send_00h02_nack(reason, (uint8_t)app_sn); | ||
|  | out: | ||
|  |     if (!consumed) { | ||
|  |         iot_pkt_free(pkt); | ||
|  |     } | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_send_data_handle_sta(ctrl_frame_pkt_t *frm, | ||
|  |     iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint8_t reason; | ||
|  |     uint8_t consumed = 0; | ||
|  | 
 | ||
|  |     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_3762_AFN_F0: | ||
|  |     { | ||
|  |         iot_sg_ctrl_f0h_debug(frm); | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_3762_AFN_13: | ||
|  |     { | ||
|  |         switch (frm->fn) { | ||
|  |         case PROTO_3762_F1: | ||
|  |         { | ||
|  |             afn13_fn01_router_data_fwd_2013_t *req; | ||
|  |             datagram_t *datagram; | ||
|  | 
 | ||
|  |             req = (afn13_fn01_router_data_fwd_2013_t *)(frm->app_data); | ||
|  |             datagram = (datagram_t *)req->mac[req->sec_node_cnt]; | ||
|  | 
 | ||
|  |             iot_pkt_set_data(pkt, datagram->data); | ||
|  |             iot_pkt_set_tail(pkt, datagram->data + datagram->data_len); | ||
|  |             consumed = 1; | ||
|  |             if (iot_sg_ctrl_send_data(PROTO_CTRL_CMD_TYPE_MR_STA, | ||
|  |                 (uint8_t)frm->app_sn, pkt)) { | ||
|  |                 reason = INVALID_DATA; | ||
|  |                 goto err; | ||
|  |             } | ||
|  |             break; | ||
|  |         } | ||
|  |         default: | ||
|  |             reason = MASTER_UNSUPPORTED_CMD; | ||
|  |             goto err; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     case PROTO_3762_AFN_10: | ||
|  |     { | ||
|  |         switch (frm->fn) { | ||
|  |         case PROTO_3762_F40: | ||
|  |         { | ||
|  |             afn10h_fn40_query_node_id_dl_t *req; | ||
|  |             req = (afn10h_fn40_query_node_id_dl_t *)frm->app_data; | ||
|  | 
 | ||
|  |             if (!connect_state) { | ||
|  |                 iot_sg_ctrl_proto_connect(req->mac, (uint8_t)frm->app_sn); | ||
|  |             } | ||
|  |             iot_pkt_set_data(pkt, &(req->id_type)); | ||
|  |             iot_pkt_set_tail(pkt, &(req->id_type) + sizeof(req->id_type)); | ||
|  |             consumed = 1; | ||
|  |             if (iot_sg_ctrl_send_data(PROTO_CTRL_CMD_TYPE_QR_CHIP_ID_STA, | ||
|  |                 (uint8_t)frm->app_sn, pkt)) { | ||
|  |                 reason = INVALID_DATA; | ||
|  |                 goto err; | ||
|  |             } | ||
|  |             break; | ||
|  |         } | ||
|  |         default: | ||
|  |             reason = MASTER_UNSUPPORTED_CMD; | ||
|  |             goto err; | ||
|  |         } | ||
|  |         break; | ||
|  |     } | ||
|  |     default: | ||
|  |         reason = MASTER_UNSUPPORTED_CMD; | ||
|  |         goto err; | ||
|  |     } | ||
|  |     goto out; | ||
|  | err: | ||
|  |     iot_sg_ctrl_printf("%s:data_handle error,reason is %lu,afn : %x,fn : %x\n", | ||
|  |         __FUNCTION__, reason, frm->afn, frm->fn); | ||
|  |     iot_sg_ctrl_send_00h02_nack(reason, (uint8_t)app_sn); | ||
|  | out: | ||
|  |     if (!consumed) { | ||
|  |         iot_pkt_free(pkt); | ||
|  |     } | ||
|  |     return; | ||
|  | } | ||
|  | 
 | ||
|  | static void iot_sg_ctrl_send_data_handle(ctrl_frame_pkt_t *frm, iot_pkt_t *pkt) | ||
|  | { | ||
|  |     switch (iot_sg_ctrl_get_connect_role()) { | ||
|  |     case IOT_PLC_DEV_ROLE_INVALID: | ||
|  |     case IOT_PLC_DEV_ROLE_CCO: | ||
|  |         iot_sg_ctrl_send_data_handle_cco(frm, pkt); | ||
|  |         break; | ||
|  |     case IOT_PLC_DEV_ROLE_STA: | ||
|  |     case IOT_PLC_DEV_ROLE_PCO: | ||
|  |         iot_sg_ctrl_send_data_handle_sta(frm, pkt); | ||
|  |         break; | ||
|  |     default: | ||
|  |         break; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @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_sg_ctrl_uart_data_recv_handle(iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint8_t *data = iot_pkt_data(pkt); | ||
|  |     uint16_t len = (uint16_t)iot_pkt_data_len(pkt); | ||
|  |     uint8_t *app_data = NULL, addr_cnt; | ||
|  |     uint8_t result; | ||
|  |     uint16_t app_data_len = len; | ||
|  |     user_data_t *user_data = NULL; | ||
|  |     ctrl_frame_pkt_t frm = {0}; | ||
|  |     uint32_t relsut = ERR_OK; | ||
|  | 
 | ||
|  |     if (len < sizeof(user_data_t) + PROTO_3762_DATA_OFFSET) { | ||
|  |         result = INVALID_DATA; | ||
|  |         goto err; | ||
|  |     } | ||
|  | 
 | ||
|  | parse_3762: | ||
|  |     user_data = (user_data_t*)(data + PROTO_3762_DATA_OFFSET); | ||
|  |     result = (uint8_t)proto_3762_sanity_check(data, app_data_len); | ||
|  |     if ((result == INVALID_DATA_LEN) || (result == INVALID_FORMAT)) { | ||
|  |         do { | ||
|  |             app_data_len--; | ||
|  |             data += 1; | ||
|  |             if (data[0] == PROTO_3762_SOF_BYTE) { | ||
|  |                 goto parse_3762; | ||
|  |             } | ||
|  |         } while (app_data_len > PROTO_3762_FIX_FIELD_LEN); | ||
|  |         goto err; | ||
|  |     } else if (result) { | ||
|  |         goto err; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (app_data_len < sizeof(user_data_t) + PROTO_3762_DATA_OFFSET) { | ||
|  |         result = INVALID_DATA; | ||
|  |         goto err; | ||
|  |     } | ||
|  | 
 | ||
|  |     app_data = user_data->data; | ||
|  |     app_data_len -= (sizeof(user_data->res) + PROTO_3762_DATA_OFFSET); | ||
|  |     if (user_data->res.dl_info.comm_module != 0) { | ||
|  |         addr_cnt = 2 + user_data->res.dl_info.rpter_level; | ||
|  |         app_data += PROTO_3762_MAC_ADDR_LEN * addr_cnt; | ||
|  |         app_data_len -= PROTO_3762_MAC_ADDR_LEN * addr_cnt; | ||
|  |     } | ||
|  | 
 | ||
|  |     frm.app_sn = user_data->res.dl_info.sn; | ||
|  |     app_sn = frm.app_sn; | ||
|  |     frm.afn = app_data[0]; | ||
|  |     frm.fn = proto_3762_get_fn_code(app_data + 1); | ||
|  |     frm.app_data_len = app_data_len - (PROTO_3762_AFN_FN_LEN + | ||
|  |         PROTO_3762_CHECKSUM_LEN + PROTO_3762_BACKCODE_LEN); | ||
|  |     frm.app_data = (app_data + PROTO_3762_AFN_FN_LEN); | ||
|  |     iot_sg_ctrl_send_data_handle(&frm, pkt); | ||
|  |     goto out; | ||
|  | err: | ||
|  |     iot_pkt_free(pkt); | ||
|  |     relsut = ERR_FAIL; | ||
|  | out: | ||
|  |     return relsut; | ||
|  | } | ||
|  | 
 | ||
|  | static uint32_t iot_sg_ctrl_check_data_handle(iot_pkt_t *pkt) | ||
|  | { | ||
|  |     uint8_t *data = iot_pkt_data(pkt); | ||
|  |     uint16_t len = (uint16_t)iot_pkt_data_len(pkt); | ||
|  |     uint8_t ctrl = 0; | ||
|  |     uint32_t result = INVALID_DATA; | ||
|  |     if (len < sizeof(user_data_t) + PROTO_3762_DATA_OFFSET) { | ||
|  |         return result; | ||
|  |     } | ||
|  | 
 | ||
|  | parse_3762: | ||
|  |     result = proto_3762_sanity_check(data, len); | ||
|  |     if ((result == INVALID_DATA_LEN) || (result == INVALID_FORMAT)) { | ||
|  |         do { | ||
|  |             len--; | ||
|  |             data += 1; | ||
|  |             if (data[0] == PROTO_3762_SOF_BYTE) { | ||
|  |                 goto parse_3762; | ||
|  |             } | ||
|  |         } while (len > PROTO_3762_FIX_FIELD_LEN); | ||
|  |         goto out; | ||
|  |     } else if (result) { | ||
|  |         goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (len < sizeof(user_data_t) + PROTO_3762_DATA_OFFSET) { | ||
|  |         result = INVALID_DATA; | ||
|  |         goto out; | ||
|  |     } | ||
|  | 
 | ||
|  |     ctrl = data[PROTO_3762_CTRL_OFFSET]; | ||
|  |     if ((ctrl & 0x1f) == PROTO_CTRL_COMMUNICAT_PLC) { | ||
|  |         result = ERR_OK; | ||
|  |     } else { | ||
|  |         result = INVALID_DATA; | ||
|  |     } | ||
|  | 
 | ||
|  | out: | ||
|  |     return result; | ||
|  | } | ||
|  | 
 | ||
|  | iot_ctrl_drv_t g_sg_ctrl_drv = { | ||
|  |     .drv_id = IOT_CTRL_DRV_ID_SG, | ||
|  |     .init = iot_sg_ctrl_drv_init, | ||
|  |     .deinit = iot_sg_ctrl_drv_deinit, | ||
|  |     .event_report_handle = iot_sg_ctrl_event_report_handle, | ||
|  |     .ctrl_drv_data_handle = iot_sg_ctrl_uart_data_recv_handle, | ||
|  |     .check_data_handle = iot_sg_ctrl_check_data_handle, | ||
|  |     .freq_band_report_cb = NULL, | ||
|  |     .freq_band_set_result_cb = NULL, | ||
|  | }; | ||
|  | 
 | ||
|  | #endif /* IOT_SG_CONTROLLER_ENABLE */
 |