Files
kunlun/app/grapp/iot_plctxrx.c
2024-09-28 14:24:04 +08:00

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 */