4349 lines
142 KiB
C
Executable File
4349 lines
142 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_cco_api.h"
|
|
#include "iot_plc_sta_api.h"
|
|
#include "iot_module_api.h"
|
|
#include "iot_queue_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_io_api.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_uart_api.h"
|
|
#include "iot_utils_api.h"
|
|
#include "iot_task_api.h"
|
|
#include "iot_version_api.h"
|
|
#include "iot_board_api.h"
|
|
#include "iot_plc_led_api.h"
|
|
|
|
#include "iot_grapp.h"
|
|
#include "iot_plctxrx.h"
|
|
#include "iot_proto_common.h"
|
|
#include "iot_proto_ge.h"
|
|
|
|
#if IOT_GE_AES_ENABLE
|
|
#include "iot_crypto_aes_api.h"
|
|
#endif
|
|
|
|
#if IOT_GR_APP_ENABLE
|
|
|
|
#if (IOT_PSRAM_ENABLE)
|
|
#define IOT_PLCTXRX_LIST_NODE_NUM 128
|
|
#else
|
|
#define IOT_PLCTXRX_LIST_NODE_NUM 40
|
|
#endif
|
|
|
|
/* min retry send. unit is ms */
|
|
#define IOT_PLCTXRX_RETRY_MIN_INTV 10
|
|
|
|
/* at send data packet limit size */
|
|
#define IOT_PLCTXRX_MAX_SZ 255
|
|
|
|
/* const, max cached cmd cnt */
|
|
#define IOT_PLCTXRX_CMD_MAX_CNT 32
|
|
|
|
/* snr good minimum threshold, below this value is weak */
|
|
#define IOT_SNR_GOOD_MIN_THR (5)
|
|
/* snr strong minimum threshold */
|
|
#define IOT_SNR_STRONG_MIN_THR (20)
|
|
|
|
#if (HW_PLATFORM == HW_PLATFORM_SIMU)
|
|
extern uint8_t ucIsClientMode;
|
|
#endif
|
|
|
|
iot_mem_pool_t *list_mem_pool;
|
|
extern greeplc_app_t *greeapp;
|
|
|
|
/* statistic on gree frame */
|
|
uint32_t g_gree_frm_cnt;
|
|
uint32_t g_gree_frm_total_len;
|
|
|
|
/* plctxrx global context */
|
|
plctxrx_contxt_t plctxrx_context;
|
|
|
|
/* proto pkt cache buffer */
|
|
prot_pkt_t gbl_protpkt[TXRX_SEND_BUFF_POOL_NUM];
|
|
|
|
/* cmd cache buffer */
|
|
plctxrx_cmdsave_node_t g_cmdhandle_node[IOT_PLCTXRX_CMD_MAX_CNT];
|
|
|
|
void iot_common_bin_dump(uint8_t *data, uint32_t dlen);
|
|
|
|
/* arguments of cmd_type, it's the source of current command.*/
|
|
void
|
|
plctxrx_cmd_msg_handle(iot_pkt_t *arg_pkt);
|
|
|
|
/* response upper layer the query */
|
|
void
|
|
plctxrx_cmd_resp_data_pkt(uint8_t handle_next, uint8_t oper_code,
|
|
iot_pkt_t *pkt);
|
|
|
|
/* prepare response pkt to upper */
|
|
void
|
|
plctxrx_cmd_resp_data(uint8_t cmd_id, uint8_t oper_code,
|
|
plctxrx_resp_idx_t *index, uint16_t resp, void *data, uint16_t data_len);
|
|
|
|
/* cmd saveq handle - pop */
|
|
plctxrx_cmdsave_node_t *
|
|
iot_plctxrx_commandnode_pop_front(plctxrx_cmdsave_list_t *cmdq,
|
|
cmd_queue_e_t qtype);
|
|
plctxrx_cmdsave_node_t *
|
|
iot_plctxrx_commandnode_get_front(plctxrx_cmdsave_list_t *cmdq,
|
|
cmd_queue_e_t qtype);
|
|
|
|
/* cmd saveq handle - push */
|
|
void
|
|
iot_plctxrx_commandnode_push_backend(plctxrx_cmdsave_list_t *cmdq,
|
|
list_node_t *node, cmd_queue_e_t qtype);
|
|
|
|
/* allocte a conn_less_msdu, then fill the msdu pkt with
|
|
* conn_less mode config data
|
|
*/
|
|
uint8_t iot_dev_test_send_mode_config(dev_test_mode_cfg_t *cfg)
|
|
{
|
|
uint16_t buflen = 0;
|
|
uint8_t *ptr = NULL;
|
|
iot_pkt_t *msdu_pkt;
|
|
uint8_t dest_mac[IOT_MAC_ADDR_LEN] = { 0 };
|
|
|
|
iot_set_bcast_mac(dest_mac);
|
|
|
|
buflen = sizeof(dev_test_mode_cfg_t);
|
|
|
|
msdu_pkt = iot_plc_alloc_conn_less_msdu(greeapp->app_handle,
|
|
IOT_PLC_MSG_TYPE_CONN_LESS_CMD, dest_mac,
|
|
plctxrx_context.local_state.sta_mac, plctxrx_context.link_id,
|
|
buflen, IOT_PLC_LOCAL_RETRY_CNT);
|
|
|
|
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);
|
|
os_mem_cpy(ptr, cfg, buflen);
|
|
|
|
iot_cus_printf("send mode config to [%02x:%02x:%02x:%02x:%02x:%02x]"
|
|
" band id-%lu, duration-%lu sec, mask-%lu\n",
|
|
dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3],dest_mac[4],
|
|
dest_mac[5], cfg->band_id, cfg->dur, cfg->target_id_mask);
|
|
iot_plc_send_msdu(greeapp->app_handle, msdu_pkt);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* check the conn_less pkt infor bufer every 500ms */
|
|
static void iot_plctxrx_conn_less_buf_refresh(void)
|
|
{
|
|
uint8_t i;
|
|
plcs_conn_less_pkt_info_t *pkt_info = NULL;
|
|
|
|
if (0 == plctxrx_context.used_buf_cnt) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT; i++) {
|
|
pkt_info = &plctxrx_context.conn_less_buf[i];
|
|
if (pkt_info->span_cnt >= IOT_PLCTXRX_CONN_LESS_PKT_SPAN_CNT) {
|
|
if (plctxrx_context.used_buf_cnt > 0) {
|
|
plctxrx_context.used_buf_cnt--;
|
|
}
|
|
iot_cus_printf("[gltx]conn_less pkt info[%d] is cleared, used "
|
|
"buf cnt[%d]\n", pkt_info->msdu_sn,
|
|
plctxrx_context.used_buf_cnt);
|
|
os_mem_set(pkt_info, 0, sizeof(*pkt_info));
|
|
} else {
|
|
if (pkt_info->msdu_sn != 0) {
|
|
pkt_info->span_cnt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void iot_plctxrx_conn_less_pkt_info_save(uint16_t sn, uint8_t *mac)
|
|
{
|
|
uint8_t i;
|
|
plcs_conn_less_pkt_info_t *pkt_info = NULL;
|
|
|
|
if ((0 == sn) || !iot_mac_addr_valid(mac)) {
|
|
iot_cus_printf("[gltx]invalid input param: sn %d", sn);
|
|
return ;
|
|
}
|
|
|
|
if (plctxrx_context.used_buf_cnt >= IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT) {
|
|
iot_cus_printf("[gltx]no slot for new a conn_less pkt info.\n");
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT; i++) {
|
|
pkt_info = &plctxrx_context.conn_less_buf[i];
|
|
/* msdu_sn== 0 means the buf can be used */
|
|
if (0 == pkt_info->msdu_sn) {
|
|
pkt_info->msdu_sn = sn;
|
|
iot_mac_addr_cpy(pkt_info->src_mac, mac);
|
|
pkt_info->span_cnt = 0;
|
|
if (plctxrx_context.used_buf_cnt <
|
|
IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT) {
|
|
plctxrx_context.used_buf_cnt++;
|
|
}
|
|
|
|
iot_cus_printf("[gltx]conn_less pkt[%d] info saved, used buf[%d]"
|
|
"\n", sn, plctxrx_context.used_buf_cnt);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool_t iot_plctxrx_conn_less_rpt_check(uint16_t sn, uint8_t *mac)
|
|
{
|
|
uint8_t i;
|
|
bool_t need_rpt = false;
|
|
plcs_conn_less_pkt_info_t *pkt_info = NULL;
|
|
|
|
if ((0 == sn) || !iot_mac_addr_valid(mac)) {
|
|
iot_cus_printf("invalid input param: sn %d\n", sn);
|
|
return need_rpt;
|
|
}
|
|
|
|
for (i = 0; i < IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT; i++) {
|
|
pkt_info = &plctxrx_context.conn_less_buf[i];
|
|
if ((sn == pkt_info->msdu_sn) &&
|
|
(iot_mac_addr_cmp(mac, pkt_info->src_mac))) {
|
|
need_rpt = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= IOT_PLCTXRX_CONN_LESS_PKT_BUF_CNT) {
|
|
need_rpt = true;
|
|
/* if a new pkt received, store into infor buffer */
|
|
iot_plctxrx_conn_less_pkt_info_save(sn, mac);
|
|
}
|
|
|
|
return need_rpt;
|
|
}
|
|
|
|
|
|
uint8_t iot_plctxrx_list_init(void)
|
|
{
|
|
//iot_cus_printf("[gltx]rptlist num:%d\n",IOT_PLCTXRX_LIST_NODE_NUM);
|
|
if (iot_mem_pool_new(IOT_GREE_APP_MID,IOT_PLCTXRX_LIST_NODE_NUM,
|
|
sizeof(list_node_t), &list_mem_pool, 1)) {
|
|
iot_cus_printf("[gltx]mem pool init fail.\n");
|
|
return ERR_FAIL;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
void iot_plctxrx_list_free(protpkt_list_t *list)
|
|
{
|
|
list_node_t *node, *next;
|
|
|
|
if (!list->list_head)
|
|
{
|
|
iot_cus_printf("[gltx]list empty\n");
|
|
return;
|
|
}
|
|
node = list->list_head;
|
|
while (node) {
|
|
next = node->next;
|
|
iot_mem_pool_free(list_mem_pool, node);
|
|
node = next;
|
|
}
|
|
}
|
|
|
|
void iot_plctxrx_queue_init(prot_pktq_t *queue)
|
|
{
|
|
queue->list_head = NULL;
|
|
queue->list_tail = NULL;
|
|
queue->depth = 0;
|
|
}
|
|
|
|
uint8_t iot_plctxrx_queue_empty_check(prot_pktq_t *queue) {
|
|
|
|
uint32_t depth;
|
|
|
|
/* TODO : 32bits get is atomic opcode. Not need mutex. */
|
|
os_acquire_mutex(queue->lock);
|
|
depth = queue->depth;
|
|
os_release_mutex(queue->lock);
|
|
|
|
iot_cus_printf("[gltx]depth:%d\n",depth);
|
|
|
|
return (depth > 0) ? ERR_OK : ERR_FAIL;
|
|
}
|
|
|
|
/* push in tail/backend */
|
|
void iot_plctxrx_pkt_enqueue(prot_pktq_t *queue, list_node_t *pkt)
|
|
{
|
|
IOT_ASSERT(pkt->next == NULL);
|
|
|
|
os_acquire_mutex(queue->lock);
|
|
|
|
|
|
if (queue->list_head== NULL) {
|
|
queue->list_head = pkt;
|
|
}
|
|
|
|
if (queue->list_tail) {
|
|
IOT_ASSERT(queue->list_head);
|
|
queue->list_tail->next = pkt;
|
|
}
|
|
queue->list_tail = pkt;
|
|
queue->depth++;
|
|
os_release_mutex(queue->lock);
|
|
}
|
|
|
|
/* pop from head/front */
|
|
list_node_t *iot_plctxrx_pkt_dequeue(prot_pktq_t *queue)
|
|
{
|
|
list_node_t *entry = NULL;
|
|
|
|
os_acquire_mutex(queue->lock);
|
|
if (queue->list_head) {
|
|
IOT_ASSERT(queue->list_tail);
|
|
queue->depth--;
|
|
entry = queue->list_head;
|
|
if (queue->list_head == queue->list_tail) {
|
|
queue->list_head = NULL;
|
|
queue->list_tail = NULL;
|
|
} else {
|
|
queue->list_head = queue->list_head->next;
|
|
}
|
|
entry->next = NULL;
|
|
} else {
|
|
IOT_ASSERT(queue->list_tail == NULL);
|
|
}
|
|
os_release_mutex(queue->lock);
|
|
|
|
return entry;
|
|
}
|
|
|
|
|
|
int16_t iot_plctxrx_get_sta_indx_by_mac(uint8_t *mac)
|
|
{
|
|
uint16_t indx;
|
|
for (indx = 0; indx < STA_DEV_MAX; indx++) {
|
|
if (iot_mac_addr_cmp(mac, plctxrx_context.sta[indx].sta_mac)) {
|
|
return indx;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
uint8_t *iot_plctxrx_get_mac_by_tei(uint16_t tei)
|
|
{
|
|
uint16_t indx;
|
|
for (indx = 0; indx < plctxrx_context.cur_stanum; indx++) {
|
|
if (plctxrx_context.sta[indx].sta_tei == tei) {
|
|
return plctxrx_context.sta[indx].sta_mac;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void iot_plctxrx_timer_reset(timer_id_t task_timer, uint32_t period)
|
|
{
|
|
if (os_is_timer_active(task_timer)) {
|
|
os_stop_timer(task_timer);
|
|
}
|
|
|
|
os_start_timer(task_timer, period);
|
|
}
|
|
|
|
static void iot_plctxrx_recvd_pktseq_update(iot_plc_msdu_recv_t *msdu_pkt)
|
|
{
|
|
msdu_pkt_hdr_t *pkthdr = NULL;
|
|
uint8_t *ptr = NULL;
|
|
uint16_t i = 0;
|
|
uint8_t *mac = NULL;
|
|
|
|
ptr = msdu_pkt->data;
|
|
pkthdr = (msdu_pkt_hdr_t *)ptr;
|
|
|
|
for (i = 0; i < STA_DEV_MAX; i++) {
|
|
if (!plctxrx_context.sta[i].valid) {
|
|
continue;
|
|
}
|
|
mac = plctxrx_context.sta[i].sta_mac;
|
|
/* if the msdu src mac is the sta's mac, update the msdu seq */
|
|
if (iot_mac_addr_cmp(mac, msdu_pkt->src)) {
|
|
iot_cus_printf("[gltx]sta:%d update_msdu:%d\n", i,
|
|
pkthdr->msdusend_seq);
|
|
plctxrx_context.sta[i].lastrcv_msduseq = pkthdr->msdusend_seq;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= STA_DEV_MAX) {
|
|
iot_cus_printf("[gltx][err]msduseq [%d] update failed for mac"
|
|
" mismatch\n", pkthdr->msdusend_seq);
|
|
}
|
|
|
|
}
|
|
|
|
uint8_t iot_plctxrx_msdu_type_check(iot_plc_msdu_recv_t *msdu)
|
|
{
|
|
msdu_pkt_hdr_t *pkthdr = NULL;
|
|
uint8_t *ptr = NULL;
|
|
uint8_t ret;
|
|
|
|
ptr = msdu->data;
|
|
pkthdr = (msdu_pkt_hdr_t *)ptr;
|
|
|
|
if ( pkthdr->recvconf_seq != 0) {
|
|
ret = PLCTXRX_TYPE_ACK;
|
|
} else {
|
|
ret = PLCTXRX_TYPE_DATA;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
uint8_t iot_plctxrx_push_aggred_pkt_to_sendq(prot_pktq_t *queue)
|
|
{
|
|
prot_pkt_t *prot_pkt = NULL;
|
|
prot_pkt_t *send_pkt = NULL;
|
|
|
|
prot_pkt = plctxrx_context.aggrpkt;
|
|
|
|
if (prot_pkt == NULL) {
|
|
iot_cus_printf("[gltx]aggrtimer no aggr pkt\n");
|
|
return ERR_OK;
|
|
}
|
|
prot_pkt->send_cnt = 0;
|
|
/* old aggr pkt will send. no aggrpkt cached now */
|
|
plctxrx_context.aggrpkt = NULL;
|
|
/* in send queue, push backend */
|
|
iot_plctxrx_pkt_enqueue(queue, (list_node_t*)prot_pkt);
|
|
|
|
switch (prot_pkt->txinfo.send_type) {
|
|
case PLCTXRX_UNICAST:
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt++;
|
|
break;
|
|
case PLCTXRX_BORADCAST:
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt++;
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
|
|
/* get front of sendq. note: may not the aggr pkt in queue upper */
|
|
send_pkt = (prot_pkt_t *)plctxrx_context.sendq->list_head;
|
|
|
|
iot_cus_printf("[gltx]pushed into the queue "
|
|
"sendq:%d, freeq:%d, sendpkt:0x%x sendcnt:%d\n",
|
|
plctxrx_context.sendq->depth, plctxrx_context.freeq->depth, send_pkt,
|
|
send_pkt->send_cnt);
|
|
|
|
/* if first send, trigger send */
|
|
if (send_pkt->send_cnt == 0) {
|
|
iot_plctxrx_msdu_send(send_pkt);
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint8_t iot_plctxrx_msdu_duplicate_check(iot_plc_msdu_recv_t *pkt)
|
|
{
|
|
msdu_pkt_hdr_t *pkthdr = NULL;
|
|
uint8_t *ptr = NULL;
|
|
uint8_t isdup = 0;
|
|
uint8_t *mac = NULL;
|
|
uint16_t i = 0;
|
|
|
|
ptr = pkt->data;
|
|
pkthdr = (msdu_pkt_hdr_t *)ptr;
|
|
|
|
for (i = 0; i < STA_DEV_MAX; i++) {
|
|
if (!plctxrx_context.sta[i].valid) {
|
|
continue;
|
|
}
|
|
mac = plctxrx_context.sta[i].sta_mac;
|
|
if (iot_mac_addr_cmp(mac, pkt->src)) {
|
|
if (plctxrx_context.sta[i].lastrcv_msduseq == pkthdr->msdusend_seq) {
|
|
iot_cus_printf("[gltx]dupcheck failed mac:%x:%x:%x:%x:%x:%x(%d)\n"
|
|
,mac[0],mac[1],mac[2],mac[3], mac[4], mac[5],
|
|
plctxrx_context.sta[i].lastrcv_msduseq);
|
|
isdup = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isdup) {
|
|
iot_cus_printf("[gltx]dupcheck pass stanum:%d\n",
|
|
plctxrx_context.cur_stanum);
|
|
}
|
|
|
|
return isdup;
|
|
}
|
|
|
|
#if IOT_GE_AES_ENABLE
|
|
|
|
#define iot_grapp_aes_get_len(x) (((x) + 0xF) & (~0xF))
|
|
#define iot_grapp_aes_get_key(key, dest_mac, seq) do{ \
|
|
os_mem_cpy(key, dest_mac, IOT_MAC_ADDR_LEN); \
|
|
key[6] = (seq >> 8) & 0xFF; \
|
|
key[7] = seq & 0xFF; } while(0)
|
|
|
|
/* a complete PKT structure is shown below
|
|
* |_iot_pkt_t_|_resv_|_iot_plc_msg_header_t_|_iot_plc_msdu_send_t_|_msdu_pkt_hdr_t_|_cmd_|
|
|
* we just encrypt msdu_pkt_hdr_t and cmd
|
|
*/
|
|
static uint8_t iot_plctxrx_aes_encrypt(iot_pkt_t *pkt, uint16_t len)
|
|
{
|
|
uint8_t *ptr = NULL;
|
|
msdu_pkt_hdr_t *hdr_msdu_pkt = NULL;
|
|
iot_plc_msdu_send_t *hdr_msdu_send = NULL;
|
|
uint16_t buffer_len,data_len;
|
|
uint8_t delta_len = 0;
|
|
uint8_t destmac_to_key[16] = {0};
|
|
uint8_t i;
|
|
uint8_t *encrypt_buffer = NULL;
|
|
|
|
if (!greeapp->aes.enable) {
|
|
goto out;
|
|
}
|
|
ptr = iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL);
|
|
hdr_msdu_pkt = (msdu_pkt_hdr_t*)ptr;
|
|
hdr_msdu_pkt->aes_encrypt = 1;
|
|
ptr += sizeof(msdu_pkt_hdr_t);
|
|
hdr_msdu_send = (iot_plc_msdu_send_t *)
|
|
(iot_pkt_data(pkt) + sizeof(iot_plc_msg_header_t));
|
|
/* The data length cannot be encrypted, otherwise it will cause crash
|
|
* when the receiving module is not decrypted
|
|
*/
|
|
data_len = len - 1;
|
|
/* AES processes data in blocks of 16 bytes,
|
|
* meaning less than 16 bytes need to be filled
|
|
*/
|
|
buffer_len = iot_grapp_aes_get_len(data_len);
|
|
encrypt_buffer = os_mem_malloc(IOT_GREE_APP_MID, buffer_len);
|
|
if (encrypt_buffer == NULL) {
|
|
iot_cus_printf("[gltx]memory malloc failed, aes encrypt failed\n");
|
|
goto out;
|
|
}
|
|
os_mem_set(encrypt_buffer, 0, buffer_len);
|
|
|
|
delta_len = buffer_len - data_len;
|
|
ptr[0] += delta_len;
|
|
hdr_msdu_pkt->aes_padding = delta_len;
|
|
os_mem_cpy(encrypt_buffer, ptr + 1, data_len);
|
|
iot_grapp_aes_get_key(destmac_to_key, hdr_msdu_pkt->dst_mac,
|
|
hdr_msdu_pkt->msdusend_seq);
|
|
iot_crypto_aes_setkey_enc(destmac_to_key, 128);
|
|
for (i = 0; i < (buffer_len / 16); i++) {
|
|
iot_crypto_aes_ecb(IOT_AES_ENCRYPT, buffer_len,
|
|
&encrypt_buffer[i*16], &encrypt_buffer[i*16]);
|
|
}
|
|
|
|
os_mem_cpy(ptr + 1, encrypt_buffer, buffer_len);
|
|
hdr_msdu_send->len += delta_len;
|
|
os_mem_free(encrypt_buffer);
|
|
out:
|
|
return delta_len;
|
|
}
|
|
|
|
static bool_t iot_plctxrx_aes_decrypt(iot_pkt_t *pkt)
|
|
{
|
|
uint8_t *ptr = NULL;
|
|
msdu_pkt_hdr_t *hdr_msdu_pkt = NULL;
|
|
iot_plc_msdu_recv_t *hdr_msdu_recv= NULL;
|
|
uint16_t buffer_len,data_len;
|
|
uint8_t delta_len = 0;
|
|
uint8_t destmac_to_key[16] = {0};
|
|
uint8_t i;
|
|
proto_fn_code_e fn_list;
|
|
uint8_t *decrypt_buffer = NULL;
|
|
|
|
ptr = (uint8_t *)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
|
|
ptr += sizeof(iot_plc_msg_header_t);
|
|
hdr_msdu_recv = (iot_plc_msdu_recv_t *)(ptr);
|
|
ptr = hdr_msdu_recv->data;
|
|
hdr_msdu_pkt = (msdu_pkt_hdr_t*)ptr;
|
|
if (hdr_msdu_pkt->aes_encrypt) {
|
|
ptr = (uint8_t *)hdr_msdu_pkt + sizeof(msdu_pkt_hdr_t);
|
|
delta_len = hdr_msdu_pkt->aes_padding;
|
|
buffer_len = hdr_msdu_recv->len - sizeof(msdu_pkt_hdr_t) - 1;
|
|
data_len = buffer_len - delta_len;
|
|
decrypt_buffer = os_mem_malloc(IOT_GREE_APP_MID, buffer_len);
|
|
if (decrypt_buffer == NULL) {
|
|
iot_cus_printf("[gltx]memory malloc failed, aes decrypt failed\n");
|
|
return false;
|
|
}
|
|
os_mem_set(decrypt_buffer, 0, buffer_len);
|
|
|
|
os_mem_cpy(decrypt_buffer, ptr + 1, buffer_len);
|
|
iot_grapp_aes_get_key(destmac_to_key, hdr_msdu_pkt->dst_mac,
|
|
hdr_msdu_pkt->msdusend_seq);
|
|
iot_crypto_aes_setkey_enc(destmac_to_key, 128);
|
|
for (i = 0; i < (buffer_len / 16); i++) {
|
|
iot_crypto_aes_ecb(IOT_AES_DECRYPT, buffer_len,
|
|
&decrypt_buffer[i*16], &decrypt_buffer[i*16]);
|
|
}
|
|
os_mem_cpy(ptr + 1, decrypt_buffer, data_len);
|
|
hdr_msdu_recv->len -= delta_len;
|
|
ptr[0] -= delta_len;
|
|
os_mem_free(decrypt_buffer);
|
|
|
|
/* returns true if decryption succeeds */
|
|
for (fn_list = PROTO_FNCODE_MIN;
|
|
fn_list < PROTO_FNCODE_MAX; fn_list++) {
|
|
if (ptr[1] == fn_list) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#else
|
|
static uint8_t iot_plctxrx_aes_encrypt(iot_pkt_t *pkt, uint16_t len)
|
|
{
|
|
(void)pkt;
|
|
(void)len;
|
|
return 0;
|
|
}
|
|
|
|
static bool_t iot_plctxrx_aes_decrypt(iot_pkt_t *pkt)
|
|
{
|
|
(void)pkt;
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
|
|
void iot_plctxrx_send_msdu_to_plc(iot_pkt_t *msdu_pkt, prot_pkt_t *prot_pkt,
|
|
bool_t is_unicast, uint8_t *dst_mac, uint16_t buf_len)
|
|
{
|
|
uint8_t *ptr = NULL;
|
|
msdu_pkt_hdr_t *hdr = NULL;
|
|
|
|
IOT_ASSERT(msdu_pkt);
|
|
|
|
ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
|
|
hdr = (msdu_pkt_hdr_t*)ptr;
|
|
hdr->msdusend_seq = prot_pkt->msdu_seq;
|
|
hdr->recvconf_seq = 0;
|
|
if (is_unicast) {
|
|
hdr->dest_cnt = 1;
|
|
} else {
|
|
hdr->dest_cnt = 0xFF;
|
|
}
|
|
hdr->need_ack = prot_pkt->txinfo.need_ack;
|
|
hdr->src_module = prot_pkt->txinfo.src_module;
|
|
|
|
iot_mac_addr_cpy(hdr->org_mac, prot_pkt->txinfo.org_mac);
|
|
iot_mac_addr_cpy(hdr->src_mac, prot_pkt->txinfo.src_mac);
|
|
iot_mac_addr_cpy(hdr->dst_mac, dst_mac);
|
|
|
|
ptr += sizeof(msdu_pkt_hdr_t);
|
|
os_mem_cpy(ptr, prot_pkt->buf, prot_pkt->msdu_data_len);
|
|
|
|
buf_len += iot_plctxrx_aes_encrypt(msdu_pkt, prot_pkt->msdu_data_len);
|
|
|
|
iot_pkt_put(msdu_pkt, sizeof(uint8_t)*buf_len);
|
|
iot_cus_printf("[gltx]unicast=%d, send msduseq:%d len:%d, ack_flag:%d, "
|
|
"sendcnt:%d\n", is_unicast, prot_pkt->msdu_seq, buf_len,
|
|
prot_pkt->ack_flag, prot_pkt->send_cnt);
|
|
iot_cus_printf("[gltx]unicast=%d,send:"
|
|
"pkt_dest_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
|
|
is_unicast, dst_mac[0], dst_mac[1], dst_mac[2],
|
|
dst_mac[3], dst_mac[4], dst_mac[5]);
|
|
iot_plc_send_msdu(greeapp->app_handle, msdu_pkt);
|
|
}
|
|
|
|
/*
|
|
Please note, in plctxrx, sta always send to cco, no matter dest mac is cco
|
|
or other station. cco will judge handle or forward packet based on dest mac.
|
|
*/
|
|
uint8_t iot_plctxrx_msdu_unicast_send(prot_pkt_t *prot_pkt, uint8_t *dst_mac,
|
|
protpkt_tx_info_t* txinfo)
|
|
{
|
|
uint8_t msg_type;
|
|
uint16_t buflen = 0;
|
|
iot_pkt_t *msdu_pkt = NULL;
|
|
uint8_t *destptr = NULL;
|
|
|
|
buflen = sizeof(msdu_pkt_hdr_t) + prot_pkt->msdu_data_len;
|
|
|
|
/* check if the device of target destination mac address is online */
|
|
if (txinfo->force_tx_connless == 0) {
|
|
if (plctxrx_context.local_state.role == IOT_PLC_DEV_ROLE_CCO) {
|
|
if (!iot_plctxrx_check_sta_in_nw_by_mac(dst_mac)) {
|
|
txinfo->force_tx_connless = 1;
|
|
txinfo->retry_cnt = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (txinfo->force_tx_connless == 0) {
|
|
/* only first send set bitmap. retry not do this */
|
|
if (prot_pkt->send_cnt == 0 && txinfo->need_ack == 1) {
|
|
prot_pkt->ack_flag = 1;
|
|
} else if (txinfo->need_ack == 0) {
|
|
prot_pkt->ack_flag = 0;
|
|
}
|
|
if (plctxrx_context.nw_role == IOT_PLC_DEV_ROLE_CCO) {
|
|
destptr = dst_mac;
|
|
} else {
|
|
/* STA always send to CCO */
|
|
destptr = plctxrx_context.local_state.cco_mac;
|
|
}
|
|
msg_type = IOT_PLC_MSG_TYPE_UNICAST;
|
|
msdu_pkt = iot_plc_alloc_msdu(greeapp->app_handle,
|
|
msg_type, IOT_PLC_ACK_TYPE_NONE, destptr,
|
|
plctxrx_context.local_state.sta_mac,
|
|
plctxrx_context.link_id, buflen, IOT_PLC_LOCAL_RETRY_CNT);
|
|
} else {
|
|
prot_pkt->ack_flag = 0;
|
|
txinfo->need_ack = 0;
|
|
destptr = dst_mac;
|
|
msg_type = IOT_PLC_MSG_TYPE_CONN_LESS_DATA;
|
|
msdu_pkt = iot_plc_alloc_conn_less_msdu(greeapp->app_handle,
|
|
msg_type, destptr, plctxrx_context.local_state.sta_mac,
|
|
plctxrx_context.link_id, buflen, IOT_PLC_LOCAL_RETRY_CNT);
|
|
}
|
|
|
|
iot_plctxrx_send_msdu_to_plc(msdu_pkt, prot_pkt, true, dst_mac, buflen);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* only cco can send brdcast */
|
|
extern uint8_t ge_bcast_addr[];
|
|
int8_t iot_plctxrx_msdu_brdcast_send(prot_pkt_t *prot_pkt)
|
|
{
|
|
uint8_t msg_type;
|
|
uint16_t buflen = 0;
|
|
|
|
buflen = sizeof(msdu_pkt_hdr_t) + prot_pkt->msdu_data_len;
|
|
|
|
/* connect packet send */
|
|
if (prot_pkt->txinfo.force_tx_connless == 0) {
|
|
iot_pkt_t *msdu_pkt = NULL;
|
|
msg_type = IOT_PLC_MSG_TYPE_BCAST;
|
|
msdu_pkt = iot_plc_alloc_msdu(greeapp->app_handle,
|
|
msg_type, IOT_PLC_ACK_TYPE_NONE,NULL,
|
|
plctxrx_context.local_state.sta_mac,
|
|
plctxrx_context.link_id, buflen, 1);
|
|
IOT_ASSERT(msdu_pkt);
|
|
iot_plctxrx_send_msdu_to_plc(msdu_pkt, prot_pkt, false,
|
|
prot_pkt->txinfo.dst_mac, buflen);
|
|
}
|
|
/* connless packet send */
|
|
else {
|
|
iot_pkt_t *connless_msdu_pkt = NULL;
|
|
msg_type = IOT_PLC_MSG_TYPE_CONN_LESS_DATA;
|
|
connless_msdu_pkt = iot_plc_alloc_conn_less_msdu(greeapp->app_handle,
|
|
msg_type, ge_bcast_addr,
|
|
plctxrx_context.local_state.sta_mac,
|
|
plctxrx_context.link_id, buflen, 1);
|
|
IOT_ASSERT(connless_msdu_pkt);
|
|
iot_plctxrx_send_msdu_to_plc(connless_msdu_pkt, prot_pkt,
|
|
false, prot_pkt->txinfo.dst_mac, buflen);
|
|
}
|
|
|
|
prot_pkt->send_cnt++;
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint8_t iot_plctxrx_msdu_send(prot_pkt_t* prot_pkt)
|
|
{
|
|
int8_t ret = ERR_OK;
|
|
uint32_t send_type = prot_pkt->txinfo.send_type;
|
|
uint8_t *destptr = NULL;
|
|
uint8_t i;
|
|
|
|
if (prot_pkt->send_cnt == 0) {
|
|
plctxrx_context.pktseq++;
|
|
if (plctxrx_context.pktseq == 0) {
|
|
plctxrx_context.pktseq = 1;
|
|
}
|
|
prot_pkt->msdu_seq =plctxrx_context.pktseq;
|
|
iot_cus_printf("[gltx]new seq alloced:%d\n",
|
|
prot_pkt->msdu_seq);
|
|
}
|
|
|
|
iot_cus_printf("[gltx]msdu send:send_type=%d,sta_cnt=%d,need ack=%d,"
|
|
"send cnt=%d,msdu_data_len=%d\n", send_type, prot_pkt->txinfo.sta_cnt,
|
|
prot_pkt->txinfo.need_ack, prot_pkt->send_cnt,prot_pkt->msdu_data_len);
|
|
|
|
if (send_type == PLCTXRX_BORADCAST) {
|
|
ret = iot_plctxrx_msdu_brdcast_send(prot_pkt);
|
|
if (ret == ERR_OK) {
|
|
plctxrx_context.local_state.txrx_status.msdu_sent_brd_cnt++;
|
|
}
|
|
} else {
|
|
if (prot_pkt->txinfo.sta_cnt == 1) {
|
|
plctxrx_context.local_state.txrx_status.msdu_sent_uni_cnt++;
|
|
}
|
|
for (i = 0; i< prot_pkt->txinfo.sta_cnt; i++) {
|
|
destptr = prot_pkt->txinfo.dst_mac + i * IOT_MAC_ADDR_LEN;
|
|
ret = iot_plctxrx_msdu_unicast_send(prot_pkt, destptr,\
|
|
&prot_pkt->txinfo);
|
|
if (ret != ERR_OK) {
|
|
break;
|
|
}
|
|
}
|
|
prot_pkt->send_cnt++;
|
|
}
|
|
/* if need ack or one more times retry needed,reset the timer */
|
|
if ((prot_pkt->txinfo.retry_cnt != 0) || ( prot_pkt->txinfo.need_ack)) {
|
|
if (prot_pkt->txinfo.retry_intvl == 0) {
|
|
prot_pkt->txinfo.retry_intvl = IOT_PLCXRX_RETRY_INTVAL_DEFAULT;
|
|
}
|
|
iot_plctxrx_timer_reset(plctxrx_context.datapath_timer,
|
|
prot_pkt->txinfo.retry_intvl);
|
|
iot_cus_printf("[gltx]retrytimer active intvl:%d\n",
|
|
prot_pkt->txinfo.retry_intvl);
|
|
} else {
|
|
iot_plctxrx_timer_reset(plctxrx_context.datapath_timer,
|
|
IOT_PLCTXRX_RETRY_MIN_INTV);
|
|
iot_cus_printf("[gltx]retrytimer active for sending "\
|
|
"whithout retry!\n");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void iot_plctxrx_msdu_retry_handle(prot_pkt_t* prot_pkt)
|
|
{
|
|
/* if the revievers need not send back ack, check the retry counter,
|
|
if the retry count don't equals the required counter, do retry!
|
|
otherwise, free the buffer, remove the pkt from the queue*/
|
|
|
|
list_node_t *node = NULL;
|
|
|
|
iot_cus_printf("[gltx][retry]protpkt seq:%d ackflag:%d sendcnt:%d max:%d "
|
|
"needack:%d\n", prot_pkt->msdu_seq, prot_pkt->ack_flag,
|
|
prot_pkt->send_cnt, prot_pkt->txinfo.retry_cnt,
|
|
prot_pkt->txinfo.need_ack);
|
|
|
|
if (prot_pkt->txinfo.need_ack == 0) {
|
|
if (prot_pkt->send_cnt < prot_pkt->txinfo.retry_cnt + 1) {
|
|
iot_plctxrx_msdu_send(prot_pkt);
|
|
} else {
|
|
switch (prot_pkt->txinfo.send_type) {
|
|
case PLCTXRX_UNICAST:
|
|
if(plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt){
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt--;
|
|
}
|
|
break;
|
|
case PLCTXRX_BORADCAST:
|
|
if(plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt){
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt--;
|
|
}
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
/* reaching the assigned retry times, free the pkt */
|
|
node = iot_plctxrx_pkt_dequeue(plctxrx_context.sendq);
|
|
if (NULL == node) {
|
|
iot_cus_printf("[gltx]dequeue failed!\n");
|
|
return;
|
|
}
|
|
|
|
iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, node);
|
|
/* send the next pkt in queue*/
|
|
iot_cus_printf("[gltx]retryout pkt. now sendq:%d freeq:%d\n",
|
|
plctxrx_context.sendq->depth,
|
|
plctxrx_context.freeq->depth);
|
|
if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
|
|
prot_pkt = (prot_pkt_t*)plctxrx_context.sendq->list_head;
|
|
iot_plctxrx_msdu_send(prot_pkt);
|
|
}
|
|
}
|
|
} else {
|
|
if ((prot_pkt->ack_flag != 0) &&
|
|
(prot_pkt->send_cnt < prot_pkt->txinfo.retry_cnt + 1)) {
|
|
iot_plctxrx_msdu_send(prot_pkt);
|
|
} else {
|
|
switch (prot_pkt->txinfo.send_type) {
|
|
case PLCTXRX_UNICAST:
|
|
if(plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt){
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt--;
|
|
}
|
|
break;
|
|
case PLCTXRX_BORADCAST:
|
|
if(plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt){
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt--;
|
|
}
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
node = iot_plctxrx_pkt_dequeue(plctxrx_context.sendq);
|
|
if (node == NULL) {
|
|
iot_cus_printf("[gltx]dequeue failed!\n");
|
|
return;
|
|
}
|
|
|
|
iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, node);
|
|
plctxrx_context.local_state.txrx_status.msdu_lost_pkt_cnt++;
|
|
iot_cus_printf("[gltx]retryout pkt forced free,"
|
|
"sendq:%d freeq:%d total lost:%d\n",
|
|
plctxrx_context.sendq->depth, plctxrx_context.freeq->depth,
|
|
plctxrx_context.local_state.txrx_status.msdu_lost_pkt_cnt);
|
|
|
|
/* send the next pkt in queue*/
|
|
if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
|
|
prot_pkt = (prot_pkt_t*)plctxrx_context.sendq->list_head;
|
|
iot_plctxrx_msdu_send(prot_pkt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void iot_plctxrx_msdu_ack_handle(iot_pkt_t* pkt)
|
|
{
|
|
msdu_pkt_hdr_t* pkthdr = NULL;
|
|
uint8_t *ptr;
|
|
prot_pkt_t *prot_pkt;
|
|
list_node_t *node = NULL;
|
|
|
|
iot_plc_msdu_recv_t *msdu =
|
|
(iot_plc_msdu_recv_t*)(iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA));
|
|
|
|
ptr = msdu->data;
|
|
pkthdr = (msdu_pkt_hdr_t*)ptr;
|
|
|
|
iot_cus_printf("[gltx]pkt[%d]'s ack received\n",
|
|
pkthdr->recvconf_seq);
|
|
|
|
prot_pkt = (prot_pkt_t*)plctxrx_context.sendq->list_head;
|
|
|
|
if (prot_pkt == NULL) {
|
|
iot_cus_printf("[gltx] no pkt in sendq\n");
|
|
goto out;
|
|
}
|
|
|
|
if (pkthdr->recvconf_seq != prot_pkt->msdu_seq) {
|
|
iot_cus_printf("[gltx] ackseq mismatch%d vs %d\n",
|
|
pkthdr->recvconf_seq, prot_pkt->msdu_seq);
|
|
goto out;
|
|
}
|
|
|
|
if (!iot_mac_addr_cmp(msdu->dst, plctxrx_context.local_state.sta_mac)) {
|
|
iot_cus_printf("[gltx]dest not for sta\n");
|
|
goto out;
|
|
} else {
|
|
/* once the msdu's dst mac matches with the local mac, clear up the
|
|
* ack flag to stop sending retry.
|
|
*/
|
|
prot_pkt->ack_flag = 0;
|
|
}
|
|
|
|
iot_cus_printf("[gltx]ackflag:%x\n", prot_pkt->ack_flag);
|
|
if (prot_pkt->ack_flag == 0) {
|
|
iot_cus_printf("[gltx]send done.\n");
|
|
switch (prot_pkt->txinfo.send_type) {
|
|
case PLCTXRX_UNICAST:
|
|
if (plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt) {
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt--;
|
|
}
|
|
break;
|
|
case PLCTXRX_BORADCAST:
|
|
if (plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt){
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt--;
|
|
}
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
/* delete the first node in sendq */
|
|
if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
|
|
node = iot_plctxrx_pkt_dequeue(plctxrx_context.sendq);
|
|
if (node == NULL) {
|
|
iot_cus_printf("[gltx]msdu_ack:dequeue failed!\n");
|
|
iot_pkt_free(pkt);
|
|
return;
|
|
}
|
|
iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, node);
|
|
iot_cus_printf("[gltx]sendq:%d freeq:%d,addr:%x\n",
|
|
plctxrx_context.sendq->depth, plctxrx_context.freeq->depth,
|
|
node);
|
|
}
|
|
|
|
/* send the next pkt in queue*/
|
|
if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
|
|
prot_pkt = (prot_pkt_t*)plctxrx_context.sendq->list_head;
|
|
iot_plctxrx_msdu_send(prot_pkt);
|
|
}
|
|
}
|
|
out:
|
|
iot_pkt_free(pkt);
|
|
}
|
|
|
|
/* based on msdu data buffer, filter out each gree frame, tag head and end
|
|
with one list chain. then, reprot to upper layer. after finsed call,
|
|
msdu buffer freed.
|
|
*/
|
|
uint8_t iot_plctxrx_msdu_split_frame_to_propkt(iot_pkt_t *msdu_pkt,
|
|
uint8_t rx_type)
|
|
{
|
|
uint16_t total_len;
|
|
uint8_t *ptr;
|
|
uint16_t frm_len;
|
|
uint16_t i;
|
|
uint8_t ret = ERR_FAIL;
|
|
list_node_t *node = NULL;
|
|
protpkt_list_t rpt_list = {NULL, 0, 0};
|
|
plctxrx_rx_data_info_t rx_info = { 0 };
|
|
|
|
node = iot_mem_pool_alloc(list_mem_pool);
|
|
if (node == NULL) {
|
|
iot_cus_printf("[gltx]list mem_pool alloc failed!\n");
|
|
goto out;
|
|
}
|
|
rpt_list.list_head = node;
|
|
rpt_list.frame_cnt = 0;
|
|
rpt_list.total_len = 0;
|
|
|
|
iot_plc_msdu_recv_t *msdu =
|
|
(iot_plc_msdu_recv_t*)(iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_DATA));
|
|
ptr = msdu->data + sizeof(msdu_pkt_hdr_t);
|
|
total_len = msdu->len - sizeof(msdu_pkt_hdr_t);
|
|
iot_cus_printf("[gltx]recv msdu len:%d\n",total_len);
|
|
|
|
IOT_ASSERT(total_len);
|
|
|
|
iot_mac_addr_cpy(rx_info.mac, msdu->src);
|
|
rx_info.rx_type = rx_type;
|
|
|
|
for (i = 0; i < total_len;) {
|
|
frm_len = iot_proto_get_plc_data_len(ptr + i, total_len - i);
|
|
if (frm_len == 0) {
|
|
iot_cus_printf("[gltx][err]frm_len err\n");
|
|
goto out;
|
|
}
|
|
iot_cus_printf("[gltx]fn:0x%x, frm_len=%d\n",*(ptr + i + 1), frm_len);
|
|
node->len = frm_len;
|
|
node->next = NULL;
|
|
node->data = ptr + i;
|
|
i += frm_len;
|
|
|
|
rpt_list.frame_cnt++;
|
|
rpt_list.total_len += frm_len;
|
|
if (i< total_len) {
|
|
node->next = iot_mem_pool_alloc(list_mem_pool);
|
|
if(node->next == NULL) {
|
|
iot_cus_printf("[gltx][err]list mem_pool alloc failed\n");
|
|
goto out;
|
|
}
|
|
node = node->next;
|
|
}
|
|
}
|
|
|
|
iot_cus_printf("[gltx] frame cnt:%d, total len:%d\n",
|
|
rpt_list.frame_cnt,rpt_list.total_len);
|
|
|
|
plctxrx_context.local_state.txrx_status.fram_report_cnt +=
|
|
rpt_list.frame_cnt;
|
|
|
|
if (greeapp->uart_mode == GR_MCU_OP_MODE) {
|
|
ret = plctxrx_context.gree_cb.gree_proto_recv_cb(&rpt_list, &rx_info);
|
|
} else {
|
|
ret = plctxrx_context.dev_test_cb.dev_test_recv_cb(&rpt_list, &rx_info);
|
|
}
|
|
|
|
out:
|
|
if (rpt_list.list_head != NULL) {
|
|
iot_plctxrx_list_free(&rpt_list);
|
|
}
|
|
iot_pkt_free(msdu_pkt);
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint8_t iot_plctxrx_msdu_frame_to_at(iot_pkt_t *msdu_pkt )
|
|
{
|
|
#if INCLUDE_AT_COMMAND_MODULE
|
|
uint8_t *p_data;
|
|
iot_pkt_t *p_pkt;
|
|
uint16_t pkt_len, data_len, total_len;
|
|
iot_plc_msdu_recv_t *p_plcmsdu;
|
|
plctxrx_cmd_resp_t *p_resp;
|
|
msdu_pkt_hdr_t *p_txrxmsduhr;
|
|
plctxrx_handle_recv_t *p_recv;
|
|
|
|
/* pkt format */
|
|
/* plcmsdu_hdr + txrxmsdu_hdr + at_hdr + at_hdr... */
|
|
|
|
if (NULL == msdu_pkt) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
p_plcmsdu = (iot_plc_msdu_recv_t *)iot_pkt_data(msdu_pkt);
|
|
|
|
p_txrxmsduhr = (msdu_pkt_hdr_t *)p_plcmsdu->data;
|
|
|
|
/* all aggr data length */
|
|
total_len = p_plcmsdu->len - sizeof(msdu_pkt_hdr_t);
|
|
|
|
p_data =(uint8_t*)(p_txrxmsduhr + 1);
|
|
|
|
while (total_len > 0) {
|
|
/* p_data include at_payload_t */
|
|
data_len = (uint16_t)((p_data[1] << 8) | p_data[0]);
|
|
|
|
data_len = data_len > total_len ? total_len : data_len;
|
|
|
|
pkt_len = sizeof(plctxrx_cmd_resp_t) + sizeof(plctxrx_handle_recv_t) +
|
|
data_len;
|
|
|
|
if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID))) {
|
|
iot_pkt_free(msdu_pkt);
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
p_resp = (plctxrx_cmd_resp_t *)iot_pkt_put(p_pkt, pkt_len);
|
|
p_recv = (plctxrx_handle_recv_t *)p_resp->data;
|
|
|
|
iot_mac_addr_cpy(p_recv->rxinfo.mac,p_txrxmsduhr->org_mac);
|
|
os_mem_cpy(p_recv->data, p_data, data_len);
|
|
p_recv->dlen =(uint8_t)data_len;
|
|
|
|
p_resp->dlen = (uint16_t)(data_len + sizeof(plctxrx_handle_recv_t));
|
|
p_resp->cid.cid = PLCTXRX_CID_SEND;
|
|
p_resp->cid.opcode = PLCTXRX_OP_RECEIVE;
|
|
p_resp->index.current = 1;
|
|
p_resp->index.total = 1;
|
|
p_resp->resp = PLCTXRX_RESP_OK;
|
|
|
|
iot_cus_printf("iot_plctxrx_msdu_frame_to_at from "\
|
|
"%02x:%02x:%02x:%02x:%02x:%02x:",
|
|
p_txrxmsduhr->org_mac[0], p_txrxmsduhr->org_mac[1],
|
|
p_txrxmsduhr->org_mac[2], p_txrxmsduhr->org_mac[3],
|
|
p_txrxmsduhr->org_mac[4], p_txrxmsduhr->org_mac[5]);
|
|
iot_cus_printf("total_len:%d datalen:%d", total_len, data_len);
|
|
|
|
iot_common_bin_dump(p_recv->data, p_recv->dlen);
|
|
|
|
plctxrx_context.at_cb.at_cmd_resp_cb(p_pkt);
|
|
|
|
/* move to next */
|
|
p_data += data_len;
|
|
total_len -= data_len;
|
|
}
|
|
#endif
|
|
|
|
iot_pkt_free(msdu_pkt);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* function to dump txrx statistic information */
|
|
void iot_plctxrx_infor_print(void)
|
|
{
|
|
#if 1
|
|
plc_txrx_statics_t *txrx_infor = &plctxrx_context.local_state.txrx_status;
|
|
iot_cus_printf("[gltx] receive msdu:%d send frame:%d, "
|
|
"drop fram:%d report frame:%d send uni:%d remain uni:%d"
|
|
"send brd:%d remain brd:%d lost msdu:%d\n",
|
|
txrx_infor->msdu_receivd_cnt, txrx_infor->fram_send_cnt,
|
|
txrx_infor->fram_send_drop_cnt, txrx_infor->fram_report_cnt,
|
|
txrx_infor->msdu_sent_uni_cnt, txrx_infor->msdu_remain_uni_cnt,
|
|
txrx_infor->msdu_sent_brd_cnt, txrx_infor->msdu_remain_brd_cnt,
|
|
txrx_infor->msdu_lost_pkt_cnt);
|
|
|
|
// iot_cus_printf("[gltx]received proto frame:%d frm_total_len:%d\n",
|
|
// g_gree_frm_cnt, g_gree_frm_total_len);
|
|
|
|
#endif
|
|
}
|
|
|
|
void iot_plctxrx_handle_timer_msg(plctxrx_task_msg_t* task_msg)
|
|
{
|
|
switch (task_msg->msg.id) {
|
|
case IOT_PLCTXRX_TIMER_DATA_PATH:
|
|
{
|
|
if (!iot_plctxrx_queue_empty_check(plctxrx_context.sendq)) {
|
|
prot_pkt_t *prot_pkt =
|
|
(prot_pkt_t *)plctxrx_context.sendq->list_head;
|
|
iot_plctxrx_msdu_retry_handle(prot_pkt);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_TIMER_TXRX_PATH:
|
|
{
|
|
plctxrx_context.txrx_tm_cnt++;
|
|
if (plctxrx_context.txrx_tm_cnt >= IOT_PLCTXRX_STASTIC_PRINT_INTVL_CNT) {
|
|
iot_plctxrx_infor_print();
|
|
plctxrx_context.txrx_tm_cnt = 0;
|
|
}
|
|
|
|
if (plctxrx_context.nw_role == IOT_PLC_DEV_ROLE_STA &&
|
|
0 == plctxrx_context.txrx_tm_cnt % IOT_PLC_SINGAL_LED_SHOW_INTVAL_CNT) {
|
|
if (plctxrx_context.u_snr >= IOT_SNR_STRONG_MIN_THR) {
|
|
iot_plc_led_request(IOT_PLC_LED_SIGNAL_STRONG);
|
|
} else if (plctxrx_context.u_snr >= IOT_SNR_GOOD_MIN_THR) {
|
|
iot_plc_led_request(IOT_PLC_LED_SIGNAL_GOOD);
|
|
} else {
|
|
iot_plc_led_request(IOT_PLC_LED_SIGNAL_WEAK);
|
|
}
|
|
iot_plc_query_dev_info(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT);
|
|
}
|
|
|
|
iot_plctxrx_conn_less_buf_refresh();
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_TIMER_AGGR_PATH:
|
|
{
|
|
iot_plctxrx_push_aggred_pkt_to_sendq(plctxrx_context.sendq);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void iot_plctxrx_timer_data_path_func(timer_id_t timer_id, void * arg)
|
|
{
|
|
(void)timer_id;
|
|
(void)arg;
|
|
iot_cus_printf("[gltx]data retry timer fired\n");
|
|
iot_plctxrx_post_msg(
|
|
IOT_PLCTXRX_TIMER_MSG, IOT_PLCTXRX_TIMER_DATA_PATH, NULL, 0);
|
|
}
|
|
|
|
/* txrx statstic timer */
|
|
void iot_plctxrx_timer_txrx_path_func(timer_id_t timer_id, void * arg)
|
|
{
|
|
(void)timer_id;
|
|
(void)arg;
|
|
iot_cus_printf("[gltx]statistic timer fired\n");
|
|
iot_plctxrx_post_msg(
|
|
IOT_PLCTXRX_TIMER_MSG, IOT_PLCTXRX_TIMER_TXRX_PATH, NULL, 0);
|
|
}
|
|
|
|
/* aggr time out handler */
|
|
void iot_plctxrx_timer_aggr_path_func(timer_id_t timer_id, void * arg)
|
|
{
|
|
(void)timer_id;
|
|
(void)arg;
|
|
iot_cus_printf("[gltx]aggr timer fired\n");
|
|
iot_plctxrx_post_msg(
|
|
IOT_PLCTXRX_TIMER_MSG, IOT_PLCTXRX_TIMER_AGGR_PATH, NULL, 0);
|
|
}
|
|
|
|
prot_pkt_t* iot_plctxrx_do_aggr(prot_pkt_t* pkt)
|
|
{
|
|
prot_pkt_t* aggrpkt = plctxrx_context.aggrpkt;
|
|
|
|
if (!pkt) {
|
|
return NULL;
|
|
}
|
|
/* no aggr packet,send it directly */
|
|
if (pkt->txinfo.force_noaggr == 1) {
|
|
prot_pkt_t *send_pkt = NULL;
|
|
pkt->send_cnt = 0;
|
|
/* in send queue, push backend */
|
|
iot_plctxrx_pkt_enqueue(plctxrx_context.sendq, (list_node_t*)pkt);
|
|
switch (pkt->txinfo.send_type) {
|
|
case PLCTXRX_UNICAST:
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_uni_cnt++;
|
|
break;
|
|
case PLCTXRX_BORADCAST:
|
|
plctxrx_context.local_state.txrx_status.msdu_remain_brd_cnt++;
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
/* get front of sendq. note: may not the aggr pkt in queue upper */
|
|
send_pkt = (prot_pkt_t *)plctxrx_context.sendq->list_head;
|
|
if (!send_pkt) {
|
|
return NULL;
|
|
}
|
|
|
|
iot_cus_printf("[gltx]pushed into the queue "
|
|
"sendq:%d, freeq:%d, sendpkt:0x%x sendcnt:%d\n",
|
|
plctxrx_context.sendq->depth, plctxrx_context.freeq->depth, send_pkt,
|
|
send_pkt->send_cnt);
|
|
|
|
/* if first send, trigger send */
|
|
if (send_pkt->send_cnt == 0) {
|
|
iot_plctxrx_msdu_send(send_pkt);
|
|
}
|
|
} else {
|
|
uint8_t* pdata = NULL;
|
|
|
|
if (!aggrpkt) {
|
|
iot_cus_printf("[gltx][aggrcheck]no pending,add candidate:%x\n", pkt);
|
|
plctxrx_context.aggrpkt = pkt;
|
|
iot_plctxrx_timer_reset(plctxrx_context.aggr_timer,
|
|
IOT_PLCTXRX_AGGR_TIMER_INTVAL);
|
|
return NULL;
|
|
}
|
|
/* do aggr if possible. */
|
|
if (iot_plctxrx_aggr_frame_condition_check(pkt, aggrpkt) == ERR_OK) {
|
|
pdata = aggrpkt->buf + aggrpkt->msdu_data_len;
|
|
os_mem_cpy(pdata, pkt->buf, pkt->msdu_data_len);
|
|
aggrpkt->msdu_data_len += pkt->msdu_data_len;
|
|
/* if the condition is satisfied, reset the aggr timer */
|
|
iot_plctxrx_timer_reset(plctxrx_context.aggr_timer,
|
|
IOT_PLCTXRX_AGGR_TIMER_INTVAL);
|
|
/* free the aggrpkt into freeq */
|
|
iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, (list_node_t*)pkt);
|
|
return NULL;
|
|
} else {
|
|
/* if aggr condiction is not satisfied push the previous pkt into the queue*/
|
|
iot_plctxrx_push_aggred_pkt_to_sendq(plctxrx_context.sendq);
|
|
/* set the aggrpkt pointer with the new pkt*/
|
|
plctxrx_context.aggrpkt = pkt;
|
|
iot_cus_printf("[gltx][aggrcheck]aggred msdu data len:%d\n",
|
|
plctxrx_context.aggrpkt->msdu_data_len);
|
|
}
|
|
}
|
|
return aggrpkt;
|
|
}
|
|
|
|
int8_t iot_plctxrx_get_node_level(uint8_t *mac)
|
|
{
|
|
int8_t level = -1;
|
|
uint16_t indx = 0;
|
|
|
|
/* first check STA is existed. */
|
|
for (indx = 0; indx < STA_DEV_MAX; indx++) {
|
|
if (iot_mac_addr_cmp(plctxrx_context.sta[indx].sta_mac, mac)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (indx >= STA_DEV_MAX) {
|
|
iot_cus_printf("[gltx]no mac existed\n");
|
|
} else {
|
|
level = plctxrx_context.sta[indx].level;
|
|
}
|
|
|
|
return level;
|
|
}
|
|
|
|
bool_t iot_plctxrx_add_sta(plcsta_info_t* stainfo)
|
|
{
|
|
uint16_t indx = 0;
|
|
plcsta_info_t* psta = NULL;
|
|
bool_t duplicate_flag = false;
|
|
|
|
/* first check if the new joined STA is existed. */
|
|
for (indx = 0; indx < STA_DEV_MAX; indx++) {
|
|
if (iot_mac_addr_cmp(plctxrx_context.sta[indx].sta_mac,
|
|
stainfo->sta_mac)) {
|
|
duplicate_flag = true;
|
|
break;
|
|
}
|
|
}
|
|
/**
|
|
* if duplicate_flag is false,it means
|
|
* we have not found duplicated STA.
|
|
*/
|
|
if (!duplicate_flag) {
|
|
/* find a empty place to insert new joined STA. */
|
|
for (indx = 0; indx < STA_DEV_MAX; indx++) {
|
|
if (plctxrx_context.sta[indx].valid == 0) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (indx >= STA_DEV_MAX) {
|
|
iot_cus_printf("[gltx]no free sta slot indx:%d or dupmac\n", indx);
|
|
} else {
|
|
psta = &plctxrx_context.sta[indx];
|
|
*psta = *stainfo;
|
|
psta->valid = 1;
|
|
if (!duplicate_flag) {
|
|
plctxrx_context.cur_stanum++;
|
|
} else {
|
|
iot_cus_printf("[gltx]duplicated cur_sta:%d,"
|
|
"mac-%02X:%02X:%02X:%02X:%02X:%02X\n",
|
|
plctxrx_context.cur_stanum, stainfo->sta_mac[0],
|
|
stainfo->sta_mac[1], stainfo->sta_mac[2], stainfo->sta_mac[3],
|
|
stainfo->sta_mac[4], stainfo->sta_mac[5]);
|
|
}
|
|
}
|
|
|
|
iot_cus_printf("[gltx]addsta cur_sta:%d\n", plctxrx_context.cur_stanum);
|
|
return duplicate_flag;
|
|
}
|
|
|
|
uint8_t iot_plctxrx_del_sta_by_mac(uint8_t* mac)
|
|
{
|
|
uint8_t ret = ERR_OK;
|
|
uint16_t indx = 0;
|
|
plcsta_info_t* psta = NULL;
|
|
|
|
for (indx = 0; indx < STA_DEV_MAX; indx++) {
|
|
psta = &plctxrx_context.sta[indx];
|
|
if (plctxrx_context.sta[indx].valid == 1) {
|
|
if (iot_mac_addr_cmp(psta->sta_mac, mac)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (indx >= STA_DEV_MAX) {
|
|
ret = ERR_FAIL;
|
|
iot_cus_printf("[gltx]delsta no slot find\n");
|
|
} else {
|
|
os_mem_set(psta, 0, sizeof(plcsta_info_t));
|
|
plctxrx_context.cur_stanum--;
|
|
}
|
|
|
|
iot_cus_printf("[gltx]delsta cur_sta:%d\n", plctxrx_context.cur_stanum);
|
|
return ret;
|
|
}
|
|
|
|
bool_t iot_plctxrx_check_sta_in_nw_by_mac(uint8_t* mac)
|
|
{
|
|
bool_t ret = false;
|
|
uint16_t indx = 0;
|
|
plcsta_info_t* psta = NULL;
|
|
|
|
for (indx = 0; indx < STA_DEV_MAX; indx++) {
|
|
psta = &plctxrx_context.sta[indx];
|
|
if (plctxrx_context.sta[indx].valid == 1) {
|
|
if (iot_mac_addr_cmp(psta->sta_mac, mac)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (indx >= STA_DEV_MAX) {
|
|
iot_cus_printf("[gltx]delsta no slot find\n");
|
|
} else {
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
uint8_t iot_plctxrx_del_sta_by_tei(uint16_t deltei)
|
|
{
|
|
uint8_t ret = ERR_OK;
|
|
uint16_t indx = 0;
|
|
plcsta_info_t* psta = NULL;
|
|
|
|
for (indx = 0; indx < STA_DEV_MAX; indx++) {
|
|
psta = &plctxrx_context.sta[indx];
|
|
if (plctxrx_context.sta[indx].valid == 1 &&
|
|
psta->sta_tei == deltei) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (indx >= STA_DEV_MAX) {
|
|
ret = ERR_FAIL;
|
|
iot_cus_printf("[gltx]delsta no slot find\n");
|
|
} else {
|
|
os_mem_set(psta, 0, sizeof(plcsta_info_t));
|
|
plctxrx_context.cur_stanum--;
|
|
}
|
|
|
|
iot_cus_printf("[gltx]delsta cur_sta:%d\n", plctxrx_context.cur_stanum);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_plctxrx_node_info_rpt() - report node infomation to upper layer
|
|
* @param node node infomation v0 report from cvg
|
|
* @param total_count node infomation total count need report
|
|
* @param count node information count this time
|
|
* @param done report done flag
|
|
* @retval: report to upper layer success or not
|
|
*/
|
|
bool_t iot_plctxrx_node_info_rpt(iot_plc_node_info_v0_t *node,
|
|
uint16_t total_count, uint16_t count, uint8_t done)
|
|
{
|
|
uint16_t i;
|
|
uint16_t last_tei;
|
|
uint16_t data_len = 0;
|
|
plctxrx_cmd_resp_t *cmd_resp;
|
|
iot_pkt_t *pkt;
|
|
node_info_v1_t *node_info_v1;
|
|
node_info_v2_t *node_info_v2;
|
|
node_info_v3_t *node_info_v3;
|
|
node_info_v4_t *node_info_v4;
|
|
node_info_v5_t *node_info_v5;
|
|
|
|
iot_cus_printf("[txrx]node type=v%d reply:t_count=%d cur_cnt=%d\n",
|
|
plctxrx_context.node_info_type, total_count, count);
|
|
|
|
switch (plctxrx_context.node_info_type) {
|
|
case NODE_INFO_TYPE_V1:
|
|
data_len = sizeof(node_info_v1_t) * count;
|
|
break;
|
|
case NODE_INFO_TYPE_V2:
|
|
data_len = sizeof(node_info_v2_t) * count;
|
|
break;
|
|
case NODE_INFO_TYPE_V3:
|
|
data_len = sizeof(node_info_v3_t) * count;
|
|
break;
|
|
case NODE_INFO_TYPE_V4:
|
|
data_len = sizeof(node_info_v4_t) * count;
|
|
break;
|
|
case NODE_INFO_TYPE_V5:
|
|
data_len = sizeof(node_info_v5_t) * count;
|
|
break;
|
|
default:
|
|
iot_cus_printf("[txrx] node_info_rpt error[%d]\n",
|
|
plctxrx_context.node_info_type);
|
|
return false;
|
|
}
|
|
|
|
pkt = iot_pkt_alloc(sizeof(plctxrx_cmd_resp_t) + data_len,
|
|
IOT_GREE_APP_MID);
|
|
if (NULL == pkt) {
|
|
iot_cus_printf("[txrx] alloc pkt error\n");
|
|
return false;
|
|
}
|
|
cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(pkt);
|
|
iot_pkt_put(pkt, sizeof(plctxrx_cmd_resp_t) + data_len);
|
|
|
|
/* use low byte reserved field save type and report to uplayer,
|
|
* high byte still reserved
|
|
*/
|
|
cmd_resp->resv = plctxrx_context.node_info_type;
|
|
cmd_resp->done = done;
|
|
cmd_resp->cid.cid = PLCTXRX_CID_NODE_INFO;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
cmd_resp->index.current = count;
|
|
cmd_resp->index.total = total_count;
|
|
cmd_resp->dlen = data_len;
|
|
|
|
switch (plctxrx_context.node_info_type) {
|
|
case NODE_INFO_TYPE_V1:
|
|
{
|
|
node_info_v1 = (node_info_v1_t *)(cmd_resp->data);
|
|
for (i = 0; i < count; i++) {
|
|
(node_info_v1+i)->sta_tei = (node+i)->sta_tei;
|
|
(node_info_v1+i)->proxy_tei = (node+i)->proxy_tei;
|
|
iot_mac_addr_cpy((node_info_v1+i)->mac, (node+i)->addr);
|
|
}
|
|
break;
|
|
}
|
|
case NODE_INFO_TYPE_V2:
|
|
{
|
|
node_info_v2 = (node_info_v2_t *)(cmd_resp->data);
|
|
for (i = 0; i < count; i++) {
|
|
(node_info_v2+i)->snr = (node+i)->ul_snr;
|
|
(node_info_v2+i)->dev_type = (node+i)->dev_type;
|
|
(node_info_v2+i)->dl_tf_sr = (node+i)->dl_tf_sr;
|
|
(node_info_v2+i)->ul_tf_sr = (node+i)->ul_tf_sr;
|
|
(node_info_v2+i)->vendor = (node+i)->vendor;
|
|
(node_info_v2+i)->build_ver = (node+i)->build_ver;
|
|
iot_mac_addr_cpy((node_info_v2+i)->mac, (node+i)->addr);
|
|
iot_cus_printf("mac:%02X:%02X:%02X:%02X:%02X:%02X build_ver:%X\n",
|
|
(node+i)->addr[0], (node+i)->addr[1], (node+i)->addr[2],
|
|
(node+i)->addr[3], (node+i)->addr[4], (node+i)->addr[5],
|
|
(node+i)->build_ver);
|
|
}
|
|
break;
|
|
}
|
|
case NODE_INFO_TYPE_V3:
|
|
{
|
|
node_info_v3 = (node_info_v3_t *)(cmd_resp->data);
|
|
for (i = 0; i < count; i++) {
|
|
(node_info_v3+i)->assoc_rx_cnt = (node+i)->assoc_rx_cnt;
|
|
(node_info_v3+i)->proxy_chg_rx_cnt = (node+i)->proxy_chg_rx_cnt;
|
|
(node_info_v3+i)->proxy_chg_accept_cnt =
|
|
(node+i)->proxy_chg_accept_cnt;
|
|
iot_mac_addr_cpy((node_info_v3+i)->mac, (node+i)->addr);
|
|
}
|
|
break;
|
|
}
|
|
case NODE_INFO_TYPE_V4:
|
|
{
|
|
node_info_v4 = (node_info_v4_t *)(cmd_resp->data);
|
|
for (i = 0; i < count; i++) {
|
|
(node_info_v4+i)->inactive_time = (node+i)->inactive_time;
|
|
(node_info_v4+i)->in_network_time = (node+i)->in_network_time;
|
|
iot_mac_addr_cpy((node_info_v4+i)->mac, (node+i)->addr);
|
|
}
|
|
break;
|
|
}
|
|
case NODE_INFO_TYPE_V5:
|
|
{
|
|
node_info_v5 = (node_info_v5_t *)(cmd_resp->data);
|
|
for (i = 0; i < count; i++) {
|
|
(node_info_v5+i)->last_assoc_rx_time = (node+i)->last_assoc_rx_time;
|
|
(node_info_v5+i)->last_proxy_chg_time =
|
|
(node+i)->last_proxy_chg_time;
|
|
iot_mac_addr_cpy((node_info_v5+i)->mac, (node+i)->addr);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
iot_pkt_free(pkt);
|
|
return false;
|
|
}
|
|
|
|
plctxrx_cmd_resp_data_pkt(done, PLCTXRX_OP_RESPONSE, pkt);
|
|
/* not report done */
|
|
if (!done) {
|
|
last_tei = node[count - 1].sta_tei;
|
|
/* query node info use query topo v0 */
|
|
iot_plc_query_nw_topo(greeapp->app_handle,
|
|
IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
|
|
IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0,
|
|
IOT_PLC_QUERY_TOPO_START_AS_TEI, last_tei + 1,
|
|
QUERY_NODE_INFO_MAX_CNT_ONCE);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_plctxrx_topo_info_rpt() - report topo infomation to upper layer
|
|
* @param node node infomation v1 report from cvg
|
|
* @param total_count node infomation total count need report
|
|
* @param count node information count this time
|
|
* @param done report done flag
|
|
* @retval: report to upper layer success or not
|
|
*/
|
|
bool_t iot_plctxrx_topo_info_rpt(iot_plc_node_info_v1_t *node,
|
|
uint16_t total_count, uint16_t count, uint8_t done)
|
|
{
|
|
uint16_t i;
|
|
uint16_t last_tei;
|
|
uint16_t data_len = 0;
|
|
plctxrx_cmd_resp_t *cmd_resp;
|
|
iot_pkt_t *pkt;
|
|
plctxrx_handle_topo_t *topo_data;
|
|
|
|
data_len = sizeof(plctxrx_handle_topo_t) +
|
|
sizeof(plctxrx_cmd_topo_t) * count;
|
|
pkt = iot_pkt_alloc(data_len + sizeof(plctxrx_cmd_resp_t),
|
|
IOT_GREE_APP_MID);
|
|
|
|
if (!pkt) {
|
|
iot_cus_printf("[gltx]alloc pkt err\n");
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(pkt);
|
|
cmd_resp->cid.cid = PLCTXRX_CID_TOPO;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
if (0 == done) {
|
|
cmd_resp->index.current = count;
|
|
} else {
|
|
cmd_resp->index.current = total_count;
|
|
}
|
|
cmd_resp->index.total = total_count;
|
|
cmd_resp->done = done;
|
|
cmd_resp->dlen = data_len;
|
|
topo_data = (plctxrx_handle_topo_t *)cmd_resp->data;
|
|
topo_data->cnt = (uint8_t)count;
|
|
for (i = 0; i < count; ++i) {
|
|
topo_data->topo[i].logic_phase = ((node+i)->logic_phase3) << 4
|
|
| ((node+i)->logic_phase2) << 2 | ((node+i)->logic_phase1);
|
|
topo_data->topo[i].phy_phase = ((node+i)->phy_phase3) << 4
|
|
| ((node+i)->phy_phase2) << 2 | ((node+i)->phy_phase1);
|
|
iot_cus_printf("[gltx]topo reply:role=%d tei=%d proxy:%d ",
|
|
(node+i)->role, (node+i)->sta_tei, (node+i)->proxy_tei);
|
|
iot_cus_printf("mac=[%02X:%02X:%02X:%02X:%02X:%02X], level:%d," \
|
|
"logic_phase:0x%02x, phy_phase:0x%02x.\n",
|
|
(node+i)->addr[0], (node+i)->addr[1], (node+i)->addr[2],
|
|
(node+i)->addr[3], (node+i)->addr[4], (node+i)->addr[5],
|
|
(node+i)->level, topo_data->topo[i].logic_phase,
|
|
topo_data->topo[i].phy_phase);
|
|
iot_mac_addr_cpy(topo_data->topo[i].mac, (node+i)->addr);
|
|
topo_data->topo[i].level = (node+i)->level;
|
|
}
|
|
|
|
last_tei = node[count - 1].sta_tei;
|
|
iot_pkt_put(pkt, data_len + sizeof(plctxrx_cmd_resp_t));
|
|
plctxrx_cmd_resp_data_pkt(done, PLCTXRX_OP_RESPONSE, pkt);
|
|
if (0 == done) {
|
|
iot_plc_query_nw_topo(greeapp->app_handle,
|
|
IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
|
|
IOT_PLC_CCO_TOPO_REQ_DATA_VER_V1,
|
|
IOT_PLC_QUERY_TOPO_START_AS_TEI, last_tei + 1,
|
|
STA_DEV_MAX);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_plctxrx_topo_info_v2_rpt() - report topo infomation to upper layer
|
|
* @param node node infomation v2 report from cvg
|
|
* @param total_count node infomation total count need report
|
|
* @param count node information count this time
|
|
* @param done report done flag
|
|
* @retval: report to upper layer success or not
|
|
*/
|
|
bool_t iot_plctxrx_topo_info_v2_rpt(iot_plc_node_info_v2_t *node,
|
|
uint16_t total_count, uint16_t count, uint8_t done)
|
|
{
|
|
uint16_t i;
|
|
uint16_t data_len = 0;
|
|
plctxrx_cmd_resp_t *cmd_resp;
|
|
iot_pkt_t *pkt;
|
|
plctxrx_handle_topo_v2_t *topo_data;
|
|
|
|
data_len = sizeof(plctxrx_handle_topo_v2_t) +
|
|
sizeof(plctxrx_cmd_topov2_t) * count;
|
|
pkt = iot_pkt_alloc(data_len + sizeof(plctxrx_cmd_resp_t),
|
|
IOT_GREE_APP_MID);
|
|
|
|
if (!pkt) {
|
|
iot_cus_printf("[gltx]alloc pkt err\n");
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(pkt);
|
|
cmd_resp->cid.cid = PLCTXRX_CID_TOPO;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
if (0 == done) {
|
|
cmd_resp->index.current = count;
|
|
} else {
|
|
cmd_resp->index.current = total_count;
|
|
}
|
|
cmd_resp->index.total = total_count;
|
|
cmd_resp->done = done;
|
|
cmd_resp->dlen = data_len;
|
|
topo_data = (plctxrx_handle_topo_v2_t *)cmd_resp->data;
|
|
topo_data->cnt = (uint8_t)count;
|
|
for (i = 0; i < count; ++i) {
|
|
iot_cus_printf("[gltx]topo reply:role=%d tei=%d proxy:%d ",
|
|
(node+i)->role, (node+i)->sta_tei, (node+i)->proxy_tei);
|
|
iot_cus_printf("mac=[%02X:%02X:%02X:%02X:%02X:%02X], level:%d\n",
|
|
(node+i)->addr[0], (node+i)->addr[1], (node+i)->addr[2],
|
|
(node+i)->addr[3], (node+i)->addr[4], (node+i)->addr[5],
|
|
(node+i)->level);
|
|
iot_mac_addr_cpy(topo_data->node[i].mac, (node+i)->addr);
|
|
topo_data->node[i].level = (node+i)->level;
|
|
}
|
|
|
|
iot_pkt_put(pkt, data_len + sizeof(plctxrx_cmd_resp_t));
|
|
plctxrx_cmd_resp_data_pkt(true, PLCTXRX_OP_RESPONSE, pkt);
|
|
|
|
return true;
|
|
}
|
|
|
|
void iot_plctxrx_handle_xmit_msg(plctxrx_task_msg_t* task_msg)
|
|
{
|
|
switch (task_msg->msg.id) {
|
|
case IOT_PLCTXRX_ID_RECV_MSG:
|
|
{
|
|
iot_pkt_t *msdu_pkt = task_msg->data;
|
|
iot_plc_msdu_recv_t *msdu =
|
|
(iot_plc_msdu_recv_t*)(iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_DATA));
|
|
msdu_pkt_hdr_t* pkthdr;
|
|
uint8_t *pdata;
|
|
uint16_t total_len;
|
|
bool_t is_ready = plctxrx_context.local_state.dev_ready;
|
|
|
|
pkthdr = (msdu_pkt_hdr_t*)msdu->data;
|
|
|
|
iot_cus_printf("[gltx]handle_xmit_msg src(%d):"
|
|
"pkt_src_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x,"
|
|
"pkt_org_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x,"
|
|
"pkt_dest_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x,"
|
|
"CCO_mac-0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", pkthdr->src_module,
|
|
pkthdr->src_mac[0], pkthdr->src_mac[1],
|
|
pkthdr->src_mac[2], pkthdr->src_mac[3],
|
|
pkthdr->src_mac[4], pkthdr->src_mac[5],
|
|
pkthdr->org_mac[0], pkthdr->org_mac[1],
|
|
pkthdr->org_mac[2], pkthdr->org_mac[3],
|
|
pkthdr->org_mac[4], pkthdr->org_mac[5],
|
|
pkthdr->dst_mac[0], pkthdr->dst_mac[1],
|
|
pkthdr->dst_mac[2], pkthdr->dst_mac[3],
|
|
pkthdr->dst_mac[4], pkthdr->dst_mac[5],
|
|
plctxrx_context.local_state.cco_mac[0],
|
|
plctxrx_context.local_state.cco_mac[1],
|
|
plctxrx_context.local_state.cco_mac[2],
|
|
plctxrx_context.local_state.cco_mac[3],
|
|
plctxrx_context.local_state.cco_mac[4],
|
|
plctxrx_context.local_state.cco_mac[5]);
|
|
/*
|
|
for cco, judge pkt is for itself or for other station.
|
|
requeue pkt to send queue if for other station.
|
|
sta to sta ack is not in plctxrx level. it's in proto level.
|
|
txrx level is do forward and do default retry.
|
|
*/
|
|
if ((plctxrx_context.nw_role == IOT_PLC_DEV_ROLE_CCO)\
|
|
&& (plctxrx_context.cur_stanum > 2)) {
|
|
if (iot_mac_addr_cmp(pkthdr->dst_mac,
|
|
plctxrx_context.local_state.cco_mac) ==0) {
|
|
iot_cus_printf("[gltx]handle_xmit_msg:forward pkt\n");
|
|
if (!is_ready) {
|
|
iot_cus_printf("[glpr][err]CCO not ready!\n");
|
|
iot_pkt_free(msdu_pkt);
|
|
return;
|
|
}
|
|
|
|
total_len = msdu->len - sizeof(msdu_pkt_hdr_t);
|
|
if(total_len > TXRX_AGGR_PKT_LEN) {
|
|
iot_cus_printf("[gltx]len:%d, exceed\n", total_len);
|
|
iot_pkt_free(msdu_pkt);
|
|
return;
|
|
}
|
|
|
|
prot_pkt_t* proto_pkt =
|
|
(prot_pkt_t*)iot_plctxrx_pkt_dequeue(plctxrx_context.freeq);
|
|
if (!proto_pkt) {
|
|
iot_cus_printf("[gltx][forward]no aviable "
|
|
"prot_pkt, freeq:%d,sendq:%d\n",
|
|
plctxrx_context.freeq->depth, plctxrx_context.sendq->depth);
|
|
iot_pkt_free(msdu_pkt);
|
|
return;
|
|
}
|
|
/* not mine, and get one free slot, start to forward */
|
|
os_mem_set(proto_pkt, 0 , sizeof(prot_pkt_t));
|
|
/* build the rocket */
|
|
pdata = msdu->data + sizeof(msdu_pkt_hdr_t);
|
|
os_mem_cpy(proto_pkt->buf, pdata, total_len);
|
|
iot_mac_addr_cpy(proto_pkt->txinfo.dst_mac, pkthdr->dst_mac);
|
|
iot_mac_addr_cpy(proto_pkt->txinfo.src_mac,
|
|
plctxrx_context.local_state.cco_mac);
|
|
iot_mac_addr_cpy(proto_pkt->txinfo.org_mac, pkthdr->org_mac);
|
|
/*
|
|
iot_cus_printf("[gltx] org mac[%2x:%2x:%2x:%2x"
|
|
":%2x:%2x:]\n", proto_pkt->txinfo.org_mac[0],
|
|
proto_pkt->txinfo.org_mac[1], proto_pkt->txinfo.org_mac[2],
|
|
proto_pkt->txinfo.org_mac[3], proto_pkt->txinfo.org_mac[4],
|
|
proto_pkt->txinfo.org_mac[5]);
|
|
*/
|
|
proto_pkt->txinfo.force_tx_connless = 0;
|
|
|
|
/*check fwd is unicast or bcast based on dest mac: FF FF FF*/
|
|
if (iot_mac_addr_cmp(pkthdr->dst_mac ,ge_bcast_addr)) {
|
|
proto_pkt->txinfo.send_type = PLCTXRX_BORADCAST;
|
|
proto_pkt->txinfo.retry_cnt = 0;
|
|
proto_pkt->txinfo.retry_intvl = 0;
|
|
proto_pkt->txinfo.txpwr = 0xFF;
|
|
proto_pkt->txinfo.sta_cnt = 0;
|
|
proto_pkt->txinfo.need_ack = false;
|
|
proto_pkt->msdu_data_len = total_len;
|
|
proto_pkt->txinfo.src_module = pkthdr->src_module;
|
|
/* the pkt sent by sta should report to proto layer
|
|
the masked method is unicast pkt not forward to cco.
|
|
current methos requested by gree for cco see all pkt.
|
|
*/
|
|
//iot_plctxrx_msdu_split_frame_to_propkt(task_msg->data,
|
|
//(uint8_t)task_msg->data2 );
|
|
} else {
|
|
proto_pkt->txinfo.send_type = PLCTXRX_UNICAST;
|
|
proto_pkt->txinfo.retry_cnt = 3;
|
|
proto_pkt->txinfo.retry_intvl = 100;
|
|
proto_pkt->txinfo.txpwr = 0xFF;
|
|
proto_pkt->txinfo.sta_cnt = 1;
|
|
if (proto_pkt->txinfo.force_tx_connless == 0) {
|
|
proto_pkt->txinfo.need_ack = true;
|
|
} else {
|
|
proto_pkt->txinfo.need_ack = false;
|
|
}
|
|
proto_pkt->txinfo.src_module = pkthdr->src_module;
|
|
proto_pkt->msdu_data_len = total_len;
|
|
//iot_pkt_free(msdu_pkt);
|
|
}
|
|
if (pkthdr->src_module == IOT_PLCTXRX_MSDU_SRCMODULE_PROTO) {
|
|
iot_plctxrx_msdu_split_frame_to_propkt(task_msg->data,
|
|
(uint8_t)task_msg->data2);
|
|
} else {
|
|
iot_plctxrx_msdu_frame_to_at(task_msg->data);
|
|
}
|
|
iot_plctxrx_post_msg(IOT_PLCTXRX_XMIT_MSG,
|
|
IOT_PLCTXRX_ID_SEND_MSG, proto_pkt, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pkthdr->src_module == IOT_PLCTXRX_MSDU_SRCMODULE_PROTO ||
|
|
pkthdr->src_module == IOT_PLCTXRX_MSDU_SRCMODULE_DEV_TEST) {
|
|
iot_plctxrx_msdu_split_frame_to_propkt(task_msg->data,
|
|
(uint8_t)task_msg->data2);
|
|
} else {
|
|
iot_plctxrx_msdu_frame_to_at(task_msg->data);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_ID_SEND_MSG:
|
|
{
|
|
prot_pkt_t *prot_pkt = (prot_pkt_t*)task_msg->data;
|
|
iot_plctxrx_do_aggr(prot_pkt);
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_ID_ACK_MSG:
|
|
{
|
|
iot_plctxrx_msdu_ack_handle(task_msg->data);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* TODO. we should split it into each small function by switchcase*/
|
|
void iot_plctxrx_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);
|
|
|
|
if (hdr->app_id != IOT_PLC_APP_ID_BCAST &&
|
|
hdr->app_id != IOT_GR_APP_ID) {
|
|
// drop corrupted message
|
|
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("[gltx]IOT_PLC_MSG_APP_REG_CONF result:%d\n",
|
|
rpt->result);
|
|
if (rpt->result == IOT_PLC_SUCCESS ||
|
|
rpt->result == IOT_PLC_SUCCESS_MODIFIED) {
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_GRAPP_REG_CONF,
|
|
PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, NULL, 0);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_DEV_STATE_CHANGE_RPT:
|
|
{
|
|
plcsta_state_t *local = &plctxrx_context.local_state;
|
|
plcsta_info_t stainfo = { 0 };
|
|
iot_plc_dev_state_change_rpt_t* rpt =
|
|
(iot_plc_dev_state_change_rpt_t*)(hdr + 1);
|
|
local->role = rpt->dev_role;
|
|
if (!local->dev_ready && rpt->is_ready) {
|
|
/* dev becomes available to serve app request */
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_DEV_STATE_CHANGE_RPT "\
|
|
"nid=%lu, cco mac=%02X:%02X:%02X:%02X:%02X:%02X, role:%d\n",
|
|
rpt->nid, rpt->cco_mac[0], rpt->cco_mac[1],
|
|
rpt->cco_mac[2], rpt->cco_mac[3], rpt->cco_mac[4],
|
|
rpt->cco_mac[5], rpt->dev_role);
|
|
|
|
local->dev_ready = rpt->is_ready;
|
|
iot_mac_addr_cpy(local->sta_mac, rpt->local_mac);
|
|
iot_mac_addr_cpy(local->cco_mac, rpt->cco_mac);
|
|
local->sta_tei = rpt->dev_tei;
|
|
|
|
stainfo.role = IOT_PLC_DEV_ROLE_CCO;
|
|
stainfo.sta_tei= 1;
|
|
iot_mac_addr_cpy(stainfo.sta_mac, rpt->cco_mac);
|
|
iot_plctxrx_add_sta(&stainfo);
|
|
|
|
if (rpt->dev_role != IOT_PLC_DEV_ROLE_CCO) {
|
|
stainfo.role = rpt->dev_role;
|
|
stainfo.sta_tei = rpt->dev_tei;
|
|
iot_mac_addr_cpy(stainfo.sta_mac, rpt->local_mac);
|
|
iot_plctxrx_add_sta(&stainfo);
|
|
/* report sta joined indication to protocol layer */
|
|
plctxrx_cmd_joined_network_t net = { 0 };
|
|
net.role = rpt->dev_role;
|
|
net.nid = (uint8_t)(rpt->nid & 0xFF);
|
|
iot_mac_addr_cpy(net.mac, rpt->cco_mac);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_JOIN_NETWORK,
|
|
PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, (void*)&net,
|
|
sizeof(plctxrx_cmd_joined_network_t));
|
|
} else {
|
|
/* report CCO state change event to protocol layer */
|
|
plctxrx_cmd_cco_sta_ind_t sta = { 0 };
|
|
sta.dev_ready = rpt->is_ready;
|
|
sta.nid = (uint8_t)(rpt->nid & 0xFF);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_CCO_STATE,
|
|
PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, (void*)&sta,
|
|
sizeof(plctxrx_cmd_cco_sta_ind_t));
|
|
}
|
|
} else if (local->dev_ready && !rpt->is_ready) {
|
|
uint16_t pkt_data_len = sizeof(plctxrx_cmd_leave_net_t) +
|
|
IOT_MAC_ADDR_LEN;
|
|
|
|
/* dev becomes unavailable. It cannot serve app request */
|
|
iot_cus_printf("[gltx]STATE_CHANGE: MAC layer is NOT ready!\n");
|
|
local->dev_ready = rpt->is_ready;
|
|
if (local->role != IOT_PLC_DEV_ROLE_CCO) {
|
|
iot_pkt_t *resp_pkt = iot_pkt_alloc(pkt_data_len +
|
|
sizeof(plctxrx_cmd_resp_t), IOT_GREE_APP_MID);
|
|
if (!resp_pkt) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
plctxrx_cmd_resp_t *cmd_resp =
|
|
(plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
|
|
cmd_resp->cid.cid = PLCTXRX_CID_LEAVE_NETWORK;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_INDICATION;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
cmd_resp->index.current = 0;
|
|
cmd_resp->index.total = 0;
|
|
cmd_resp->dlen = pkt_data_len;
|
|
plctxrx_cmd_leave_net_t *net =
|
|
(plctxrx_cmd_leave_net_t*)cmd_resp->data;
|
|
net->cnt = 1;
|
|
iot_mac_addr_cpy(net->mac[0], local->cco_mac );
|
|
iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
|
|
plctxrx_cmd_resp_data_pkt(0, PLCTXRX_OP_INDICATION, resp_pkt);
|
|
|
|
} else {
|
|
/* report CCO state change event to protocol layer */
|
|
plctxrx_cmd_cco_sta_ind_t sta = { 0 };
|
|
sta.dev_ready = rpt->is_ready;
|
|
sta.nid = 0;
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_CCO_STATE,
|
|
PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, (void*)&sta,
|
|
sizeof(plctxrx_cmd_cco_sta_ind_t));
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_DEV_INFO_RPT:
|
|
{
|
|
plcsta_state_t *local = &plctxrx_context.local_state;
|
|
iot_plc_dev_info_rpt_t* rpt = (iot_plc_dev_info_rpt_t*)(hdr + 1);
|
|
local->role= rpt->dev_role;
|
|
iot_mac_addr_cpy(local->sta_mac, rpt->local_mac);
|
|
local->dev_ready = rpt->is_ready;
|
|
plctxrx_context.u_snr = rpt->snr;
|
|
if (local->dev_ready) {
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_DEV_INFO_RPT MAC "\
|
|
"layer is ready role:%d mac:%02X:%02X:%02X:%02X:%02X:%02X\n",
|
|
rpt->dev_role, rpt->local_mac[0], rpt->local_mac[1],
|
|
rpt->local_mac[2], rpt->local_mac[3],
|
|
rpt->local_mac[4],rpt->local_mac[5]);
|
|
} else {
|
|
iot_cus_printf(
|
|
"[gltx]IOT_PLC_MSG_DEV_INFO_RPT: MAC layer is NOT ready!\n");
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_STA_JOIN_INFO:
|
|
{
|
|
plcsta_info_t stainfo = {0};
|
|
plctxrx_cmd_joined_network_t net = { 0 };
|
|
iot_plc_sta_join_info_t* rpt = (iot_plc_sta_join_info_t*)(hdr + 1);
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_STA_JOIN_INFO %d sta_joined."
|
|
"proxy=%d mac=%02X:%02X:%02X:%02X:%02X:%02X. dev_type=%d."
|
|
"physical phase[1-3]=%d.%d.%d. boot_reason=%d vendor=%04X "
|
|
"build_ver=%X, level=%d.\n",
|
|
rpt->sta_info.sta_tei, rpt->sta_info.proxy_tei,
|
|
rpt->sta_info.addr[0], rpt->sta_info.addr[1],
|
|
rpt->sta_info.addr[2], rpt->sta_info.addr[3],
|
|
rpt->sta_info.addr[4], rpt->sta_info.addr[5],
|
|
rpt->sta_info.dev_type, rpt->sta_info.logic_phase1,
|
|
rpt->sta_info.logic_phase2, rpt->sta_info.logic_phase3,
|
|
rpt->sta_info.boot_reason, rpt->sta_info.vendor,
|
|
rpt->sta_info.build_ver, rpt->sta_info.level);
|
|
|
|
stainfo.role = rpt->sta_info.role;
|
|
stainfo.sta_tei= rpt->sta_info.sta_tei;
|
|
stainfo.level = rpt->sta_info.level;
|
|
iot_mac_addr_cpy(stainfo.sta_mac, rpt->sta_info.addr);
|
|
iot_plctxrx_add_sta(&stainfo);
|
|
iot_mac_addr_cpy(net.mac, rpt->sta_info.addr);
|
|
net.role = rpt->sta_info.role;
|
|
iot_mac_addr_cpy(net.pco_mac, rpt->sta_info.proxy_addr);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_JOIN_NETWORK,
|
|
PLCTXRX_OP_INDICATION, NULL, PLCTXRX_RESP_OK, (void*)&net,
|
|
sizeof(plctxrx_cmd_joined_network_t));
|
|
iot_plc_led_request(IOT_PLC_LED_ASSOCIATED);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_STA_LEAVE_INFO:
|
|
{
|
|
iot_plc_sta_leave_info_t* rpt = (iot_plc_sta_leave_info_t*)(hdr + 1);
|
|
iot_cus_printf("[gltx]sta leave info sta_count = %d\n",rpt->sta_count);
|
|
if (rpt->sta_count > 0) {
|
|
uint16_t pkt_data_len = sizeof(plctxrx_cmd_leave_net_t) +
|
|
IOT_MAC_ADDR_LEN * rpt->sta_count;
|
|
iot_pkt_t *resp_pkt = iot_pkt_alloc(pkt_data_len +
|
|
sizeof(plctxrx_cmd_resp_t), IOT_GREE_APP_MID);
|
|
|
|
if (!resp_pkt) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
plctxrx_cmd_resp_t *cmd_resp =
|
|
(plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
|
|
cmd_resp->cid.cid = PLCTXRX_CID_LEAVE_NETWORK;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_INDICATION;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
cmd_resp->index.current = 0;
|
|
cmd_resp->index.total = 0;
|
|
cmd_resp->dlen = pkt_data_len;
|
|
plctxrx_cmd_leave_net_t *net =
|
|
(plctxrx_cmd_leave_net_t*)cmd_resp->data;
|
|
net->cnt = rpt->sta_count;
|
|
|
|
for (uint8_t i = 0; i < rpt->sta_count; ++i) {
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_STA_LEAVE_INFO: "\
|
|
"tei=%d sta_leave[%d].proxy = %d:"\
|
|
"mac=%02X:%02X:%02X:%02X:%02X:%02X\n",
|
|
rpt->sta[i].tei, i, rpt->sta[i].proxy,
|
|
rpt->sta[i].mac_addr[0], rpt->sta[i].mac_addr[1],
|
|
rpt->sta[i].mac_addr[2], rpt->sta[i].mac_addr[3],
|
|
rpt->sta[i].mac_addr[4], rpt->sta[i].mac_addr[5]);
|
|
iot_mac_addr_cpy(net->mac[i], rpt->sta[i].mac_addr);
|
|
iot_plctxrx_del_sta_by_mac(rpt->sta[i].mac_addr);
|
|
}
|
|
|
|
iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
|
|
plctxrx_cmd_resp_data_pkt(0, PLCTXRX_OP_INDICATION, resp_pkt);
|
|
iot_plc_led_request(IOT_PLC_LED_DIS_ASSOCIATED);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_STA_JOIN_REJECTED:
|
|
{
|
|
plctxrx_cmd_resp_t *cmd_resp;
|
|
plctxrx_cmd_reject_info_t *reject_info;
|
|
iot_plc_sta_join_rejected_t *rpt =
|
|
(iot_plc_sta_join_rejected_t*)(hdr + 1);
|
|
iot_pkt_t *resp_pkt = NULL;
|
|
|
|
iot_cus_printf("[gltx]reject sta:%02X%02X%02X%02X%02X%02X, reason%d\n",
|
|
rpt->addr[0], rpt->addr[1], rpt->addr[2],
|
|
rpt->addr[3], rpt->addr[4], rpt->addr[5], rpt->reason);
|
|
resp_pkt = iot_pkt_alloc(sizeof(*cmd_resp) + sizeof(*reject_info),
|
|
IOT_GREE_APP_MID);
|
|
|
|
if (NULL == resp_pkt) {
|
|
break;
|
|
}
|
|
cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_put(resp_pkt,
|
|
sizeof(*cmd_resp) + sizeof(*reject_info));
|
|
cmd_resp->cid.cid = PLCTXRX_CID_REJECT_STA;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_INDICATION;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
cmd_resp->index.current = 0;
|
|
cmd_resp->index.total = 0;
|
|
cmd_resp->dlen = sizeof(*reject_info);
|
|
|
|
reject_info = (plctxrx_cmd_reject_info_t*)cmd_resp->data;
|
|
iot_mac_addr_cpy(reject_info->mac, rpt->addr);
|
|
reject_info->reason = rpt->reason;
|
|
|
|
plctxrx_cmd_resp_data_pkt(0, PLCTXRX_OP_INDICATION, resp_pkt);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_CONN_LESS_RECV:
|
|
case IOT_PLC_MSG_MSDU_RECV:
|
|
{
|
|
uint8_t *ptr = 0;
|
|
msdu_pkt_hdr_t *pkthdr = 0;
|
|
iot_pkt_t *msdu_pkt;
|
|
uint8_t *msdu_ptr;
|
|
uint16_t msdu_pkt_len;
|
|
uint8_t msdu_pkt_type;
|
|
bool_t connless_type;
|
|
|
|
iot_plc_msdu_recv_t *msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
|
|
plctxrx_context.u_snr = (int8_t)msdu->snr;
|
|
ptr = msdu->data;
|
|
pkthdr = (msdu_pkt_hdr_t*)ptr;
|
|
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_MSDU_RECV: ackseq:%d "
|
|
"msduseq:%d mac:[%2X:%2X:%2X:%2X:%2X:%2X] size=%d "
|
|
"module_src=%d dstcnt:%d needack:%d srctype:%d\n",pkthdr->recvconf_seq,
|
|
pkthdr->msdusend_seq, msdu->src[0], msdu->src[1], msdu->src[2],
|
|
msdu->src[3], msdu->src[4], msdu->src[5], msdu->len,
|
|
pkthdr->src_module, pkthdr->dest_cnt, pkthdr->need_ack,
|
|
pkthdr->src_module);
|
|
|
|
iot_plctxrx_aes_decrypt(pkt);
|
|
|
|
if (IOT_PLC_MSG_MSDU_RECV == hdr->msg_id) {
|
|
connless_type = 0;
|
|
if (!plctxrx_context.local_state.dev_ready) {
|
|
/* if dev is not ready, don't handle the MSDU */
|
|
iot_cus_printf("[gltx][err] dev not ready, drop pkt\n");
|
|
iot_pkt_free(pkt);
|
|
return ;
|
|
}
|
|
} else {
|
|
connless_type = 1;
|
|
iot_cus_printf("[gltx][info]app connless packet recv!\n");
|
|
}
|
|
msdu_pkt_len = sizeof(iot_plc_msdu_recv_t) + msdu->len;
|
|
msdu_pkt = iot_pkt_alloc(msdu_pkt_len,IOT_GREE_APP_MID);
|
|
|
|
iot_cus_printf("[gltx] msdu alloc pkt:%d\n",msdu_pkt_len);
|
|
|
|
if (msdu_pkt == NULL) {
|
|
iot_cus_printf("[gltx] allocate pkt fail!\n");
|
|
iot_pkt_free(pkt);
|
|
return;
|
|
}
|
|
|
|
msdu_ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_DATA);
|
|
os_mem_cpy(msdu_ptr, msdu, msdu_pkt_len);
|
|
|
|
msdu_pkt_type = iot_plctxrx_msdu_type_check(msdu);
|
|
if (msdu_pkt_type == PLCTXRX_TYPE_ACK) {
|
|
iot_plctxrx_post_msg(IOT_PLCTXRX_XMIT_MSG,
|
|
IOT_PLCTXRX_ID_ACK_MSG, msdu_pkt, 0);
|
|
} else {
|
|
/*unicast*/
|
|
if ((pkthdr->dest_cnt == 1) && pkthdr->need_ack) {
|
|
iot_plctxrx_msdu_send_ack_back(msdu);
|
|
}
|
|
|
|
if (connless_type == 0) {
|
|
if (iot_plctxrx_msdu_duplicate_check(msdu)) {
|
|
iot_pkt_free(pkt);
|
|
iot_pkt_free(msdu_pkt);
|
|
return;
|
|
}
|
|
} else {
|
|
if (!iot_plctxrx_conn_less_rpt_check(pkthdr->msdusend_seq,
|
|
msdu->src)) {
|
|
iot_cus_printf("[gltx]dupplicated conn_less pkt[%d] "
|
|
"received!\n", pkthdr->msdusend_seq);
|
|
iot_pkt_free(pkt);
|
|
iot_pkt_free(msdu_pkt);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* sta may receive cco broadcast pkt which sent out by self */
|
|
if (iot_mac_addr_cmp(plctxrx_context.local_state.sta_mac,
|
|
pkthdr->org_mac) == 1) {
|
|
iot_cus_printf("[gltx]cco forwardbcast mac:%x:%x:%x:%x:%x vs"\
|
|
"%x:%x:%x:%x:%x:%x\n",
|
|
plctxrx_context.local_state.sta_mac[0],
|
|
plctxrx_context.local_state.sta_mac[1],
|
|
plctxrx_context.local_state.sta_mac[2],
|
|
plctxrx_context.local_state.sta_mac[3],
|
|
plctxrx_context.local_state.sta_mac[4],
|
|
plctxrx_context.local_state.sta_mac[5],
|
|
pkthdr->org_mac[0],pkthdr->org_mac[1],
|
|
pkthdr->org_mac[2],pkthdr->org_mac[3],
|
|
pkthdr->org_mac[4],pkthdr->org_mac[5]);
|
|
iot_pkt_free(pkt);
|
|
iot_pkt_free(msdu_pkt);
|
|
return;
|
|
}
|
|
|
|
plctxrx_context.local_state.txrx_status.msdu_receivd_cnt++;
|
|
|
|
iot_plctxrx_recvd_pktseq_update(msdu);
|
|
iot_plctxrx_post_msg(IOT_PLCTXRX_XMIT_MSG,
|
|
IOT_PLCTXRX_ID_RECV_MSG, msdu_pkt, connless_type);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NW_ID_RPT:
|
|
{
|
|
iot_plc_nid_rpt_t *rpt = (iot_plc_nid_rpt_t*)(hdr + 1);
|
|
iot_cus_printf("[gltx] query nid reply:[0x%06X]\n", rpt->nid);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_LID_CONF:
|
|
{
|
|
iot_plc_lid_alloc_conf_t *cfm = (iot_plc_lid_alloc_conf_t*)(hdr + 1);
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_LID_CONF lid alloc:"\
|
|
"result = %d, lid=%d\n", cfm->result, cfm->lid);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NEIGHBOR_DEV_RPT:
|
|
{
|
|
uint16_t i;
|
|
iot_plc_neighbor_dev_rpt_t * nb_info =
|
|
(iot_plc_neighbor_dev_rpt_t*)(hdr + 1);
|
|
//iot_cus_printf("[gltx]IOT_PLC_MSG_NEIGHBOR_DEV_RPT :\n");
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_NEIGHBOR_DEV_RPT:count = %d "\
|
|
"total_cnt:%d done:%d\n",
|
|
nb_info->cnt, nb_info->total_cnt, nb_info->done);
|
|
|
|
if (nb_info->cnt > 0) {
|
|
plctxrx_cmd_resp_t *cmd_resp;
|
|
plctxrx_net_sts_data_info_t *net;
|
|
uint16_t pkt_data_len = sizeof(plctxrx_net_sts_data_info_t) +
|
|
sizeof(plctxrx_net_sts_t) * nb_info->total_cnt;
|
|
iot_pkt_t *resp_pkt = iot_pkt_alloc(pkt_data_len +
|
|
sizeof(plctxrx_cmd_resp_t), IOT_GREE_APP_MID);
|
|
|
|
if (!resp_pkt) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
|
|
cmd_resp->cid.cid = PLCTXRX_CID_NET_STS;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
cmd_resp->dlen = pkt_data_len;
|
|
net = (plctxrx_net_sts_data_info_t *)cmd_resp->data;
|
|
net->count = (uint8_t)nb_info->cnt;
|
|
|
|
for (i = 0; i < net->count; i++) {
|
|
net->net_sts_data[i].ul_tf_sr = nb_info->node[i].ul_tf_sr;
|
|
net->net_sts_data[i].dl_tf_sr = nb_info->node[i].dl_tf_sr;
|
|
net->net_sts_data[i].snr = nb_info->node[i].snr;
|
|
net->net_sts_data[i].nf = 0;
|
|
iot_mac_addr_cpy(net->net_sts_data[i].mac,
|
|
nb_info->node[i].addr);
|
|
iot_cus_printf("[gltx]snr=%d,nf=%d,count=%d,"\
|
|
"cur=%d,mac=0x%02x,0x%02x,0x%02x,tsf=%d,rsf=%d\n",\
|
|
net->net_sts_data[i].snr, net->net_sts_data[i].nf,
|
|
net->count, i, net->net_sts_data[i].mac[0],
|
|
net->net_sts_data[i].mac[1],
|
|
net->net_sts_data[i].mac[2],
|
|
net->net_sts_data[i].ul_tf_sr,
|
|
net->net_sts_data[i].dl_tf_sr);
|
|
}
|
|
iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
|
|
plctxrx_cmd_resp_data_pkt(1, PLCTXRX_OP_RESPONSE, resp_pkt);
|
|
} else {
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_NET_STS, PLCTXRX_OP_RESPONSE,
|
|
NULL, PLCTXRX_RESP_ERROR, NULL, 0);
|
|
}
|
|
if (nb_info->cnt == 1 && iot_mac_addr_cmp(nb_info->node->addr,
|
|
plctxrx_context.local_state.sta_mac)) {
|
|
/* update local state info */
|
|
plcsta_state_t *local_state = &plctxrx_context.local_state;
|
|
local_state->role = (uint8_t)nb_info->node->role;
|
|
local_state->net_status.snr = nb_info->node->snr;
|
|
local_state->net_status.ul_tf_sr = nb_info->node->ul_tf_sr;
|
|
local_state->net_status.dl_tf_sr = nb_info->node->dl_tf_sr;
|
|
if (nb_info->node->phase1 > 0) {
|
|
local_state->net_status.phase = nb_info->node->phase1;
|
|
} else if (nb_info->node->phase2 > 0) {
|
|
local_state->net_status.phase = nb_info->node->phase2;
|
|
} else {
|
|
local_state->net_status.phase = nb_info->node->phase3;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NW_NEIGHBOR_RPT:
|
|
{
|
|
uint16_t i;
|
|
iot_plc_nb_nw_rpt_t *rpt = (iot_plc_nb_nw_rpt_t*)(hdr + 1);
|
|
plctxrx_cmd_resp_t *cmd_resp;
|
|
plctxrx_cmd_network_t *net;
|
|
iot_cus_printf("[gltx] nbnw reply: count = %d\n", rpt->count);
|
|
uint16_t pkt_data_len = sizeof(plctxrx_cmd_network_t) +
|
|
sizeof(plctxrx_cmd_network_info_t) * rpt->count;
|
|
iot_pkt_t *resp_pkt = iot_pkt_alloc(pkt_data_len +
|
|
sizeof(plctxrx_cmd_resp_t), IOT_GREE_APP_MID);
|
|
|
|
if (!resp_pkt) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
|
|
cmd_resp->cid.cid = PLCTXRX_CID_FIND_NETWORK;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
cmd_resp->index.current = rpt->count;
|
|
cmd_resp->index.total = rpt->count;
|
|
cmd_resp->dlen = pkt_data_len;
|
|
net = (plctxrx_cmd_network_t*)cmd_resp->data;
|
|
net->count = rpt->count;
|
|
for (i = 0; i < rpt->count; ++i) {
|
|
iot_cus_printf("[gltx]nbnw reply:nid[%d],sp_flag = %d,bd = %d\n",
|
|
rpt->nb_info[i].nid, rpt->nb_info[i].sp_flag,
|
|
rpt->nb_info[i].bandwidth);
|
|
net->node[i].nid = rpt->nb_info[i].nid;
|
|
|
|
/* get best snr */
|
|
net->node[i].snr = (rpt->nb_info[i].snr[0] >=
|
|
rpt->nb_info[i].snr[1]? \
|
|
rpt->nb_info[i].snr[0]:rpt->nb_info[i].snr[1]);
|
|
net->node[i].snr = (net->node[i].snr >= rpt->nb_info[i].snr[2]?
|
|
net->node[i].snr:rpt->nb_info[i].snr[2]);
|
|
iot_mac_addr_cpy(net->node[i].mac, rpt->nb_info[i].addr);
|
|
}
|
|
iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
|
|
plctxrx_cmd_resp_data_pkt(1, PLCTXRX_OP_RESPONSE, resp_pkt);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NW_WL_RPT:
|
|
{
|
|
iot_plc_wl_rpt_t *rpt = (iot_plc_wl_rpt_t*)(hdr + 1);
|
|
iot_cus_printf("[gltx] IOT_PLC_MSG_NW_WL_RPT wl reply:");
|
|
iot_cus_printf("total=%d,count=%d,done=%d\n",
|
|
rpt->total_count, rpt->count, rpt->done);
|
|
for (int i = 0; i < rpt->count; ++i) {
|
|
iot_cus_printf("[gltx]mac[%d]=%02X:%02X:%02X:%02X:%02X:%02X\n", i,
|
|
rpt->mac_addr[i][0], rpt->mac_addr[i][1],
|
|
rpt->mac_addr[i][2], rpt->mac_addr[i][3],
|
|
rpt->mac_addr[i][4], rpt->mac_addr[i][5]);
|
|
}
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_WHITELIST, PLCTXRX_OP_RESPONSE,
|
|
NULL, PLCTXRX_RESP_OK, (void*)rpt, sizeof(iot_plc_wl_rpt_t));
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NW_WL_SET_RPT:
|
|
{
|
|
uint8_t cmdid;
|
|
iot_plc_wl_set_rpt_t *rpt = (iot_plc_wl_set_rpt_t*)(hdr + 1);
|
|
uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
|
|
|
|
cmdid = plctxrx_context.command.cur_cid.cid;
|
|
|
|
plctxrx_cmd_resp_data(cmdid, PLCTXRX_OP_CFM, NULL, resp, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NW_TOPO_RPT:
|
|
{
|
|
iot_plc_nw_topo_rpt_t* rpt = (iot_plc_nw_topo_rpt_t*)(hdr + 1);
|
|
if (rpt->version == IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0) {
|
|
/* v0 is used for node info */
|
|
iot_plctxrx_node_info_rpt((iot_plc_node_info_v0_t *)rpt->data,
|
|
rpt->total_count, rpt->count, rpt->done);
|
|
} else if (rpt->version == IOT_PLC_CCO_TOPO_REQ_DATA_VER_V1 &&
|
|
rpt->count > 0) {
|
|
/* v1 is used for topo info */
|
|
iot_plctxrx_topo_info_rpt((iot_plc_node_info_v1_t *)rpt->data,
|
|
rpt->total_count, rpt->count, rpt->done);
|
|
} else if (rpt->version == IOT_PLC_CCO_TOPO_REQ_DATA_VER_V2 &&
|
|
rpt->count > 0) {
|
|
iot_plctxrx_topo_info_v2_rpt((iot_plc_node_info_v2_t *)rpt->data,
|
|
rpt->total_count, rpt->count, rpt->done);
|
|
} else {
|
|
plctxrx_cmd_resp_data(plctxrx_context.command.cur_cid.cid,
|
|
PLCTXRX_OP_RESPONSE, NULL, PLCTXRX_RESP_ERROR, NULL, 0);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NODE_INFO_QUERY_RPT:
|
|
{
|
|
iot_plc_node_info_rpt_t* rpt = (iot_plc_node_info_rpt_t*)(hdr + 1);
|
|
iot_cus_printf("[glpr]report node info count=%d\n", rpt->count);
|
|
if (rpt->version == IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0) {
|
|
iot_plctxrx_node_info_rpt((iot_plc_node_info_v0_t *)rpt->data,
|
|
rpt->total_count, rpt->count, rpt->done);
|
|
} else {
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_NODE_INFO,
|
|
PLCTXRX_OP_RESPONSE, NULL, PLCTXRX_RESP_ERROR, NULL, 0);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NW_INFO_QUERY_RPT:
|
|
{
|
|
uint16_t pkt_data_len;
|
|
plctxrx_cmd_resp_t *cmd_resp;
|
|
iot_pkt_t *resp_pkt;
|
|
iot_plc_nw_info_query_rpt_t* rpt =
|
|
(iot_plc_nw_info_query_rpt_t*)(hdr + 1);
|
|
|
|
iot_cus_printf("[gltx]report network max level=%d\n", rpt->max_level);
|
|
pkt_data_len = sizeof(iot_plc_nw_info_query_rpt_t) +
|
|
sizeof(iot_plc_nw_level_info_t) * rpt->max_level ;
|
|
resp_pkt = iot_pkt_alloc(pkt_data_len + sizeof(plctxrx_cmd_resp_t),
|
|
IOT_GREE_APP_MID);
|
|
|
|
if (resp_pkt == NULL) {
|
|
iot_cus_printf("[glpr]alloc pkt length=%d err\n",
|
|
pkt_data_len + sizeof(plctxrx_cmd_resp_t));
|
|
break;
|
|
}
|
|
|
|
cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(resp_pkt);
|
|
cmd_resp->cid.cid = PLCTXRX_CID_NW_INFO;
|
|
cmd_resp->cid.opcode = PLCTXRX_OP_RESPONSE;
|
|
cmd_resp->resp = PLCTXRX_RESP_OK;
|
|
cmd_resp->index.current = 1;
|
|
cmd_resp->index.total = 1;
|
|
cmd_resp->dlen = pkt_data_len;
|
|
os_mem_cpy(cmd_resp->data, rpt, pkt_data_len);
|
|
iot_pkt_put(resp_pkt, pkt_data_len + sizeof(plctxrx_cmd_resp_t));
|
|
plctxrx_cmd_resp_data_pkt(true, PLCTXRX_OP_RESPONSE, resp_pkt);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_CFG_SET_CONF:
|
|
{
|
|
iot_plc_cfg_set_conf_t *conf = (iot_plc_cfg_set_conf_t*)(hdr + 1);
|
|
uint16_t resp = !(conf->result == IOT_PLC_SUCCESS);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_MAC, PLCTXRX_OP_CFM, NULL,
|
|
resp, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_BEACON_DATA_SET_RPT:
|
|
{
|
|
iot_plc_beacon_data_set_rpt_t *rpt =
|
|
(iot_plc_beacon_data_set_rpt_t*)(hdr + 1);
|
|
uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
|
|
plctxrx_cmd_resp_data(plctxrx_context.command.cur_cid.cid,
|
|
PLCTXRX_OP_CFM, NULL, resp, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_BEACON_DATA_RPT:
|
|
{
|
|
iot_plc_beacon_data_rpt_t *rpt = (iot_plc_beacon_data_rpt_t*)(hdr + 1);
|
|
#if ENABLE_GE_DATA_SEND_TO_BEACON
|
|
iot_cus_printf("[gltx]beacon rpt\n");
|
|
if (!os_mem_cmp(plctxrx_context.verinfo.data, rpt->data,
|
|
sizeof(iot_plc_beacon_data_rpt_t))) {
|
|
/* only new beacon data receive, report to proto */
|
|
break;
|
|
}
|
|
iot_pkt_t *vend_pkt = iot_pkt_alloc(sizeof(iot_plc_beacon_data_rpt_t),
|
|
IOT_GREE_APP_MID);
|
|
if (!vend_pkt) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
iot_pkt_put(vend_pkt, sizeof(iot_plc_beacon_data_rpt_t));
|
|
os_mem_cpy(iot_pkt_data(vend_pkt), rpt->data,
|
|
sizeof(iot_plc_beacon_data_rpt_t));
|
|
|
|
os_mem_cpy(plctxrx_context.verinfo.data, rpt->data,
|
|
sizeof(iot_plc_beacon_data_rpt_t));
|
|
plctxrx_context.gree_cb.gree_vendr_cb(vend_pkt);
|
|
#endif
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_FREQ_BAND_SET_RPT:
|
|
{
|
|
/* handle freq band set response */
|
|
iot_plc_freq_band_set_rpt_t *rpt =
|
|
(iot_plc_freq_band_set_rpt_t *)(hdr + 1);
|
|
uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_BAND_ID, PLCTXRX_OP_CFM, NULL,
|
|
resp, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_BAND_INFO_QUERY_RPT:
|
|
{
|
|
iot_plc_freq_band_info_query_rpt_t *rpt =
|
|
(iot_plc_freq_band_info_query_rpt_t*)(hdr + 1);
|
|
|
|
if (PLCTXRX_CID_TX_PWR == plctxrx_context.command.cur_cid.cid) {
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_TX_PWR, PLCTXRX_OP_RESPONSE,
|
|
NULL, PLCTXRX_RESP_OK, (void*)&(rpt->power_cap),
|
|
sizeof(plctxrx_cmd_tx_pwr_t));
|
|
} else if (PLCTXRX_CID_BAND_ID == plctxrx_context.command.cur_cid.cid){
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_BAND_ID, PLCTXRX_OP_RESPONSE,
|
|
NULL, PLCTXRX_RESP_OK, (void*)&(rpt->freq_band),
|
|
sizeof(plctxrx_cmd_band_info_t));
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_TX_POWER_CAP_SET_RPT:
|
|
{
|
|
iot_plc_tx_power_cap_set_rpt_t *rpt
|
|
= (iot_plc_tx_power_cap_set_rpt_t *)(hdr + 1);
|
|
uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_TX_PWR, PLCTXRX_OP_CFM,
|
|
NULL, resp, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_NW_ID_SET_RPT:
|
|
{
|
|
iot_plc_nw_id_set_rpt_t *rpt = (iot_plc_nw_id_set_rpt_t*)(hdr + 1);
|
|
uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_NID,
|
|
PLCTXRX_OP_CFM, NULL, resp, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_SCANBAND_BITMAP_SET_RPT:
|
|
{
|
|
iot_plc_set_scanband_bitmap_rpt_t *rpt = \
|
|
(iot_plc_set_scanband_bitmap_rpt_t*)(hdr + 1);
|
|
uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_FB_BITMAP, PLCTXRX_OP_CFM,
|
|
NULL, resp, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_QUERYBAND_BITMAP_RPT:
|
|
{
|
|
iot_plc_query_band_bitmap_rpt_t *rpt = \
|
|
(iot_plc_query_band_bitmap_rpt_t*)(hdr + 1);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_FB_BITMAP,
|
|
PLCTXRX_OP_RESPONSE, NULL, PLCTXRX_RESP_OK,
|
|
(void *)&rpt->is_scan_band,
|
|
sizeof(plctxrx_cmd_fb_bitmap_resp_t));
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_SET_RATE_ADAPT_MODE_RPT:
|
|
{
|
|
iot_plc_set_rate_adapt_mode_rpt_t *rpt =
|
|
(iot_plc_set_rate_adapt_mode_rpt_t*)(hdr + 1);
|
|
uint16_t resp = !(rpt->result == IOT_PLC_SUCCESS);
|
|
if (resp) {
|
|
plctxrx_context.local_state.rate_node =
|
|
plctxrx_context.local_state.rate_node_last;
|
|
} else {
|
|
plctxrx_context.local_state.rate_node_last =
|
|
plctxrx_context.local_state.rate_node;
|
|
}
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_FIXED_RATE, PLCTXRX_OP_CFM,
|
|
NULL, resp, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_WDG_SET_CONF:
|
|
{
|
|
iot_plc_wdg_set_conf_t *conf = (iot_plc_wdg_set_conf_t*)(hdr + 1);
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_WDG_SET_CONF watchdog status = %d\n",
|
|
conf->status);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_WDG, PLCTXRX_OP_CFM, NULL,
|
|
PLCTXRX_RESP_OK, NULL, 0);
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_STA_PROXY_CHANGED:
|
|
{
|
|
plcsta_info_t stainfo = {0};
|
|
iot_plc_sta_proxy_changed_t* rpt = (iot_plc_sta_proxy_changed_t*)(hdr + 1);
|
|
iot_cus_printf("[gltx]IOT_PLC_MSG_STA_PROXY_CHANGED %d sta_proxy_changed."
|
|
"proxy=%d,level=%d,proxy mac=%02X:%02X:%02X:%02X:%02X:%02X."
|
|
"sta mac=%02X:%02X:%02X:%02X:%02X:%02X.\n",
|
|
rpt->sta_tei, rpt->proxy_tei, rpt->level, rpt->proxy_addr[0],
|
|
rpt->proxy_addr[1], rpt->proxy_addr[2], rpt->proxy_addr[3],
|
|
rpt->proxy_addr[4], rpt->proxy_addr[5], rpt->sta_addr[0],
|
|
rpt->sta_addr[1], rpt->sta_addr[2], rpt->sta_addr[3],
|
|
rpt->sta_addr[4], rpt->sta_addr[5]);
|
|
|
|
stainfo.level = rpt->level;
|
|
stainfo.sta_tei= rpt->sta_tei;
|
|
stainfo.role = rpt->role;
|
|
iot_mac_addr_cpy(stainfo.sta_mac, rpt->sta_addr);
|
|
iot_plctxrx_add_sta(&stainfo);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
iot_pkt_free(pkt);
|
|
}
|
|
|
|
static void iot_plctxrx_task_msg_exe(iot_task_h task_h, iot_task_msg_t *msg)
|
|
{
|
|
plctxrx_task_msg_t *task_msg;
|
|
IOT_ASSERT(task_h == plctxrx_context.task_handle);
|
|
IOT_ASSERT(msg);
|
|
|
|
task_msg = (plctxrx_task_msg_t*)msg;
|
|
switch (task_msg->msg.type) {
|
|
case IOT_PLCTXRX_MAC_MSG:
|
|
{
|
|
iot_plctxrx_handle_mac_msg(task_msg->data);
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_TIMER_MSG:
|
|
{
|
|
iot_plctxrx_handle_timer_msg(task_msg);
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_XMIT_MSG:
|
|
{
|
|
iot_plctxrx_handle_xmit_msg(task_msg);
|
|
break;
|
|
}
|
|
|
|
case IOT_PLCTXRX_CMD_MSG:
|
|
{
|
|
plctxrx_cmd_msg_handle(task_msg->data);
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
iot_task_free_msg(plctxrx_context.task_handle, &task_msg->msg);
|
|
}
|
|
|
|
static void iot_plctxrx_task_msg_cancel(iot_task_h task_h,
|
|
iot_task_msg_t *msg)
|
|
{
|
|
plctxrx_task_msg_t *task_msg;
|
|
IOT_ASSERT(task_h == plctxrx_context.task_handle);
|
|
IOT_ASSERT(msg);
|
|
|
|
task_msg = (plctxrx_task_msg_t*)msg;
|
|
switch (task_msg->msg.type) {
|
|
case IOT_PLCTXRX_MAC_MSG:
|
|
{
|
|
if (task_msg->data) {
|
|
iot_pkt_free(task_msg->data);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_TIMER_MSG:
|
|
{
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_XMIT_MSG:
|
|
{
|
|
if (task_msg->data) {
|
|
iot_pkt_free(task_msg->data);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLCTXRX_CMD_MSG:
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
iot_task_free_msg(plctxrx_context.task_handle, &task_msg->msg);
|
|
|
|
}
|
|
|
|
void iot_plctxrx_post_msg(uint16_t msg_type,uint16_t msg_id, void* data,
|
|
uint32_t data2)
|
|
{
|
|
iot_task_msg_t *msg;
|
|
plctxrx_task_msg_t *task_msg;
|
|
msg = iot_task_alloc_msg_with_reserved(plctxrx_context.task_handle, 0);
|
|
if (!msg) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
iot_cus_printf("[gltx]txrx task msg post: "\
|
|
"msg_type(%d)msg_id(%d)\n",msg_type, msg_id);
|
|
|
|
task_msg = (plctxrx_task_msg_t*)msg;
|
|
task_msg->msg.type = msg_type;
|
|
task_msg->msg.id = msg_id;
|
|
task_msg->data = data;
|
|
task_msg->data2 = data2;
|
|
iot_task_queue_msg(plctxrx_context.task_handle, &task_msg->msg, 0);
|
|
}
|
|
|
|
/* pkt entry from cvg up to plctxrx */
|
|
void iot_plctxrx_msdu_from_cvg(void *param, iot_pkt_t *pkt)
|
|
{
|
|
(void)param;
|
|
iot_plctxrx_post_msg(IOT_PLCTXRX_MAC_MSG, 0, pkt, 0);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
when upper callin.
|
|
1. get one free protopkt and past it on msg queue
|
|
2. when message queue receive it, do aggr function.
|
|
3. then, generate one new protopkt or just send it down.
|
|
*/
|
|
uint8_t iot_plctxrx_proto_data_send_cbk(uint8_t* data, uint16_t len,
|
|
protpkt_tx_info_t *txinfo)
|
|
{
|
|
prot_pkt_t* proto_pkt = NULL;
|
|
|
|
if(len > TXRX_AGGR_PKT_LEN) {
|
|
iot_cus_printf("[gltx]len:%d, exceeds txrx_aggr_pkt_len\n", len);
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
plctxrx_context.local_state.txrx_status.fram_send_cnt++;
|
|
if (plctxrx_context.local_state.txrx_status.fram_send_cnt == 0) {
|
|
plctxrx_context.local_state.txrx_status.fram_send_cnt++;
|
|
}
|
|
|
|
proto_pkt = (prot_pkt_t*)iot_plctxrx_pkt_dequeue(plctxrx_context.freeq);
|
|
if (proto_pkt == NULL) {
|
|
iot_cus_printf("[gltx]no aviable prot_pkt, freeq:%d,"\
|
|
"sendq:%d len:%d\n", plctxrx_context.freeq->depth,
|
|
plctxrx_context.sendq->depth, len);
|
|
|
|
plctxrx_context.local_state.txrx_status.fram_send_drop_cnt++;
|
|
if (plctxrx_context.local_state.txrx_status.fram_send_drop_cnt == 0) {
|
|
plctxrx_context.local_state.txrx_status.fram_send_drop_cnt++;
|
|
}
|
|
return ERR_NOMEM;
|
|
}
|
|
|
|
g_gree_frm_cnt++;
|
|
g_gree_frm_total_len += len;
|
|
iot_cus_printf("[gltx]received proto data:%d frm_cnt:%d frm_total_len:%d\n",
|
|
len,g_gree_frm_cnt,g_gree_frm_total_len);
|
|
iot_cus_printf("[gltx]txinfo:type:%d sta_cnt:%d,need_ack:%d, "
|
|
"retry_cnt:%d, retry_intvl:%d\n", txinfo->send_type, txinfo->sta_cnt,
|
|
txinfo->need_ack, txinfo->retry_cnt, txinfo->retry_intvl);
|
|
|
|
os_mem_cpy(proto_pkt->buf, data, len);
|
|
os_mem_cpy(&proto_pkt->txinfo, txinfo,(uint32_t)sizeof(protpkt_tx_info_t));
|
|
proto_pkt->msdu_data_len = len;
|
|
|
|
iot_plctxrx_post_msg(IOT_PLCTXRX_XMIT_MSG, IOT_PLCTXRX_ID_SEND_MSG,
|
|
proto_pkt, 0);
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* when unicast and needack set, send msdu-ack back */
|
|
uint8_t iot_plctxrx_msdu_send_ack_back(iot_plc_msdu_recv_t *msdu)
|
|
{
|
|
uint8_t msg_type = IOT_PLC_MSG_TYPE_UNICAST;
|
|
uint8_t *ptr = 0;
|
|
uint8_t *destptr = 0;
|
|
uint16_t buflen = sizeof(msdu_pkt_hdr_t);
|
|
msdu_pkt_hdr_t *send_hdr = NULL;
|
|
msdu_pkt_hdr_t *hdr = NULL;
|
|
|
|
ptr = msdu->data;
|
|
hdr = (msdu_pkt_hdr_t *)ptr;
|
|
|
|
destptr = msdu->src;
|
|
iot_pkt_t *pkt_msdu = iot_plc_alloc_msdu(greeapp->app_handle, msg_type,
|
|
IOT_PLC_ACK_TYPE_NONE, destptr, plctxrx_context.local_state.sta_mac,
|
|
plctxrx_context.link_id, buflen, IOT_PLC_LOCAL_RETRY_CNT);
|
|
|
|
if (pkt_msdu == NULL) {
|
|
iot_cus_printf("[gltx] allocate msdu fail\n");
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
ptr = iot_pkt_block_ptr(pkt_msdu, IOT_PKT_BLOCK_TAIL);
|
|
|
|
send_hdr = (msdu_pkt_hdr_t*)ptr;
|
|
|
|
send_hdr->msdusend_seq = 0;
|
|
send_hdr->recvconf_seq = hdr->msdusend_seq;
|
|
send_hdr->dest_cnt = 1;
|
|
send_hdr->need_ack = 0;
|
|
send_hdr->src_module = hdr->src_module;
|
|
|
|
iot_pkt_put(pkt_msdu, sizeof(uint8_t)*buflen);
|
|
iot_plc_send_msdu(greeapp->app_handle, pkt_msdu);
|
|
|
|
iot_cus_printf("[gltx]ack for msduseq:%d\n",hdr->msdusend_seq);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
|
|
uint32_t iot_plctxrx_aggr_frame_condition_check(prot_pkt_t* in_pkt,
|
|
prot_pkt_t* aggr_pkt)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
|
|
if (in_pkt->msdu_data_len > (TXRX_AGGR_PKT_LEN - aggr_pkt->msdu_data_len)) {
|
|
return REASON_NO_SPACE;
|
|
}
|
|
|
|
if (in_pkt->txinfo.sta_cnt != aggr_pkt->txinfo.sta_cnt) {
|
|
ret |= (1<< REASON_DEST_MISMATCH);
|
|
iot_cus_printf("[gltx][aggrcheck]sta_cnt mismatch:%d vs %d\n",
|
|
in_pkt->txinfo.sta_cnt, aggr_pkt->txinfo.sta_cnt);
|
|
|
|
} else {
|
|
if (os_mem_cmp(in_pkt->txinfo.dst_mac, aggr_pkt->txinfo.dst_mac,
|
|
(uint32_t)(in_pkt->txinfo.sta_cnt*IOT_MAC_ADDR_LEN))) {
|
|
ret |= 1<< REASON_DEST_MISMATCH;
|
|
/*
|
|
iot_cus_printf("[gltx][aggrcheck]dst mac mismatch "\
|
|
"[%2x:%2x:%2x:%2x:%2x:%2x] vs [%2x:%2x:%2x:%2x:%2x:%2x]\n",
|
|
in_pkt->txinfo.dst_mac[0],in_pkt->txinfo.dst_mac[1],
|
|
in_pkt->txinfo.dst_mac[2],in_pkt->txinfo.dst_mac[3],
|
|
in_pkt->txinfo.dst_mac[4],in_pkt->txinfo.dst_mac[5],
|
|
aggr_pkt->txinfo.dst_mac[0],aggr_pkt->txinfo.dst_mac[1],
|
|
aggr_pkt->txinfo.dst_mac[2],aggr_pkt->txinfo.dst_mac[3],
|
|
aggr_pkt->txinfo.dst_mac[4],aggr_pkt->txinfo.dst_mac[5]);
|
|
*/
|
|
}
|
|
|
|
if (!iot_mac_addr_cmp(in_pkt->txinfo.org_mac,
|
|
aggr_pkt->txinfo.org_mac)) {
|
|
ret |= 1<< REASON_ORG_MAC_MISMATCH;
|
|
/* iot_cus_printf("[gltx][aggrcheck]org mac mismatch "\
|
|
"in[%2x:%2x:%2x:%2x:%2x:%2x] vs aggr[%2x:%2x:%2x:%2x:%2x:%2x]\n",
|
|
in_pkt->txinfo.org_mac[0],in_pkt->txinfo.org_mac[1],
|
|
in_pkt->txinfo.org_mac[2],in_pkt->txinfo.org_mac[3],
|
|
in_pkt->txinfo.org_mac[4],in_pkt->txinfo.org_mac[5],
|
|
aggr_pkt->txinfo.org_mac[0],aggr_pkt->txinfo.org_mac[1],
|
|
aggr_pkt->txinfo.org_mac[2],aggr_pkt->txinfo.org_mac[3],
|
|
aggr_pkt->txinfo.org_mac[4],aggr_pkt->txinfo.org_mac[5]);*/
|
|
}
|
|
|
|
if (!iot_mac_addr_cmp(in_pkt->txinfo.src_mac,
|
|
aggr_pkt->txinfo.src_mac)) {
|
|
ret |= 1<< REASON_ORG_MAC_MISMATCH;
|
|
/* iot_cus_printf("[gltx][aggrcheck]src mac mismatch "\
|
|
"in[%2x:%2x:%2x:%2x:%2x:%2x] vs aggr[%2x:%2x:%2x:%2x:%2x:%2x]\n",
|
|
in_pkt->txinfo.src_mac[0],in_pkt->txinfo.src_mac[1],
|
|
in_pkt->txinfo.src_mac[2],in_pkt->txinfo.src_mac[3],
|
|
in_pkt->txinfo.src_mac[4],in_pkt->txinfo.src_mac[5],
|
|
aggr_pkt->txinfo.src_mac[0],aggr_pkt->txinfo.src_mac[1],
|
|
aggr_pkt->txinfo.src_mac[2],aggr_pkt->txinfo.src_mac[3],
|
|
aggr_pkt->txinfo.src_mac[4],aggr_pkt->txinfo.src_mac[5]);*/
|
|
}
|
|
}
|
|
|
|
if ((in_pkt->txinfo.retry_cnt != aggr_pkt->txinfo.retry_cnt)
|
|
|| (in_pkt->txinfo.retry_intvl != aggr_pkt->txinfo.retry_intvl)) {
|
|
ret = 1<< REASON_RETRY_CFG_MISMATCH;
|
|
}
|
|
|
|
if (in_pkt->txinfo.need_ack != aggr_pkt->txinfo.need_ack) {
|
|
ret |= 1<< REASON_ACK_OPT_MISMATCH;
|
|
}
|
|
|
|
if (in_pkt->txinfo.send_type != aggr_pkt->txinfo.send_type) {
|
|
ret |= 1<< REASON_TYPE_MISMATCH;
|
|
}
|
|
|
|
if (in_pkt->txinfo.force_tx_connless != aggr_pkt->txinfo.force_tx_connless) {
|
|
ret |= 1<< REASON_SEND_TYPE_FLAG_MISMATCH;
|
|
}
|
|
|
|
if (ret !=0){
|
|
iot_cus_printf("[gltx]no aggred reason: %x\n",ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* internal command,
|
|
* proto layer request to set device mac, plc_txrx layer received,
|
|
* and set the device mac.
|
|
* both cco and sta role need handle this event
|
|
* @param mac: the mac address get from proto layer.
|
|
*/
|
|
void plctxrx_set_device_mac(uint8_t *mac, uint8_t dev_type)
|
|
{
|
|
iot_plc_cfg_set_req_t cfg;
|
|
|
|
IOT_ASSERT(mac);
|
|
iot_cus_printf("[gltx]set_device_mac:"
|
|
"%02x,%02x,%02x,%02x,%02x,%02x dev_type=%d\n",
|
|
mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],dev_type);
|
|
|
|
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 = dev_type;
|
|
iot_plc_set_cfg(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
|
|
}
|
|
|
|
#if INCLUDE_AT_COMMAND_MODULE
|
|
/* set system time from Gree keep-alive packet.
|
|
* will plug-into central beacon, and broadcast to all sta.
|
|
* sta will get time and generate Gree keep-alive packet self and
|
|
* report to host mcu.
|
|
*/
|
|
static uint32_t plctxrx_cco_set_keepalive(time_data_t *time)
|
|
{
|
|
uint32_t ret;
|
|
|
|
(void)time;
|
|
|
|
/* save to local */
|
|
ret = iot_plc_set_beacon_data(greeapp->app_handle,
|
|
(uint8_t*)&plctxrx_context.verinfo, sizeof(plctxrx_cmd_vendor_info_t));
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* cco dev use this api.
|
|
* add mac to whitelist or delete mac from whitelist.
|
|
*/
|
|
static void plctxrx_set_dev_whitelist(plctxrx_cmd_whitelist_t *list)
|
|
{
|
|
uint8_t action = 0;
|
|
IOT_ASSERT(list);
|
|
iot_cus_printf("action:%d cnt:%d needack:%d\n", list->action,
|
|
list->listcnt, plctxrx_context.command.need_ack);
|
|
/* transform action between protocol and plctxrx */
|
|
switch (list->action) {
|
|
case GE_PROTO_ACTION_DEL:
|
|
action = IOT_PLC_WL_DEL;
|
|
break;
|
|
case GE_PROTO_ACTION_ADD:
|
|
action = IOT_PLC_WL_ADD;
|
|
break;
|
|
case GE_PROTO_WL_DISABLE:
|
|
action = IOT_PLC_WL_DISABLE;
|
|
break;
|
|
case GE_PROTO_WL_ENABLE:
|
|
action = IOT_PLC_WL_ENABLE;
|
|
break;
|
|
case GE_PROTO_ACTION_DEL_ALL:
|
|
action = IOT_PLC_WL_DEL_ALL;
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
if (IOT_PLC_WL_ENABLE == action ||
|
|
IOT_PLC_WL_DISABLE == action ||
|
|
IOT_PLC_WL_DEL_ALL == action) {
|
|
iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
action, 0, NULL);
|
|
} else if (list->listcnt > 0) {
|
|
for (uint8_t i = 0; i < list->listcnt; i++) {
|
|
iot_cus_printf("[gltx]whitelist-MAC[%d]"
|
|
":%x:%x:%x:%x:%x:%x\n", i,
|
|
list->maclist[i][0], list->maclist[i][1],
|
|
list->maclist[i][2], list->maclist[i][3],
|
|
list->maclist[i][4], list->maclist[i][5]);
|
|
}
|
|
iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
action, list->listcnt, list->maclist[0]);
|
|
} else {
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_WHITELIST, PLCTXRX_OP_CFM,
|
|
NULL, PLCTXRX_RESP_ERROR, NULL, 0);
|
|
}
|
|
}
|
|
|
|
/* cco dev use only. query current white list in cvg */
|
|
static void plctxrx_request_dev_whitelist(iot_plc_wl_query_t *list)
|
|
{
|
|
iot_cus_printf("request_dev_whitelist--start:%d count:%d\n",
|
|
list->start, list->count);
|
|
iot_plc_query_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
list->start, list->count);
|
|
}
|
|
|
|
/* for control mac info, set, query or response */
|
|
static void plctxrx_handle_mac(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
plctxrx_handle_mac_t *mac_hd = (plctxrx_handle_mac_t*)arg->arg;
|
|
iot_mac_addr_cpy(plctxrx_context.local_state.sta_mac, mac_hd->mac);
|
|
plctxrx_set_device_mac(mac_hd->mac, mac_hd->dev_type);
|
|
break;
|
|
}
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
plctxrx_handle_mac_t mac_hd;
|
|
mac_hd.dev_type = 0;
|
|
iot_mac_addr_cpy(mac_hd.mac, plctxrx_context.local_state.sta_mac);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_MAC, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, (void*)&mac_hd, sizeof(plctxrx_handle_mac_t));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_time(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
#if INCLUDE_AT_COMMAND_MODULE
|
|
uint32_t ret;
|
|
IOT_ASSERT(arg);
|
|
|
|
time_data_t *time = (time_data_t*)arg->arg;
|
|
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
/* set time */
|
|
ret = plctxrx_cco_set_keepalive(time);
|
|
if(ret != ERR_OK)
|
|
{
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_TIME, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_ERROR, NULL, 0);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#else
|
|
(void)arg;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_sys_info(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
/* query system info */
|
|
plctxrx_cmd_systeminfo_t sys_info;
|
|
os_mem_set(&sys_info, 0, sizeof(plctxrx_cmd_systeminfo_t));
|
|
|
|
/* get system info and response */
|
|
iot_board_get_boot_reason(&sys_info.last_reboot_reason);
|
|
sys_info.total_reboot_times =
|
|
iot_board_get_reset_count(SYSTEM_RESET_PWR) +
|
|
iot_board_get_reset_count(SYSTEM_RESET_WDT) +
|
|
iot_board_get_reset_count(SYSTEM_RESET_SOFT);
|
|
sys_info.os_running_time = (uint32_t)os_boot_time64() / 1000;
|
|
sys_info.software_ver = iot_version_hex();
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_SYSTEMINFO, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, (void*)&sys_info, sizeof(plctxrx_cmd_systeminfo_t));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_uart(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
#if INCLUDE_AT_COMMAND_MODULE
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
/* set uart */
|
|
plctxrx_handle_uart_t *uart = (plctxrx_handle_uart_t*)arg->arg;
|
|
grapp_uart_cfg_t cfg;
|
|
os_mem_set(&cfg, 0 , sizeof(grapp_uart_cfg_t));
|
|
cfg.port = uart->uart_port;
|
|
cfg.baud = uart->bandrate;
|
|
cfg.parity = uart->parity;
|
|
cfg.data = uart->data_len;
|
|
cfg.stop = uart->stop_bit;
|
|
|
|
if (iot_grapp_set_uart(greeapp->uart_com, &cfg)) {
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_UART, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, NULL, 0);
|
|
} else {
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_UART, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_ERROR, NULL, 0);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
#else
|
|
(void)arg;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_topo(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
plctxrx_cmd_query_topo_t *cmd;
|
|
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
cmd = (plctxrx_cmd_query_topo_t*)arg->arg;
|
|
/* cmd->ver :1,2 topo info */
|
|
iot_cus_printf("txrx query topo: ver:%d, start:%d cnt:%d\n",
|
|
cmd->ver, cmd->start, cmd->cnt);
|
|
if (cmd->ver != IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0) {
|
|
iot_plc_query_nw_topo(greeapp->app_handle,
|
|
IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
|
|
cmd->ver,
|
|
IOT_PLC_QUERY_TOPO_START_AS_TEI,
|
|
cmd->start, cmd->cnt);
|
|
} else {
|
|
iot_cus_printf("topo V0 not support\n");
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
#if INCLUDE_AT_COMMAND_MODULE
|
|
static void plctxrx_handle_send(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
plctxrx_handle_send_t *send = (plctxrx_handle_send_t*)arg->arg;
|
|
|
|
IOT_ASSERT(arg);
|
|
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_EXECUTE:
|
|
{
|
|
iot_cus_printf("\n[gltx]plctxrx_handle_send:%p datalen:%d\n",
|
|
send->data, send->dlen);
|
|
if (send->dlen <= TXRX_AGGR_PKT_LEN) {
|
|
iot_common_bin_dump(send->data , send->dlen);
|
|
|
|
/* post msg direct to send enginee */
|
|
iot_plctxrx_proto_data_send_cbk(send->data, send->dlen,
|
|
&send->txinfo);
|
|
} else {
|
|
iot_cus_printf("\n[gltx][err] send->dlen need smaller than %d\n",
|
|
TXRX_AGGR_PKT_LEN);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_SEND, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, NULL, 0);
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
static void plctxrx_handle_whitelist(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
plctxrx_cmd_whitelist_t *list = (plctxrx_cmd_whitelist_t*)arg->arg;
|
|
plctxrx_set_dev_whitelist(list);
|
|
break;
|
|
}
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
iot_plc_wl_query_t *list = (iot_plc_wl_query_t*)arg->arg;
|
|
if (list->count > 0)
|
|
plctxrx_request_dev_whitelist(list);
|
|
else
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_WHITELIST, PLCTXRX_OP_RESPONSE,
|
|
NULL, PLCTXRX_RESP_ERROR, NULL, 0);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_find_network(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
/* to find avail network */
|
|
iot_plc_query_nb_nw_info(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_join_network(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
plctxrx_cmd_join_network_t *net_info =
|
|
(plctxrx_cmd_join_network_t*)arg->arg;
|
|
/* join the selected nid network */
|
|
//(void)join_info;
|
|
// MCU will send command to indicate which network we connect
|
|
iot_cus_printf("join_network--mac:%x:%x:%x:%x:%x:%x\n",
|
|
net_info->mac[0],net_info->mac[1],net_info->mac[2],
|
|
net_info->mac[3],net_info->mac[4],net_info->mac[5]
|
|
);
|
|
iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
IOT_PLC_WL_ADD, 1, net_info->mac);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_leave_network(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
/* leave the network */
|
|
plctxrx_cmd_leave_net_t *leave_net = (plctxrx_cmd_leave_net_t*)arg->arg;
|
|
iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
IOT_PLC_WL_DEL, leave_net->cnt, (uint8_t*)leave_net->mac);
|
|
iot_cus_printf("[gltx]leave_network mac:%x:%x:%x:%x:%x:%x\n",
|
|
leave_net->mac[0][0],leave_net->mac[0][1],leave_net->mac[0][2],
|
|
leave_net->mac[0][3],leave_net->mac[0][4],leave_net->mac[0][5]);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_vendor_info(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
(void)arg;
|
|
}
|
|
|
|
static void plctxrx_handle_vendor_data(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_EXECUTE:
|
|
{
|
|
/* send data, cco will add to beacon for broadcast */
|
|
iot_plc_set_beacon_data(greeapp->app_handle, (uint8_t*)arg->arg,
|
|
(uint8_t)arg->dlen);
|
|
/* wait IOT_PLC_MSG_BEACON_DATA_SET_RPT */
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_ntb(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
plctxrx_cmd_ntb_resp_t resp_ntb = { 0 };
|
|
/* query network time base */
|
|
|
|
#if HW_PLATFORM == HW_PLATFORM_SIMU
|
|
resp_ntb.ntb = os_boot_time32()/25;
|
|
#else
|
|
resp_ntb.ntb = iot_plc_get_ntb(greeapp->app_handle);
|
|
#endif
|
|
iot_cus_printf("[getx]get ntb=%lu\n", resp_ntb.ntb);
|
|
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_NTB, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, (void*)&resp_ntb, sizeof(plctxrx_cmd_ntb_resp_t));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_swver(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
/* query software version info */
|
|
plctxrx_cmd_software_ver_resp_t swver = { 0 };
|
|
swver.version = iot_version_hex();
|
|
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_SWVER, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, (void*)&swver,
|
|
sizeof(plctxrx_cmd_software_ver_resp_t));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_bootinfo(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
/* query boot info */
|
|
plctxrx_cmd_boot_info_resp_t boot_info = { 0 };
|
|
|
|
iot_board_get_boot_reason(&boot_info.last_reboot_reason);
|
|
boot_info.total_boot_cnt = (uint16_t)(
|
|
iot_board_get_reset_count(SYSTEM_RESET_PWR) +
|
|
iot_board_get_reset_count(SYSTEM_RESET_WDT) +
|
|
iot_board_get_reset_count(SYSTEM_RESET_SOFT));
|
|
boot_info.os_running_time = (uint32_t)os_boot_time64() / 1000;
|
|
/* post boot info to upper layer */
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_BOOTINFO, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, (void*)&boot_info,
|
|
sizeof(plctxrx_cmd_boot_info_resp_t));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_net_sts(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
uint8_t tmp_mac[IOT_MAC_ADDR_LEN] = { 0 };
|
|
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
if (plctxrx_context.local_state.role == IOT_PLC_DEV_ROLE_CCO &&
|
|
iot_mac_addr_cmp(ge_bcast_addr, arg->arg)) {
|
|
/* query all joined states info, for cco */
|
|
iot_cus_printf("[gltx]query all net states\n");
|
|
iot_plc_query_neighbor_dev(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, 2, STA_DEV_MAX,
|
|
IOT_PLC_QUERY_TOPO_START_AS_TEI);
|
|
} else if (iot_mac_addr_cmp(tmp_mac, arg->arg)){
|
|
iot_cus_printf("[gltx]query local net states\n");
|
|
iot_plc_query_neighbor_dev(
|
|
greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT,
|
|
plctxrx_context.local_state.sta_tei, 1,
|
|
IOT_PLC_QUERY_TOPO_START_AS_TEI);
|
|
} else {
|
|
/* find the mac whether in local list */
|
|
iot_mac_addr_cpy(tmp_mac, arg->arg);
|
|
int16_t index = iot_plctxrx_get_sta_indx_by_mac(tmp_mac);
|
|
if (index >= 0) {
|
|
iot_cus_printf("[gltx]query tei=%d net states\n",
|
|
plctxrx_context.sta[index].sta_tei);
|
|
iot_plc_query_neighbor_dev(
|
|
greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT,
|
|
plctxrx_context.sta[index].sta_tei, 1,
|
|
IOT_PLC_QUERY_TOPO_START_AS_TEI);
|
|
} else {
|
|
iot_cus_printf("[gltx]query net state, tei error!\n");
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_NET_STS, PLCTXRX_OP_RESPONSE,
|
|
NULL, PLCTXRX_RESP_ERROR, NULL, 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief plctxrx_handle_node_info() - node infomation handler
|
|
* @param arg the command handle argument include operation code and
|
|
* other parameter
|
|
*/
|
|
static void plctxrx_handle_node_info(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
plctxrx_cmd_query_node_info_t *query_node_info =
|
|
(plctxrx_cmd_query_node_info_t*)arg->arg;
|
|
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
plctxrx_context.node_info_type = query_node_info->type;
|
|
if (iot_mac_addr_cmp(query_node_info->mac, ge_bcast_addr)) {
|
|
/* query all node info use query topo v0 */
|
|
iot_plc_query_nw_topo(greeapp->app_handle,
|
|
IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
|
|
IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0,
|
|
IOT_PLC_QUERY_TOPO_START_AS_TEI, 1,
|
|
QUERY_NODE_INFO_MAX_CNT_ONCE);
|
|
} else {
|
|
/* query one node info according to mac address use query node v0 */
|
|
iot_plc_query_node_info(greeapp->app_handle,
|
|
IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO,
|
|
IOT_PLC_CCO_TOPO_REQ_DATA_VER_V0,
|
|
query_node_info->mac, 1);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief plctxrx_handle_nw_info() - nwtwork infomation handler
|
|
* @param arg the command handler argument include operation code and
|
|
* other parameter
|
|
*/
|
|
static void plctxrx_handle_nw_info(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
/* query network info */
|
|
iot_plc_query_nw_info(greeapp->app_handle,
|
|
IOT_PLCTXRX_CCO_REQ_ID_GET_TOPO);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief plctxrx_handle_wdg() - watchdog handler
|
|
* @param arg the command handler argument include operation code and
|
|
* other parameter
|
|
*/
|
|
static void plctxrx_handle_wdg(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
plctxrx_cmd_wdg_t *wdg = (plctxrx_cmd_wdg_t *)arg->arg;
|
|
iot_plc_wdg_set(greeapp->app_handle, wdg->action, wdg->interval);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief plctxrx_handle_mode_config() - mode config handler
|
|
* @param arg the command handler argument include operation code and
|
|
* other parameter
|
|
*/
|
|
static void plctxrx_handle_mode_config(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
dev_test_mode_cfg_t *cfg = (dev_test_mode_cfg_t *)arg->arg;
|
|
iot_dev_test_send_mode_config(cfg);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_MODE_CONF, PLCTXRX_OP_CFM, NULL,
|
|
PLCTXRX_RESP_OK, NULL, 0);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* TODO add plc_txrx_statics_t query command here */
|
|
|
|
/* internal command,
|
|
* cco device receive cmd to start group net, set group net state.
|
|
* @param arg: command message
|
|
*/
|
|
static void plctxrx_handle_txrx_sts(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
plc_txrx_statics_t *txrx_state =
|
|
&plctxrx_context.local_state.txrx_status;
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_TXRX_STS, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, txrx_state, sizeof(plc_txrx_statics_t));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_start_group_net(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
/* disable whitelist and set status */
|
|
iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
IOT_PLC_WL_DISABLE, 0, NULL);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* internal command,
|
|
* cco device receive cmd to end group net, set end group net state.
|
|
* @param arg: command message
|
|
*/
|
|
static void plctxrx_handle_end_group_net(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
/* add white list and then enable whitelist */
|
|
iot_plc_set_whitelist(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
IOT_PLC_WL_ENABLE, 0, NULL);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* internal command,
|
|
* set, query or response the tx power.
|
|
* @param arg: command message
|
|
*/
|
|
static void plctxrx_handle_tx_pwr(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
plctxrx_cmd_tx_pwr_t *tx_pwr = (plctxrx_cmd_tx_pwr_t*)arg->arg;
|
|
iot_plc_set_tx_power_cap(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, &tx_pwr->tx_pwr, NULL);
|
|
break;
|
|
}
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
iot_plc_query_band_info(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
|
|
}
|
|
|
|
/* internal command,
|
|
* set network id
|
|
* @param arg: command message
|
|
*/
|
|
static void plctxrx_handle_nid(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
plctxrx_cmd_nid_t *net_nid = (plctxrx_cmd_nid_t*)arg->arg;
|
|
if (net_nid->nid > 99) {
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_NID,
|
|
PLCTXRX_OP_CFM, NULL, PLCTXRX_RESP_ERROR, NULL, 0);
|
|
} else {
|
|
iot_cus_printf("[gltx]set nid=%d\n", net_nid->nid);
|
|
iot_plc_set_nid(greeapp->app_handle, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
net_nid->nid);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* internal command,
|
|
* delete the sta's information after sta leaving network positivly
|
|
* @param arg: command message
|
|
*/
|
|
static void plctxrx_handle_sta_pos_leave(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
plctxrx_cmd_sta_pos_leave_ind_t *sta_info =
|
|
(plctxrx_cmd_sta_pos_leave_ind_t*)arg->arg;
|
|
iot_plctxrx_del_sta_by_mac(sta_info->mac);
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_STA_POS_LEAVE,
|
|
PLCTXRX_OP_CFM, NULL, PLCTXRX_RESP_OK, NULL, 0);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* internal command,
|
|
* band id set and query
|
|
* @param arg: command message
|
|
*/
|
|
static void plctxrx_handle_band_id(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
if (plctxrx_context.local_state.role == IOT_PLC_DEV_ROLE_CCO ||
|
|
greeapp->uart_mode == GR_DEV_TEST_OP_MODE) {
|
|
plctxrx_cmd_band_info_t *band_info =
|
|
(plctxrx_cmd_band_info_t*)arg->arg;
|
|
iot_cus_printf("[gltx]set freq_band=%d\n",band_info->band_id);
|
|
iot_plc_set_freq_band(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, band_info->band_id);
|
|
}
|
|
break;
|
|
}
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
if (plctxrx_context.local_state.role == IOT_PLC_DEV_ROLE_CCO) {
|
|
iot_cus_printf("[gltx]query freq_band\n");
|
|
iot_plc_query_band_info(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* internal command,
|
|
* STA set band bitmap
|
|
* @param arg: command message
|
|
*/
|
|
static void plctxrx_handle_fb_bitmap(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
plctxrx_cmd_fb_bitmap_t *band_bitmap =
|
|
(plctxrx_cmd_fb_bitmap_t*)arg->arg;
|
|
iot_plc_set_scan_band_bitmap(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, band_bitmap->fb_bitmap,
|
|
IOT_GE_FB_SCAN_BITMAP_SIZE);
|
|
break;
|
|
}
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
uint8_t is_scan_bitmap = arg->arg[0];
|
|
IOT_ASSERT(is_scan_bitmap <= 1);
|
|
iot_plc_query_band_bitmap(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, is_scan_bitmap);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void plctxrx_handle_fix_rate_mode(plctxrx_cmd_arg_t *arg)
|
|
{
|
|
IOT_ASSERT(arg);
|
|
switch (arg->cid.opcode) {
|
|
case PLCTXRX_OP_CONFIG:
|
|
{
|
|
/* 1:Fix rate mode 2:auto rate mode */
|
|
uint8_t rate_mode;
|
|
plctxrx_cmd_fix_rate_t *fix_rate =
|
|
(plctxrx_cmd_fix_rate_t*)arg->arg;
|
|
IOT_ASSERT(fix_rate->fix_rate_mode <= 1);
|
|
if (1 == fix_rate->fix_rate_mode) {
|
|
/* fix rate mode */
|
|
rate_mode = GE_PLC_RATE_ADAPT_FIX_MODE;
|
|
} else {
|
|
/* auto rate mode */
|
|
rate_mode = GE_PLC_RATE_ADAPT_AUTO_MODE;
|
|
}
|
|
plctxrx_context.local_state.rate_node = rate_mode;
|
|
iot_plc_set_rate_adapt_mode(greeapp->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, IOT_PLC_RATE_ADAPT_NODE_NETWORK,
|
|
rate_mode, IOT_PLC_RATE_ADAPT_RATE_LOW);
|
|
break;
|
|
}
|
|
case PLCTXRX_OP_QUERY:
|
|
{
|
|
uint8_t rate_node_rpt;
|
|
if (plctxrx_context.local_state.rate_node == 1) {
|
|
rate_node_rpt = 1;
|
|
} else {
|
|
rate_node_rpt = 0;
|
|
}
|
|
plctxrx_cmd_resp_data(PLCTXRX_CID_FIXED_RATE, PLCTXRX_OP_RESPONSE, NULL,
|
|
PLCTXRX_RESP_OK, (void*)&rate_node_rpt, sizeof(rate_node_rpt));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static plctxrx_handle handle_table[PLCTXRX_CID_MAX] =
|
|
{
|
|
plctxrx_handle_mac, //PLCTXRX_CID_MAC
|
|
plctxrx_handle_time, //PLCTXRX_CID_TIME
|
|
plctxrx_handle_bootinfo, //PLCTXRX_CID_BOOTINFO
|
|
plctxrx_handle_uart, //PLCTXRX_CID_UART
|
|
plctxrx_handle_topo, //PLCTXRX_CID_TOPO
|
|
#if INCLUDE_AT_COMMAND_MODULE
|
|
plctxrx_handle_send, //PLCTXRX_CID_SEND
|
|
#endif
|
|
plctxrx_handle_whitelist, //PLCTXRX_CID_WHITELIST
|
|
plctxrx_handle_find_network, //PLCTXRX_CID_FIND_NETWORK
|
|
plctxrx_handle_join_network, //PLCTXRX_CID_JOIN_NETWORK
|
|
plctxrx_handle_leave_network, //PLCTXRX_CID_LEAVE_NETWORK
|
|
NULL, //PLCTXRX_CID_CCO_STATE
|
|
plctxrx_handle_vendor_info, //PLCTXRX_CID_VENDOR_INFO
|
|
plctxrx_handle_swver, //PLCTXRX_CID_SWVER
|
|
plctxrx_handle_sys_info, //PLCTXRX_CID_SYSTEMINFO
|
|
plctxrx_handle_net_sts, //PLCTXRX_CID_NET_STS
|
|
plctxrx_handle_start_group_net, //PLCTXRX_CID_START_GROUP_NET
|
|
plctxrx_handle_end_group_net, //PLCTXRX_CID_END_GROUP_NET
|
|
plctxrx_handle_txrx_sts, //PLCTXRX_CID_TXRX_STS
|
|
plctxrx_handle_tx_pwr, //PLCTXRX_CID_TX_PWR
|
|
plctxrx_handle_nid, //PLCTXRX_CID_NID
|
|
NULL, //PLCTXRX_CID_COMM_FAULT
|
|
NULL, //PLCTXRX_CID_GRAPP_REG_CONF
|
|
plctxrx_handle_sta_pos_leave, //PLCTXRX_CID_STA_POS_LEAVE
|
|
plctxrx_handle_band_id, //PLCTXRX_CID_BAND_ID
|
|
plctxrx_handle_vendor_data, //PLCTXRX_CID_VENDOR_DATA
|
|
plctxrx_handle_ntb, //PLCTXRX_CID_NTB
|
|
plctxrx_handle_fb_bitmap, //PLCTXRX_CID_FB_BITMAP
|
|
plctxrx_handle_fix_rate_mode, //PLCTXRX_CID_FIXED_RATE
|
|
plctxrx_handle_node_info, //PLCTXRX_CID_NODE_INFO
|
|
plctxrx_handle_nw_info, //PLCTXRX_CID_NW_INFO
|
|
plctxrx_handle_wdg, //PLCTXRX_CID_WDG
|
|
plctxrx_handle_mode_config //PLCTXRX_CID_MODE_CONF
|
|
|
|
};
|
|
|
|
void plctxrx_cmd_resp_send_to_proto(iot_pkt_t *pkt)
|
|
{
|
|
IOT_ASSERT(pkt);
|
|
if (greeapp->uart_mode == GR_AT_OP_MODE) {
|
|
plctxrx_context.at_cb.at_cmd_resp_cb(pkt);
|
|
} else if (greeapp->uart_mode == GR_MCU_OP_MODE) {
|
|
plctxrx_context.gree_cb.gree_network_event_cb(pkt);
|
|
} else if (greeapp->uart_mode == GR_DEV_TEST_OP_MODE) {
|
|
plctxrx_context.dev_test_cb.dev_test_event_cb(pkt);
|
|
} else {
|
|
/* drop this command. */
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
/*
|
|
cur_cid: current handling cid
|
|
cur_opcode: current handling opcode
|
|
cur_resp_pkt : current response pkt.
|
|
each handle cmd first push in saveq, when handle complete, then,
|
|
cmd will pop from saveq and push in freeq.
|
|
*/
|
|
void plctxrx_cmd_handle_next(uint8_t cur_cid, uint8_t cur_opcode,
|
|
iot_pkt_t *cur_resp_pkt)
|
|
{
|
|
iot_pkt_t *savecmd_pkt;
|
|
plctxrx_cmd_arg_t *arg;
|
|
plctxrx_cmdsave_node_t *cmd_node;
|
|
|
|
(void)cur_opcode;
|
|
IOT_ASSERT(plctxrx_context.command.cmd_running);
|
|
|
|
cmd_node =
|
|
iot_plctxrx_commandnode_pop_front(&plctxrx_context.command.save_q,
|
|
PLCTXRX_SAVEQ);
|
|
if(cmd_node == NULL){
|
|
goto no_next;
|
|
}
|
|
savecmd_pkt = (iot_pkt_t *)cmd_node->data;
|
|
arg = (plctxrx_cmd_arg_t*)iot_pkt_data(savecmd_pkt);
|
|
iot_cus_printf("cur_cid = %d,arg->cid.cid = %d\n",cur_cid,arg->cid.cid);
|
|
if (cur_cid != arg->cid.cid) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
/* check if response need send to protocol layer */
|
|
if (arg->need_ack) {
|
|
plctxrx_cmd_resp_send_to_proto(cur_resp_pkt);
|
|
} else {
|
|
iot_pkt_free(cur_resp_pkt);
|
|
}
|
|
|
|
iot_cus_printf("[gltx]handle_next--Need ack: %d!\n", arg->need_ack);
|
|
/* free packet saved in cmdnode */
|
|
iot_pkt_free(savecmd_pkt);
|
|
/* free current node */
|
|
cmd_node->data = NULL;
|
|
/* push node into free cmd queue */
|
|
iot_plctxrx_commandnode_push_backend(&plctxrx_context.command.free_q,
|
|
&cmd_node->node, PLCTXRX_FREEQ);
|
|
/* check if next command is exist */
|
|
cmd_node =
|
|
iot_plctxrx_commandnode_get_front(&plctxrx_context.command.save_q,
|
|
PLCTXRX_SAVEQ);
|
|
if (cmd_node) {
|
|
/* handle next command */
|
|
IOT_ASSERT(cmd_node->data);
|
|
arg = (plctxrx_cmd_arg_t*)iot_pkt_data((iot_pkt_t *)cmd_node->data);
|
|
iot_cus_printf("[gltx]handle_next--"
|
|
"next cmd=%d, opcode=%d\n", arg->cid.cid, arg->cid.opcode);
|
|
plctxrx_context.command.cur_cid = arg->cid;
|
|
plctxrx_context.command.cmd_running = true;
|
|
plctxrx_context.command.need_ack = (bool_t)arg->need_ack;
|
|
plctxrx_context.command.table.handle[arg->cid.cid](arg);
|
|
} else {
|
|
no_next:
|
|
plctxrx_context.command.cmd_running = false;
|
|
plctxrx_context.command.need_ack = false;
|
|
iot_cus_printf("[gltx]handle_next--NO next cmd exists!\n");
|
|
}
|
|
}
|
|
|
|
void plctxrx_cmd_resp_data_pkt(uint8_t handle_next, uint8_t oper_code,
|
|
iot_pkt_t *pkt)
|
|
{
|
|
IOT_ASSERT(pkt);
|
|
|
|
if(handle_next)
|
|
{
|
|
plctxrx_cmd_handle_next(plctxrx_context.command.cur_cid.cid,
|
|
oper_code, pkt);
|
|
} else {
|
|
plctxrx_cmd_resp_send_to_proto(pkt);
|
|
}
|
|
}
|
|
|
|
void plctxrx_cmd_resp_data(uint8_t cmd_id, uint8_t oper_code,
|
|
plctxrx_resp_idx_t *index, uint16_t resp, void *data, uint16_t data_len)
|
|
{
|
|
|
|
iot_pkt_t *pkt = iot_pkt_alloc(data_len + sizeof(plctxrx_cmd_resp_t),
|
|
IOT_GREE_APP_MID);
|
|
iot_cus_printf("[gltx]resp_data--cid=%d,op_code=%d,resp=%d\n",
|
|
cmd_id, oper_code, resp);
|
|
|
|
if (!pkt) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
plctxrx_cmd_resp_t *cmd_resp = (plctxrx_cmd_resp_t*)iot_pkt_data(pkt);
|
|
cmd_resp->cid.cid = cmd_id;
|
|
cmd_resp->cid.opcode = oper_code;
|
|
if (index) {
|
|
cmd_resp->index.current = index->current;
|
|
cmd_resp->index.total = index->total;
|
|
} else {
|
|
cmd_resp->index.current = 1;
|
|
cmd_resp->index.total = 1;
|
|
}
|
|
|
|
cmd_resp->resp = resp;
|
|
|
|
if (data_len && data) {
|
|
os_mem_cpy(cmd_resp->data, data, data_len);
|
|
cmd_resp->dlen = data_len;
|
|
|
|
iot_pkt_put(pkt, sizeof(plctxrx_cmd_resp_t) + data_len);
|
|
}
|
|
|
|
if (oper_code != PLCTXRX_OP_INDICATION &&
|
|
(cmd_resp->index.total == cmd_resp->index.current)) {
|
|
plctxrx_cmd_handle_next(plctxrx_context.command.cur_cid.cid,
|
|
oper_code, pkt);
|
|
} else {
|
|
plctxrx_cmd_resp_send_to_proto(pkt);
|
|
}
|
|
}
|
|
|
|
void plctxrx_cmd_msg_handle(iot_pkt_t *arg_pkt)
|
|
{
|
|
plctxrx_cmd_arg_t *arg = (plctxrx_cmd_arg_t*)iot_pkt_data(arg_pkt);
|
|
IOT_ASSERT(arg);
|
|
|
|
uint8_t cid = arg->cid.cid & 0xFFFFFF;
|
|
plctxrx_cmdsave_node_t *cmd_node;
|
|
|
|
|
|
iot_cus_printf("[gltx]cmd_msg_handle--cid=%d,op_code=%d\n",
|
|
cid, arg->cid.opcode);
|
|
if (cid >= PLCTXRX_CID_MAX) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
cmd_node =
|
|
iot_plctxrx_commandnode_pop_front(&plctxrx_context.command.free_q,
|
|
PLCTXRX_FREEQ);
|
|
|
|
IOT_ASSERT(cmd_node);
|
|
|
|
if(!cmd_node)
|
|
{
|
|
iot_cus_printf("[gltx]cmd_freeq no free");
|
|
return;
|
|
}
|
|
/** Note: Any cmd will be pushed to save queue.
|
|
* And we will pop it out when response cmd.
|
|
*/
|
|
cmd_node->data = (void *)arg_pkt;
|
|
iot_plctxrx_commandnode_push_backend(&plctxrx_context.command.save_q,
|
|
&cmd_node->node, PLCTXRX_SAVEQ);
|
|
/* check if cmd_running is false. */
|
|
if (plctxrx_context.command.cmd_running == false)
|
|
{
|
|
plctxrx_context.command.cur_cid = arg->cid;
|
|
plctxrx_context.command.cmd_running = true;
|
|
plctxrx_context.command.need_ack = (bool_t)arg->need_ack;
|
|
plctxrx_context.command.table.handle[cid](arg);
|
|
} else {
|
|
iot_cus_printf("[gltx][war]pre-cmd:%d"\
|
|
" running cur-cmd:%d handle later!\n",
|
|
plctxrx_context.command.cur_cid.cid, arg->cid.cid);
|
|
}
|
|
}
|
|
|
|
/* proto layer send message, plctxrx layer use */
|
|
uint8_t plctxrx_cmd_send_mssage(iot_pkt_t *arg)
|
|
{
|
|
iot_plctxrx_post_msg(IOT_PLCTXRX_CMD_MSG, 0, arg, 0);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* end cmd handle */
|
|
|
|
uint8_t iot_plctxrx_proto_register(proto_recv_cb datacb,
|
|
proto_network_event_cb netcb, proto_vendr_cb vendrcb)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
|
|
if (datacb && netcb && vendrcb) {
|
|
plctxrx_context.gree_cb.gree_proto_recv_cb = datacb;
|
|
plctxrx_context.gree_cb.gree_network_event_cb = netcb;
|
|
plctxrx_context.gree_cb.gree_vendr_cb = vendrcb;
|
|
ret = ERR_OK;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint8_t iot_plctxrx_at_register(at_resp_cb at_cb)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
|
|
if (at_cb) {
|
|
plctxrx_context.at_cb.at_cmd_resp_cb = at_cb;
|
|
ret = ERR_OK;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint8_t iot_plctxrx_dev_test_register(dev_test_recv_cb_t recv_cb,
|
|
dev_test_event_cb_t event_cb)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
|
|
if (recv_cb && event_cb) {
|
|
plctxrx_context.dev_test_cb.dev_test_recv_cb = recv_cb;
|
|
plctxrx_context.dev_test_cb.dev_test_event_cb = event_cb;
|
|
ret = ERR_OK;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
two queues. cmd free queue and save queue. used for cache cmd and
|
|
process one by one
|
|
*/
|
|
void iot_plctxrx_cmd_freeq_init()
|
|
{
|
|
uint8_t i;
|
|
|
|
os_mem_set(g_cmdhandle_node, 0,
|
|
sizeof(plctxrx_cmdsave_node_t) * IOT_PLCTXRX_CMD_MAX_CNT);
|
|
/* link node */
|
|
for (i = 1; i < IOT_PLCTXRX_CMD_MAX_CNT; i++) {
|
|
g_cmdhandle_node[i-1].node.next = &g_cmdhandle_node[i].node;
|
|
}
|
|
/* point to tail */
|
|
g_cmdhandle_node[i-1].node.next = NULL;
|
|
|
|
plctxrx_context.command.free_q.first =
|
|
&g_cmdhandle_node[0].node;
|
|
plctxrx_context.command.free_q.tail =
|
|
&g_cmdhandle_node[i-1].node;
|
|
plctxrx_context.command.free_q.depth = IOT_PLCTXRX_CMD_MAX_CNT;
|
|
}
|
|
|
|
void iot_plctxrx_cmd_saveq_init()
|
|
{
|
|
os_mem_set(&plctxrx_context.command.save_q, 0,
|
|
sizeof(plctxrx_cmdsave_list_t));
|
|
}
|
|
|
|
plctxrx_cmdsave_node_t *
|
|
iot_plctxrx_commandnode_pop_front(plctxrx_cmdsave_list_t *cmdq,
|
|
cmd_queue_e_t qtype)
|
|
{
|
|
list_node_t *link;
|
|
plctxrx_cmdsave_node_t *ret_node;
|
|
if (cmdq->depth <= 0) {
|
|
IOT_ASSERT(!cmdq->first && !cmdq->tail);
|
|
iot_cus_printf("[gltx][war]cmd pop front:cmdq[%d] is empty!\n", qtype);
|
|
return NULL;
|
|
}
|
|
|
|
if (cmdq->first == cmdq->tail) {
|
|
IOT_ASSERT(1 == cmdq->depth);
|
|
link = cmdq->first;
|
|
cmdq->first = cmdq->tail = NULL;
|
|
link->next = NULL;
|
|
} else {
|
|
link = cmdq->first;
|
|
cmdq->first = link->next;
|
|
}
|
|
cmdq->depth--;
|
|
ret_node = container_of(link, plctxrx_cmdsave_node_t, node);
|
|
|
|
iot_cus_printf("[gltx]cmd pop front--queue type:%d"
|
|
"queue depth=%d,ret_node=0x%x!\n", qtype, cmdq->depth, ret_node);
|
|
return ret_node;
|
|
}
|
|
|
|
/**
|
|
* @brief iot_plctxrx_commandnode_get_front() - get the first data without pop
|
|
* @param cmdq: the list to get data
|
|
* @param cmdq: the type of the data
|
|
* @result : the first data of the list
|
|
*/
|
|
plctxrx_cmdsave_node_t *
|
|
iot_plctxrx_commandnode_get_front(plctxrx_cmdsave_list_t *cmdq,
|
|
cmd_queue_e_t qtype)
|
|
{
|
|
list_node_t *link;
|
|
plctxrx_cmdsave_node_t *ret_node;
|
|
if (cmdq->depth <= 0) {
|
|
IOT_ASSERT(!cmdq->first && !cmdq->tail);
|
|
iot_cus_printf("[gltx][war]cmd pop front:cmdq[%d] is empty!\n", qtype);
|
|
return NULL;
|
|
}
|
|
|
|
link = cmdq->first;
|
|
ret_node = container_of(link, plctxrx_cmdsave_node_t, node);
|
|
|
|
iot_cus_printf("[gltx]cmd nopop front--queue type:%d"
|
|
"queue depth=%d,ret_node=0x%x!\n", qtype, cmdq->depth, ret_node);
|
|
return ret_node;
|
|
}
|
|
|
|
void iot_plctxrx_commandnode_push_backend(plctxrx_cmdsave_list_t *cmdq,
|
|
list_node_t *node, cmd_queue_e_t qtype)
|
|
{
|
|
if (0 == cmdq->depth) {
|
|
IOT_ASSERT(!cmdq->first && !cmdq->tail);
|
|
cmdq->first = cmdq->tail = node;
|
|
} else {
|
|
cmdq->tail->next = node;
|
|
cmdq->tail = node;
|
|
}
|
|
node->next = NULL;
|
|
cmdq->depth++;
|
|
|
|
iot_cus_printf("[gltx]push_back--type:%d, queue depth=%d\n",
|
|
qtype, cmdq->depth);
|
|
return;
|
|
}
|
|
|
|
int iot_plctxrx_task_init(void)
|
|
{
|
|
uint8_t ret = ERR_OK;
|
|
uint16_t i;
|
|
iot_task_config_t task_cfg;
|
|
|
|
os_mem_set(&plctxrx_context, 0, sizeof(plctxrx_contxt_t));
|
|
|
|
os_mem_set(&gbl_protpkt, 0x0, sizeof(gbl_protpkt));
|
|
|
|
task_cfg.stack_size = 0;
|
|
task_cfg.task_prio = IOT_PLCUART_TASK_PRIO;
|
|
task_cfg.msg_size = sizeof(plctxrx_task_msg_t);
|
|
task_cfg.msg_cnt = IOT_PLCTXRX_TASK_POOL_SIZE;
|
|
task_cfg.queue_cnt = 1;
|
|
task_cfg.queue_cfg[0].quota = 0;
|
|
task_cfg.msg_exe_func = iot_plctxrx_task_msg_exe;
|
|
task_cfg.msg_cancel_func = iot_plctxrx_task_msg_cancel;
|
|
|
|
plctxrx_context.task_handle = iot_task_create(IOT_GREE_APP_MID, &task_cfg);
|
|
|
|
plctxrx_context.link_id = IOT_PLCTXRX_TASK_LIKE_ID;
|
|
|
|
if (NULL == plctxrx_context.task_handle)
|
|
{
|
|
ret = ERR_FAIL;
|
|
goto error_0;
|
|
}
|
|
|
|
plctxrx_context.datapath_timer = os_create_timer(IOT_GREE_APP_MID, 0,
|
|
iot_plctxrx_timer_data_path_func, &plctxrx_context);
|
|
if (plctxrx_context.datapath_timer == 0) {
|
|
ret = ERR_FAIL;
|
|
goto error_1;
|
|
}
|
|
|
|
plctxrx_context.txrx_timer = os_create_timer(IOT_GREE_APP_MID, 1,
|
|
iot_plctxrx_timer_txrx_path_func, &plctxrx_context);
|
|
if (plctxrx_context.txrx_timer == 0) {
|
|
ret = ERR_FAIL;
|
|
goto error_2;
|
|
}
|
|
|
|
os_start_timer(plctxrx_context.txrx_timer, IOT_PLCTXRX_TXRX_TIMER_INTVAL);
|
|
|
|
plctxrx_context.aggr_timer = os_create_timer(IOT_GREE_APP_MID, 0,
|
|
iot_plctxrx_timer_aggr_path_func, &plctxrx_context);
|
|
if (plctxrx_context.aggr_timer == 0) {
|
|
ret = ERR_FAIL;
|
|
goto error_3;
|
|
}
|
|
|
|
plctxrx_context.command.table.handle = handle_table;
|
|
|
|
|
|
/* init free queue and put all free proto pkt in queue */
|
|
plctxrx_context.sendq = os_mem_malloc(IOT_GREE_APP_MID,
|
|
sizeof(prot_pktq_t));
|
|
if (plctxrx_context.sendq == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto error_4;
|
|
}
|
|
|
|
plctxrx_context.freeq = os_mem_malloc(IOT_GREE_APP_MID,
|
|
sizeof(prot_pktq_t));
|
|
if (plctxrx_context.freeq == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto error_5;
|
|
}
|
|
iot_plctxrx_queue_init(plctxrx_context.sendq);
|
|
iot_plctxrx_queue_init(plctxrx_context.freeq);
|
|
|
|
plctxrx_context.sendq->lock = os_create_mutex(IOT_GREE_APP_MID);
|
|
if (plctxrx_context.sendq->lock == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto error_6;
|
|
}
|
|
|
|
|
|
plctxrx_context.freeq->lock = os_create_mutex(IOT_GREE_APP_MID);
|
|
if (plctxrx_context.freeq->lock == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto error_7;
|
|
}
|
|
|
|
|
|
for (i = 0; i < TXRX_SEND_BUFF_POOL_NUM; i++) {
|
|
iot_plctxrx_pkt_enqueue(plctxrx_context.freeq, &gbl_protpkt[i].node);
|
|
}
|
|
|
|
/* allocate list for aggr data split to upper layer */
|
|
ret = iot_plctxrx_list_init();
|
|
if (ret) {
|
|
goto error_8;
|
|
}
|
|
|
|
/* init local device */
|
|
#if (HW_PLATFORM == HW_PLATFORM_SIMU)
|
|
if (ucIsClientMode == 0) {
|
|
plctxrx_context.nw_role = IOT_PLC_DEV_ROLE_CCO;
|
|
} else {
|
|
plctxrx_context.nw_role = IOT_PLC_DEV_ROLE_STA;
|
|
}
|
|
#else
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
plctxrx_context.nw_role = IOT_PLC_DEV_ROLE_CCO;
|
|
#else
|
|
plctxrx_context.nw_role = IOT_PLC_DEV_ROLE_STA;
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/* init command free queue */
|
|
iot_plctxrx_cmd_freeq_init();
|
|
/* init command save queue */
|
|
iot_plctxrx_cmd_saveq_init();
|
|
|
|
iot_cus_printf("[gltx]plctxrx task init succ!\n");
|
|
|
|
goto success;
|
|
|
|
error_8:
|
|
os_delete_mutex(plctxrx_context.freeq->lock);
|
|
error_7:
|
|
os_delete_mutex(plctxrx_context.sendq->lock);
|
|
error_6:
|
|
os_mem_free(plctxrx_context.freeq);
|
|
error_5:
|
|
os_mem_free(plctxrx_context.sendq);
|
|
error_4:
|
|
os_delete_timer(plctxrx_context.aggr_timer);
|
|
error_3:
|
|
os_delete_timer(plctxrx_context.txrx_timer);
|
|
error_2:
|
|
os_delete_timer(plctxrx_context.datapath_timer);
|
|
error_1:
|
|
iot_task_delete(plctxrx_context.task_handle);
|
|
error_0:
|
|
os_mem_set(&plctxrx_context, 0, sizeof(plctxrx_contxt_t));
|
|
success:
|
|
return ret;
|
|
}
|
|
|
|
void iot_plctxrx_task_deinit(void)
|
|
{
|
|
os_delete_timer(plctxrx_context.datapath_timer);
|
|
os_delete_timer(plctxrx_context.txrx_timer);
|
|
os_delete_timer(plctxrx_context.aggr_timer);
|
|
/* send Q free */
|
|
if (plctxrx_context.sendq) {
|
|
if (plctxrx_context.sendq->lock) {
|
|
os_delete_mutex(plctxrx_context.sendq->lock);
|
|
}
|
|
|
|
if (plctxrx_context.freeq->lock) {
|
|
os_delete_mutex(plctxrx_context.freeq->lock);
|
|
}
|
|
|
|
os_mem_free(plctxrx_context.sendq);
|
|
}
|
|
/* free Q free */
|
|
if (plctxrx_context.freeq) {
|
|
os_mem_free(plctxrx_context.freeq);
|
|
}
|
|
if (plctxrx_context.task_handle) {
|
|
os_delete_task(plctxrx_context.task_handle);
|
|
}
|
|
os_mem_set(&plctxrx_context, 0, sizeof(plctxrx_contxt_t));
|
|
}
|
|
|
|
#endif /* end IOT_GR_APP_ENABLE */
|
|
|