3373 lines
		
	
	
		
			114 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			3373 lines
		
	
	
		
			114 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /****************************************************************************
 | |
| 
 | |
| Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | |
| 
 | |
| This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | |
| be copied by any method or incorporated into another program without
 | |
| the express written consent of Aerospace C.Power. This Information or any portion
 | |
| thereof remains the property of Aerospace C.Power. The Information contained herein
 | |
| is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | |
| liability for its use in any way and conveys no license or title under
 | |
| any patent or copyright and makes no representation or warranty that this
 | |
| Information is free from patent or copyright infringement.
 | |
| 
 | |
| ****************************************************************************/
 | |
| 
 | |
| /* os_ship header files */
 | |
| #include "os_task_api.h"
 | |
| #include "os_event_api.h"
 | |
| #include "os_timer_api.h"
 | |
| #include "os_utils_api.h"
 | |
| 
 | |
| /* iot common header files */
 | |
| #include "iot_plc_api.h"
 | |
| #include "iot_module_api.h"
 | |
| #include "iot_queue_api.h"
 | |
| #include "iot_config_api.h"
 | |
| #include "iot_plc_msg_api.h"
 | |
| #include "iot_board_api.h"
 | |
| 
 | |
| #include "iot_mem_pool_api.h"
 | |
| #include "iot_config_api.h"
 | |
| #include "iot_app_api.h"
 | |
| #include "iot_errno_api.h"
 | |
| #include "iot_sg_drv_api.h"
 | |
| #include "iot_pib_api.h"
 | |
| #include "iot_ntoh_api.h"
 | |
| #include "iot_oem_api.h"
 | |
| 
 | |
| #include "proto_645.h"
 | |
| #include "proto_645_vendor.h"
 | |
| #include "proto_69845.h"
 | |
| #include "proto_69845_vendor.h"
 | |
| #include "proto_crc16.h"
 | |
| #include "proto_conn_less.h"
 | |
| #include "iot_frame_parse_api.h"
 | |
| #include "proto_dlms.h"
 | |
| #include "proto_qsxj.h"
 | |
| #include "proto_gw_app.h"
 | |
| 
 | |
| #include "iot_io_api.h"
 | |
| #include "iot_dbglog_api.h"
 | |
| #include "iot_uart_api.h"
 | |
| #include "iot_utils_api.h"
 | |
| #include "iot_dev_test.h"
 | |
| #include "iot_proto_dev_test.h"
 | |
| 
 | |
| /* define the length of the packet used for ppm detect */
 | |
| #define IOT_DEV_TEST_PPM_DETCT_PKG_LEN          400
 | |
| 
 | |
| #if IOT_DEV_TEST_BROADCAST_MODD_CFG
 | |
| 
 | |
| /* ppm detect function switch,  for the normal controller, this is always off */
 | |
| #define IOT_DEV_TEST_PPM_DETECT_EN              0
 | |
| 
 | |
| #else
 | |
| 
 | |
| /* ppm detect function switch, for HX applications, turn on this function when
 | |
|  * ppm detect is needed.
 | |
|  * for example, some CIU factories have problems in production test, you can
 | |
|  * try to open this function
 | |
|  */
 | |
| #define IOT_DEV_TEST_PPM_DETECT_EN              0
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #if (IOT_STA_CONTROL_MODE == 2) || (IOT_DEV_TEST_CCO_MODE)
 | |
| 
 | |
| static iot_dev_test_task_data_t *dev_test_task_data;
 | |
| 
 | |
| static uint8_t iot_dev_test_send_mode_config(uint8_t *dst_mac);
 | |
| 
 | |
| static void iot_dev_test_flash_info_init(void);
 | |
| 
 | |
| static void iot_dev_test_close_uart(iot_uart_h uart);
 | |
| 
 | |
| static bool_t iot_dev_test_set_uart_config(iot_uart_h uart);
 | |
| 
 | |
| static uint8_t iot_dev_test_flash_save(iot_dev_test_pib_t *p_info);
 | |
| 
 | |
| #if (IOT_DEV_TEST_DEBUG_EN == 1)
 | |
| 
 | |
| static char dev_test_log_buf[IOT_DEV_TEST_LOG_BUF_LEN] = { 0 };
 | |
| 
 | |
| void iot_dev_test_data_print(const char* str, uint8_t* buf, uint16_t len)
 | |
| {
 | |
|     uint32_t offset = 0;
 | |
| 
 | |
|     offset = iot_sprintf(dev_test_log_buf, "%s[len:%d]", str, len);
 | |
|     for (uint32_t i = 0; i < len; ++i) {
 | |
|         offset += iot_sprintf(dev_test_log_buf + offset, "%02X ", buf[i]);
 | |
|         if (IOT_DEV_TEST_LOG_BUF_LEN <= offset + 4) {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     dev_test_log_buf[offset] = 0;
 | |
|     iot_cus_printf("%s\n", dev_test_log_buf);
 | |
| }
 | |
| 
 | |
| #else /* IOT_DEV_TEST_DEBUG_EN == 1 */
 | |
| 
 | |
| void iot_dev_test_data_print(const char* str, uint8_t* buf, uint16_t len)
 | |
| {
 | |
|     (void)str;
 | |
|     (void)buf;
 | |
|     (void)len;
 | |
|     return;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #if IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER
 | |
| 
 | |
| /* mac addr of CIU TESTER */
 | |
| static const uint8_t ciu_tester_mac[IOT_MAC_ADDR_LEN] =
 | |
|     { 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x01 };
 | |
| 
 | |
| /* UART baudrate lookup table */
 | |
| static const uint32_t baud_tbl[SUPPORTED_BAUD_CNT] = {
 | |
|     2400,        // baudidx 0
 | |
|     4800,        // baudidx 1
 | |
|     9600,        // baudidx 2
 | |
|     115200,      // baudidx 3
 | |
| };
 | |
| 
 | |
| #endif
 | |
| 
 | |
| static void iot_dev_test_post_task_msg(uint16_t msg_type, uint16_t msg_id,
 | |
|     void *data)
 | |
| {
 | |
|     iot_task_msg_t *msg;
 | |
|     iot_dev_test_task_msg_t *task_msg;
 | |
|     iot_task_h task_hdl = dev_test_task_data->task_handle;
 | |
| 
 | |
|     msg = iot_task_alloc_msg_with_reserved(task_hdl, 0);
 | |
|     if (!msg) {
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     task_msg = (iot_dev_test_task_msg_t*)msg;
 | |
|     task_msg->msg.type = msg_type;
 | |
|     task_msg->msg.id = msg_id;
 | |
|     task_msg->data = data;
 | |
|     iot_task_queue_msg(dev_test_task_data->task_handle, &task_msg->msg, 1);
 | |
| 
 | |
| }
 | |
| 
 | |
| /* send mode config to all the sta and lock the stas' band */
 | |
| static void iot_dev_test_config_all_sta_test_mode(void)
 | |
| {
 | |
|     static uint8_t check_cnt = IOT_DEV_TEST_BCAST_TIMER_CNT;
 | |
| 
 | |
|     check_cnt++;
 | |
|     if (check_cnt >= IOT_DEV_TEST_BCAST_TIMER_CNT) {
 | |
|         iot_dev_test_send_mode_config((uint8_t *)bcast_mac);
 | |
|         check_cnt = 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER)
 | |
| 
 | |
| /* define the max tool ppm value, which the tool may config */
 | |
| #define IOT_DEV_TEST_MAX_TOOL_PPM       15
 | |
| 
 | |
| static uint8_t spec_mac[IOT_MAC_ADDR_LEN] = {0xAA, 0xBB,0xCC, 0xCC,0xBB, 0xAA};
 | |
| 
 | |
| static void iot_dev_test_uart_send(iot_pkt_t *pkt);
 | |
| static bool_t iot_dev_test_frame_rpt_check(uint8_t *mac, uint16_t sn);
 | |
| static uint16_t iot_dev_test_app_get_sn(void);
 | |
| 
 | |
| static iot_uart_h iot_dev_test_open_uart(uint8_t port);
 | |
| 
 | |
| static void iot_dev_test_set_mac(uint8_t *mac);
 | |
| 
 | |
| static bool_t iot_dev_test_app_pkt_report_check(uint8_t *mac, uint32_t in_sn) {
 | |
|     bool_t need_rpt = false;
 | |
| 
 | |
|     iot_cus_printf("dst mac[%02x:%02x:%02x:%02x:%02x:%02x], stored sn[%lu], "
 | |
|         "recv sn[%lu]\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],
 | |
|         dev_test_task_data->stored_app_sn, in_sn);
 | |
| 
 | |
|     iot_cus_printf("local mac[%02x:%02x:%02x:%02x:%02x:%02x]\n",
 | |
|         dev_test_task_data->mac_addr[0], dev_test_task_data->mac_addr[1],
 | |
|         dev_test_task_data->mac_addr[2], dev_test_task_data->mac_addr[3],
 | |
|         dev_test_task_data->mac_addr[4], dev_test_task_data->mac_addr[5]);
 | |
| 
 | |
|     if (iot_mac_addr_cmp(mac, dev_test_task_data->mac_addr)
 | |
|             || iot_mac_is_bcast(mac)) {
 | |
|         need_rpt = true;
 | |
|         if (dev_test_task_data->stored_app_sn != in_sn) {
 | |
| //            need_rpt = true;
 | |
|             dev_test_task_data->stored_app_sn = in_sn;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
|     return need_rpt;
 | |
| }
 | |
| 
 | |
| static uint8_t iot_dev_test_fullfil_rsp_snr_cmd(uint8_t *data, uint16_t len,
 | |
|     int8_t snr, int8_t rssi)
 | |
| {
 | |
|     proto_645_header_t *hdr_645 = NULL;
 | |
|     uint8_t *t_ptr;
 | |
|     uint32_t di = 0;
 | |
|     uint8_t reason = 0;
 | |
|     uint8_t ret = ERR_FAIL;
 | |
|     proto_645_07_ext_signal_resp_t *signal_attr;
 | |
|     proto_645_tailer_t *tail;
 | |
|     proto_69845_frame_head_info_t *hdr_698;
 | |
|     proto_dlms_hdlc_head_t *hdr_dlms;
 | |
|     proto_dlms_hdlc_cache_t cache_dlms;
 | |
| 
 | |
|     hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
 | |
|     if (NULL == hdr_645) {
 | |
|         hdr_698 = proto_69845_sanity_check(data, len);
 | |
|         if (NULL != hdr_698) {
 | |
|             iot_cus_printf("RECV_PLC_69845 frame, fn 0x%04x, "
 | |
|                 "data_len %lu\n", hdr_698->len, hdr_698->ctrl.fn);
 | |
|         } else {
 | |
|             hdr_dlms = proto_dlms_hdlc_parse(data, len, &cache_dlms);
 | |
|             if (hdr_dlms) {
 | |
|                 iot_cus_printf("RECV_PLC_DLMS frame, type %lu, \n",
 | |
|                     hdr_dlms->frame_format.bit.frame_type);
 | |
|             } else {
 | |
|                 iot_cus_printf("RECV_PLC_unknown frame, len %lu\n", len);
 | |
|             }
 | |
|         }
 | |
|         reason = 1;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     if (ERR_OK != proto_645_get_di_by_sub33(hdr_645->data,
 | |
|         PROTO_645_2007_DI_LEN, PROTO_645_2007_ID, &di)) {
 | |
|         iot_cus_printf("RECV_PLC_645 frame, di 0x%04x, data_len %lu\n", di,
 | |
|             hdr_645->len);
 | |
|         reason = 2;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     if (di != PROTO_645_2007_EXT_QUERY_SIGNAL_ID) {
 | |
|         reason = 3;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     iot_cus_printf("uplink snr %d, rssi %lu\n", snr, rssi);
 | |
| 
 | |
|     t_ptr = &hdr_645->data[PROTO_645_2007_DI_LEN];
 | |
|     signal_attr = (proto_645_07_ext_signal_resp_t *)t_ptr;
 | |
|     signal_attr->ul_rssi = rssi + 0x33;
 | |
|     signal_attr->ul_snr = snr + 0x33;
 | |
|     tail = (proto_645_tailer_t *)&hdr_645->data[hdr_645->len];
 | |
|     tail->cs = proto_645_calc_cs(hdr_645);
 | |
|     ret = ERR_OK;
 | |
| out:
 | |
|     if (reason != 0) {
 | |
|         iot_cus_printf("fuillfil frame failed for reason %lu\n", reason);
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /* get the address from the response message, until now, dev_test app only
 | |
|  * support DL/T 645-2007, DL/T 698.45 and dlms
 | |
|  */
 | |
| static uint8_t iot_dev_test_addr_in_data_check(uint8_t *data, uint32_t len,
 | |
|     uint16_t sn)
 | |
| {
 | |
|     uint8_t ret = ERR_FAIL;
 | |
|     uint8_t addr[IOT_MAC_ADDR_LEN] = {0};
 | |
|     proto_645_header_t *hdr_645;
 | |
|     proto_69845_frame_head_info_t *hdr_698;
 | |
|     proto_dlms_hdlc_head_t *hdr_dlms;
 | |
|     proto_dlms_hdlc_cache_t cache_dlms;
 | |
| 
 | |
|     if (!data || !len) {
 | |
|         goto out;
 | |
|     }
 | |
|     hdr_645 = proto_645_format_check_ext(data, len, PROTO_645_DIR_SLAVE);
 | |
|     if (hdr_645) {
 | |
|         iot_mac_addr_cpy(addr, hdr_645->addr);
 | |
|     } else {
 | |
|         hdr_698 = proto_69845_sanity_check_ext(data, (uint16_t)len);
 | |
|         if (hdr_698) {
 | |
|             iot_mac_addr_cpy(addr, proto_69845_get_ser_addr(hdr_698));
 | |
|         } else {
 | |
|             hdr_dlms = proto_dlms_hdlc_parse(data, len, &cache_dlms);
 | |
|             if (hdr_dlms) {
 | |
|                 if (cache_dlms.dest_addr.type != PROTO_DLMS_HDLC_ADD_TYPE_4) {
 | |
|                     goto out;
 | |
|                 }
 | |
|                 proto_dlms_hdlc_type_4_addr_to_bcd_addr(addr,
 | |
|                     &cache_dlms.dest_addr);
 | |
|             } else {
 | |
|                 goto out;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     iot_mac_addr_reverse(addr);
 | |
|     if (iot_dev_test_frame_rpt_check(addr, sn)) {
 | |
|         ret = ERR_OK;
 | |
|     }
 | |
| out:
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /* update the collector's mac */
 | |
| static void iot_dev_test_update_collector_mac(uint8_t *mac)
 | |
| {
 | |
| #if IOT_DEV_TEST_SUPPORT_CT_MR_EN
 | |
| 
 | |
|     if (!dev_test_task_data->collector_vaild) {
 | |
|         if (!iot_mac_addr_valid(mac) || iot_mac_is_bcast(mac)) {
 | |
|             return;
 | |
|         }
 | |
|         iot_mac_addr_cpy(dev_test_task_data->collector, mac);
 | |
|         dev_test_task_data->collector_vaild = 1;
 | |
|         iot_cus_printf("%s: collector mac[%02x:%02x:%02x:%02x:%02x:"
 | |
|             "%02x] updated\n", __FUNCTION__,
 | |
|              mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 | |
|     }
 | |
|     /* clear the cnt for expand the span of collector's address */
 | |
|     dev_test_task_data->collector_vaild_cnt = 0;
 | |
| 
 | |
| #else
 | |
| 
 | |
|     (void)mac;
 | |
| 
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static uint8_t iot_dev_test_handle_normal_data(iot_pkt_t *pkt)
 | |
| {
 | |
|     uint8_t consumed = 0;
 | |
|     uint8_t *ptr = NULL;
 | |
|     iot_plc_msdu_recv_t *msdu = NULL;
 | |
|     proto_conn_less_mr_t *meter;
 | |
|     uint8_t *mac;
 | |
|     uint16_t app_sn;
 | |
|     uint16_t offset_sz;
 | |
| 
 | |
|     iot_plc_msg_header_t *hdr =
 | |
|         (iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | |
|     msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
 | |
| 
 | |
|     ptr = msdu->data;
 | |
| 
 | |
|     meter = (proto_conn_less_mr_t *)(ptr + sizeof(proto_conn_less_hdr_t));
 | |
|     app_sn = meter->seq;
 | |
|     if (dev_test_task_data->m2m_sub_mode == IOT_DEV_TEST_M2M_SUBMODE_CIU
 | |
|         && meter->m2m_switch_mode == IOT_DEV_TEST_M2M_MODE_SWITCH_ENABLE
 | |
|         && dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2S) {
 | |
|         dev_test_task_data->dev_mode = IOT_DEV_TEST_APP_MODE_M2M;
 | |
|         iot_cus_printf("%s: set dev mode from M2S to M2M\n", __FUNCTION__);
 | |
|         /* If M2M CIU mode, need to query addr from CIU */
 | |
|         os_start_timer(dev_test_task_data->query_addr_tm,
 | |
|             IOT_DEV_TEST_QUERY_ADDR_TIMER_INTERVAL);
 | |
|     }
 | |
| 
 | |
|     if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2S) {
 | |
|         /* data direction must: slave->master */
 | |
|         if (meter->dir != CONN_LESS_APP_DIR_SLAVE) {
 | |
|             iot_cus_printf("%s:M2S MODE -- invalid direction\n", __FUNCTION__);
 | |
|             return consumed;
 | |
|         }
 | |
|         /* when conditions satisfied, send the response data to UART:
 | |
|          * rule 1: the msdu source address is matched with the address
 | |
|          *         stored in the frame data infor pool;
 | |
|          * rule 2: the address field of the response message is same as
 | |
|                    the address stored in the frame data infor pool.
 | |
|          * any one of the rule 1 and rule 2 is effective, together with the
 | |
|          * sequnce number matched, the reponse message should be reported.
 | |
|          */
 | |
|         mac = msdu->src;
 | |
|         if (iot_dev_test_frame_rpt_check(mac, app_sn)
 | |
|             || (iot_dev_test_addr_in_data_check(meter->data, meter->data_len,
 | |
|             app_sn) == ERR_OK)) {
 | |
|             iot_cus_printf("%s: rpt condition satisfied, sn %lu,"
 | |
|                 "mac[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__, app_sn,
 | |
|                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 | |
|             offset_sz = sizeof(*msdu) + sizeof(*hdr) + sizeof(*meter) +
 | |
|                 sizeof(proto_conn_less_hdr_t);
 | |
|             iot_pkt_pull(pkt, offset_sz);
 | |
|             /* update the collector'a address if neccessory */
 | |
|             iot_dev_test_update_collector_mac(mac);
 | |
| 
 | |
|             /* check the frame is a signal attr response command or not */
 | |
|             iot_dev_test_fullfil_rsp_snr_cmd(iot_pkt_data(pkt),
 | |
|                 iot_pkt_data_len(pkt), msdu->snr, msdu->rssi);
 | |
| 
 | |
|             iot_dev_test_data_print("m2s msdu recv", iot_pkt_data(pkt),
 | |
|                 (uint16_t)iot_pkt_data_len(pkt));
 | |
| 
 | |
|             iot_dev_test_uart_send(pkt);
 | |
|             consumed = 1;
 | |
|         } else {
 | |
|             iot_cus_printf("%s: pkt dropped for info mismatch, sn %lu, mac"
 | |
|                 "[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__, app_sn,
 | |
|                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 | |
|         }
 | |
|     } else if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2M) {
 | |
|         if (IOT_DEV_TEST_BROADCAST_MODD_CFG) {
 | |
|             if (meter->dir != CONN_LESS_APP_DIR_M2M) {
 | |
|                 iot_cus_printf("%s:M2M MODE -- invalid direction\n",
 | |
|                     __FUNCTION__);
 | |
|                 return consumed;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         mac = msdu->dst;
 | |
|         if (iot_dev_test_app_pkt_report_check(mac, app_sn))  {
 | |
|             iot_cus_printf("%s: received master -> master pkt from"
 | |
|                 "[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__,
 | |
|                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 | |
|             offset_sz = sizeof(*msdu) + sizeof(*hdr) + sizeof(*meter) +
 | |
|                 sizeof(proto_conn_less_hdr_t);
 | |
|             iot_pkt_pull(pkt, offset_sz);
 | |
|             iot_dev_test_uart_send(pkt);
 | |
|             consumed = 1;
 | |
|         } else {
 | |
|             iot_cus_printf("%s: pkt drooped for local addr is set "
 | |
|                 "and dst addr is not matched with local addr", __FUNCTION__);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return consumed;
 | |
| 
 | |
| }
 | |
| 
 | |
| static int8_t iot_dev_test_get_fix_ppm(void)
 | |
| {
 | |
|     iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
 | |
|     iot_dev_test_ppm_detec_desc_t * ppm_desc = &dev_test_task_data->ppm_desc;
 | |
|     int8_t ppm = ppm_desc->fix_ppm;
 | |
| 
 | |
|     if (pib->tool_ppm_valid) {
 | |
|         ppm = ppm_desc->fix_ppm - pib->tool_ppm;
 | |
|     }
 | |
|     return ppm;
 | |
| }
 | |
| 
 | |
| #if (IOT_DEV_TEST_HANDLE_PUSH_DATA_EN == 1) || (IOT_DEV_TEST_BROADCAST_MODD_CFG == 0)
 | |
| 
 | |
| /* ask for mac to indicate the modual is ready to handle cmd from CIU */
 | |
| static void iot_dev_test_send_bootup_indication(void)
 | |
| {
 | |
| 
 | |
|     iot_pkt_t *pkt = NULL;
 | |
|     static uint8_t boot_ind_cnt = 0;
 | |
|     static uint8_t intvl_cnt = 0;
 | |
| 
 | |
|     if (dev_test_task_data->boot_ind_en) {
 | |
|         intvl_cnt++;
 | |
|         if (intvl_cnt >= IOT_DEV_TEST_BOOT_IND_RETRY_INTV) {
 | |
|             pkt = proto_645_2007_build_ra_msg();
 | |
| 
 | |
|             if (NULL != pkt) {
 | |
|                 iot_dev_test_data_print("send bootup indicatio: ",
 | |
|                     iot_pkt_data(pkt), (uint16_t)iot_pkt_data_len(pkt));
 | |
|                 iot_dev_test_uart_send(pkt);
 | |
|                 boot_ind_cnt++;
 | |
|                 if (boot_ind_cnt > IOT_DEV_TEST_BOOT_IND_RETRY_MAX_CNT) {
 | |
|                     dev_test_task_data->boot_ind_en = 0;
 | |
|                 }
 | |
|                 intvl_cnt = 0;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /* stop sending indication after received the response from CIU */
 | |
| static void iot_dev_test_stop_send_bootup_ind(void)
 | |
| {
 | |
|     if (dev_test_task_data->boot_ind_en == 1) {
 | |
|         dev_test_task_data->boot_ind_en = 0;
 | |
|         iot_cus_printf("stop sending the ind\n", __FUNCTION__);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static uint8_t iot_dev_test_pushed_data_rpt_check(uint8_t *mac, uint16_t seq)
 | |
| {
 | |
|     uint8_t ret = 0;
 | |
|     uint8_t *match_mac = dev_test_task_data->flashinfo.match_mac;
 | |
|     if (iot_mac_addr_cmp(mac, match_mac)
 | |
|         && (seq != dev_test_task_data->pushed_seq) && (seq != 0)) {
 | |
|         /* update pushed-data's seq */
 | |
|         dev_test_task_data->pushed_seq = seq;
 | |
|         ret = 1;
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /* handle pushed-data from PLC */
 | |
| static uint8_t iot_dev_test_handle_pushed_data(iot_pkt_t *pkt)
 | |
| {
 | |
|     uint8_t consumed = 0;
 | |
|     uint8_t *ptr = NULL;
 | |
|     iot_plc_msdu_recv_t *msdu = NULL;
 | |
|     proto_conn_less_push_data_t *p_data;
 | |
|     uint8_t *mac;
 | |
|     uint16_t seq;
 | |
|     uint16_t offset_sz;
 | |
| 
 | |
|     iot_plc_msg_header_t *hdr =
 | |
|         (iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | |
|     msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
 | |
| 
 | |
|     ptr = msdu->data;
 | |
| 
 | |
|     p_data =
 | |
|         (proto_conn_less_push_data_t *)(ptr + sizeof(proto_conn_less_hdr_t));
 | |
|     seq = p_data->seq;
 | |
| 
 | |
|     iot_dev_test_data_print("pushed msdu recv all", iot_pkt_data(pkt),
 | |
|         (uint16_t)iot_pkt_data_len(pkt));
 | |
| 
 | |
|     if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2S) {
 | |
|         /* data direction must: master->slave */
 | |
|         if (p_data->dir != CONN_LESS_APP_DIR_SLAVE) {
 | |
|             iot_cus_printf("%s:invalid direction\n", __FUNCTION__);
 | |
|             return consumed;
 | |
|         }
 | |
| 
 | |
|         mac = p_data->addr;
 | |
|         iot_mac_addr_reverse(mac);
 | |
|         if (iot_dev_test_pushed_data_rpt_check(mac, seq)) {
 | |
|             iot_cus_printf("%s: pushed data rpt condition satisfied, seq %lu,"
 | |
|                 "mac[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__, seq,
 | |
|                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 | |
|             offset_sz = sizeof(*msdu) + sizeof(*hdr) + sizeof(*p_data) +
 | |
|                 sizeof(proto_conn_less_hdr_t);
 | |
|             iot_pkt_pull(pkt, offset_sz);
 | |
| 
 | |
|             iot_dev_test_data_print("pushed msdu recv", iot_pkt_data(pkt),
 | |
|                 (uint16_t)iot_pkt_data_len(pkt));
 | |
| 
 | |
|             iot_dev_test_uart_send(pkt);
 | |
|             consumed = 1;
 | |
|         } else {
 | |
|             iot_cus_printf("%s: pkt dropped for info mismatch: seq[%lu], from"
 | |
|                 "[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__, seq,
 | |
|                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return consumed;
 | |
| 
 | |
| }
 | |
| 
 | |
| /* handle pushed-data's ack from CIU */
 | |
| static uint8_t iot_dev_test_handle_ack_data_from_host(
 | |
|     proto_645_header_t *hdr_645)
 | |
| {
 | |
|     uint16_t total_sz, payload_sz;
 | |
|     proto_conn_less_hdr_t *hdr;
 | |
|     proto_conn_less_push_data_t *p_data;
 | |
|     iot_pkt_t *msdu_pkt;
 | |
|     uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 };
 | |
|     uint8_t *ptr = NULL;
 | |
|     uint8_t ret = ERR_FAIL;
 | |
|     uint8_t reason = 0;
 | |
| 
 | |
|     if (0 == dev_test_task_data->collector_vaild) {
 | |
|         iot_mac_addr_cpy(dst_mac,(uint8_t *)bcast_mac);
 | |
|     } else {
 | |
|         iot_mac_addr_cpy(dst_mac, dev_test_task_data->collector);
 | |
|     }
 | |
| 
 | |
|     if (!iot_mac_addr_valid(dst_mac)) {
 | |
|         reason = 1;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     payload_sz = sizeof(*hdr_645) + hdr_645->len + sizeof(proto_645_tailer_t);
 | |
|     total_sz = sizeof(*hdr) + sizeof(*p_data) + payload_sz;
 | |
| 
 | |
|     msdu_pkt = iot_plc_alloc_conn_less_msdu(dev_test_task_data->app_handle,
 | |
|         IOT_PLC_MSG_TYPE_CONN_LESS_DATA, dst_mac, dev_test_task_data->mac_addr,
 | |
|         CONN_LESS_APP_PRIO_METER_READ, total_sz, IOT_PLC_MAX_RETRY_CNT);
 | |
|     if (msdu_pkt) {
 | |
|         ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | |
|         /* fill in header */
 | |
|         hdr = (proto_conn_less_hdr_t *)ptr;
 | |
|         hdr->id = CONN_LESS_APP_ID_DATA_PUSH;
 | |
|         hdr->port = CONN_LESS_APP_PORT;
 | |
| 
 | |
|         p_data = (proto_conn_less_push_data_t *)(hdr + 1);
 | |
|         p_data->seq = iot_dev_test_app_get_sn();
 | |
|         p_data->data_len = payload_sz;
 | |
|         p_data->dir = CONN_LESS_APP_DIR_MASTER;
 | |
|         /* fill in payload */
 | |
|         os_mem_cpy(p_data->data, hdr_645, payload_sz);
 | |
|         iot_pkt_put(msdu_pkt, total_sz);
 | |
|         iot_plc_send_msdu(dev_test_task_data->app_handle, msdu_pkt);
 | |
|         ret = ERR_OK;
 | |
|     } else {
 | |
|         reason = 2;
 | |
|     }
 | |
| 
 | |
| out:
 | |
|     iot_cus_printf("%s result %lu, reason %lu\n", __FUNCTION__, ret, reason);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /* set module address once the meter address changed */
 | |
| static void iot_dev_test_config_mac(uint8_t *mac)
 | |
| {
 | |
|     iot_plc_cfg_set_req_t cfg = {0};
 | |
|     iot_plc_app_h app_hdl = dev_test_task_data->app_handle;
 | |
| 
 | |
|     if (!iot_mac_addr_valid(mac) || iot_mac_is_bcast(mac)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     iot_mac_addr_cpy(cfg.addr, mac);
 | |
|     cfg.addr_valid = 1;
 | |
|     cfg.reset = 1;
 | |
|     cfg.dev_type_valid = 1;
 | |
|     cfg.dev_type = IOT_PLC_DEV_TYPE_METER_CONTROLLER;
 | |
|     iot_plc_set_cfg(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
 | |
|     iot_cus_printf("%s: config local mac[%02x:%02x:%02x:%02x:%02x:%02x] "
 | |
|         "successfully\n", __FUNCTION__, cfg.addr[0], cfg.addr[1],
 | |
|         cfg.addr[2], cfg.addr[3], cfg.addr[4], cfg.addr[5]);
 | |
|     os_delay (500);
 | |
| 
 | |
|     /* here, update the local MAC in advance to avoid dropping the
 | |
|      * first packet.
 | |
|      */
 | |
|     iot_mac_addr_cpy(dev_test_task_data->mac_addr, mac);
 | |
| 
 | |
|         /* set default frequnce band */
 | |
| #if (IOT_DEV_TEST_SUPPORT_MUTIBAND == 1)
 | |
|     iot_plc_set_freq_band(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
 | |
|         PLC_LIB_FREQ_BAND_MULTI_1_2);
 | |
| #else
 | |
|     iot_plc_set_freq_band(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
 | |
|         dev_test_task_data->band_id);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /* update the matching mac when a new cmd received */
 | |
| static void iot_dev_test_update_match_mac(uint8_t *mac)
 | |
| {
 | |
|     uint8_t reason = 0;
 | |
|     iot_dev_test_pib_t *p_info = &dev_test_task_data->flashinfo;
 | |
| 
 | |
|     if (!iot_mac_addr_valid(mac) || iot_mac_is_bcast(mac)) {
 | |
|         reason = 1;
 | |
|         goto out;
 | |
|     }
 | |
|     if (iot_mac_addr_cmp(mac, p_info->match_mac)) {
 | |
|         reason = 2;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     iot_mac_addr_cpy(p_info->match_mac, mac);
 | |
|     iot_dev_test_flash_save(p_info);
 | |
|     iot_dev_test_config_mac(mac);
 | |
|     dev_test_task_data->collector_vaild = 0;
 | |
| 
 | |
|     iot_cus_printf("%s: matching mac[%02x:%02x:%02x:%02x:%02x:%02x] "
 | |
|         "successfully, collector address vaild: %d\n", __FUNCTION__, mac[0],
 | |
|         mac[1], mac[2],mac[3], mac[4], mac[5],
 | |
|         dev_test_task_data->collector_vaild);
 | |
| out:
 | |
|     iot_cus_printf("%s reason %lu\n", __FUNCTION__, reason);
 | |
| }
 | |
| 
 | |
| #else /* IOT_DEV_TEST_HANDLE_PUSH_DATA_EN == 1 */
 | |
| 
 | |
| static void iot_dev_test_send_bootup_indication(void)
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_stop_send_bootup_ind(void)
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static uint8_t iot_dev_test_handle_pushed_data(iot_pkt_t *pkt)
 | |
| {
 | |
|     (void)pkt;
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| static uint8_t iot_dev_test_handle_ack_data_from_host(
 | |
|     proto_645_header_t *hdr_645)
 | |
| {
 | |
|     (void)hdr_645;
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_update_match_mac(uint8_t *mac)
 | |
| {
 | |
|     (void)mac;
 | |
| }
 | |
| 
 | |
| #endif /* IOT_DEV_TEST_HANDLE_PUSH_DATA_EN == 0 */
 | |
| 
 | |
| static uint8_t iot_dev_test_config_data_hdl_check(uint8_t *mac, uint16_t seq)
 | |
| {
 | |
|     uint8_t ret = 0;
 | |
|     uint8_t *local_mac = dev_test_task_data->mac_addr;
 | |
| 
 | |
|     if (!mac || !seq) {
 | |
|         goto out;
 | |
|     }
 | |
|     if (seq == dev_test_task_data->config_seq) {
 | |
|         goto out;
 | |
|     }
 | |
|     if (iot_mac_addr_cmp(mac, local_mac)) {
 | |
|         dev_test_task_data->config_seq = seq;
 | |
|         ret = 1;
 | |
|     }
 | |
| out:
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static uint8_t iot_dev_test_config_pack_plc_rsp_data(uint8_t *dst, uint16_t sn,
 | |
|     uint8_t *data, uint16_t len)
 | |
| {
 | |
|     uint32_t buflen = 0;
 | |
|     uint8_t *ptr = NULL;
 | |
|     iot_pkt_t *msdu_pkt;
 | |
|     proto_conn_less_hdr_t  *proto_hdr;
 | |
|     proto_conn_less_mr_t *meter;
 | |
|     iot_dev_test_task_data_t *dev_glb = dev_test_task_data;
 | |
|     int8_t fix_ppm;
 | |
| 
 | |
|     if(!dst || !data || !len) {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     fix_ppm = iot_dev_test_get_fix_ppm();
 | |
|     buflen = sizeof(proto_conn_less_hdr_t) + sizeof(proto_conn_less_mr_t) + len;
 | |
|     msdu_pkt = iot_plc_alloc_conn_less_msdu_ext(dev_glb->app_handle,
 | |
|         IOT_PLC_MSG_TYPE_CONN_LESS_DATA, dst, dev_glb->mac_addr,
 | |
|         dev_glb->link_id, (uint16_t)buflen, IOT_PLC_MAX_RETRY_CNT,
 | |
|         fix_ppm, 0, dev_glb->tx_link_type);
 | |
| 
 | |
|     if (msdu_pkt == NULL) {
 | |
|         iot_cus_printf("allocate msdu fail\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | |
|     iot_pkt_put(msdu_pkt, buflen);
 | |
|     proto_hdr = (proto_conn_less_hdr_t *)ptr;
 | |
|     proto_hdr->id = CONN_LESS_APP_ID_CONFIG;
 | |
|     proto_hdr->port = CONN_LESS_APP_PORT;
 | |
| 
 | |
|     ptr += sizeof(proto_conn_less_hdr_t);
 | |
|     meter = (proto_conn_less_mr_t *)ptr;
 | |
|     meter->data_len = len;
 | |
|     meter->mr_timeout = IOT_DEV_TEST_CFG_MR_TIMEOUT;
 | |
| 
 | |
|     meter->seq = sn;
 | |
|     meter->dir = CONN_LESS_APP_DIR_SLAVE;
 | |
|     meter->option.dl_ppm_desc.value = 0;
 | |
|     meter->data_type = GW_APP_DATA_TYPE_645_2007;
 | |
|     meter->retry_cnt = 0;
 | |
|     os_mem_cpy(meter->data, data, len);
 | |
| 
 | |
|     iot_cus_printf("app conn_less send to[%02x:%02x:%02x:%02x:%02x:%02x]"
 | |
|         ", sn %lu, len %lu, fix ppm %d\n", dst[0], dst[1],
 | |
|         dst[2], dst[3], dst[4], dst[5], sn, buflen, fix_ppm);
 | |
|     iot_plc_send_msdu(dev_test_task_data->app_handle, msdu_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: creat a rsponse frame based on 645 protocal.
 | |
|  * @param  rsp_fn:  response Fn code
 | |
|  * @param  data:    pointer to data that fullfiled into the frame's data field
 | |
|  * @param  len:     data lenth that fullfiled into the frame's data field
 | |
|  * @retval: 0      --   success
 | |
|  * @retval: others --   failed
 | |
|  */
 | |
| static uint8_t iot_dev_test_form_rsp_data_frame(uint8_t rsp_fn, uint8_t *data,
 | |
|     uint8_t len)
 | |
| {
 | |
|     iot_pkt_t *pkt = NULL;
 | |
|     proto_645_header_t *hdr_645;
 | |
|     proto_645_tailer_t *tail_645;
 | |
|     uint8_t pkt_len;
 | |
|     uint8_t *ptr = NULL;
 | |
|     uint8_t ret = ERR_OK;
 | |
| 
 | |
|     pkt_len = IOT_DEV_TEST_RSP_FRAME_LEN_MIN + len;
 | |
|     pkt = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
 | |
|     if (pkt != NULL) {
 | |
|         ptr = iot_pkt_data(pkt);
 | |
|         hdr_645 = (proto_645_header_t *)ptr;
 | |
| 
 | |
|         hdr_645->start_char_1 = PROTO_645_START_CHAR;
 | |
|         iot_mac_addr_cpy(hdr_645->addr, spec_mac);
 | |
|         iot_mac_addr_reverse(hdr_645->addr);
 | |
|         hdr_645->len = len;
 | |
|         hdr_645->control.fn  = rsp_fn;
 | |
|         hdr_645->control.dir = PROTO_645_DIR_SLAVE;
 | |
|         hdr_645->control.ack = PROTO_645_ACK_NORMAL;
 | |
|         hdr_645->control.follow = PROTO_645_FOLLOW_INVALID;
 | |
|         hdr_645->start_char_2 = PROTO_645_START_CHAR;
 | |
|         os_mem_cpy(hdr_645->data, data, len);
 | |
|         proto_645_add33_handle(hdr_645->data, len);
 | |
|         ptr += sizeof(proto_645_header_t) + len;
 | |
|         tail_645 = (proto_645_tailer_t *)ptr;
 | |
|         tail_645->cs = proto_645_calc_cs(hdr_645);
 | |
|         tail_645->end_char = PROTO_645_END_CHAR;
 | |
|         iot_pkt_put (pkt, (sizeof(*hdr_645) + len + sizeof(*tail_645)));
 | |
|         iot_dev_test_uart_send(pkt);
 | |
|     } else {
 | |
|         iot_cus_printf("%s: alloc pkt failed!\n", __FUNCTION__);
 | |
|         ret = ERR_FAIL;
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: creat a confirm frame based on 645 protocal.
 | |
|  * @param  result:  0-no error, 1-error
 | |
|  * @param  reason:  error reason
 | |
|  * @param  len:     data lenth that fullfiled into the frame's data field
 | |
|  * @retval: 0   --   success
 | |
|  * @retval: others  --   failed
 | |
|  */
 | |
| static uint8_t iot_dev_test_form_rsp_cfm_frame(uint8_t fn, uint8_t result,
 | |
|     uint8_t reason)
 | |
| {
 | |
|     iot_pkt_t *pkt = NULL;
 | |
|     proto_645_header_t *hdr_645;
 | |
|     proto_645_tailer_t *tail_645;
 | |
|     uint8_t pkt_len;
 | |
|     uint8_t *ptr = NULL;
 | |
|     uint8_t ret = ERR_OK;
 | |
| 
 | |
|     if (result != 0) {
 | |
|         pkt_len = IOT_DEV_TEST_RSP_FRAME_LEN_MIN + 1;
 | |
|     } else {
 | |
|         pkt_len = IOT_DEV_TEST_RSP_FRAME_LEN_MIN;
 | |
|     }
 | |
| 
 | |
|     pkt = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
 | |
|     if (pkt != NULL) {
 | |
|         ptr = iot_pkt_data(pkt);
 | |
|         hdr_645 = (proto_645_header_t *)ptr;
 | |
|         hdr_645->control.fn  = fn;
 | |
|         hdr_645->start_char_1 = PROTO_645_START_CHAR;
 | |
|         iot_mac_addr_cpy(hdr_645->addr, spec_mac);
 | |
|         iot_mac_addr_reverse(hdr_645->addr);
 | |
|         hdr_645->control.dir = PROTO_645_DIR_SLAVE;
 | |
|         hdr_645->control.follow = PROTO_645_FOLLOW_INVALID;
 | |
|         hdr_645->start_char_2 = PROTO_645_START_CHAR;
 | |
| 
 | |
|         if (result == 0) {
 | |
|             /* ack normal */
 | |
|             hdr_645->len = 0;
 | |
|             hdr_645->control.ack = PROTO_645_ACK_NORMAL;
 | |
|         } else {
 | |
|             hdr_645->len = 1;
 | |
|             hdr_645->control.ack = PROTO_645_ACK_ABNORMAL;
 | |
|             hdr_645->data[0] = reason + 0x33;
 | |
|         }
 | |
| 
 | |
|         ptr += sizeof(proto_645_header_t) + hdr_645->len;
 | |
|         tail_645 = (proto_645_tailer_t *)ptr;
 | |
|         tail_645->cs = proto_645_calc_cs(hdr_645);
 | |
|         tail_645->end_char = PROTO_645_END_CHAR;
 | |
|         iot_pkt_put (pkt, (sizeof(*hdr_645) + hdr_645->len +
 | |
|             sizeof(*tail_645)));
 | |
|         iot_dev_test_data_print("SEND_UART frame:", iot_pkt_data(pkt),
 | |
|             (uint16_t)iot_pkt_data_len(pkt));
 | |
| 
 | |
|         iot_cus_printf("SEND_UART_CMD_RSP frame: fn 0x%02x, result 0x%02x\n",
 | |
|             fn, result);
 | |
| 
 | |
|         iot_dev_test_uart_send(pkt);
 | |
|     } else {
 | |
|         iot_cus_printf("%s: alloc pkt failed!\n", __FUNCTION__);
 | |
|         ret = ERR_FAIL;
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: set frequnce band
 | |
|  * @param  bandid:  band index
 | |
|  */
 | |
| static void iot_dev_test_set_band(uint8_t bandid)
 | |
| {
 | |
|     if (bandid > IOT_DEV_TEST_MAX_BAND) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_BAND,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
 | |
|         iot_cus_printf("%s [err]band setting out of range\n", __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (dev_test_task_data->band_id == bandid) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_BAND,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_DUP_SET);
 | |
|         iot_cus_printf("%s [err]Already in band-%lu\n", __FUNCTION__, bandid);
 | |
|         return;
 | |
|     }
 | |
|     dev_test_task_data->band_id = bandid;
 | |
|     iot_plc_set_freq_band(dev_test_task_data->app_handle,
 | |
|         IOT_PLC_API_REQ_ID_DEFAULT, bandid);
 | |
|     iot_printf("%s set freq-band to band-%lu ok\n",__FUNCTION__, bandid);
 | |
|     iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_BAND,
 | |
|         IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
 | |
| }
 | |
| 
 | |
| /* get the band's ID and creat a respons frame then send to mointor */
 | |
| static void iot_dev_test_querry_band_handle(void)
 | |
| {
 | |
|     uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN] = { 0 };
 | |
|     rsp_data[0] = dev_test_task_data->band_id;
 | |
|     iot_cus_printf("%s rsponse band id: %lu\n", __FUNCTION__, rsp_data[0]);
 | |
|     iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERRY_BAND_RSP,
 | |
|         rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN);
 | |
| }
 | |
| 
 | |
| /* get the software version and creat a respons frame then send  to mointor */
 | |
| static void iot_dev_test_querry_ver_handle(void)
 | |
| {
 | |
|     uint32_t ver = 0;
 | |
|     uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN] = { 0 };
 | |
|     ver = iot_version_hex();
 | |
|     rsp_data[0] = ver & 0xFF;
 | |
|     rsp_data[1] = (ver >> 8) & 0xFF;
 | |
|     rsp_data[2] = (ver >> 16) & 0xFF;
 | |
|     rsp_data[3] = (ver >> 24) & 0xFF;
 | |
|     iot_cus_printf("%s software verison: 0x%x\n", __FUNCTION__, ver);
 | |
|     iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERRY_VER_RSP,
 | |
|         rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: set mac address
 | |
|  * @param  mac:  pointer to mac address which will be set
 | |
|  */
 | |
| static void iot_dev_test_set_mac(uint8_t *mac)
 | |
| {
 | |
|     iot_plc_cfg_set_req_t cfg;
 | |
|     iot_plc_app_h app_hdl = dev_test_task_data->app_handle;
 | |
| 
 | |
|     if (!iot_mac_addr_valid(mac) || iot_mac_is_bcast(mac)) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_MAC,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_MAC_INVALID);
 | |
|         iot_cus_printf("%s [err]mac invalid, all zero or boardcast mac will "
 | |
|             "not be set!\n", __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (iot_mac_addr_cmp(dev_test_task_data->mac_addr, mac))
 | |
|     {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_MAC,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_DUP_SET);
 | |
|         iot_cus_printf("%s [err]new mac is same as the using one\n",
 | |
|             __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     os_mem_set(&cfg, 0, sizeof(cfg));
 | |
|     cfg.addr_valid = 1;
 | |
|     cfg.addr_type = IOT_PLC_MAC_ADDR_TYPE_METER;
 | |
|     iot_mac_addr_cpy(cfg.addr, mac);
 | |
|     cfg.reset = 1;
 | |
|     cfg.dev_type_valid = 1;
 | |
|     cfg.dev_type = IOT_PLC_DEV_TYPE_METER_CONTROLLER;
 | |
|     iot_plc_set_cfg(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
 | |
| 
 | |
|     iot_printf("%s set mac to [%02x:%02x:%02x:%02x:%02x:%02x] successfully\n",
 | |
|         __FUNCTION__, mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
 | |
|     dev_test_task_data->m2m_check_addr = IOT_DEV_TEST_ADDR_SET;
 | |
|     iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_MAC,
 | |
|         IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
 | |
| }
 | |
| 
 | |
| /* get the local mac address and creat a respons frame then send to mointor */
 | |
| static void iot_dev_test_querry_mac_handle(void)
 | |
| {
 | |
|     uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN + 2] = { 0 };
 | |
|     iot_mac_addr_cpy(rsp_data, dev_test_task_data->mac_addr);
 | |
|     iot_cus_printf("%s rsponse local mac:[%02x:%02x:%02x:%02x:%02x:%02x]\n",
 | |
|         __FUNCTION__, rsp_data[0], rsp_data[1], rsp_data[2], rsp_data[3],
 | |
|         rsp_data[4], rsp_data[5]);
 | |
|     iot_mac_addr_reverse (rsp_data);
 | |
|     iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERRY_MAC_RSP,
 | |
|         rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN + 2);
 | |
| }
 | |
| 
 | |
| /* set dev test op mode and creat a respons frame then send to mointor */
 | |
| static void iot_dev_test_set_op_mode(uint8_t op_mode)
 | |
| {
 | |
|     if (op_mode >= IOT_DEV_TEST_APP_MODE_MAX) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_OP_MODE,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
 | |
|         iot_cus_printf("%s [err]invalid op mode\n", __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (dev_test_task_data->dev_mode == op_mode) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_OP_MODE,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_DUP_SET);
 | |
|         iot_cus_printf("%s [err]new op mode is same as the using one\n",
 | |
|             __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->dev_mode = op_mode;
 | |
|     iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_OP_MODE,
 | |
|         IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
 | |
| }
 | |
| 
 | |
| /* query CKQ current operation mode */
 | |
| static void iot_dev_test_query_op_mode()
 | |
| {
 | |
|     uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN] = { 0 };
 | |
|     /* rsp_data is a 4-byte array, refer to 645 frame format */
 | |
|     rsp_data[0] = dev_test_task_data->dev_mode;
 | |
|     iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERY_OP_MODE_RSP,
 | |
|         rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN);
 | |
| }
 | |
| 
 | |
| /* set the compensation ppm value, */
 | |
| static uint32_t proto_handle_645_set_tool_ppm(uint8_t *in_data,
 | |
|     uint8_t in_len, uint8_t* out_buf, uint8_t *out_len)
 | |
| {
 | |
|     iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
 | |
|     int8_t tool_ppm;
 | |
|     uint8_t *ptr = NULL;
 | |
|     uint32_t di = PROTO_645_2007_EXT_WRITE_TOOL_PPM;
 | |
| 
 | |
|     ptr =  in_data + PROTO_645_2007_DI_LEN;
 | |
|     tool_ppm = (int8_t)*ptr;
 | |
|     if (IOT_ABS(tool_ppm) > IOT_DEV_TEST_MAX_TOOL_PPM) {
 | |
|         iot_cus_printf("%s invalid tool_ppm %d\n", __FUNCTION__, tool_ppm);
 | |
|         return PROTO_645_2007_ERR_OTHER;
 | |
|     }
 | |
| 
 | |
|     if ((tool_ppm != pib->tool_ppm) || !pib->tool_ppm_valid) {
 | |
|         pib->tool_ppm = tool_ppm;
 | |
|         pib->tool_ppm_valid = 1;
 | |
|         iot_dev_test_flash_save(pib);
 | |
|         iot_cus_printf("tool ppm %d saved into PIB\n", tool_ppm);
 | |
|     } else {
 | |
|         iot_cus_printf("Duplicated ppm %d setting, skip saving\n", tool_ppm);
 | |
| 
 | |
|     }
 | |
| 
 | |
|     proto_645_2007_di_to_byte(di, out_buf);
 | |
|     *out_len = PROTO_645_2007_DI_LEN;
 | |
| 
 | |
|     return PROTO_645_2007_ERR_OK;
 | |
| }
 | |
| 
 | |
| static uint32_t proto_handle_645_read_pt_info(uint8_t *in_data,
 | |
|     uint8_t in_len, uint8_t* out_buf, uint8_t *out_len)
 | |
| {
 | |
|     proto_645_ext_read_pt_info_rsp_t *rsp_info = NULL;
 | |
|     iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
 | |
|     iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
 | |
|     iot_board_pt_info_t pt_info = {0};
 | |
| 
 | |
|     iot_board_get_pt_info(&pt_info);
 | |
| 
 | |
|     rsp_info = (proto_645_ext_read_pt_info_rsp_t *)(out_buf);
 | |
|     os_mem_set(rsp_info, 0, sizeof(*rsp_info));
 | |
| 
 | |
|     /* production test ppm */
 | |
|     if (pt_info.ppm_valid) {
 | |
|         rsp_info->local_pt_ppm_valid = 1;
 | |
|         rsp_info->local_pt_ppm = pt_info.ppm;
 | |
|     }
 | |
|     /* compensation ppm, configured by the tool */
 | |
|     if (pib->tool_ppm_valid) {
 | |
|         rsp_info->local_tool_ppm_valid = 1;
 | |
|         rsp_info->local_tool_ppm = pib->tool_ppm;
 | |
|     }
 | |
|     /* basic production test info */
 | |
|     if (pt_info.basic_info_valid) {
 | |
|         rsp_info->basic_data_valid = 1;
 | |
|         iot_mac_addr_cpy(rsp_info->basic_data.golden_mac,
 | |
|             pt_info.basic_info.golden_mac);
 | |
|         rsp_info->basic_data.year = pt_info.basic_info.year;
 | |
|         rsp_info->basic_data.month = pt_info.basic_info.month;
 | |
|         rsp_info->basic_data.day = pt_info.basic_info.day;
 | |
|         rsp_info->basic_data.hour = pt_info.basic_info.hour;
 | |
|         rsp_info->basic_data.min = pt_info.basic_info.min;
 | |
|         rsp_info->basic_data.golden_fw_ver = pt_info.basic_info.golden_fw_ver;
 | |
|         rsp_info->basic_data.pt_tool_ver = pt_info.basic_info.pt_tool_ver;
 | |
|         rsp_info->basic_data.pt_board_ver = pt_info.basic_info.pt_board_ver;
 | |
|     }
 | |
|     /* the dut firmware version, which supported the production test */
 | |
|     if (pt_info.pt_dut_ver_valid) {
 | |
|         rsp_info->pt_dut_fw_valid = 1;
 | |
|         rsp_info->pt_dut_fw_ver = pt_info.pt_dut_ver;
 | |
|     }
 | |
|     /* fix ppm */
 | |
|     rsp_info->local_fix_ppm = ppm_desc->fix_ppm;
 | |
|     rsp_info->local_fix_ppm_valid = 1;
 | |
| 
 | |
|     *out_len = sizeof(*rsp_info);
 | |
| 
 | |
|     return PROTO_645_2007_ERR_OK;
 | |
| }
 | |
| 
 | |
|  static iot_pkt_t *iot_dev_test_config_cmd_handle(proto_645_header_t *hdr)
 | |
| {
 | |
|     uint8_t fn, err_code = 0;
 | |
|     uint32_t len;
 | |
|     uint8_t out_len;
 | |
|     iot_pkt_t *pkt_645 = NULL;
 | |
|     uint32_t pkt_len, di;
 | |
|     uint8_t *out_ds, *out_buf;
 | |
|     uint8_t follow = PROTO_645_FOLLOW_INVALID;
 | |
|     uint8_t addr[IOT_MAC_ADDR_LEN] = {0};
 | |
| 
 | |
|     if (!hdr ) {
 | |
|         goto out;
 | |
|     }
 | |
|     proto_645_get_di_by_sub33(hdr->data, PROTO_645_2007_DI_LEN,
 | |
|         PROTO_645_2007_ID, &di);
 | |
|     proto_645_sub33_handle(hdr->data, hdr->len);
 | |
|     pkt_len = PROTO_645_READ_DATA_MAX_LEN + sizeof(hdr)
 | |
|         + sizeof(proto_645_tailer_t);
 | |
|     pkt_645 = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
 | |
|     out_ds = iot_pkt_data(pkt_645);
 | |
|     os_mem_set(dev_test_task_data->data_buf, 0, IOT_DEV_TEST_DATA_BUFF_LEN);
 | |
|     out_buf = dev_test_task_data->data_buf;
 | |
|     out_len = IOT_DEV_TEST_DATA_BUFF_LEN;
 | |
|     fn = hdr->control.fn;
 | |
|     iot_mac_addr_cpy(addr, hdr->addr);
 | |
| 
 | |
|     switch (fn) {
 | |
|     case PROTO_645_2007_FN_READ_DATA:
 | |
|     {
 | |
|         switch (di) {
 | |
|         case PROTO_645_2007_EXT_QUERY_PT_INFO:
 | |
|         {
 | |
|             err_code = proto_handle_645_read_pt_info(hdr->data,
 | |
|                 hdr->len, out_buf, &out_len);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|             err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
 | |
|             break;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case PROTO_645_2007_FN_WRITE_DATA:
 | |
|     {
 | |
|         switch (di) {
 | |
|         case PROTO_645_2007_EXT_WRITE_TOOL_PPM:
 | |
|         {
 | |
|             err_code = proto_handle_645_set_tool_ppm(hdr->data,
 | |
|                 hdr->len, out_buf, &out_len);
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|             err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
 | |
|             break;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     if (err_code) {
 | |
|         len = proto_645_fill_frame(out_ds, PROTO_645_2007_ID,
 | |
|             addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_ABNORMAL,
 | |
|             follow, fn, PROTO_645_INVALID_DI, 1, &err_code);
 | |
|     } else {
 | |
|         iot_cus_printf("di 0x%04x, out len %d\n", di, out_len);
 | |
|         len = proto_645_fill_frame(out_ds, PROTO_645_2007_ID,
 | |
|             addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
 | |
|             follow, fn, di, out_len, out_buf);
 | |
|     }
 | |
|     iot_pkt_put(pkt_645, len);
 | |
| 
 | |
|     iot_dev_test_data_print("uplink 645: ", iot_pkt_data(pkt_645),
 | |
|         iot_pkt_data_len(pkt_645));
 | |
| out:
 | |
|     return pkt_645;
 | |
| }
 | |
| 
 | |
| /* set UART baudrate */
 | |
| static void iot_dev_test_set_baudrate(uint8_t baud_index)
 | |
| {
 | |
|     iot_dev_test_pib_t *p_info = &dev_test_task_data->flashinfo;
 | |
|     iot_uart_h uart_hdl = NULL;
 | |
| 
 | |
|     if (baud_index >= SUPPORTED_BAUD_CNT) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_UART_BAUDRATE,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
 | |
|         iot_cus_printf("%s [err]invalid input val\n", __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (p_info->baud_index == baud_index) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_UART_BAUDRATE,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_DUP_SET);
 | |
|         iot_cus_printf("%s [err]new baudrate is same as the using one\n",
 | |
|             __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_info->baud_index = baud_index;
 | |
|     if (iot_dev_test_flash_save(p_info)) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_UART_BAUDRATE,
 | |
|             IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
 | |
|     } else {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_UART_BAUDRATE,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_SAVE_ERR);
 | |
|     }
 | |
| 
 | |
|     os_delay (2000);
 | |
| 
 | |
|     iot_dev_test_close_uart(dev_test_task_data->host_com);
 | |
| 
 | |
|     os_delay (1000);
 | |
|     uart_hdl = iot_dev_test_open_uart(iot_board_get_uart(UART_METER_PORT));
 | |
|     if (uart_hdl == NULL) {
 | |
|         iot_cus_printf("open uart meter port failed!\n");
 | |
|     } else {
 | |
|         if (iot_dev_test_set_uart_config(uart_hdl)) {
 | |
|             iot_cus_printf("open uart meter port successfully!\n");
 | |
|         }
 | |
|     }
 | |
|     dev_test_task_data->host_com = uart_hdl;
 | |
| 
 | |
| }
 | |
| 
 | |
| /* query UART baudrate */
 | |
| static void iot_dev_test_query_baudrate()
 | |
| {
 | |
|     uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN] = { 0 };
 | |
|     /* rsp_data is a 4-byte array, refer to 645 frame format */
 | |
|     rsp_data[0] = dev_test_task_data->flashinfo.baud_index;
 | |
|     iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERY_BAUD_RSP,
 | |
|         rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: set rf
 | |
|  * @param rf_option:  rf option
 | |
|  * @param rf_channel:  rf channel
 | |
|  * @param need_rsp:  if need to response
 | |
|  */
 | |
| static void iot_dev_test_set_rf(uint8_t rf_option, uint8_t rf_channel,
 | |
|     uint8_t need_rsp)
 | |
| {
 | |
|     uint8_t rf_valid = 0;
 | |
| 
 | |
|     if (rf_option == IOT_PLC_RF_OPTION_1) {
 | |
|         rf_valid = (rf_channel < IOT_PLC_OPTION1_CHANNEL_ID_MAX);
 | |
|     } else if (rf_option == IOT_PLC_RF_OPTION_2) {
 | |
|         rf_valid = (rf_channel < IOT_PLC_OPTION2_CHANNEL_ID_MAX);
 | |
|     } else if (rf_option == IOT_PLC_RF_OPTION_3) {
 | |
|         rf_valid = (rf_channel < IOT_PLC_OPTION3_CHANNEL_ID_MAX);
 | |
|     }
 | |
| 
 | |
|     if (!rf_valid) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
 | |
|         iot_cus_printf("%s [err]rf setting out of range\n", __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (dev_test_task_data->ext_cfg.rf_valid &&
 | |
|         dev_test_task_data->ext_cfg.rf_option == rf_option &&
 | |
|         dev_test_task_data->ext_cfg.rf_channel == rf_channel) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF,
 | |
|             IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_DUP_SET);
 | |
|         iot_cus_printf("%s already in option-%lu channel-%lu\n",
 | |
|             __FUNCTION__, rf_option, rf_channel);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->ext_cfg.rf_valid = 1;
 | |
|     dev_test_task_data->ext_cfg.rf_option = rf_option;
 | |
|     dev_test_task_data->ext_cfg.rf_channel = rf_channel;
 | |
|     iot_plc_set_rf_channel(dev_test_task_data->app_handle,
 | |
|         IOT_PLC_API_REQ_ID_DEFAULT, rf_option, rf_channel, 0);
 | |
|     iot_printf("%s set option to %lu channel to %lu ok\n", __FUNCTION__,
 | |
|         rf_option, rf_channel);
 | |
|     if (need_rsp) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF,
 | |
|             IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: set rf tx power
 | |
|  * @param rf_power:  rf tx power
 | |
|  */
 | |
| static void iot_dev_test_set_rf_tx_power(int8_t rf_power)
 | |
| {
 | |
|     if (!(rf_power >= IOT_PLC_RF_TX_POWER_MIN_DBM &&
 | |
|         rf_power <= IOT_PLC_RF_TX_POWER_MAX_DBM)) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF_TX_POWER,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
 | |
|         iot_cus_printf("%s [err]rf tx power setting out of range\n",
 | |
|             __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (dev_test_task_data->ext_cfg.rf_power_valid &&
 | |
|         dev_test_task_data->ext_cfg.rf_tx_power == rf_power) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF_TX_POWER,
 | |
|             IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_DUP_SET);
 | |
|         iot_cus_printf("%s already in rf tx power-%d\n", __FUNCTION__,
 | |
|             rf_power);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->ext_cfg.rf_power_valid = 1;
 | |
|     dev_test_task_data->ext_cfg.rf_tx_power = rf_power;
 | |
|     iot_plc_set_tx_power_cap(dev_test_task_data->app_handle,
 | |
|         IOT_PLC_API_REQ_ID_DEFAULT, NULL,
 | |
|         &dev_test_task_data->ext_cfg.rf_tx_power);
 | |
|     iot_printf("%s set to rf tx power: %d ok\n", __FUNCTION__, rf_power);
 | |
|     iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF_TX_POWER,
 | |
|         IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: set hplc tx power
 | |
|  * @param hplc_power:  hplc tx power
 | |
|  */
 | |
| static void iot_dev_test_set_hplc_tx_power(uint8_t hplc_power)
 | |
| {
 | |
|     if (!(hplc_power >= IOT_PLC_HPLC_TX_POWER_MIN_DBUV &&
 | |
|         hplc_power <= IOT_PLC_HPLC_TX_POWER_MAX_DBUV)) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_HPLC_TX_POWER,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
 | |
|         iot_cus_printf("%s [err]hplc tx power setting out of range\n",
 | |
|             __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (dev_test_task_data->ext_cfg.hplc_power_valid &&
 | |
|         dev_test_task_data->ext_cfg.hplc_tx_power == hplc_power) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_HPLC_TX_POWER,
 | |
|             IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_DUP_SET);
 | |
|         iot_cus_printf("%s already in hplc tx power-%lu\n", __FUNCTION__,
 | |
|             hplc_power);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->ext_cfg.hplc_power_valid = 1;
 | |
|     dev_test_task_data->ext_cfg.hplc_tx_power = hplc_power;
 | |
|     iot_plc_set_tx_power_cap(dev_test_task_data->app_handle,
 | |
|         IOT_PLC_API_REQ_ID_DEFAULT, &dev_test_task_data->ext_cfg.hplc_tx_power,
 | |
|         NULL);
 | |
|     iot_printf("%s set to hplc tx power: %lu ok\n", __FUNCTION__, hplc_power);
 | |
|     iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_HPLC_TX_POWER,
 | |
|         IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: set tx link type
 | |
|  * @param link_type: link type, see IOT_DEV_TEST_LINK_TYPE_XXX.
 | |
|  * @param need_rsp:  if need to response
 | |
|  */
 | |
| static void iot_dev_test_set_tx_link_type(uint8_t link_type, uint8_t need_rsp)
 | |
| {
 | |
|     if (link_type > IOT_PLC_TX_LINK_TYPE_MAX) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_TX_LINK_TYPE,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
 | |
|         iot_cus_printf("%s [err]link type setting out of range\n",
 | |
|             __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if ((link_type == IOT_PLC_TX_LINK_TYPE_RF ||
 | |
|         link_type == IOT_PLC_TX_LINK_TYPE_DUAL) &&
 | |
|         (!dev_test_task_data->ext_cfg.rf_valid ||
 | |
|         !dev_test_task_data->ext_cfg_en)) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_TX_LINK_TYPE,
 | |
|             IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_CFG_INVALID);
 | |
|         iot_cus_printf("%s [err]invalid configuration for link type setting\n",
 | |
|             __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->tx_link_type = link_type;
 | |
|     iot_printf("%s set to link type: %lu ok\n", __FUNCTION__, link_type);
 | |
|     if (need_rsp) {
 | |
|         iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_TX_LINK_TYPE,
 | |
|             IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static int8_t iot_dev_test_info_buf_find_slot(uint8_t *mac)
 | |
| {
 | |
|     int8_t index;
 | |
|     info_pool_t *pool = &dev_test_task_data->info_pool;
 | |
|     uint8_t slot_found = 0;
 | |
|     int8_t found_indx = -1;
 | |
|     /* rule 1: frames' infor stored in the buffer should have different dst
 | |
|      * address, if one frame has same dst address with others, the new one
 | |
|      * should replace the old one.
 | |
|      * rule 2: if the flag -- send_cnt is 0, that means slot found!
 | |
|      */
 | |
|     for (index = 0; index < IOT_DEV_TEST_POOL_NUM; index++) {
 | |
|         if (pool->frm_info[index].send_cnt != 0) {
 | |
|             if (iot_mac_addr_cmp(pool->frm_info[index].frm.dst_mac, mac)) {
 | |
|                 found_indx = index;
 | |
|                 iot_cus_printf("duplicated frame found, mac[%02x:%02x:%02x:"
 | |
|                     "%02x:%02x:%02x], stored sn %lu!\n", mac[0], mac[1], mac[2],
 | |
|                     mac[3], mac[4], mac[5], pool->frm_info[index].frm.app_sn);
 | |
|                 break;
 | |
|             }
 | |
|         } else {
 | |
|             if (slot_found == 0) {
 | |
|                 slot_found = 1;
 | |
|                 found_indx = index;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return found_indx;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: send pkt at M2M mode.
 | |
|  * @param  frm_pkt: pkt for fullfil the msdu pkt
 | |
|  * @retval: 0      --   success
 | |
|  * @retval: others --   failed
 | |
|  */
 | |
| static uint8_t iot_dev_test_msdu_m2m_send(frame_pkt_t* frm_pkt)
 | |
| {
 | |
|     uint32_t buflen = 0;
 | |
|     uint8_t *ptr = NULL;
 | |
|     iot_pkt_t *msdu_pkt;
 | |
|     proto_conn_less_hdr_t  *proto_hdr;
 | |
|     proto_conn_less_mr_t *meter;
 | |
|     uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 };
 | |
| 
 | |
|     buflen = sizeof(proto_conn_less_hdr_t) + sizeof(proto_conn_less_mr_t)
 | |
|         + iot_pkt_data_len(frm_pkt->data);
 | |
| 
 | |
|     if (IOT_DEV_TEST_M2M_SUBMODE_CIU == dev_test_task_data->m2m_sub_mode) {
 | |
|         iot_mac_addr_cpy(dst_mac, (uint8_t *)ciu_tester_mac);
 | |
|     } else {
 | |
|         if (iot_mac_addr_cmp(frm_pkt->dst_mac, proto_645_any_addr)) {
 | |
|             iot_set_bcast_mac(dst_mac);
 | |
|         } else {
 | |
|             iot_mac_addr_cpy(dst_mac, frm_pkt->dst_mac);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     msdu_pkt = iot_plc_alloc_conn_less_msdu_ext(dev_test_task_data->app_handle,
 | |
|         IOT_PLC_MSG_TYPE_CONN_LESS_DATA, dst_mac, dev_test_task_data->mac_addr,
 | |
|         dev_test_task_data->link_id, (uint16_t)buflen, 0, 0, 0,
 | |
|         dev_test_task_data->tx_link_type);
 | |
| 
 | |
|     if (msdu_pkt == NULL) {
 | |
|         iot_cus_printf("allocate msdu fail\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | |
|     iot_pkt_put(msdu_pkt, buflen);
 | |
|     proto_hdr = (proto_conn_less_hdr_t *)ptr;
 | |
|     proto_hdr->id = CONN_LESS_APP_ID_METER_R;
 | |
|     proto_hdr->port = CONN_LESS_APP_PORT;
 | |
| 
 | |
|     ptr += sizeof(proto_conn_less_hdr_t);
 | |
|     meter = (proto_conn_less_mr_t *)ptr;
 | |
|     meter->data_len = iot_pkt_data_len(frm_pkt->data);
 | |
|     meter->mr_timeout = IOT_DEV_TEST_CFG_MR_TIMEOUT;
 | |
|     meter->seq = iot_dev_test_app_get_sn();
 | |
|     /* Check the dev operation mode to set DIR */
 | |
|     meter->dir = CONN_LESS_APP_DIR_M2M;
 | |
|     if (dev_test_task_data->m2m_sub_mode ==IOT_DEV_TEST_M2M_SUBMODE_CIUTESTER) {
 | |
|         meter->m2m_switch_mode = IOT_DEV_TEST_M2M_MODE_SWITCH_ENABLE;
 | |
|     }
 | |
|     meter->option.dl_ppm_desc.value = 0;
 | |
| 
 | |
|     if (frm_pkt->data) {
 | |
|         ptr = iot_pkt_data(frm_pkt->data);
 | |
|         os_mem_cpy(meter->data, ptr, iot_pkt_data_len(frm_pkt->data));
 | |
|         iot_pkt_free(frm_pkt->data);
 | |
|     }
 | |
| 
 | |
|     iot_cus_printf("%s: app conn_less send to[%02x:%02x:%02x:%02x:%02x:%02x],"
 | |
|         " len %lu, link_type %lu\n", __FUNCTION__, frm_pkt->dst_mac[0],
 | |
|         frm_pkt->dst_mac[1], frm_pkt->dst_mac[2], frm_pkt->dst_mac[3],
 | |
|         frm_pkt->dst_mac[4], frm_pkt->dst_mac[5], buflen,
 | |
|         dev_test_task_data->tx_link_type);
 | |
|     iot_plc_send_msdu(dev_test_task_data->app_handle, msdu_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief: send pkt at m2s mode.
 | |
|  * @param  frm_pkt: pkt for fullfil the msdu pkt
 | |
|  * @retval: 0      --   success
 | |
|  * @retval: others --   failed
 | |
|  */
 | |
| static uint8_t iot_dev_test_msdu_m2s_send(frame_pkt_t* frm_pkt)
 | |
| {
 | |
|     uint32_t buflen = 0;
 | |
|     uint8_t *ptr = NULL;
 | |
|     iot_pkt_t *msdu_pkt;
 | |
|     proto_conn_less_hdr_t  *proto_hdr;
 | |
|     proto_conn_less_mr_t *meter;
 | |
|     uint8_t *dst_mac = NULL;
 | |
|     iot_dev_test_task_data_t *dev_glb = dev_test_task_data;
 | |
|     iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_glb->ppm_desc;
 | |
|     int8_t fix_ppm, temp;
 | |
| 
 | |
|     if (IOT_DEV_TEST_SUPPORT_CT_MR_EN) {
 | |
|         if (0 == dev_glb->collector_vaild) {
 | |
|             dst_mac = (uint8_t *)bcast_mac;
 | |
|         } else {
 | |
|             dst_mac = dev_glb->collector;
 | |
|         }
 | |
|     } else {
 | |
|         dst_mac = frm_pkt->dst_mac;
 | |
|     }
 | |
| 
 | |
|     buflen = sizeof(proto_conn_less_hdr_t) + sizeof(proto_conn_less_mr_t)
 | |
|         + iot_pkt_data_len(frm_pkt->data);
 | |
|     if (frm_pkt->ppm_detect) {
 | |
|         if (buflen < IOT_DEV_TEST_PPM_DETCT_PKG_LEN) {
 | |
|             buflen = IOT_DEV_TEST_PPM_DETCT_PKG_LEN;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (frm_pkt->ppm_detect) {
 | |
|         temp = ppm_desc->ppm_detect_cnt + 1;
 | |
|         fix_ppm = (temp >> 1) * PPM_DETECT_STEP_VALUE;
 | |
|         fix_ppm *=  (temp & 0x01 ? 1 : -1);
 | |
|         ppm_desc->fix_ppm = fix_ppm;
 | |
|         ppm_desc->ppm_detect_cnt++;
 | |
|         if (ppm_desc->ppm_detect_cnt >= ((PPM_DETECT_STEP_MAX_CNT * 2) + 1))
 | |
|             ppm_desc->ppm_detect_cnt = 0;
 | |
|     }
 | |
|     fix_ppm = iot_dev_test_get_fix_ppm();
 | |
| 
 | |
|     msdu_pkt = iot_plc_alloc_conn_less_msdu_ext(dev_glb->app_handle,
 | |
|         IOT_PLC_MSG_TYPE_CONN_LESS_DATA, dst_mac, dev_glb->mac_addr,
 | |
|         dev_glb->link_id, (uint16_t)buflen, IOT_PLC_MAX_RETRY_CNT,
 | |
|         fix_ppm, 0, dev_glb->tx_link_type);
 | |
| 
 | |
|     if (msdu_pkt == NULL) {
 | |
|         iot_cus_printf("allocate msdu fail\n");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | |
|     iot_pkt_put(msdu_pkt, buflen);
 | |
|     proto_hdr = (proto_conn_less_hdr_t *)ptr;
 | |
|     proto_hdr->id = CONN_LESS_APP_ID_METER_R;
 | |
|     proto_hdr->port = CONN_LESS_APP_PORT;
 | |
| 
 | |
|     ptr += sizeof(proto_conn_less_hdr_t);
 | |
|     meter = (proto_conn_less_mr_t *)ptr;
 | |
|     meter->data_len = iot_pkt_data_len(frm_pkt->data);
 | |
|     meter->mr_timeout = IOT_DEV_TEST_CFG_MR_TIMEOUT;
 | |
| 
 | |
|     if (!frm_pkt->sn_valid || frm_pkt->ppm_detect) {
 | |
|         frm_pkt->app_sn = iot_dev_test_app_get_sn();
 | |
|         frm_pkt->sn_valid = 1;
 | |
|     }
 | |
| 
 | |
|     meter->seq = frm_pkt->app_sn;
 | |
|     meter->dir = CONN_LESS_APP_DIR_MASTER;
 | |
|     meter->option.dl_ppm_desc.value = 0;
 | |
|     meter->data_type = frm_pkt->p_type;
 | |
|     meter->retry_cnt = 1;
 | |
| 
 | |
|     ptr = iot_pkt_data(frm_pkt->data);
 | |
|     os_mem_cpy(meter->data, ptr, iot_pkt_data_len(frm_pkt->data));
 | |
| 
 | |
|     if (frm_pkt->ppm_detect) {
 | |
|         ppm_desc->ppm_detect_rec[ppm_desc->ppm_detect_rec_idx].sn =
 | |
|             frm_pkt->app_sn;
 | |
|         ppm_desc->ppm_detect_rec[ppm_desc->ppm_detect_rec_idx].fix_ppm =
 | |
|             fix_ppm;
 | |
|         ppm_desc->ppm_detect_rec_idx++;
 | |
|         if (ppm_desc->ppm_detect_rec_idx >= IOT_DEV_TEST_PPM_DETECT_REC_MAX) {
 | |
|             ppm_desc->ppm_detect_rec_idx = 0;
 | |
|         }
 | |
|         if (ppm_desc->ppm_detect_rec_cnt < IOT_DEV_TEST_PPM_DETECT_REC_MAX)
 | |
|             ppm_desc->ppm_detect_rec_cnt++;
 | |
|     }
 | |
| 
 | |
|     iot_cus_printf("app conn_less send to[%02x:%02x:%02x:%02x:%02x:%02x], sn "
 | |
|         "%lu, len %lu, link_type %lu, fix ppm %d\n", frm_pkt->dst_mac[0],
 | |
|         frm_pkt->dst_mac[1], frm_pkt->dst_mac[2], frm_pkt->dst_mac[3],
 | |
|         frm_pkt->dst_mac[4], frm_pkt->dst_mac[5], frm_pkt->app_sn, buflen,
 | |
|         dev_glb->tx_link_type, fix_ppm);
 | |
|     iot_plc_send_msdu(dev_glb->app_handle, msdu_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| static uint16_t iot_dev_test_app_get_sn(void)
 | |
| {
 | |
|     dev_test_task_data->app_sn++;
 | |
|     if (dev_test_task_data->app_sn == 0) {
 | |
|         dev_test_task_data->app_sn = 1;
 | |
|     }
 | |
|     return dev_test_task_data->app_sn;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_fullfill_info_buf(uint8_t index, frame_pkt_t *frm)
 | |
| {
 | |
|     info_pool_t *pool = &dev_test_task_data->info_pool;
 | |
| 
 | |
|     /* if the send_cnt is none-zero, that means, a duplicated frame is
 | |
|      * found, the remain_cnt should not be updated.
 | |
|      */
 | |
| 
 | |
|     if (pool->frm_info[index].send_cnt == 0) {
 | |
|         pool->remain_cnt--;
 | |
|     }
 | |
|     /* if the old data would be replaced by new one, free the pkt first, just in
 | |
|      * case of memory leakage.
 | |
|      */
 | |
|     if (pool->frm_info[index].frm.data) {
 | |
|         iot_pkt_free(pool->frm_info[index].frm.data);
 | |
|     }
 | |
| 
 | |
|     os_mem_set(&pool->frm_info[index], 0, sizeof(frame_info_t));
 | |
|     os_mem_cpy(&pool->frm_info[index].frm, frm, sizeof(frame_pkt_t));
 | |
|     pool->frm_info[index].send_cnt++;
 | |
| }
 | |
| 
 | |
| void iot_dev_test_buf_info_del(frame_info_t *frame)
 | |
| {
 | |
|     info_pool_t *pool = &dev_test_task_data->info_pool;
 | |
|     frame_pkt_t *frm = &frame->frm;
 | |
|     if (frm->data) {
 | |
|        iot_pkt_free(frm->data);
 | |
|     }
 | |
|     os_mem_set(frame, 0, sizeof(*frame));
 | |
|     if (pool->remain_cnt < IOT_DEV_TEST_POOL_NUM) {
 | |
|         pool->remain_cnt++;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void iot_dev_tset_buf_info_clean()
 | |
| {
 | |
|     iot_dev_test_task_data_t *dev_glb = dev_test_task_data;
 | |
|     info_pool_t *info_pool = &dev_glb->info_pool;
 | |
|     uint8_t i;
 | |
|     if (info_pool->remain_cnt == IOT_DEV_TEST_POOL_NUM) {
 | |
|         return;
 | |
|     }
 | |
|     for (i = 0; i < IOT_DEV_TEST_POOL_NUM; i++) {
 | |
|          if (iot_mac_addr_valid(info_pool->frm_info[i].frm.dst_mac)) {
 | |
|              iot_dev_test_buf_info_del(&info_pool->frm_info[i]);
 | |
|          }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * 1. allocate a msdu SN for all frame stored in sending pool.
 | |
|  * 2. find slot to cache the frame info in sending pool
 | |
|  * 3. copy the frame info into the sending pool.
 | |
|  * 4. send the frame data to plc
 | |
|  */
 | |
| static uint32_t iot_dev_test_msdu_send_handle(frame_pkt_t *frm)
 | |
| {
 | |
|     int8_t index;
 | |
|     uint32_t ret = ERR_OK;
 | |
|     if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2M) {
 | |
|         /* In M2M mode, no retry, so no need app_sn from slot  */
 | |
|         if (ERR_OK != iot_dev_test_msdu_m2m_send(frm)) {
 | |
|             ret = ERR_FAIL;
 | |
|         }
 | |
|     } else if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2S) {
 | |
|         index = iot_dev_test_info_buf_find_slot(frm->dst_mac);
 | |
|         if (index >= 0) {
 | |
|             iot_dev_test_send_mode_config(frm->dst_mac);// send mode config
 | |
|             if (!iot_dev_test_msdu_m2s_send(frm)) {
 | |
|                 iot_dev_test_fullfill_info_buf(index, frm);
 | |
|             }
 | |
|         } else {
 | |
|             iot_cus_printf("NO buffer slot, frame sent to [%02x:%02x:%02x:%02x:"
 | |
|                 "%02x:%02x]failed!\n", frm->dst_mac[0], frm->dst_mac[1],
 | |
|                 frm->dst_mac[2], frm->dst_mac[3], frm->dst_mac[4],
 | |
|                 frm->dst_mac[5]);
 | |
|             ret = ERR_FAIL;
 | |
|         }
 | |
|     } else {
 | |
|         iot_cus_printf("%s: invalid dev_mode[%d]\n", __FUNCTION__,
 | |
|             dev_test_task_data->dev_mode);
 | |
|         ret = ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_ppm_detect_done_handle(int8_t *fix_ppm)
 | |
| {
 | |
|     iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
 | |
|     iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
 | |
|     if (!IOT_DEV_TEST_PPM_DETECT_EN) {
 | |
|         return;
 | |
|     }
 | |
|     ppm_desc->ppm_detect_rec_idx = 0;
 | |
|     ppm_desc->ppm_detect_rec_cnt = 0;
 | |
|     if (fix_ppm) {
 | |
|         ppm_desc->ppm_detect_state = PPM_DETECT_STATE_DONE;
 | |
|         ppm_desc->fix_ppm = *fix_ppm;
 | |
|         pib->fix_ppm = ppm_desc->fix_ppm;
 | |
|         pib->ppm_valid = 1;
 | |
|         iot_mac_addr_cpy(pib->ppm_target_mac, ppm_desc->ppm_target_mac);
 | |
|         iot_dev_test_flash_save(pib);
 | |
|         iot_cus_printf("%s ok, ppm value %d\n", __FUNCTION__,
 | |
|             ppm_desc->fix_ppm);
 | |
|     } else {
 | |
|         ppm_desc->ppm_detect_state = PPM_DETECT_STATE_IDLE;
 | |
|         ppm_desc->fix_ppm = 0;
 | |
|         iot_cus_printf("%s fail\n", __FUNCTION__);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_ppm_detect_restart(void)
 | |
| {
 | |
|     iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
 | |
| 
 | |
|     if ((!IOT_DEV_TEST_PPM_DETECT_EN) ||
 | |
|         (PPM_DETECT_STATE_DONE != ppm_desc->ppm_detect_state)){
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     ppm_desc->ppm_detect_state = PPM_DETECT_STATE_IDLE;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_ppm_detect_load(uint8_t *addr)
 | |
| {
 | |
|      iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
 | |
|      if (!IOT_DEV_TEST_PPM_DETECT_EN) {
 | |
|         return;
 | |
|      }
 | |
|      if (!iot_mac_addr_cmp(ppm_desc->ppm_target_mac, addr)) {
 | |
|         /* if the target address changes, PPM needs to be
 | |
|          * detected again.
 | |
|          */
 | |
|         iot_mac_addr_cpy(ppm_desc->ppm_target_mac, addr);
 | |
|         iot_dev_tset_buf_info_clean();
 | |
|         ppm_desc->ppm_detect_state = PPM_DETECT_STATE_IDLE;
 | |
|         ppm_desc->ppm_detect_rec_idx = 0;
 | |
|         ppm_desc->ppm_detect_rec_cnt = 0;
 | |
|         ppm_desc->ppm_detect_cnt = 0;
 | |
|         ppm_desc->fix_ppm = 0;
 | |
|      }
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_ppm_detect_init(void)
 | |
| {
 | |
|     iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
 | |
|     iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
 | |
|     os_mem_set(ppm_desc, 0x0, sizeof(*ppm_desc));
 | |
|     if (!IOT_DEV_TEST_PPM_DETECT_EN) {
 | |
|         ppm_desc->ppm_detect_state = PPM_DETECT_STATE_DONE;
 | |
|         ppm_desc->fix_ppm = 0;
 | |
|     } else if (pib->ppm_valid) {
 | |
|         ppm_desc->ppm_detect_state = PPM_DETECT_STATE_DONE;
 | |
|         iot_mac_addr_cpy(ppm_desc->ppm_target_mac,
 | |
|             pib->ppm_target_mac);
 | |
|         ppm_desc->fix_ppm = pib->fix_ppm;
 | |
|     }
 | |
|     iot_cus_printf("%s en %lu, ppm_detect_state %lu, ppm %d\n",
 | |
|         __FUNCTION__, IOT_DEV_TEST_PPM_DETECT_EN,
 | |
|         ppm_desc->ppm_detect_state, ppm_desc->fix_ppm);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * @brief:  check if the mac and sn are both in the same queue node, if so,
 | |
|  *          return true if not, return false.
 | |
|  * @param   mac: mac address of meter who sent the msdu pkt
 | |
|  * @param   sn:  meter sent back, originally assigned by sta control
 | |
|  * @retval: true  --   sn and mac both matched
 | |
|  * @retval: false --   info mismached
 | |
|  */
 | |
| static bool_t iot_dev_test_frame_rpt_check(uint8_t *mac, uint16_t sn)
 | |
| {
 | |
|     bool_t ret = false;
 | |
|     uint8_t i, j;
 | |
|     iot_dev_test_task_data_t *dev_glb = dev_test_task_data;
 | |
|     iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_glb->ppm_desc;
 | |
|     info_pool_t *info_pool = &dev_glb->info_pool;
 | |
| 
 | |
|     if (info_pool->remain_cnt != IOT_DEV_TEST_POOL_NUM) {
 | |
|         for (i = 0; i < IOT_DEV_TEST_POOL_NUM; i++) {
 | |
|             if (iot_mac_is_bcast(info_pool->frm_info[i].frm.dst_mac) ||
 | |
|                 iot_mac_addr_cmp(mac, info_pool->frm_info[i].frm.dst_mac)) {
 | |
|                 if (info_pool->frm_info[i].frm.ppm_detect) {
 | |
|                     for (j = 0; j < ppm_desc->ppm_detect_rec_cnt; j ++) {
 | |
|                         if (ppm_desc->ppm_detect_rec[j].sn == sn) {
 | |
|                             iot_dev_test_ppm_detect_done_handle(
 | |
|                                 &ppm_desc->ppm_detect_rec[j].fix_ppm);
 | |
|                             ret = true;
 | |
|                             goto done;
 | |
|                         }
 | |
|                     }
 | |
|                 } else if (sn == info_pool->frm_info[i].frm.app_sn) {
 | |
|                     ret = true;
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| done:
 | |
|     if (ret) {
 | |
|         iot_dev_test_buf_info_del(&info_pool->frm_info[i]);
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| uint16_t iot_dev_get_mr_retry_intval(frame_info_t *frame)
 | |
| {
 | |
|     if (frame->frm.ppm_detect) {
 | |
|         return 8;
 | |
|     } else {
 | |
|         return IOT_DEV_TEST_APP_MAX_RETRY_INTV_CNT;
 | |
|     }
 | |
| }
 | |
| 
 | |
| uint16_t iot_dev_get_mr_max_age(frame_info_t *frame)
 | |
| {
 | |
|     if (frame->frm.ppm_detect) {
 | |
|         return ((PPM_DETECT_STEP_MAX_CNT * 2 + 1) *
 | |
|             iot_dev_get_mr_retry_intval(frame));
 | |
|     } else {
 | |
|         return IOT_DEV_TEST_MAX_LIFE_SPAN_CNT;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /* once the periodicly timer is fired up, we should check the frame's
 | |
|  * life-span counter, if the counter reaches the limit, the stored info
 | |
|  * should be wiped out.
 | |
|  */
 | |
| static void iot_dev_test_buf_refresh(void)
 | |
| {
 | |
|     uint8_t i;
 | |
|     info_pool_t *pool = &dev_test_task_data->info_pool;
 | |
|     iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
 | |
|     frame_pkt_t *frm = NULL;
 | |
|     uint16_t intval, max_age;
 | |
| 
 | |
|     if ((dev_test_task_data->collector_vaild) &&
 | |
|         IOT_DEV_TEST_SUPPORT_CT_MR_EN &&
 | |
|         IOT_DEV_TEST_COLLECTOR_AUTO_CLR) {
 | |
|         dev_test_task_data->collector_vaild_cnt++;
 | |
|         if (dev_test_task_data->collector_vaild_cnt >=
 | |
|             IOT_DEV_TEST_COLLECTOR_VAILID_CNT) {
 | |
|             dev_test_task_data->collector_vaild = 0;
 | |
|             dev_test_task_data->collector_vaild_cnt = 0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (pool->remain_cnt != IOT_DEV_TEST_POOL_NUM) {
 | |
|         for (i = 0; i < IOT_DEV_TEST_POOL_NUM; i++) {
 | |
|             if (pool->frm_info[i].send_cnt != 0) {
 | |
|                 intval = iot_dev_get_mr_retry_intval(&pool->frm_info[i]);
 | |
|                 max_age = iot_dev_get_mr_max_age(&pool->frm_info[i]);
 | |
|                 frm = &pool->frm_info[i].frm;
 | |
|                 pool->frm_info[i].span_cnt++;
 | |
|                 if (pool->frm_info[i].span_cnt >= max_age) {
 | |
|                     iot_cus_printf("%s: frame mac[%02x:%02x:%02x:%02x:%02x:%02x"
 | |
|                         "], app_sn %lu is dropped for timeout\n", __FUNCTION__,
 | |
|                         frm->dst_mac[0], frm->dst_mac[1], frm->dst_mac[2],
 | |
|                         frm->dst_mac[3], frm->dst_mac[4], frm->dst_mac[5],
 | |
|                         frm->app_sn);
 | |
|                     if (PPM_DETECT_STATE_DOING == ppm_desc->ppm_detect_state) {
 | |
|                         iot_dev_test_ppm_detect_done_handle(NULL);
 | |
|                     } else if (PPM_DETECT_STATE_DONE == ppm_desc->ppm_detect_state) {
 | |
|                         iot_dev_test_ppm_detect_restart();
 | |
|                     }
 | |
|                     iot_dev_test_buf_info_del(&pool->frm_info[i]);
 | |
|                     continue;
 | |
|                 } else if ((pool->frm_info[i].span_cnt % intval) == 0) {
 | |
|                     if (!iot_dev_test_msdu_m2s_send(frm)) {
 | |
|                         pool->frm_info[i].send_cnt++;
 | |
|                         iot_cus_printf("%s: sending retry, app_sn %lu, "
 | |
|                             "retry cnt %lu\n", __FUNCTION__, frm->app_sn,
 | |
|                             pool->frm_info[i].send_cnt - 1);
 | |
|                     }
 | |
|                 }
 | |
|                 /* send the mode config to sta at every 750ms in unicast way */
 | |
|                 if (pool->frm_info[i].span_cnt %
 | |
|                     (IOT_DEV_TEST_APP_MAX_RETRY_INTV_CNT - 1) == 0) {
 | |
|                     iot_dev_test_send_mode_config(frm->dst_mac);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* once received a uart data, allocate a pkt, then post a msg to handle
 | |
|  * the data
 | |
|  */
 | |
| static void iot_dev_test_uart_meter_port_func(uint8_t* buffer,
 | |
|     uint32_t buffer_len, bool_t is_full_frame,uint32_t invalid_data_len)
 | |
| {
 | |
|     iot_pkt_t *pkt;
 | |
| 
 | |
|     (void)invalid_data_len;
 | |
|     (void)is_full_frame;
 | |
| 
 | |
|     if (dev_test_task_data->dev_ready == 0) {
 | |
|         iot_cus_printf("%s: Device is not ready, pkt dropped!\n", __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     pkt = iot_pkt_alloc(buffer_len, IOT_APP_DEV_TEST_MID);
 | |
|     if (pkt) {
 | |
|         os_mem_cpy(iot_pkt_put(pkt, buffer_len), buffer, buffer_len);
 | |
|         iot_dev_test_post_task_msg(IOT_DEV_TEST_UART_RECV_MSG, 0, pkt);
 | |
|     } else {
 | |
|         iot_cus_printf("%s: alloc failed\n", __FUNCTION__);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_handle_mr_req(uint8_t proto_type,
 | |
|     uint8_t *ds, uint32_t len, uint8_t *dst)
 | |
| {
 | |
|     frame_pkt_t frm = { 0 };
 | |
|     iot_pkt_t *buf;
 | |
|     uint8_t *data;
 | |
|     iot_dev_test_ppm_detec_desc_t * ppm_desc = &dev_test_task_data->ppm_desc;
 | |
|     iot_mac_addr_cpy(frm.dst_mac, dst);
 | |
|     iot_dev_test_ppm_detect_load(dst);
 | |
|     frm.p_type = proto_type;
 | |
| 
 | |
|     if ((NULL == ds) || (!len)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (ppm_desc->ppm_detect_state != PPM_DETECT_STATE_DONE) {
 | |
|         frm.ppm_detect = 1;
 | |
|         ppm_desc->ppm_detect_state = PPM_DETECT_STATE_DOING;
 | |
|     }
 | |
| 
 | |
|     buf = iot_pkt_alloc(len, IOT_APP_DEV_TEST_MID);
 | |
|     if (buf == NULL) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     data = iot_pkt_data(buf);
 | |
|     os_mem_cpy(data, ds, len);
 | |
|     iot_pkt_put(buf, len);
 | |
|     frm.data = buf;
 | |
|     if (ERR_OK != iot_dev_test_msdu_send_handle(&frm)) {
 | |
|         iot_pkt_free(buf);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* handle config data from PLC */
 | |
| static uint8_t iot_dev_test_handle_config_data(iot_pkt_t *pkt)
 | |
| {
 | |
|     uint8_t *ptr = NULL;
 | |
|     iot_plc_msdu_recv_t *msdu = NULL;
 | |
|     proto_conn_less_mr_t *meter;
 | |
|     uint8_t *mac;
 | |
|     uint16_t app_sn;
 | |
|     uint16_t offset_sz;
 | |
|     proto_645_header_t *hdr_645 = NULL;
 | |
|     uint8_t t_mac[IOT_MAC_ADDR_LEN];
 | |
|     iot_pkt_t *msg_645 = NULL;
 | |
| 
 | |
|     iot_plc_msg_header_t *hdr = (iot_plc_msg_header_t*)iot_pkt_data(pkt);
 | |
|     msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
 | |
| 
 | |
|     ptr = msdu->data;
 | |
|     iot_dev_test_data_print("msdu data", msdu->data, msdu->len);
 | |
|     meter = (proto_conn_less_mr_t *)(ptr + sizeof(proto_conn_less_hdr_t));
 | |
|     app_sn = meter->seq;
 | |
| 
 | |
|     /* data direction must: master ->slave */
 | |
|     if (meter->dir != CONN_LESS_APP_DIR_MASTER) {
 | |
|         iot_cus_printf("%s: invalid direction\n", __FUNCTION__);
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     mac = msdu->src;
 | |
|     offset_sz = sizeof(*msdu) + sizeof(*hdr) + sizeof(*meter) +
 | |
|         sizeof(proto_conn_less_hdr_t);
 | |
|     iot_pkt_pull(pkt, offset_sz);
 | |
| 
 | |
|     hdr_645 = proto_645_format_check(iot_pkt_data(pkt),
 | |
|         iot_pkt_data_len(pkt), PROTO_645_DIR_MASTER);
 | |
|     if (NULL == hdr_645) {
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     iot_mac_addr_cpy(t_mac, hdr_645->addr);
 | |
|     iot_mac_addr_reverse(t_mac);
 | |
| 
 | |
|     if (iot_dev_test_config_data_hdl_check(t_mac, app_sn)) {
 | |
|         iot_cus_printf("Received config data, sn %lu, mac[%02x:%02x:"
 | |
|             "%02x:%02x:%02x:%02x]\n", app_sn, t_mac[0], t_mac[1],
 | |
|             t_mac[2], t_mac[3], t_mac[4], t_mac[5]);
 | |
|         iot_dev_test_data_print("dlt645 data:", iot_pkt_data(pkt),
 | |
|             (uint16_t)iot_pkt_data_len(pkt));
 | |
| 
 | |
|         msg_645 = iot_dev_test_config_cmd_handle(hdr_645);
 | |
|         if (NULL !=  msg_645) {
 | |
|             iot_dev_test_config_pack_plc_rsp_data(mac, app_sn,
 | |
|                 iot_pkt_data(msg_645), iot_pkt_data_len(msg_645));
 | |
|             iot_pkt_free(msg_645);
 | |
|         }
 | |
|     } else {
 | |
|         iot_cus_printf("config data dropped, sn %lu, mac"
 | |
|             "[%02x:%02x:%02x:%02x:%02x:%02x]\n", app_sn,
 | |
|             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 | |
|     }
 | |
| out:
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static
 | |
| uint8_t iot_dev_test_check_addr_set_condition(proto_645_header_t *hdr_645)
 | |
| {
 | |
|     if (!hdr_645) {
 | |
|         iot_cus_printf("%s invalid hdr_645\n", __FUNCTION__);
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     return (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2M
 | |
|         && dev_test_task_data->m2m_sub_mode == IOT_DEV_TEST_M2M_SUBMODE_CIU
 | |
|         && dev_test_task_data->m2m_ciu_query_addr !=
 | |
|         IOT_DEV_TEST_QUERY_CIU_ADDR_SUCC
 | |
|         && (hdr_645->control.fn == PROTO_645_2007_FN_READ_ADDR)
 | |
|         && (hdr_645->control.ack == PROTO_645_ACK_NORMAL)
 | |
|         && (hdr_645->control.dir == PROTO_645_DIR_SLAVE));
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_uart_qsxj_hw_ver_resp()
 | |
| {
 | |
|     uint16_t pkt_len, i, hw_ver_hex;
 | |
|     iot_pkt_t *pkt, *resp_pkt;
 | |
|     proto_qsxj_data_t *qsxj_data;
 | |
|     proto_qsxj_hw_ver_t *hw_ver;
 | |
|     iot_oem_hw_ver_info_t hw_ver_info = { 0 };
 | |
| 
 | |
|     pkt_len = sizeof(*qsxj_data) + sizeof(*hw_ver);
 | |
|     pkt = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
 | |
|     if (!pkt) {
 | |
|         return;
 | |
|     }
 | |
|     qsxj_data = (proto_qsxj_data_t *)iot_pkt_put(pkt, pkt_len);
 | |
|     proto_qsxj_di_to_byte(PROTO_QSXJ_DI_HARDWARE_VER, &qsxj_data->di);
 | |
|     qsxj_data->len = PROTO_QSXJ_MODE_INFO_LEN_HW_VER;
 | |
|     hw_ver = (proto_qsxj_hw_ver_t *)qsxj_data->data;
 | |
|     iot_oem_get_hw_ver_info(&hw_ver_info);
 | |
|     hw_ver_hex = hw_ver_info.module_version[1];
 | |
|     hw_ver_hex = hw_ver_hex << 8;
 | |
|     hw_ver_hex |= hw_ver_info.module_version[0];
 | |
|     for (i = 0; i < PROTO_QSXJ_MODE_INFO_LEN_HW_VER; i++) {
 | |
|         hw_ver->hw_ver[i] = iot_byte_to_ascii(hw_ver_hex & 0x0f, 1);
 | |
|         hw_ver_hex >>= 4;
 | |
|     }
 | |
|     iot_data_reverse(hw_ver->hw_ver, PROTO_QSXJ_MODE_INFO_LEN_HW_VER);
 | |
|     /* ver/flag_follow/channel fields is meaningless for qsxj dev_test proto */
 | |
|     resp_pkt = proto_qsxj_build_msg((uint8_t *)qsxj_data, pkt_len,
 | |
|         PROTO_QSXJ_COMMAND_SET_RESP, PROTO_QSXJ_VER_SX_V04, 0,
 | |
|         PROTO_QSXJ_CHANNEL_NUM0);
 | |
|     if (resp_pkt) {
 | |
|         iot_dev_test_uart_send(resp_pkt);
 | |
|     }
 | |
|     if (pkt) {
 | |
|         iot_pkt_free(pkt);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_uart_qsxj_sw_ver_resp()
 | |
| {
 | |
|     uint16_t pkt_len, sw_ver_hex, i;
 | |
|     iot_pkt_t *pkt, *resp_pkt;
 | |
|     proto_qsxj_data_t *qsxj_data;
 | |
|     proto_qsxj_sw_ver_t *sw_ver;
 | |
|     iot_build_info_t build_info = { 0 };
 | |
| 
 | |
|     pkt_len = sizeof(*qsxj_data) + sizeof(*sw_ver);
 | |
|     pkt = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
 | |
|     if (!pkt) {
 | |
|         return;
 | |
|     }
 | |
|     qsxj_data = (proto_qsxj_data_t *)iot_pkt_put(pkt, pkt_len);
 | |
|     proto_qsxj_di_to_byte(PROTO_QSXJ_DI_SOFTWARE_VER, &qsxj_data->di);
 | |
|     qsxj_data->len = PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FIX +
 | |
|         PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FILL;
 | |
|     sw_ver = (proto_qsxj_sw_ver_t *)qsxj_data->data;
 | |
|     os_mem_cpy(sw_ver->ver_fix, fixed_ver, PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FIX);
 | |
|     iot_version_get_user_build_info(&build_info);
 | |
|     sw_ver_hex = build_info.sw_ver;
 | |
|     for (i = 0; i < PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FILL; i++) {
 | |
|         if (i == 2) {
 | |
|             sw_ver->ver_fill[i] = '.';
 | |
|             continue;
 | |
|         }
 | |
|         sw_ver->ver_fill[i] = iot_byte_to_ascii(sw_ver_hex & 0x0f, 1);
 | |
|         sw_ver_hex >>= 4;
 | |
|     }
 | |
|     iot_data_reverse(sw_ver->ver_fill, PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FILL);
 | |
|     /* ver/flag_follow/channel fields is meaningless for qsxj dev_test proto */
 | |
|     resp_pkt = proto_qsxj_build_msg((uint8_t *)qsxj_data, pkt_len,
 | |
|         PROTO_QSXJ_COMMAND_SET_RESP, PROTO_QSXJ_VER_SX_V04, 0,
 | |
|         PROTO_QSXJ_CHANNEL_NUM0);
 | |
|     if (resp_pkt) {
 | |
|         iot_dev_test_uart_send(resp_pkt);
 | |
|     }
 | |
|     if (pkt) {
 | |
|         iot_pkt_free(pkt);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_uart_qsxj_data_handle(iot_pkt_t *pkt)
 | |
| {
 | |
|     uint8_t *data, flag_nack = 0, addr_len, i;
 | |
|     uint8_t di_data_len, addr, meter_addr[IOT_MAC_ADDR_LEN] = { 0 };
 | |
|     uint16_t di, data_len;
 | |
|     uint32_t len;
 | |
|     proto_qsxj_head_t *head;
 | |
|     proto_qsxj_data_t *qsxj_data;
 | |
|     iot_pkt_t *resp_pkt;
 | |
|     frame_pkt_t frm = {0};
 | |
| 
 | |
|     data = iot_pkt_data(pkt);
 | |
|     len = iot_pkt_data_len(pkt);
 | |
|     iot_cus_printf("%s received uart data, len %lu\n", __FUNCTION__, len);
 | |
|     iot_dev_test_data_print("uart recv", data, len);
 | |
|     head = proto_qsxj_sanity_check(data, (uint16_t)len);
 | |
|     if (head) {
 | |
|         if (head->command != PROTO_QSXJ_COMMAND_SET_REQ) {
 | |
|             flag_nack = 1;
 | |
|             goto ack;
 | |
|         }
 | |
|         data_len = proto_qsxj_len_get(head) - sizeof(head->command) -
 | |
|             PROTO_QSXJ_CRC16_LEN;
 | |
|         if (data_len < sizeof(di)) {
 | |
|             flag_nack = 1;
 | |
|             goto ack;
 | |
|         }
 | |
|         di = iot_bytes_to_uint16(head->data, 1);
 | |
|         switch (di) {
 | |
|         case PROTO_QSXJ_DI_METER_NUM:
 | |
|         {
 | |
|             if (data_len < sizeof(*qsxj_data)) {
 | |
|                 flag_nack = 1;
 | |
|                 goto ack;
 | |
|             }
 | |
|             data_len -= sizeof(*qsxj_data);
 | |
|             qsxj_data = (proto_qsxj_data_t *)head->data;
 | |
|             di_data_len = qsxj_data->len;
 | |
|             if (data_len < di_data_len) {
 | |
|                 flag_nack = 1;
 | |
|                 goto ack;
 | |
|             }
 | |
|             addr_len = min(di_data_len, IOT_MAC_ADDR_LEN * 2);
 | |
|             for (i = 0; i < addr_len; i++) {
 | |
|                 addr = iot_ascii_to_byte(qsxj_data->data[addr_len - 1 - i]) &
 | |
|                     0x0f;
 | |
|                 if (i % 2) {
 | |
|                     meter_addr[i / 2] |= (addr << 4);
 | |
|                 } else {
 | |
|                     meter_addr[i / 2] |= addr;
 | |
|                 }
 | |
|             }
 | |
|             if (!iot_mac_addr_valid(meter_addr) ||
 | |
|                 iot_mac_is_bcast(meter_addr)) {
 | |
|                 flag_nack = 1;
 | |
|                 goto ack;
 | |
|             }
 | |
|             iot_mac_addr_reverse(meter_addr);
 | |
|             iot_mac_addr_cpy(dev_test_task_data->qsxj_addr, meter_addr);
 | |
|             goto ack;
 | |
|         }
 | |
|         case PROTO_QSXJ_DI_HARDWARE_VER:
 | |
|         {
 | |
|             iot_dev_test_uart_qsxj_hw_ver_resp();
 | |
|             break;
 | |
|         }
 | |
|         case PROTO_QSXJ_DI_SOFTWARE_VER:
 | |
|         {
 | |
|             iot_dev_test_uart_qsxj_sw_ver_resp();
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|             flag_nack = 1;
 | |
|             goto ack;
 | |
|         }
 | |
|     } else {
 | |
|         if (iot_mac_addr_valid(dev_test_task_data->qsxj_addr) &&
 | |
|             !iot_mac_is_bcast(dev_test_task_data->qsxj_addr)) {
 | |
|             frm.data = pkt;
 | |
|             frm.p_type = CONN_LESS_PROTO_TYPE_TRANSPARENT;
 | |
|             iot_mac_addr_cpy(frm.dst_mac, dev_test_task_data->qsxj_addr);
 | |
|             if (ERR_OK == iot_dev_test_msdu_send_handle(&frm)) {
 | |
|                 return;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     goto out;
 | |
| ack:
 | |
|     resp_pkt = proto_qsxj_build_ack(PROTO_QSXJ_VER_SX_V04,
 | |
|         PROTO_QSXJ_COMMAND_SET_RESP, flag_nack);
 | |
|     if (resp_pkt) {
 | |
|         iot_dev_test_uart_send(resp_pkt);
 | |
|     }
 | |
| out:
 | |
|     if (pkt) {
 | |
|         iot_pkt_free(pkt);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static uint32_t iot_dev_test_69845_control_cmd(proto_69845_frame_head_info_t *hdr_698)
 | |
| {
 | |
|     uint8_t reason;
 | |
|     uint32_t ret = ERR_OK;
 | |
|     apdu_info_t apdu = {0};
 | |
|     proto_69845_apdu_t *req_apdu;
 | |
|     proto_69845_app_set_req_t *set;
 | |
|     proto_69845_app_set_req_normal_t *normal_data;
 | |
|     uint32_t oad_value;
 | |
|     proto_69845_app_ele_data_t *ele_data;
 | |
|     proto_69845_ext_rf_param_t *rf_param;
 | |
|     proto_69845_ext_work_mode_t *control_mode;
 | |
|     addr_info_t addr_info = {0};
 | |
|     iot_pkt_t *pkt;
 | |
|     proto_69845_app_oad_t app_oad = {0};
 | |
| 
 | |
|     if (hdr_698->ctrl.fn != PROTO_69845_FN_USER_DATA) {
 | |
|         reason = 1;
 | |
|         ret = ERR_INVAL;
 | |
|         goto err;
 | |
|     }
 | |
|     if (hdr_698->ctrl.dir_prm != PROTO_69845_D_P_CLIENT_RESPONSE
 | |
|         && hdr_698->ctrl.dir_prm != PROTO_69845_D_P_CLIENT_REQUEST) {
 | |
|         reason = 2;
 | |
|         ret = ERR_INVAL;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     if (proto_69845_get_apdu(hdr_698, hdr_698->len + PROTO_69845_START_END_LEN,
 | |
|         &apdu) != ERR_OK) {
 | |
|         reason = 3;
 | |
|         ret = ERR_INVAL;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     req_apdu = (proto_69845_apdu_t *)apdu.ptr;
 | |
|     if (req_apdu->type != PROTO_69845_C_APP_SET_REQ) {
 | |
|         reason = 4;
 | |
|         ret = ERR_INVAL;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     set = (proto_69845_app_set_req_t *)req_apdu->data;
 | |
|     if (set->data_type != PROTO_69845_APP_SET_NORMAL) {
 | |
|         reason = 5;
 | |
|         ret = ERR_INVAL;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     normal_data = (proto_69845_app_set_req_normal_t *)set->data;
 | |
|     oad_value = iot_bytes_to_uint32((uint8_t *)&normal_data->oad.oi, 1);
 | |
|     ele_data = (proto_69845_app_ele_data_t *)(&normal_data->data);
 | |
|     if (ele_data->data_type != PROTO_69845_APP_DATA_OCTET_STRING) {
 | |
|         reason = 6;
 | |
|         ret = ERR_INVAL;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     switch (oad_value) {
 | |
|     case PROTO_69845_EXT_APP_OAD_BROADCAST_RF_PARAM:
 | |
|     {
 | |
|         rf_param = (proto_69845_ext_rf_param_t *)ele_data->data;
 | |
|         iot_dev_test_set_rf(rf_param->option, rf_param->channel, 0);
 | |
|         ret = ERR_EXIST;
 | |
|         break;
 | |
|     }
 | |
|     case PROTO_69845_EXT_APP_OAD_HRF_MODE:
 | |
|     {
 | |
|         uint8_t link_type;
 | |
|         control_mode = (proto_69845_ext_work_mode_t *)ele_data->data;
 | |
|         if (control_mode->mode == PROTO_69845_CONTROLLER_MODE_HPLC) {
 | |
|             link_type = IOT_PLC_TX_LINK_TYPE_HPLC;
 | |
|         } else {
 | |
|             link_type = IOT_PLC_TX_LINK_TYPE_RF;
 | |
|         }
 | |
|         iot_dev_test_set_tx_link_type(link_type, 0);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         reason = 7;
 | |
|         ret = ERR_INVAL;
 | |
|         goto err;
 | |
|     }
 | |
| 
 | |
|     addr_info.ser_info.type = PROTO_69845_SA_TYPE_SIG;
 | |
|     addr_info.ser_info.len = IOT_MAC_ADDR_LEN;
 | |
|     addr_info.ser_info.logical_addr = 0;
 | |
|     iot_mac_addr_cpy(addr_info.ser_info.addr, dev_test_task_data->mac_addr);
 | |
|     addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
 | |
|     app_oad.oi = iot_bytes_to_uint16((uint8_t *)&normal_data->oad.oi, 1);
 | |
|     app_oad.attribute_id = normal_data->oad.attribute_id;
 | |
|     app_oad.attribute_char = normal_data->oad.attribute_char;
 | |
|     app_oad.element_index = normal_data->oad.element_index;
 | |
| 
 | |
|     pkt = proto_69845_set_normal_ack(&addr_info, &normal_data->piid,
 | |
|         &app_oad, PROTO_69845_APP_DAR_SUCCESS);
 | |
|     if (pkt == NULL) {
 | |
|         reason = 8;
 | |
|         ret = ERR_INVAL;
 | |
|         goto err;
 | |
|     }
 | |
|     iot_dev_test_uart_send(pkt);
 | |
|     goto out;
 | |
| err:
 | |
|     if (reason >= 7) {
 | |
|         iot_cus_printf("%s error reason:%lu", __FUNCTION__, reason);
 | |
|     }
 | |
| out:
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_uart_data_handle(iot_pkt_t *pkt)
 | |
| {
 | |
|     uint16_t len = 0;
 | |
|     proto_645_header_t *hdr_645;
 | |
|     proto_69845_frame_head_info_t *hdr_698;
 | |
|     proto_dlms_hdlc_head_t *hdr_dlms;
 | |
|     proto_dlms_hdlc_cache_t cache_dlms;
 | |
|     union proto_dlms_hdlc_format frame_format = {0};
 | |
|     addr_info_t svr_info = {0};
 | |
|     uint8_t *data;
 | |
|     uint16_t  fe_cnt = 0;
 | |
|     uint16_t pkt_len;
 | |
|     uint8_t band_id;
 | |
|     uint8_t op_mode;
 | |
|     uint8_t baud_index;
 | |
|     uint8_t t_mac[IOT_MAC_ADDR_LEN] = { 0 };
 | |
|     uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 };
 | |
|     uint32_t di;
 | |
|     uint8_t rf_option, rf_channel;
 | |
|     int8_t rf_tx_power;
 | |
|     uint8_t hplc_tx_power, link_type;
 | |
| 
 | |
|     len = (uint16_t)iot_pkt_block_len(pkt, IOT_PKT_BLOCK_DATA);
 | |
|     data = iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | |
| 
 | |
|     iot_cus_printf("%s received uart data, len %lu\n", __FUNCTION__, len);
 | |
|     iot_dev_test_data_print("uart recv", data, len);
 | |
| 
 | |
| again:
 | |
|     if (dev_test_task_data->m2m_sub_mode == IOT_DEV_TEST_M2M_SUBMODE_CIU
 | |
|         && dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2M) {
 | |
|         hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
 | |
|     } else {
 | |
|         hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
 | |
|     }
 | |
| 
 | |
|     if (hdr_645) {
 | |
|         pkt_len = sizeof(*hdr_645) + hdr_645->len + sizeof(proto_645_tailer_t);
 | |
|         if (iot_mac_addr_cmp(hdr_645->addr, spec_mac)) {
 | |
|             iot_cus_printf("RECV_UART_CMD frame, fn: 0x%02x\n",
 | |
|                 hdr_645->control.fn);
 | |
|             proto_645_sub33_handle(hdr_645->data, hdr_645->len);
 | |
|             switch (hdr_645->control.fn) {
 | |
|                 case IOT_DEV_TEST_FN_SET_BAND:
 | |
|                     band_id = hdr_645->data[0];
 | |
|                     iot_cus_printf("[dev_test]recved set band cmd, band-id: "
 | |
|                         "%lu\n", band_id);
 | |
|                     iot_dev_test_set_band(band_id);
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_QUERRY_VER:
 | |
|                     iot_dev_test_querry_ver_handle();
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_QUERRY_BAND:
 | |
|                     iot_dev_test_querry_band_handle();
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_SET_MAC:
 | |
|                     iot_mac_addr_cpy(t_mac, hdr_645->data);
 | |
|                     iot_mac_addr_reverse(t_mac);
 | |
|                     iot_dev_test_set_mac(t_mac);
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_QUERRY_MAC:
 | |
|                     iot_dev_test_querry_mac_handle();
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_SET_OP_MODE:
 | |
|                     op_mode = hdr_645->data[0];
 | |
|                     iot_dev_test_set_op_mode(op_mode);
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_QUERY_OP_MODE:
 | |
|                     iot_dev_test_query_op_mode();
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_SET_UART_BAUDRATE:
 | |
|                     baud_index = hdr_645->data[0];
 | |
|                     iot_dev_test_set_baudrate(baud_index);
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_QUERY_BAUDRATE:
 | |
|                     iot_dev_test_query_baudrate();
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_SET_RF:
 | |
|                     rf_option = hdr_645->data[0];
 | |
|                     rf_channel = hdr_645->data[1];
 | |
|                     iot_dev_test_set_rf(rf_option, rf_channel, 1);
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_SET_RF_TX_POWER:
 | |
|                     rf_tx_power = hdr_645->data[0];
 | |
|                     iot_dev_test_set_rf_tx_power(rf_tx_power);
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_SET_HPLC_TX_POWER:
 | |
|                     hplc_tx_power = hdr_645->data[0];
 | |
|                     iot_dev_test_set_hplc_tx_power(hplc_tx_power);
 | |
|                     break;
 | |
|                 case IOT_DEV_TEST_FN_SET_TX_LINK_TYPE:
 | |
|                     link_type = hdr_645->data[0];
 | |
|                     iot_dev_test_set_tx_link_type(link_type, 1);
 | |
|                     break;
 | |
|                 default:
 | |
|                     iot_dev_test_form_rsp_cfm_frame(hdr_645->control.fn,
 | |
|                         IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_NOT_SUPPORT);
 | |
|                     iot_cus_printf("[err]cmd fn: %lu not supported!\n",
 | |
|                         hdr_645->control.fn);
 | |
|                     break;
 | |
|             }
 | |
|             proto_645_add33_handle(hdr_645->data, hdr_645->len);
 | |
|         } else {
 | |
|             proto_645_get_di_by_sub33(hdr_645->data, PROTO_645_2007_DI_LEN,
 | |
|                 PROTO_645_2007_ID, &di);
 | |
|             iot_cus_printf("RECV_UART_645 frame, di 0x%04x, data_len %lu\n",
 | |
|                 di, hdr_645->len);
 | |
| 
 | |
|             if (iot_dev_test_check_addr_set_condition(hdr_645)) {
 | |
|                 iot_mac_addr_cpy(t_mac, hdr_645->data);
 | |
|                 proto_645_sub33_handle(t_mac, IOT_MAC_ADDR_LEN);
 | |
|                 iot_mac_addr_reverse(t_mac);
 | |
|                 iot_dev_test_set_mac(t_mac);
 | |
| 
 | |
|                 dev_test_task_data->m2m_ciu_query_addr =
 | |
|                     IOT_DEV_TEST_QUERY_CIU_ADDR_SUCC;
 | |
|             }
 | |
|             if (iot_mac_addr_valid(hdr_645->addr) &&
 | |
|                 !iot_mac_is_bcast(hdr_645->addr)) {
 | |
|                 if (iot_mac_addr_cmp(hdr_645->addr, proto_645_any_addr)) {
 | |
|                     iot_set_bcast_mac(t_mac);
 | |
|                 } else {
 | |
|                     iot_mac_addr_cpy(t_mac, hdr_645->addr);
 | |
|                 }
 | |
|                 iot_mac_addr_reverse(t_mac);
 | |
|                 /* only if the dev_test support pushed-data handling,
 | |
|                  * matching mac can be updated.
 | |
|                  */
 | |
|                 iot_dev_test_update_match_mac(t_mac);
 | |
|                 iot_dev_test_stop_send_bootup_ind();
 | |
| 
 | |
|                 iot_dev_test_handle_mr_req(GW_APP_DATA_TYPE_645_2007,
 | |
|                     (uint8_t *)hdr_645, pkt_len, t_mac);
 | |
|             }
 | |
|         }
 | |
|         fe_cnt = (uint16_t)((uint8_t*)hdr_645 - data);
 | |
|         data = pkt_len + (uint8_t*)hdr_645;
 | |
|     } else {
 | |
|         hdr_698 = proto_69845_sanity_check(data, len);
 | |
|         if (hdr_698) {
 | |
|             iot_cus_printf("RECV_UART_69845 frame, fn 0x%04x, data_len %lu\n",
 | |
|                 hdr_698->len, hdr_698->ctrl.fn);
 | |
| 
 | |
|             proto_69845_get_addr_info(hdr_698, &svr_info);
 | |
|             iot_mac_addr_cpy(t_mac, svr_info.ser_info.addr);
 | |
|             iot_mac_addr_reverse(t_mac);
 | |
|             if (iot_dev_test_69845_control_cmd(hdr_698) == ERR_OK) {
 | |
|                 goto out;
 | |
|             }
 | |
|             pkt_len = (uint8_t)(hdr_698->len + PROTO_69845_START_END_LEN);
 | |
|             iot_dev_test_handle_mr_req(GW_APP_DATA_TYPE_69845,
 | |
|                 (uint8_t *)hdr_698, hdr_698->len + PROTO_69845_START_END_LEN,
 | |
|                 t_mac);
 | |
|             fe_cnt = (uint16_t)((uint8_t*)hdr_698 - data);
 | |
|             data = pkt_len + (uint8_t*)hdr_698;
 | |
|         } else {
 | |
|             hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
 | |
|             if (hdr_645) {
 | |
|                 pkt_len = sizeof(*hdr_645) + hdr_645->len +
 | |
|                     sizeof(proto_645_tailer_t);
 | |
|                 switch (hdr_645->control.fn) {
 | |
|                 case IOT_DEV_TEST_645_FN_ACK_FROM_CIU:
 | |
|                 {
 | |
|                     iot_dev_test_handle_ack_data_from_host(hdr_645);
 | |
|                     break;
 | |
|                 }
 | |
|                 case IOT_DEV_TEST_645_FN_RSP_BOOTUP_IND:
 | |
|                 {
 | |
|                     iot_dev_test_stop_send_bootup_ind();
 | |
|                     break;
 | |
|                 }
 | |
|                 default:
 | |
|                     iot_cus_printf("%s FN not supported!\n", __FUNCTION__);
 | |
|                     break;
 | |
|                 }
 | |
|                 fe_cnt = (uint16_t)((uint8_t*)hdr_645 - data);
 | |
|                 data = pkt_len + (uint8_t*)hdr_645;
 | |
|             } else {
 | |
|                 hdr_dlms = proto_dlms_hdlc_parse(data, len, &cache_dlms);
 | |
|                 if (hdr_dlms) {
 | |
|                     iot_cus_printf("RECV_UART_DLMS frame, type %lu, "
 | |
|                         "data_len %lu\n", hdr_dlms->frame_format.bit.frame_type,
 | |
|                         hdr_dlms->frame_format.bit.len);
 | |
|                     if (cache_dlms.dest_addr.type !=
 | |
|                         PROTO_DLMS_HDLC_ADD_TYPE_4) {
 | |
|                         goto out;
 | |
|                     }
 | |
|                     proto_dlms_hdlc_type_4_addr_to_bcd_addr(dst_mac,
 | |
|                         &cache_dlms.dest_addr);
 | |
|                     if (!iot_mac_addr_valid(dst_mac)) {
 | |
|                         goto out;
 | |
|                     }
 | |
|                     iot_mac_addr_reverse(dst_mac);
 | |
|                     iot_mac_addr_cpy(t_mac, dst_mac);
 | |
|                     frame_format.value =
 | |
|                         iot_ntohs(hdr_dlms->frame_format.value);
 | |
|                     pkt_len = frame_format.bit.len +
 | |
|                         PROTO_DLMS_HDLC_START_END_LEN;
 | |
|                     iot_dev_test_handle_mr_req(GW_APP_DATA_TYPE_TRANSPARENT,
 | |
|                         (uint8_t *)hdr_dlms, pkt_len, t_mac);
 | |
|                 } else {
 | |
|                     iot_cus_printf("%s No more valid frame found!\n",
 | |
|                         __FUNCTION__);
 | |
|                     goto out;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     len = len - pkt_len - fe_cnt;
 | |
| 
 | |
|     if (len) {
 | |
|         goto again;
 | |
|     }
 | |
| out:
 | |
|     iot_pkt_free(pkt);
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_uart_send(iot_pkt_t *pkt)
 | |
| {
 | |
|     iot_uart_send(dev_test_task_data->host_com, pkt, NULL);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static iot_uart_h iot_dev_test_open_uart(uint8_t port)
 | |
| {
 | |
|     iot_uart_h uart = 0;
 | |
| 
 | |
|     uart = iot_uart_open(port, iot_dev_test_uart_meter_port_func,
 | |
|         IOT_DEV_TEST_UART_RECV_BUF_SIZE, NULL);
 | |
| 
 | |
|     return uart;
 | |
| }
 | |
| 
 | |
| static bool_t iot_dev_test_set_uart_config(iot_uart_h uart)
 | |
| {
 | |
|     bool_t ret = false;
 | |
|     uint8_t parity;
 | |
|     uint32_t uart_baud = baud_tbl[dev_test_task_data->flashinfo.baud_index];
 | |
|     iot_frame_fmt fmt = { 0 };
 | |
|     iot_cus_printf("desire baudrate:[%lu]\n", uart_baud);
 | |
|     if (dev_test_task_data->user_type == USER_TYPE_STATE_GRID_OVERSEAS_SX) {
 | |
|         parity = IOT_UART_PARITY_NONE;
 | |
|     } else {
 | |
|         parity = IOT_UART_PARITY_EVEN;
 | |
|     }
 | |
|     ret = iot_uart_set_config(uart, uart_baud, parity, IOT_UART_DLEN_8_BITS,
 | |
|         IOT_UART_STOP_1_BITS);
 | |
|     /* config the UART port settings */
 | |
|     fmt.preamble_code[0] = PROTO_645_START_CHAR;
 | |
|     fmt.preamble_codelen = 1;
 | |
|     fmt.datalen_offset   = 8;
 | |
|     fmt.datalen_size     = 1;
 | |
|     fmt.backcode_offset  = 1;
 | |
|     fmt.backcode_len     = 1;
 | |
|     fmt.datalen_fix      = 0;
 | |
|     fmt.backcode[0]      = PROTO_645_END_CHAR;
 | |
|     fmt.frame_timeout    = 30;
 | |
|     fmt.timeout_mode     = TIMEOUT_PERDATA;
 | |
|     fmt.check_frame_func = proto_645_check_frame_handler;
 | |
|     iot_uart_set_frame(uart, &fmt);
 | |
| 
 | |
|     /* report the data to app after 3 bytes' interval */
 | |
|     iot_uart_set_threshold(uart, UART_THR_RXTIMEOUT, 3);
 | |
|     /* report the data to app once received 100 bytes */
 | |
|     iot_uart_set_threshold(uart, UART_THR_RXFULL, 100);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_close_uart(iot_uart_h uart)
 | |
| {
 | |
|     iot_uart_close(uart);
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_query_ciu_addr(void)
 | |
| {
 | |
|     iot_pkt_t *pkt = NULL;
 | |
|     uint32_t length = 0;
 | |
| 
 | |
|     if (dev_test_task_data->query_addr_cnt >= IOT_DEV_TEST_QUERY_ADDR_CNT_MAX
 | |
|         || dev_test_task_data->m2m_ciu_query_addr ==
 | |
|         IOT_DEV_TEST_QUERY_CIU_ADDR_SUCC) {
 | |
|         os_stop_timer(dev_test_task_data->query_addr_tm);
 | |
|         dev_test_task_data->query_addr_cnt = 0;
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->query_addr_cnt++;
 | |
| 
 | |
|     pkt = iot_pkt_alloc(PROTO_645_2007_READ_ADDR_PKT_LEN, IOT_APP_DEV_TEST_MID);
 | |
|     if (!pkt) {
 | |
|         iot_cus_printf("%s failed to alloc pkt\n", __FUNCTION__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     iot_pkt_reserve(pkt, PROTO_645_PREAMBLE_LEN);
 | |
|     length = proto_645_fill_frame(iot_pkt_data(pkt), PROTO_645_2007_ID,
 | |
|         proto_645_any_addr, PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL,
 | |
|         PROTO_645_FOLLOW_INVALID, PROTO_645_2007_FN_READ_ADDR,
 | |
|         PROTO_645_INVALID_DI, 0, NULL);
 | |
|     IOT_ASSERT(length);
 | |
|     iot_pkt_put(pkt, length);
 | |
|     iot_dev_test_uart_send(pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static uint8_t iot_dev_test_handle_msdu_data_recv(iot_pkt_t *pkt)
 | |
| {
 | |
|     uint8_t consumed = 0;
 | |
|     uint8_t *ptr = NULL;
 | |
|     iot_plc_msdu_recv_t *msdu = NULL;
 | |
|     proto_conn_less_hdr_t *frm_hdr = NULL;
 | |
| 
 | |
|     iot_plc_msg_header_t *hdr =
 | |
|         (iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | |
|     msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
 | |
| 
 | |
|     ptr = msdu->data;
 | |
|     frm_hdr = (proto_conn_less_hdr_t *)ptr;
 | |
| 
 | |
|     if (CONN_LESS_APP_PORT != frm_hdr->port) {
 | |
|         iot_cus_printf("received msdu data: wrong port\n");
 | |
|         return consumed;
 | |
|     }
 | |
| 
 | |
|     switch (frm_hdr->id) {
 | |
|     case CONN_LESS_APP_ID_METER_R:
 | |
|         consumed = iot_dev_test_handle_normal_data(pkt);
 | |
|         break;
 | |
|     case CONN_LESS_APP_ID_DATA_PUSH:
 | |
|         consumed = iot_dev_test_handle_pushed_data(pkt);
 | |
|         break;
 | |
|     case CONN_LESS_APP_ID_CONFIG:
 | |
|         consumed = iot_dev_test_handle_config_data(pkt);
 | |
|         break;
 | |
|     default:
 | |
|         iot_cus_printf("received msdu data id 0x%04x "
 | |
|             "is not supported by app\n", frm_hdr->id);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     return consumed;
 | |
| }
 | |
| 
 | |
| #else /* IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER */
 | |
| 
 | |
| static void iot_dev_test_buf_refresh(void)
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_uart_qsxj_data_handle(iot_pkt_t *pkt)
 | |
| {
 | |
|     iot_pkt_free(pkt);
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_uart_data_handle(iot_pkt_t *pkt)
 | |
| {
 | |
|     iot_pkt_free(pkt);
 | |
| }
 | |
| 
 | |
| static uint8_t iot_dev_test_handle_msdu_data_recv(iot_pkt_t *pkt)
 | |
| {
 | |
|     (void)pkt;
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_close_uart(iot_uart_h uart)
 | |
| {
 | |
|     (void)uart;
 | |
| }
 | |
| 
 | |
| static bool_t iot_dev_test_set_uart_config(iot_uart_h uart)
 | |
| {
 | |
|     (void)uart;
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_query_ciu_addr(void)
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_send_bootup_indication(void)
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_ppm_detect_init()
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| static int8_t iot_dev_test_get_fix_ppm(void)
 | |
| {
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| #endif /* IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER */
 | |
| 
 | |
| /* Load config from PIB. */
 | |
| static uint8_t iot_dev_test_flash_load(void)
 | |
| {
 | |
|     uint8_t *rw = NULL;
 | |
|     uint8_t temp_pt = MAX_PIB_TYPE;
 | |
|     iot_pib_get_app_section(&rw, &temp_pt, IOT_PIB_APP_GET_WRITE_SECTION);
 | |
|     IOT_ASSERT(rw);
 | |
| 
 | |
|     IOT_ASSERT(temp_pt == STA_PIB_TYPE);
 | |
| 
 | |
|     os_mem_cpy(&dev_test_task_data->flashinfo, rw, sizeof(iot_dev_test_pib_t));
 | |
|     dev_test_task_data->section = rw;
 | |
| 
 | |
|     iot_dev_test_pib_t *info = &dev_test_task_data->flashinfo;
 | |
|     iot_cus_printf("boot cnt: %lu, loaded mac[%02x:%02x:%02x:%02x:%02x:%02x],"
 | |
|         "baud index: %lu\n",
 | |
|         info->boot_cnt, info->match_mac[0], info->match_mac[1],
 | |
|         info->match_mac[2], info->match_mac[3], info->match_mac[4],
 | |
|         info->match_mac[5], info->baud_index);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* Check the magic code to tell if the flash infor is damaged. */
 | |
| static uint8_t iot_dev_test_flashinfo_check(iot_dev_test_pib_t *p_info)
 | |
| {
 | |
|     uint32_t magic1, magic2;
 | |
|     uint8_t ret = ERR_OK;
 | |
| 
 | |
|     magic1 = p_info->magic1;
 | |
| 
 | |
|     magic2 = p_info->magic2;
 | |
| 
 | |
|     iot_cus_printf("Magic = 0x%08x, 0x%08x!\n", magic1, magic2);
 | |
| 
 | |
|     if ((IOT_DEV_TEST_FLASHINFO_MAGIC1 != magic1)
 | |
|         ||(IOT_DEV_TEST_FLASHINFO_MAGIC2 != magic2)) {
 | |
|         ret = ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| /* This will store config into PIB area. */
 | |
| static uint8_t iot_dev_test_flash_save(iot_dev_test_pib_t *p_info)
 | |
| {
 | |
|     uint8_t ref;
 | |
|     uint16_t ticket;
 | |
| 
 | |
|     iot_pib_acquire_app_commit_ref(&ref);
 | |
|     os_mem_cpy(dev_test_task_data->section, p_info, sizeof(*p_info));
 | |
|     iot_pib_release_app_commit_ref(&ref);
 | |
|     iot_pib_app_commit(&ticket);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* load flash infor and update local infor */
 | |
| static void iot_dev_test_flash_info_init(void)
 | |
| {
 | |
|     iot_dev_test_pib_t *p_info = &dev_test_task_data->flashinfo;
 | |
| 
 | |
|     if (ERR_FAIL == iot_dev_test_flash_load() ||
 | |
|         ERR_FAIL == iot_dev_test_flashinfo_check(p_info)) {
 | |
|         iot_cus_printf("get flash info failed\n!");
 | |
|         os_mem_set(p_info, 0x0, sizeof(*p_info));
 | |
|         p_info->baud_index = DEFAULT_BAUDRATE_INDEX;
 | |
|         p_info->magic1 = IOT_DEV_TEST_FLASHINFO_MAGIC1;
 | |
|         p_info->magic2 = IOT_DEV_TEST_FLASHINFO_MAGIC2;
 | |
|         iot_dev_test_flash_save(p_info);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /* get start-up app SN from boot cnt and rondom data */
 | |
| static uint16_t iot_dev_test_startup_app_sn_create(void) {
 | |
|     uint16_t app_sn;
 | |
|     uint16_t boot_cnt = dev_test_task_data->flashinfo.boot_cnt;
 | |
| 
 | |
|     app_sn = (boot_cnt << 12) + (uint16_t)(os_rand() & 0xFFF);
 | |
|     iot_cus_printf("[dev_test]boot_cnt %lu, created SN %lu\n",
 | |
|         dev_test_task_data->flashinfo.boot_cnt, app_sn);
 | |
|     /* update the boot cnt then store into flash */
 | |
|     iot_counter_inc(dev_test_task_data->flashinfo.boot_cnt);
 | |
|     iot_dev_test_flash_save(&dev_test_task_data->flashinfo);
 | |
|     return app_sn;
 | |
| }
 | |
| 
 | |
| /* allocte a conn_less_msdu, then fill the msdu pkt with
 | |
|  * conn_less mode config data
 | |
|  */
 | |
| static uint8_t iot_dev_test_send_mode_config(uint8_t *dst_mac)
 | |
| {
 | |
|     uint16_t buflen = 0;
 | |
|     uint8_t *ptr = NULL;
 | |
|     iot_pkt_t *msdu_pkt;
 | |
|     dev_test_mode_cfg_t  *cfg;
 | |
|     uint8_t *msdu_dst_mac = NULL;
 | |
|     int8_t fix_ppm;
 | |
| 
 | |
|     if (dev_test_task_data->user_type == USER_TYPE_YNS) {
 | |
|         return ERR_OK;
 | |
|     }
 | |
|     if (!iot_mac_addr_valid(dst_mac)) {
 | |
|         iot_cus_printf("%s: dst mac is invalid!\n", __FUNCTION__);
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
| 
 | |
| #if (IOT_DEV_TEST_BROADCAST_MODD_CFG == 1)
 | |
|     if (!iot_mac_is_bcast(dst_mac)) {
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
| #else
 | |
|     if (iot_mac_is_bcast(dst_mac)) {
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     fix_ppm = iot_dev_test_get_fix_ppm();
 | |
| 
 | |
|     if (IOT_DEV_TEST_SUPPORT_CT_MR_EN && !dev_test_task_data->collector_vaild) {
 | |
|         msdu_dst_mac = (uint8_t *)bcast_mac;
 | |
|     } else if (dev_test_task_data->collector_vaild) {
 | |
|         msdu_dst_mac = dev_test_task_data->collector;
 | |
|     } else {
 | |
|         msdu_dst_mac = dst_mac;
 | |
|     }
 | |
| 
 | |
|     buflen = sizeof(dev_test_mode_cfg_t) + sizeof(dev_test_ext_cfg_t);
 | |
| 
 | |
|     msdu_pkt = iot_plc_alloc_conn_less_msdu_ext(dev_test_task_data->app_handle,
 | |
|         IOT_PLC_MSG_TYPE_CONN_LESS_CMD, dst_mac, dev_test_task_data->mac_addr,
 | |
|         dev_test_task_data->link_id, buflen, IOT_PLC_LOCAL_RETRY_CNT,
 | |
|         fix_ppm, 0, dev_test_task_data->tx_link_type);
 | |
| 
 | |
|     if (msdu_pkt == NULL) {
 | |
|         iot_cus_printf("%s:allocate msdu failed!\n", __FUNCTION__);
 | |
|         return ERR_NOMEM;
 | |
|     }
 | |
| 
 | |
|     ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
 | |
|     iot_pkt_put(msdu_pkt, buflen);
 | |
|     cfg = (dev_test_mode_cfg_t *)ptr;
 | |
|     cfg->band_id = dev_test_task_data->band_id;
 | |
|     cfg->dur = IOT_DEV_TEST_MODE_CFG_DUR;
 | |
|     cfg->ext_cfg_en = dev_test_task_data->ext_cfg_en;
 | |
|     os_mem_cpy((uint8_t *)&cfg->ext_cfg,
 | |
|         (uint8_t *)&dev_test_task_data->ext_cfg, sizeof(dev_test_ext_cfg_t));
 | |
| #if IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER
 | |
|     cfg->target_id_mask = IOT_DEV_TEST_TARGET_ID_MSK_STA;
 | |
| #elif IOT_DEV_TEST_CCO_MODE
 | |
|     cfg->target_id_mask = IOT_DEV_TEST_TARGET_ID_MSK_CCO;
 | |
| #endif
 | |
| 
 | |
|     iot_cus_printf("send mode config to [%02x:%02x:%02x:%02x:%02x:%02x]"
 | |
|         " band id-%lu, duration-%lu sec, mask-%lu, ext en-%lu, [valid-%lu] "
 | |
|         "rf option-%lu rf channel-%lu, [valid-%lu]rf power-(%d)dbm, "
 | |
|         "[valid-%lu]hplc power-(%lu)dbuv\n",
 | |
|         msdu_dst_mac[0], msdu_dst_mac[1], msdu_dst_mac[2], msdu_dst_mac[3],
 | |
|         msdu_dst_mac[4], msdu_dst_mac[5], cfg->band_id, cfg->dur,
 | |
|         cfg->target_id_mask, cfg->ext_cfg_en, cfg->ext_cfg[0].rf_valid,
 | |
|         cfg->ext_cfg[0].rf_option, cfg->ext_cfg[0].rf_channel,
 | |
|         cfg->ext_cfg[0].rf_power_valid, cfg->ext_cfg[0].rf_tx_power,
 | |
|         cfg->ext_cfg[0].hplc_power_valid, cfg->ext_cfg[0].hplc_tx_power);
 | |
|     iot_plc_send_msdu(dev_test_task_data->app_handle, msdu_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_msdu_recv(void *param, iot_pkt_t *pkt)
 | |
| {
 | |
|     (void)param;
 | |
|     iot_dev_test_post_task_msg(IOT_DEV_TEST_MAC_MSG, 0, pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_periodic_timer_func(timer_id_t timer_id,
 | |
|     void * arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
|     (void)arg;
 | |
| 
 | |
|     iot_dev_test_post_task_msg(IOT_DEV_TEST_TIMER_MSG,
 | |
|         IOT_DEV_TEST_TIMER_CHECK, NULL);
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_query_addr_timer_func (timer_id_t timer_id, void * arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
|     (void)arg;
 | |
| 
 | |
|     iot_dev_test_post_task_msg(IOT_DEV_TEST_TIMER_MSG,
 | |
|         IOT_DEV_TEST_TIMER_QUERY_ADDR, NULL);
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_handle_timer_msg(
 | |
|     iot_dev_test_task_msg_t* task_msg)
 | |
| {
 | |
|     switch (task_msg->msg.id) {
 | |
|     case IOT_DEV_TEST_TIMER_CHECK:
 | |
|     {
 | |
|         iot_dev_test_config_all_sta_test_mode();
 | |
| 
 | |
|         iot_dev_test_buf_refresh();
 | |
| 
 | |
| 		iot_dev_test_send_bootup_indication();
 | |
|         break;
 | |
|     }
 | |
|     case IOT_DEV_TEST_TIMER_QUERY_ADDR:
 | |
|     {
 | |
|         iot_dev_test_query_ciu_addr();
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_set_cfg_after_app_reg(void)
 | |
| {
 | |
|     iot_plc_cfg_set_req_t cfg = {0};
 | |
|     iot_plc_app_h app_hdl = dev_test_task_data->app_handle;
 | |
| 
 | |
|     /* enable whitelist */
 | |
|     iot_plc_set_whitelist(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
 | |
|         IOT_PLC_WL_ENABLE, 0, NULL);
 | |
| 
 | |
|     /* stop network formation */
 | |
|     iot_plc_stop_nw_fmt(app_hdl);
 | |
| 
 | |
|     /* set configuration of local device */
 | |
|     iot_dev_test_pib_t *p_flash = &dev_test_task_data->flashinfo;
 | |
| 
 | |
| #if IOT_DEV_TEST_BUILD_CIU_TESTER && (IOT_DEV_TEST_BROADCAST_MODD_CFG == 0)
 | |
|     iot_mac_addr_cpy( p_flash->match_mac, (uint8_t *)ciu_tester_mac);
 | |
| #endif
 | |
| 
 | |
|     if (!iot_mac_is_bcast(p_flash->match_mac)
 | |
|         && iot_mac_addr_valid(p_flash->match_mac)) {
 | |
|         iot_mac_addr_cpy(cfg.addr, p_flash->match_mac);
 | |
|         cfg.addr_valid = 1;
 | |
|         iot_cus_printf("%s: set local mac[%02x:%02x:%02x:%02x:%02x:%02x] "
 | |
|             "successfully\n", __FUNCTION__, cfg.addr[0], cfg.addr[1],
 | |
|             cfg.addr[2], cfg.addr[3], cfg.addr[4], cfg.addr[5]);
 | |
|     }
 | |
|     cfg.reset = 1;
 | |
|     cfg.dev_type_valid = 1;
 | |
|     cfg.dev_type = IOT_PLC_DEV_TYPE_METER_CONTROLLER;
 | |
|     iot_plc_set_cfg(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
 | |
| 
 | |
|     /* set default frequnce band */
 | |
| #if (IOT_DEV_TEST_SUPPORT_MUTIBAND == 1)
 | |
|     iot_plc_set_freq_band(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
 | |
|         PLC_LIB_FREQ_BAND_MULTI_1_2);
 | |
| #else
 | |
|     iot_plc_set_freq_band(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
 | |
|         dev_test_task_data->band_id);
 | |
| #endif
 | |
|     /* query device infor */
 | |
|     iot_plc_query_dev_info(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT);
 | |
| 
 | |
|     /* disable watchdog */
 | |
|     iot_plc_wdg_set(app_hdl, 0, 0);
 | |
|     /* get the app SN and update the boot counter */
 | |
|     dev_test_task_data->app_sn = iot_dev_test_startup_app_sn_create();
 | |
| 
 | |
| #if IOT_DEV_TEST_CCO_MODE
 | |
|     int8_t rf_power = 16;
 | |
|     if (dev_test_task_data->user_type == USER_TYPE_STATE_GRID_LIAONING) {
 | |
|         dev_test_task_data->ext_cfg.rf_power_valid = 1;
 | |
|         dev_test_task_data->ext_cfg.rf_tx_power = 16;
 | |
|         iot_plc_set_tx_power_cap(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
 | |
|             NULL, &rf_power);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     /* start reload timer */
 | |
|     os_start_timer(dev_test_task_data->periodic_tm,
 | |
|         IOT_DEV_TEST_PERIODIC_TIMER_INTERVAL);
 | |
| 
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_handle_mac_msg(iot_pkt_t *pkt)
 | |
| {
 | |
|     iot_plc_msg_header_t *hdr =
 | |
|         (iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | |
|     uint8_t consumed = 0;
 | |
|     uint8_t app_id;
 | |
| 
 | |
| #if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER)
 | |
|     app_id = IOT_PLC_APP_SMART_GRID;
 | |
| #elif IOT_DEV_TEST_CCO_MODE
 | |
|     app_id = IOT_PLC_APP_DEV_TEST;
 | |
| #endif
 | |
| 
 | |
|     if (hdr->app_id != IOT_PLC_APP_ID_BCAST &&
 | |
|         hdr->app_id != app_id) {
 | |
|         iot_pkt_free(pkt);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (dev_test_task_data->app_registered == 0 &&
 | |
|         hdr->msg_id != IOT_PLC_MSG_APP_REG_CONF) {
 | |
|         // only handle app register confirm message before app registered
 | |
|         iot_pkt_free(pkt);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (hdr->msg_id) {
 | |
|     case IOT_PLC_MSG_APP_REG_CONF:
 | |
|     {
 | |
|         iot_plc_app_reg_conf_t* rpt = (iot_plc_app_reg_conf_t*)(hdr + 1);
 | |
|         iot_cus_printf("%s: IOT_PLC_MSG_APP_REG_CONF result:%d\n", __FUNCTION__,
 | |
|             rpt->result);
 | |
|         if (rpt->result == IOT_PLC_SUCCESS ||
 | |
|             rpt->result == IOT_PLC_SUCCESS_MODIFIED) {
 | |
|             dev_test_task_data->app_registered = 1;
 | |
|             iot_dev_test_set_cfg_after_app_reg();
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_DEV_STATE_CHANGE_RPT:
 | |
|     {
 | |
|         iot_plc_dev_state_change_rpt_t* rpt =
 | |
|             (iot_plc_dev_state_change_rpt_t*)(hdr + 1);
 | |
|         iot_cus_printf("[dev_test]IOT_PLC_MSG_DEV_STATE_CHANGE_RPT: "
 | |
|             "local mac[%02X:%02X:%02X:%02X:%02X:%02X], role:%lu, ready:%lu\n",
 | |
|             rpt->local_mac[0], rpt->local_mac[1], rpt->local_mac[2],
 | |
|             rpt->local_mac[3], rpt->local_mac[4], rpt->local_mac[5],
 | |
|             rpt->dev_role, rpt->is_ready);
 | |
|         if (iot_mac_addr_valid(rpt->local_mac)) {
 | |
|             dev_test_task_data->dev_role = rpt->dev_role;
 | |
|             iot_mac_addr_cpy(dev_test_task_data->mac_addr, rpt->local_mac);
 | |
|             dev_test_task_data->dev_ready = 1;
 | |
|             iot_dev_test_send_bootup_indication();
 | |
|         }
 | |
| #if IOT_DEV_TEST_CCO_MODE
 | |
|         /* dev_test_cco is fixed band, but when SG app configures plc, band
 | |
|          * information is lost and needs to be reconfigured.
 | |
|          */
 | |
|         iot_plc_set_freq_band(dev_test_task_data->app_handle,
 | |
|             IOT_PLC_API_REQ_ID_DEFAULT, dev_test_task_data->band_id);
 | |
| #endif
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_DEV_INFO_RPT:
 | |
|     {
 | |
|         iot_plc_dev_info_rpt_t* rpt = (iot_plc_dev_info_rpt_t*)(hdr + 1);
 | |
|         iot_cus_printf("%s: infor report--role %lu, dev type %lu, local mac"
 | |
|             "[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__,
 | |
|             rpt->dev_role, rpt->dev_type, rpt->local_mac[0], rpt->local_mac[1],
 | |
|             rpt->local_mac[2], rpt->local_mac[3], rpt->local_mac[4],
 | |
|             rpt->local_mac[5]);
 | |
|         if (iot_mac_addr_valid(rpt->local_mac)) {
 | |
|             dev_test_task_data->dev_role = rpt->dev_role;
 | |
|             dev_test_task_data->dev_type = rpt->dev_type;
 | |
|             iot_mac_addr_cpy(dev_test_task_data->mac_addr, rpt->local_mac);
 | |
|             dev_test_task_data->dev_ready = 1;
 | |
|         } else {
 | |
|             IOT_ASSERT(0);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_PLC_MSG_CONN_LESS_RECV:
 | |
|     {
 | |
|         consumed = iot_dev_test_handle_msdu_data_recv(pkt);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
|     if (consumed == 0) {
 | |
|         iot_pkt_free(pkt);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_task_handle_msg(iot_task_h task_h,
 | |
|     iot_task_msg_t *msg)
 | |
| {
 | |
|     iot_dev_test_task_msg_t *task_msg;
 | |
|     IOT_ASSERT(task_h == dev_test_task_data->task_handle);
 | |
|     IOT_ASSERT(msg);
 | |
| 
 | |
|     task_msg = (iot_dev_test_task_msg_t*)msg;
 | |
|     switch (task_msg->msg.type) {
 | |
|     case IOT_DEV_TEST_MAC_MSG:
 | |
|     {
 | |
|         iot_dev_test_handle_mac_msg(task_msg->data);
 | |
|         break;
 | |
|     }
 | |
|     case IOT_DEV_TEST_TIMER_MSG:
 | |
|     {
 | |
|         iot_dev_test_handle_timer_msg(task_msg);
 | |
|         break;
 | |
|     }
 | |
|     case IOT_DEV_TEST_UART_RECV_MSG:
 | |
|     {
 | |
|         if (dev_test_task_data->user_type ==
 | |
|             USER_TYPE_STATE_GRID_OVERSEAS_SX) {
 | |
|             iot_dev_test_uart_qsxj_data_handle(task_msg->data);
 | |
|         } else {
 | |
|             iot_dev_test_uart_data_handle(task_msg->data);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     iot_task_free_msg(dev_test_task_data->task_handle, &task_msg->msg);
 | |
| }
 | |
| 
 | |
| static void iot_dev_test_task_handle_msg_cancel(iot_task_h task_h,
 | |
|     iot_task_msg_t *msg)
 | |
| {
 | |
|     iot_dev_test_task_msg_t *task_msg;
 | |
|     IOT_ASSERT(task_h == dev_test_task_data->task_handle);
 | |
|     IOT_ASSERT(msg);
 | |
| 
 | |
|     task_msg = (iot_dev_test_task_msg_t*)msg;
 | |
|     switch (task_msg->msg.type) {
 | |
|     case IOT_DEV_TEST_MAC_MSG:
 | |
|     case IOT_DEV_TEST_UART_RECV_MSG:
 | |
|     {
 | |
|         if (task_msg->data) {
 | |
|             iot_pkt_free(task_msg->data);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case IOT_DEV_TEST_TIMER_MSG:
 | |
|     {
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     iot_task_free_msg(dev_test_task_data->task_handle, &task_msg->msg);
 | |
| }
 | |
| 
 | |
| static uint32_t iot_dev_test_task_init()
 | |
| {
 | |
|     uint32_t ret = ERR_OK;
 | |
|     iot_plc_app_t dev_test_app = {0};
 | |
|     iot_task_config_t task_cfg;
 | |
|     iot_uart_h uart_hdl = NULL;
 | |
| 
 | |
| #if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER)
 | |
| 
 | |
|     /* when IOT_STA_CONTROL_MODE equals 2, if uart port0 could not be opened,
 | |
|      * that means sta controller app is running, dev_test app should not run.
 | |
|      * when IOT_DEV_TEST_CCO_MODE equals 1, dev_test no longer using uart port,
 | |
|      * check uart port is not neccesary.
 | |
|      * when IOT_STA_CONTROL_MODE equals 2, the IOT_DEV_TEST_CCO_MODE
 | |
|      * must be 0.
 | |
|      */
 | |
|     uart_hdl = iot_dev_test_open_uart(iot_board_get_uart(UART_METER_PORT));
 | |
|     if (uart_hdl == NULL) {
 | |
|         iot_cus_printf("open uart meter port failed!\n");
 | |
|         goto out;
 | |
|     } else {
 | |
|         iot_cus_printf("open uart meter port successfully!\n");
 | |
|     }
 | |
| 
 | |
| #endif /* IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER */
 | |
| 
 | |
|     dev_test_task_data = os_mem_malloc(IOT_APP_DEV_TEST_MID,
 | |
|         sizeof(*dev_test_task_data));
 | |
|     if (!dev_test_task_data) {
 | |
|         ret = ERR_NOMEM;
 | |
|         goto error_1;
 | |
|     }
 | |
| 
 | |
|     os_mem_set(dev_test_task_data, 0, sizeof(iot_dev_test_task_data_t));
 | |
| 
 | |
|     dev_test_task_data->host_com = uart_hdl;
 | |
|     dev_test_task_data->link_id = IOT_DEV_TEST_TASK_LINK_ID;
 | |
|     dev_test_task_data->dev_role = IOT_PLC_DEV_ROLE_INVALID;
 | |
|     dev_test_task_data->dev_mode = IOT_DEV_TEST_APP_MODE_M2S;
 | |
|     dev_test_task_data->flashinfo.baud_index = DEFAULT_BAUDRATE_INDEX;
 | |
|     dev_test_task_data->user_type = iot_oem_get_user_type();
 | |
|     if ((dev_test_task_data->user_type == USER_TYPE_STATE_GRID_CQ) ||
 | |
|         (dev_test_task_data->user_type == USER_TYPE_STATE_GRID_JIBEI)) {
 | |
|         dev_test_task_data->band_id = PLC_LIB_FREQ_BAND_1;
 | |
|     } else {
 | |
|         dev_test_task_data->band_id = PLC_LIB_FREQ_BAND_2;
 | |
|     }
 | |
|     dev_test_task_data->ext_cfg_en = 1;
 | |
| 
 | |
| #if IOT_DEV_TEST_HANDLE_PUSH_DATA_EN
 | |
|     dev_test_task_data->boot_ind_en = 1;
 | |
| #else
 | |
|     dev_test_task_data->boot_ind_en = 0;
 | |
| #endif
 | |
| 
 | |
|     iot_dev_test_flash_info_init();
 | |
|     iot_dev_test_ppm_detect_init();
 | |
| 
 | |
|     /* Default is for China sg market use.
 | |
|      * For outsea market, below need to do:
 | |
|      *  1. build CIU binary.
 | |
|      *  2. set IOT_DEV_TEST_BUILD_CIU_TESTER = 1 and
 | |
|      *     set dev_mode = IOT_DEV_TEST_APP_MODE_M2M, build CIU tester binary.
 | |
|      */
 | |
| #if IOT_DEV_TEST_BUILD_CIU_TESTER
 | |
|     dev_test_task_data->m2m_sub_mode = IOT_DEV_TEST_M2M_SUBMODE_CIUTESTER;
 | |
|     dev_test_task_data->dev_mode = IOT_DEV_TEST_APP_MODE_M2M;
 | |
| #else
 | |
|     dev_test_task_data->m2m_sub_mode = IOT_DEV_TEST_M2M_SUBMODE_CIU;
 | |
| #endif
 | |
|     dev_test_task_data->m2m_check_addr = IOT_DEV_TEST_ADDR_NOT_SET;
 | |
|     dev_test_task_data->m2m_ciu_query_addr = IOT_DEV_TEST_QUERY_CIU_ADDR_FAIL;
 | |
|     dev_test_task_data->query_addr_cnt = 0;
 | |
|     dev_test_task_data->tx_link_type = IOT_PLC_TX_LINK_TYPE_HPLC;
 | |
| 
 | |
|     task_cfg.stack_size = 0;
 | |
|     task_cfg.task_prio = IOT_DEV_TEST_TASK_PRIO;
 | |
|     task_cfg.msg_size = sizeof(iot_dev_test_task_msg_t);
 | |
|     task_cfg.msg_cnt = IOT_DEV_TEST_TASK_POOL_SIZE;
 | |
|     task_cfg.queue_cnt = IOT_DEV_TEST_TASK_QUEUE_MAX_PRIO;
 | |
|     task_cfg.queue_cfg[IOT_DEV_TEST_TASK_QUEUE_HP].quota = 0;
 | |
|     task_cfg.msg_exe_func = iot_dev_test_task_handle_msg;
 | |
|     task_cfg.msg_cancel_func = iot_dev_test_task_handle_msg_cancel;
 | |
| 
 | |
|     dev_test_task_data->task_handle =
 | |
|         iot_task_create(IOT_APP_DEV_TEST_MID, &task_cfg);
 | |
| 
 | |
|     if (dev_test_task_data->task_handle == NULL) {
 | |
|         ret = ERR_FAIL;
 | |
|         goto error_2;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->periodic_tm = os_create_timer(
 | |
|         IOT_APP_DEV_TEST_MID, true, iot_dev_test_periodic_timer_func,
 | |
|         dev_test_task_data);
 | |
|     if (dev_test_task_data->periodic_tm == 0) {
 | |
|         ret = ERR_FAIL;
 | |
|         goto error_3;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->query_addr_tm = os_create_timer(
 | |
|         IOT_APP_DEV_TEST_MID, true, iot_dev_test_query_addr_timer_func,
 | |
|         dev_test_task_data);
 | |
|     if (dev_test_task_data->query_addr_tm == 0) {
 | |
|         ret = ERR_FAIL;
 | |
|         goto error_4;
 | |
|     }
 | |
| 
 | |
|     if (dev_test_task_data->host_com) {
 | |
|         if (iot_dev_test_set_uart_config(dev_test_task_data->host_com)) {
 | |
|             iot_cus_printf("host uart config success\n");
 | |
|         } else {
 | |
|             iot_cus_printf("host uart config fail\n");
 | |
|             goto error_5;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| #if IOT_DEV_TEST_CCO_MODE
 | |
|     dev_test_app.app_id = IOT_PLC_APP_DEV_TEST;
 | |
| #elif (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER)
 | |
|     dev_test_app.app_id = IOT_PLC_APP_SMART_GRID;
 | |
| #endif
 | |
| 
 | |
|     dev_test_app.param = NULL;
 | |
|     dev_test_app.prio = 3;
 | |
|     dev_test_app.recv = iot_dev_test_msdu_recv;
 | |
| 
 | |
|     dev_test_task_data->app_handle = iot_plc_register_app(&dev_test_app);
 | |
|     if (dev_test_task_data->app_handle == NULL) {
 | |
|         ret = ERR_FAIL;
 | |
|         goto error_5;
 | |
|     }
 | |
| 
 | |
|     dev_test_task_data->info_pool.remain_cnt = IOT_DEV_TEST_POOL_NUM;
 | |
| 
 | |
| #if (IOT_DEV_TEST_BUILD_CIU_TESTER && IOT_DEV_TEST_BROADCAST_MODD_CFG)
 | |
|     iot_dev_test_set_mac((uint8_t *)ciu_tester_mac);
 | |
| #endif
 | |
| 
 | |
|     goto out;
 | |
| 
 | |
| error_5:
 | |
|     os_delete_timer(dev_test_task_data->query_addr_tm);
 | |
|     dev_test_task_data->query_addr_tm = 0;
 | |
| error_4:
 | |
|     os_delete_timer(dev_test_task_data->periodic_tm);
 | |
|     dev_test_task_data->periodic_tm = 0;
 | |
| error_3:
 | |
|     iot_task_delete(dev_test_task_data->task_handle);
 | |
|     dev_test_task_data->task_handle = NULL;
 | |
| error_2:
 | |
|     os_mem_free(dev_test_task_data);
 | |
|     dev_test_task_data = NULL;
 | |
| error_1:
 | |
|     if (uart_hdl) {
 | |
|         iot_dev_test_close_uart(uart_hdl);
 | |
|         uart_hdl = NULL;
 | |
|     }
 | |
| out:
 | |
|     iot_cus_printf("[dev_test]Initializing task done, ret: %lu\n", ret);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| uint32_t app_dev_test_entry()
 | |
| {
 | |
|     uint32_t ret = ERR_NOT_READY;
 | |
|     /* if the firmware is release version(0), disabel log printing, if not,
 | |
|      * enable the log printing
 | |
|      */
 | |
|     if (iot_version_type() == 1) {
 | |
|         iot_cus_print_config(true);
 | |
|     } else {
 | |
|         iot_cus_print_config(false);
 | |
|     }
 | |
| 
 | |
|     if (iot_dev_test_task_init()) {
 | |
|         return ERR_OK;
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| #endif /* (IOT_STA_CONTROL_MODE == 2) || (IOT_DEV_TEST_CCO_MODE) */
 | |
| 
 |