/**************************************************************************** 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 shim includes */ #include "os_types.h" /* common includes */ #include "iot_errno.h" #include "iot_module.h" #include "iot_utils.h" #include "iot_ipc.h" #include "iot_io_api.h" #include "iot_pkt_api.h" #include "iot_plc_api.h" #include "iot_plc_lib.h" /* plc lib internal includes */ #include "plc_lib_internal.h" #if (PLC_SUPPORT_CCO_ROLE || PLC_SUPPORT_STA_ROLE) /* max queried node count within long buffer size by mac address */ #define IOT_PLC_NEIGHBOR_QUERY_MAC_MAX_CNT ((PLC_LIB_MSG_LONG_BUF_SIZE - \ sizeof(iot_plc_neighbor_dev_query_mac_t) - \ sizeof(iot_plc_msg_header_t)) / IOT_MAC_ADDR_LEN) /* msdu max pad length */ #define IOT_PLC_MSDU_PB_72 (72) #define IOT_PLC_MSDU_PB_136 (136) #define IOT_PLC_MSDU_PB_264 (264) #define IOT_PLC_MSDU_PB_520 (520) /* plc stack includes */ #include "plc_protocol.h" #include "plc_const.h" #include "mac_utils_api.h" #include "mpdu_frame.h" #include "plc_sila_nhm.h" iot_ipc_addr_t plc_stack_addr = {IOT_IPC_FID_PLC, IOT_IPC_CID_PLC_MAC}; uint8_t *plc_lib_prep_msg(iot_pkt_t *buf, uint8_t app_id, uint8_t msg_id, uint8_t req_id) { uint8_t *data; iot_plc_msg_header_t *header; data = iot_pkt_block_ptr(buf, IOT_PKT_BLOCK_DATA); header = (iot_plc_msg_header_t *)data; header->app_id = app_id; header->msg_id = msg_id; header->req_id = req_id; iot_pkt_put(buf, sizeof(*header)); data += sizeof(*header); return data; } void iot_plc_query(iot_plc_app_h handle, uint8_t req_id, uint8_t msg_id) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); os_release_mutex(p_plc_lib->lock); return; } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); plc_lib_prep_msg(buf, app->app_id, msg_id, req_id); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } iot_plc_app_h iot_plc_register_app(iot_plc_app_t *app) { iot_pkt_t *buf; iot_plc_app_reg_req_t *req; iot_plc_app_t *slot = NULL; if (p_plc_lib == NULL) goto out; if (app->app_id < IOT_PLC_APP_ID_MIN || app->app_id > IOT_PLC_APP_ID_MAX) goto out; if (app->recv == NULL) goto out; if (app->prio > 3) goto out; app->load = IOT_PLC_APP_LOAD_DEFAULT; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL) { slot = plc_lib_find_free_app(); if (!slot){ IOT_ASSERT(slot); os_release_mutex(p_plc_lib->lock); goto out; } } *slot = *app; buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); req = (iot_plc_app_reg_req_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_APP_REG_REQ, PLC_LIB_REQ_ID_DEFAULT); req->type = app->app_id; req->prio = app->prio; iot_pkt_put(buf, sizeof(*req)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); out: return slot; } static iot_pkt_t *iot_plc_alloc_msdu_internal(iot_plc_app_h handle, uint8_t msg_type, uint8_t ack_type, uint8_t *dst, uint8_t *src, uint8_t lid, uint16_t len, uint8_t send_cnt, uint8_t head_reserved_len, uint8_t tail_reserved_len, uint8_t msg_id, int8_t fix_ppm, uint8_t is_only_tx, uint8_t tx_link_type, uint8_t no_encrypt) { uint32_t size; iot_pkt_t *buf = NULL; iot_plc_app_t *slot, *app; iot_plc_msdu_send_t *send; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); goto out; } size = head_reserved_len + len + tail_reserved_len; if (size > PLC_LONG_BUF_SIZE) goto out; buf = iot_pkt_alloc(size, IOT_PLC_LIB_MID); if (buf) { size = head_reserved_len - sizeof(iot_plc_msdu_send_t); size -= sizeof(iot_plc_msg_header_t); iot_pkt_reserve(buf, size); send = (iot_plc_msdu_send_t *)plc_lib_prep_msg(buf, app->app_id, msg_id, PLC_LIB_REQ_ID_DEFAULT); send->len = len; send->retry_cnt = min(IOT_PLC_MAX_RETRY_CNT, send_cnt); send->msg_type = msg_type; send->ack_type = ack_type; send->fix_ppm = fix_ppm; send->is_only_tx = !!is_only_tx; send->link_type = tx_link_type; send->no_encrypt = !!no_encrypt; if (dst) { iot_mac_addr_cpy(send->dst, dst); } iot_mac_addr_cpy(send->src, src); send->type = app->app_id; if (lid == 255) send->lid = app->prio; else send->lid = lid; iot_pkt_put(buf, sizeof(*send)); } else { IOT_ASSERT(0); } out: os_release_mutex(p_plc_lib->lock); return buf; } #if IOT_ENABLE_ADD_PADDING_INFO uint16_t iot_plc_calc_msdu_len_with_pad_info(uint16_t app_len, uint8_t is_connless, uint16_t *pad_len) { uint16_t msdu_len = app_len; uint16_t reserve_len = 0; uint8_t support_72pb = 1; uint8_t support_264pb = 1; if (p_plc_lib->proto == PLC_PROTO_TYPE_SG) { #if SUPPORT_SMART_GRID && SUPPORT_IEEE_1901 /* for ieee1901 protocol */ support_264pb = 0; reserve_len = MAC_HDR_LEN_WITH_VAR_I1901 + I1901_SOF_PB_HDR_CRC_LEN + I1901_MAC_MSDU_CRC_LEN; #else reserve_len = MAC_HDR_LEN_NO_ADDR + SG_SOF_PB_HDR_CRC_LEN + SG_MAC_MSDU_CRC_LEN; #endif /* end SUPPORT_SMART_GRID && SUPPORT_IEEE_1901 */ if (is_connless) { reserve_len += sizeof(cert_test_t) + sizeof(plc_conn_less_hdr_t); } } else if (p_plc_lib->proto == PLC_PROTO_TYPE_SPG) { support_72pb = 0; support_264pb = 0; reserve_len = MAC_SHORT_HDR_LEN_SPG + MSDU_SHORT_HDR_LEN_SPG + SPG_SOF_PB_HDR_CRC_LEN + SPG_SOF_PB_RESV_LEN + SPG_MAC_MSDU_CRC_LEN; if (is_connless) { reserve_len += sizeof(spg_cert_test_hdr_t) + sizeof(plc_conn_less_hdr_t); } } if (support_72pb && app_len + reserve_len <= IOT_PLC_MSDU_PB_72) { msdu_len = IOT_PLC_MSDU_PB_72 - reserve_len; } else if (app_len + reserve_len <= IOT_PLC_MSDU_PB_136) { msdu_len = IOT_PLC_MSDU_PB_136 - reserve_len; } else if (support_264pb && app_len + reserve_len <= IOT_PLC_MSDU_PB_264) { msdu_len = IOT_PLC_MSDU_PB_264 - reserve_len; } else if (app_len + reserve_len <= IOT_PLC_MSDU_PB_520) { msdu_len = IOT_PLC_MSDU_PB_520 - reserve_len; } if (pad_len) { *pad_len = msdu_len - app_len; } iot_printf("%s app_len=%lu is_connless=%d msdu_len=%lu pad_len=%d\n", __FUNCTION__, app_len, is_connless, msdu_len, msdu_len - app_len); return msdu_len; } #else /* else IOT_ENABLE_ADD_PADDING_INFO */ uint16_t iot_plc_calc_msdu_len_with_pad_info(uint16_t app_len, uint8_t is_connless, uint16_t *pad_len) { (void)is_connless; if (pad_len) { *pad_len = 0; } return app_len; } #endif /* end IOT_ENABLE_ADD_PADDING_INFO */ iot_pkt_t *iot_plc_alloc_msdu(iot_plc_app_h handle, uint8_t msg_type, uint8_t ack_type, uint8_t *dst, uint8_t *src, uint8_t lid, uint16_t len, uint8_t send_cnt) { iot_pkt_t *pkt = NULL; if (p_plc_lib->proto == PLC_PROTO_TYPE_SG) { pkt = iot_plc_alloc_msdu_internal(handle, msg_type, ack_type, dst, src, lid, len, send_cnt, APP_HEAD_RESERVE_LEN, APP_TAIL_RESERVE_LEN, IOT_PLC_MSG_MSDU_SEND, 0, 0, IOT_PLC_TX_LINK_TYPE_HPLC, 0); } else if (p_plc_lib->proto == PLC_PROTO_TYPE_SPG) { pkt = iot_plc_alloc_msdu_internal(handle, msg_type, ack_type, dst, src, lid, len, send_cnt, APP_HEAD_RESERVE_LEN_SPG, APP_TAIL_RESERVE_LEN_SPG, IOT_PLC_MSG_MSDU_SEND, 0, 0, IOT_PLC_TX_LINK_TYPE_HPLC, 0); } return pkt; } iot_pkt_t *iot_plc_alloc_msdu_no_encrypt(iot_plc_app_h handle, uint8_t msg_type, uint8_t ack_type, uint8_t *dst, uint8_t *src, uint8_t lid, uint16_t len, uint8_t send_cnt) { iot_pkt_t *pkt = NULL; if (p_plc_lib->proto == PLC_PROTO_TYPE_SG) { pkt = iot_plc_alloc_msdu_internal(handle, msg_type, ack_type, dst, src, lid, len, send_cnt, APP_HEAD_RESERVE_LEN, APP_TAIL_RESERVE_LEN, IOT_PLC_MSG_MSDU_SEND, 0, 0, IOT_PLC_TX_LINK_TYPE_HPLC, 1); } else if (p_plc_lib->proto == PLC_PROTO_TYPE_SPG) { pkt = iot_plc_alloc_msdu_internal(handle, msg_type, ack_type, dst, src, lid, len, send_cnt, APP_HEAD_RESERVE_LEN_SPG, APP_TAIL_RESERVE_LEN_SPG, IOT_PLC_MSG_MSDU_SEND, 0, 0, IOT_PLC_TX_LINK_TYPE_HPLC, 1); } return pkt; } iot_pkt_t *iot_plc_alloc_msdu_by_tei(iot_plc_app_h handle, uint8_t msg_type, uint8_t ack_type, uint16_t dst, uint8_t *src, uint8_t lid, uint16_t len, uint8_t send_cnt) { iot_pkt_t *pkt = NULL; uint8_t dst_addr[IOT_MAC_ADDR_LEN]; os_mem_set(dst_addr, 0, IOT_MAC_ADDR_LEN); dst_addr[0] = dst & 0xFF; dst_addr[1] = (dst >> 8) & 0xFF; if (p_plc_lib->proto == PLC_PROTO_TYPE_SG) { pkt = iot_plc_alloc_msdu_internal(handle, msg_type, ack_type, dst_addr, src, lid, len, send_cnt, APP_HEAD_RESERVE_LEN, APP_TAIL_RESERVE_LEN, IOT_PLC_MSG_MSDU_SEND_BY_TEI, 0, 0, IOT_PLC_TX_LINK_TYPE_HPLC, 0); } else if (p_plc_lib->proto == PLC_PROTO_TYPE_SPG) { pkt = iot_plc_alloc_msdu_internal(handle, msg_type, ack_type, dst_addr, src, lid, len, send_cnt, APP_HEAD_RESERVE_LEN_SPG, APP_TAIL_RESERVE_LEN_SPG, IOT_PLC_MSG_MSDU_SEND_BY_TEI, 0, 0, IOT_PLC_TX_LINK_TYPE_HPLC, 0); } return pkt; } iot_pkt_t *iot_plc_alloc_ctrl_proto_msdu(iot_plc_app_h handle, uint8_t *dst, uint8_t *src, uint8_t lid, uint16_t len, uint8_t send_cnt) { iot_pkt_t *pkt = NULL; if (p_plc_lib->proto == PLC_PROTO_TYPE_SG) { pkt = iot_plc_alloc_msdu_internal(handle, 0, 0, dst, src, lid, len, send_cnt, APP_HEAD_RESERVE_LEN, APP_TAIL_RESERVE_LEN, IOT_PLC_MSG_CTRL_PROTO_SEND, 0, 0, IOT_PLC_TX_LINK_TYPE_HPLC, 1); } else { pkt = iot_plc_alloc_msdu_internal(handle, 0, 0, dst, src, lid, len, send_cnt, APP_HEAD_RESERVE_LEN_SPG, APP_TAIL_RESERVE_LEN_SPG, IOT_PLC_MSG_CTRL_PROTO_SEND, 0, 0, IOT_PLC_TX_LINK_TYPE_HPLC, 1); } return pkt; } iot_pkt_t *iot_plc_alloc_conn_less_msdu_ext(iot_plc_app_h handle, uint8_t msg_type, uint8_t *dst, uint8_t *src, uint8_t lid, uint16_t len, uint8_t send_cnt, int8_t fix_ppm, uint8_t is_only_tx, uint8_t tx_link_type) { iot_pkt_t *pkt; uint8_t head_rsvd_len = 0; if (p_plc_lib->proto == PLC_PROTO_TYPE_SG) { if (msg_type == IOT_PLC_MSG_TYPE_NHM_DATA_ALL || msg_type == IOT_PLC_MSG_TYPE_NHM_DATA) { head_rsvd_len = APP_HEAD_SILA_NHM_RESERVE_LEN; } else { head_rsvd_len = APP_HEAD_CONN_LESS_RESERVE_LEN; } } else if (p_plc_lib->proto == PLC_PROTO_TYPE_SPG) { head_rsvd_len = APP_HEAD_CONN_LESS_RESERVE_LEN_SPG; } else { IOT_ASSERT(0); } pkt = iot_plc_alloc_msdu_internal(handle, msg_type, 0, dst, src, lid, len, send_cnt, head_rsvd_len, APP_TAIL_RESERVE_LEN, IOT_PLC_MSG_CONN_LESS_SEND, fix_ppm, is_only_tx, tx_link_type, 1); return pkt; } void iot_plc_send_msdu(iot_plc_app_h handle, iot_pkt_t *pkt) { iot_pkt_t *tmp_pkt; uint32_t size; uint16_t payload_len; iot_plc_app_t* slot = NULL; iot_plc_app_t* app = (iot_plc_app_t*)handle; iot_plc_msdu_send_t *send; if (iot_pkt_tail_len(pkt) < APP_TAIL_RESERVE_LEN) { /* although we already reserved required tail len in * iot_plc_alloc_msdu. it's possible that app won't follow * the requested len strictly. try to allocate a larger packet * to overcome the issue. */ size = iot_pkt_block_len(pkt, IOT_PKT_BLOCK_ALL); size += APP_TAIL_RESERVE_LEN - iot_pkt_tail_len(pkt); tmp_pkt = iot_pkt_alloc(size, IOT_PLC_LIB_MID); if (tmp_pkt == NULL) { IOT_ASSERT(0); iot_pkt_free(pkt); return; } else { iot_pkt_cpy(tmp_pkt, pkt); iot_pkt_free(pkt); pkt = tmp_pkt; } } send = (iot_plc_msdu_send_t *)(iot_pkt_data(pkt) + sizeof(iot_plc_msg_header_t)); payload_len = (uint16_t)(iot_pkt_data_len(pkt) - sizeof(*send) - sizeof(iot_plc_msg_header_t)); if (send->len != payload_len) { iot_printf("%s len war %lu[%lu]\n", __FUNCTION__, send->len, payload_len); } os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, pkt); return; } void iot_plc_query_dev_info(iot_plc_app_h handle, uint8_t req_id) { iot_plc_query(handle, req_id, IOT_PLC_MSG_DEV_INFO_QUERY); } void iot_plc_query_nid(iot_plc_app_h handle, uint8_t req_id) { iot_plc_query(handle, req_id, IOT_PLC_MSG_NW_ID_QUERY); } void iot_plc_query_nb_nw_info(iot_plc_app_h handle, uint8_t req_id) { iot_plc_query(handle, req_id, IOT_PLC_MSG_NW_NEIGHBOR_QUERY); } void iot_plc_query_whitelist(iot_plc_app_h handle, uint8_t req_id, uint16_t start, uint16_t cnt) { iot_pkt_t *buf = NULL; iot_plc_app_t *slot = NULL, *app = NULL; iot_plc_wl_query_t *q = NULL; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); q = (iot_plc_wl_query_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_NW_WL_QUERY, req_id); q->start = start; q->count = cnt; iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; } void iot_plc_query_blacklist(iot_plc_app_h handle, uint8_t req_id, uint16_t start, uint16_t cnt) { iot_pkt_t *buf = NULL; iot_plc_app_t *slot = NULL, *app = NULL; iot_plc_bl_query_t *q = NULL; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); q = (iot_plc_bl_query_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_NW_BL_QUERY, req_id); q->start = start; q->count = cnt; iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; } void iot_plc_set_whitelist(iot_plc_app_h handle, uint8_t req_id, uint8_t action, uint16_t count, uint8_t *mac_addr_array) { iot_plc_set_whitelist_ex(handle, req_id, action, count, mac_addr_array, 1); } void iot_plc_set_whitelist_ex(iot_plc_app_h handle, uint8_t req_id, uint8_t action, uint16_t count, uint8_t *mac_addr, uint8_t big) { iot_pkt_t *buf = NULL; iot_plc_app_t *slot = NULL, *app = NULL; iot_plc_wl_set_req_t *q = NULL; uint32_t len = 0; uint16_t i = 0; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } /* allocate buf according to entry count */ buf = iot_ipc_pkt_alloc(sizeof(iot_plc_msg_header_t) + sizeof(iot_plc_wl_set_req_t) + count*IOT_MAC_ADDR_LEN, IOT_PLC_LIB_MID); IOT_ASSERT(buf); q = (iot_plc_wl_set_req_t*)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_NW_WL_SET, req_id); q->action = action; q->count = count; iot_pkt_put(buf, sizeof(*q)); /* make sure there is enough space for whitelist entries */ len = iot_pkt_block_len(buf, IOT_PKT_BLOCK_TAIL); IOT_ASSERT(len >= (uint32_t)(q->count * IOT_MAC_ADDR_LEN)); os_mem_cpy(q->mac_addr, mac_addr, IOT_MAC_ADDR_LEN * count); if (!big) { for (i = 0; i < q->count; i++) { iot_mac_addr_reverse(q->mac_addr[i]); } } iot_pkt_put(buf, q->count * IOT_MAC_ADDR_LEN); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; } void iot_plc_set_blacklist(iot_plc_app_h handle, uint8_t req_id, uint8_t action, uint16_t count, uint8_t * mac_addr_array) { iot_pkt_t *buf = NULL; iot_plc_app_t *slot = NULL, *app = NULL; iot_plc_bl_set_req_t *q = NULL; uint32_t len = 0; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } /* allocate buf according to entry count */ buf = iot_ipc_pkt_alloc(sizeof(iot_plc_msg_header_t) + sizeof(iot_plc_bl_set_req_t) + count*IOT_MAC_ADDR_LEN, IOT_PLC_LIB_MID); IOT_ASSERT(buf); q = (iot_plc_bl_set_req_t*)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_NW_BL_SET, req_id); q->action = action; q->count = count; iot_pkt_put(buf, sizeof(*q)); /* make sure there is enough space for blacklist entries */ len = iot_pkt_block_len(buf, IOT_PKT_BLOCK_TAIL); IOT_ASSERT(len >= (uint32_t)(q->count * IOT_MAC_ADDR_LEN)); os_mem_cpy(q->mac_addr, mac_addr_array, IOT_MAC_ADDR_LEN * count); iot_pkt_put(buf, q->count * IOT_MAC_ADDR_LEN); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; } void iot_plc_set_cfg(iot_plc_app_h handle, uint8_t req_id, iot_plc_cfg_set_req_t *cfg) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_cfg_set_req_t *set; app = handle; if (cfg == NULL) { return; } os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); goto drop; } if (cfg->dev_type_valid) { switch (cfg->dev_type) { case IOT_PLC_DEV_TYPE_METER_CONTROLLER: case IOT_PLC_DEV_TYPE_CONCENTRATOR: case IOT_PLC_DEV_TYPE_POWER_METER: case IOT_PLC_DEV_TYPE_REPEATER: case IOT_PLC_DEV_TYPE_COLLECTOR_1: case IOT_PLC_DEV_TYPE_COLLECTOR_2: case IOT_PLC_DEV_TYPE_POWER_METER_3P: case IOT_PLC_DEV_TYPE_BRK_MONITOR: case IOT_PLC_DEV_TYPE_TSFM_MONITOR: case IOT_PLC_DEV_TYPE_SWITCH_MONITOR: case IOT_PLC_DEV_TYPE_BSRM_MONITOR: break; default: IOT_ASSERT(0); goto drop; } } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); if (buf == NULL) { IOT_ASSERT(0); goto drop; } /* prepare a IOT_PLC_MSG_CFG_SET_REQ message */ set = (iot_plc_cfg_set_req_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_CFG_SET_REQ, req_id); os_mem_cpy(set, cfg, sizeof(*set)); iot_pkt_put(buf, sizeof(*set)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; drop: os_release_mutex(p_plc_lib->lock); return; } void iot_plc_set_freq_band(iot_plc_app_h handle, uint8_t req_id, uint8_t freq_band) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_freq_band_set_t *q = NULL; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); /* prepare a IOT_PLC_MSG_NW_FREQ_BAND_SET message */ q = (iot_plc_freq_band_set_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_FREQ_BAND_SET, req_id); q->freq_band = freq_band; iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } void iot_plc_set_rf_channel(iot_plc_app_h handle, uint8_t req_id, uint8_t option, uint8_t channel, uint8_t rf_cod_enable) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_set_rf_channel_t *q = NULL; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(sizeof(iot_plc_msg_header_t) + sizeof(iot_plc_set_rf_channel_t), IOT_PLC_LIB_MID); IOT_ASSERT(buf); /* prepare a IOT_PLC_MSG_RF_CHANNEL_SET message */ q = (iot_plc_set_rf_channel_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_RF_CHANNEL_SET, req_id); q->option = option; q->channel = channel; q->cod_enable = !!rf_cod_enable; iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } void iot_plc_start_nw_fmt(iot_plc_app_h handle, uint8_t force) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_start_nw_fmt_t *start; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); goto drop; } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); if (buf == NULL) { IOT_ASSERT(0); goto drop; } /* prepare a IOT_PLC_MSG_START_NW_FMT message */ start = (iot_plc_start_nw_fmt_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_START_NW_FMT, PLC_LIB_REQ_ID_DEFAULT); start->force = force; iot_pkt_put(buf, sizeof(*start)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; drop: os_release_mutex(p_plc_lib->lock); return; } void iot_plc_stop_nw_fmt(iot_plc_app_h handle) { iot_plc_query(handle, PLC_LIB_REQ_ID_DEFAULT, IOT_PLC_MSG_STOP_NW_FMT); } bool_t iot_plc_is_client_mode() { return (p_plc_lib->client != 0); } uint32_t iot_plc_get_ntb(iot_plc_app_h handle) { (void)handle; #if HW_PLATFORM == HW_PLATFORM_SIMU return 0; #else return mac_get_cur_ntb(); #endif } void iot_plc_query_band_info(iot_plc_app_h handle, uint8_t req_id) { iot_plc_query(handle, req_id, IOT_PLC_MSG_BAND_INFO_QUERY); } void iot_plc_wdg_set(iot_plc_app_h handle, uint8_t enable, uint16_t interval) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_wdg_set_req_t *set; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); goto drop; } if (enable && interval < 30) { goto drop; } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); if (buf == NULL) { IOT_ASSERT(0); goto drop; } /* prepare a IOT_PLC_MSG_WDG_SET_REQ message */ set = (iot_plc_wdg_set_req_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_WDG_SET_REQ, PLC_LIB_REQ_ID_DEFAULT); set->enable = !!enable; set->interval = interval; iot_pkt_put(buf, sizeof(*set)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; drop: os_release_mutex(p_plc_lib->lock); return; } void iot_plc_query_neighbor_by_mac(iot_plc_app_h handle, uint8_t req_id, uint8_t *node_mac, uint8_t node_cnt) { uint8_t real_cnt; uint16_t buf_len; iot_pkt_t *buf; iot_plc_neighbor_dev_query_mac_t *q; iot_plc_app_t *slot; iot_plc_app_t* app = (iot_plc_app_t*)handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); os_release_mutex(p_plc_lib->lock); return; } real_cnt = min(node_cnt, IOT_PLC_NEIGHBOR_QUERY_MAC_MAX_CNT); buf_len = sizeof(iot_plc_msg_header_t) + sizeof(iot_plc_neighbor_dev_query_mac_t) + real_cnt * IOT_MAC_ADDR_LEN; if (buf_len > PLC_LIB_MSG_SHORT_BUF_SIZE) { buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_LONG_BUF_SIZE, IOT_PLC_LIB_MID); } else { buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); } IOT_ASSERT(buf); q = (iot_plc_neighbor_dev_query_mac_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_NEIGHBOR_DEV_QUERY_BY_MAC, req_id); q->node_cnt = real_cnt; os_mem_cpy((uint8_t *)q->mac, node_mac, real_cnt * IOT_MAC_ADDR_LEN); iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; } void iot_plc_query_neighbor_dev(iot_plc_app_h handle, uint8_t req_id, uint16_t start, uint16_t cnt, uint8_t start_type) { iot_pkt_t *buf; iot_plc_neighbor_dev_query_t *q; iot_plc_app_t *slot; iot_plc_app_t* app = (iot_plc_app_t*)handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); os_release_mutex(p_plc_lib->lock); return; } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); q = (iot_plc_neighbor_dev_query_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_NEIGHBOR_DEV_QUERY, req_id); q->start = start; q->count = cnt; q->start_type = start_type; iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return; } void iot_plc_query_tei_addr_info(iot_plc_app_h handle, uint8_t req_id, uint16_t start_tei, uint16_t offset, uint8_t bm_len, uint8_t *bm) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_query_tei_addr_info_t *q; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); os_release_mutex(p_plc_lib->lock); return; } buf = iot_ipc_pkt_alloc(sizeof(iot_plc_msg_header_t) + sizeof(iot_plc_query_tei_addr_info_t) + bm_len, IOT_PLC_LIB_MID); IOT_ASSERT(buf); // prepare a IOT_PLC_MSG_TEI_ADDR_INFO_QUERY message q = (iot_plc_query_tei_addr_info_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_TEI_ADDR_INFO_QUERY, req_id); q->start_tei = start_tei; q->offset = offset; q->bm_len = bm_len; os_mem_cpy(q->bm, bm, bm_len); iot_pkt_put(buf, sizeof(*q) + bm_len); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } uint32_t iot_plc_set_tx_power_cap(iot_plc_app_h handle, uint8_t req_id, uint8_t *hplc_power, int8_t *rf_power) { uint8_t hplc_valid = 0, rf_valid = 0; iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_tx_power_cap_set_t *q = NULL; app = handle; if (hplc_power && ((*hplc_power >= IOT_PLC_HPLC_TX_POWER_MIN_DBUV && *hplc_power <= IOT_PLC_HPLC_TX_POWER_MAX_DBUV) || (*hplc_power == 0))) { hplc_valid = 1; } if (rf_power && ((*rf_power >= IOT_PLC_RF_TX_POWER_MIN_DBM && *rf_power <= IOT_PLC_RF_TX_POWER_MAX_DBM) || (*rf_power == IOT_PLC_RF_TX_POWER_INVALID))) { rf_valid = 1; } if (!hplc_valid && !rf_valid) { return ERR_FAIL; } os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); /* prepare a IOT_PLC_MSG_TX_POWER_CAP_SET message */ q = (iot_plc_tx_power_cap_set_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_TX_POWER_CAP_SET, req_id); if (hplc_valid) { q->hplc_valid = 1; q->hplc_power = *hplc_power; } if (rf_valid) { q->rf_valid = 1; q->rf_power = *rf_power; } iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); return ERR_OK; } void iot_plc_tsfm_state_change(iot_plc_app_h handle, uint8_t req_id, uint8_t state, uint8_t *tsfm_addr, uint8_t wl_notify_enable, uint8_t zc_notify_enable, uint16_t *net_lock_time, uint16_t *abn_lock_time, uint16_t unlock_delay) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_tsfm_change_req_t *req; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); // prepare a IOT_PLC_MSG_TSFM_CHANGE message req = (iot_plc_tsfm_change_req_t*)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_TSFM_CHANGE, req_id); req->state = state; req->wl_notify_enable = !!wl_notify_enable; req->zc_notify_enable = !!zc_notify_enable; req->unlock_delay = unlock_delay; if (tsfm_addr) { req->tfsm_addr_valid = 1; iot_mac_addr_cpy(req->tfsm_addr, tsfm_addr); } else { req->tfsm_addr_valid = 0; os_mem_set(req->tfsm_addr, 0, sizeof(req->tfsm_addr)); } if (net_lock_time && abn_lock_time) { req->lock_time_valid = 1; req->net_lock_time = *net_lock_time; req->abn_lock_time = *abn_lock_time; } else { req->lock_time_valid = 0; req->net_lock_time = 0; req->abn_lock_time = 0; } os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } void iot_plc_query_local_phase(iot_plc_app_h handle, uint8_t req_id) { iot_plc_query(handle, req_id, IOT_PLC_MSG_PHASE_QUERY); } void iot_plc_zc_collect(iot_plc_app_h handle, uint8_t req_id, uint32_t start_ntb, uint8_t cnt) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_zc_collect_req_t *req; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); /* prepare a IOT_PLC_MSG_ZC_CLCT_REQ message */ req = (iot_plc_zc_collect_req_t*)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_ZC_CLCT_REQ, req_id); req->start_ntb = start_ntb; req->clct_cnt = cnt; os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } void iot_plc_query_band_bitmap(iot_plc_app_h handle, uint8_t req_id, uint8_t is_scan_band) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_query_band_bitmap_t *q = NULL; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); /* prepare a IOT_PLC_MSG_QUERYBAND_BITMAP message */ q = (iot_plc_query_band_bitmap_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_QUERYBAND_BITMAP, req_id); q->is_scan_band = is_scan_band; iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } void iot_plc_set_rate_adapt_mode(iot_plc_app_h handle, uint8_t req_id, uint8_t target_node, uint8_t rate_adapt_mode, uint8_t fixed_rate_level) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_set_rate_adapt_mode_req_t *q = NULL; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(PLC_LIB_MSG_SHORT_BUF_SIZE, IOT_PLC_LIB_MID); IOT_ASSERT(buf); /* prepare an IOT_PLC_MSG_SET_RATE_ADAPT_MODE_REQ message */ q = (iot_plc_set_rate_adapt_mode_req_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_SET_RATE_ADAPT_MODE_REQ, req_id); q->target_node = target_node; q->rate_adapt_mode = rate_adapt_mode; q->fixed_rate_level = fixed_rate_level; iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } void iot_plc_set_authrz_dak(iot_plc_app_h handle, uint8_t req_id, iot_plc_authrz_dak_set_req_t *dak) { iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_authrz_dak_set_req_t *q = NULL; uint32_t len; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } len = (dak->count * sizeof(iot_plc_dak_mac_pair_t)) + sizeof(*dak); buf = iot_ipc_pkt_alloc(len, IOT_PLC_LIB_MID); IOT_ASSERT(buf); /* prepare an IOT_PLC_MSG_AUTH_DAK_SET_REQ message */ q = (iot_plc_authrz_dak_set_req_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_AUTH_DAK_SET_REQ, req_id); os_mem_cpy(q, dak, len); iot_pkt_put(buf, len); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } uint8_t iot_plc_get_link_load() { extern uint8_t mac_get_csma_token_usage_rate(); extern uint8_t mac_get_rf_csma_token_usage_rate(); uint8_t hplc_rate = mac_get_csma_token_usage_rate(); uint8_t rf_rate = mac_get_rf_csma_token_usage_rate(); return max(hplc_rate, rf_rate); } void iot_plc_get_link_statistics(iot_plc_link_statistics_t *stat) { extern void cvg_app_get_link_statistics( iot_plc_link_statistics_t *stat); cvg_app_get_link_statistics(stat); } uint8_t iot_plc_get_comm_type() { if (HPLC_RF_DEV_SUPPORT) { return IOT_PLC_COMM_TYPE_DUAL_MODE; } return IOT_PLC_COMM_TYPE_HPLC; } void iot_plc_set_rf_scan_tbl(iot_plc_app_h handle, uint8_t req_id, iot_plc_rf_scan_t *rf_scan_tbl, uint8_t rf_cnt) { IOT_ASSERT(rf_scan_tbl && rf_cnt && rf_cnt <= IOT_PLC_RF_SCAN_TBL_MAX); iot_pkt_t *buf; iot_plc_app_t *slot, *app; iot_plc_set_rf_scan_tbl_t *q = NULL; app = handle; os_acquire_mutex(p_plc_lib->lock); /* check if app id is already registered */ slot = plc_lib_find_app(app->app_id); if (slot == NULL || slot != app) { /* application not registered */ IOT_ASSERT(0); } buf = iot_ipc_pkt_alloc(sizeof(iot_plc_msg_header_t) + sizeof(iot_plc_set_rf_scan_tbl_t), IOT_PLC_LIB_MID); IOT_ASSERT(buf); /* prepare a IOT_PLC_MSG_RF_SCAN_TBL_SET message */ q = (iot_plc_set_rf_scan_tbl_t *)plc_lib_prep_msg(buf, app->app_id, IOT_PLC_MSG_RF_SCAN_TBL_SET, req_id); os_mem_cpy(q->rf_scan_tbl, rf_scan_tbl, rf_cnt * sizeof(iot_plc_rf_scan_t)); iot_pkt_put(buf, sizeof(*q)); os_release_mutex(p_plc_lib->lock); iot_ipc_send(p_plc_lib->ipc_h, &plc_stack_addr, buf); } uint8_t iot_plc_get_local_nf() { extern uint8_t phy_chn_nf_get(); return phy_chn_nf_get(); } #endif /* PLC_SUPPORT_CCO_ROLE || PLC_SUPPORT_STA_ROLE */