Files
kunlun/app/brm/src/iot_brm_tsfm.c
2024-09-28 14:24:04 +08:00

369 lines
12 KiB
C

/****************************************************************************
*
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
*
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
* be copied by any method or incorporated into another program without
* the express written consent of Aerospace C.Power. This Information or any portion
* thereof remains the property of Aerospace C.Power. The Information contained herein
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
* liability for its use in any way and conveys no license or title under
* any patent or copyright and makes no representation or warranty that this
* Information is free from patent or copyright infringement.
*
* ****************************************************************************/
/* iot common header files */
#include "iot_io_api.h"
#include "iot_errno_api.h"
#include "iot_plc_msg_api.h"
#include "iot_addr_hash_table_api.h"
#include "iot_sg_ext_api.h"
/* brm internal header files */
#include "iot_brm_common.h"
#include "iot_brm_tsfm.h"
/* protocol header file */
#include "proto_conn_less.h"
#if (IOT_BRM_ENABLE)
/* define the maximum number of address information to temporary storage */
#define IOT_BRM_TSFM_ADDR_LIST_MAX 256
/* define address information listed hash table size */
#define IOT_BRM_TSFM_HASH_TABLE_SIZE 6
/* define collect timeout, unit is 1s */
#define IOT_BRM_TSFM_COLLECT_TIMEOUT 1800
/* hardware tsfm identification information descriptor */
typedef struct _iot_brm_tsfm_info_desc {
/* hash table entry */
iot_addr_hash_entry_t entry;
/* rx snr of this node */
int8_t snr;
/* node protocol type, see GW_APP_DATA_TYPE_XXX */
uint8_t pro_type : 4,
/* node device type, see GW_APP_ID_INFO_DEV_TYPE_XXX */
dev_type : 4;
/* node first physical phase line, see GW_APP_DATA_PHASE_XXX */
uint8_t phase_1 : 2,
/* node second physical phase line, see GW_APP_DATA_PHASE_XXX */
phase_2 : 2,
/* node third physical phase line, see GW_APP_DATA_PHASE_XXX */
phase_3 : 2,
/* reserve for future */
reserve : 2;
} iot_brm_tsfm_info_desc_t;
/* node list descriptor */
typedef struct _iot_brm_tsfm_node_list {
/* tsfm node info hash table */
iot_addr_hash_table_h node_table;
/* pointer to the node info in the hash tsfm info */
iot_brm_tsfm_info_desc_t *entry[IOT_BRM_TSFM_ADDR_LIST_MAX];
/* node cnt */
uint16_t node_cnt;
} iot_brm_tsfm_node_list_t;
/* hardware tsfm recognition global descriptor */
typedef struct _iot_brm_tsfm_global {
/* node list structure */
iot_brm_tsfm_node_list_t node_list;
/* the time when the station identification signal was received or address
* list update last, unit is 1s.
*/
uint32_t update_ts;
/* cco mac address, little-endian */
uint8_t cco_mac[IOT_MAC_ADDR_LEN];
/* is collecting stations hardware zone identification information */
uint8_t is_collecting;
} iot_brm_tsfm_global_t;
iot_brm_tsfm_global_t *p_brm_tsfm_glb = NULL;
static void iot_brm_tsfm_hash_table_clear_handler(
iot_addr_hash_entry_t *entry, void *param)
{
iot_addr_hash_table_remove(p_brm_tsfm_glb->node_list.node_table, entry);
iot_addr_hash_table_free(p_brm_tsfm_glb->node_list.node_table, entry);
}
static iot_brm_tsfm_info_desc_t *iot_brm_same_tsfm_find_min_snr(void)
{
iot_brm_tsfm_info_desc_t *node = NULL;
iot_brm_tsfm_node_list_t *node_list = &p_brm_tsfm_glb->node_list;
int8_t min_snr;
uint16_t i;
if (!node_list->node_cnt) {
goto out;
}
min_snr = IOT_BRM_MAX_SNR;
for (i = 0; i < node_list->node_cnt; i++) {
if (!node_list->entry[i]) {
continue;
}
if (node_list->entry[i]->snr < min_snr) {
node = node_list->entry[i];
min_snr = node_list->entry[i]->snr;
}
}
out:
return node;
}
static void iot_brm_same_tsfm_node_add(int8_t snr,
proto_conn_less_tsfm_info_rpt_t *rpt_h)
{
uint16_t i;
iot_brm_tsfm_node_list_t *node_list = &p_brm_tsfm_glb->node_list;
iot_brm_tsfm_info_desc_t *node;
uint8_t is_replace = 0;
uint8_t *addr;
node = (iot_brm_tsfm_info_desc_t *)iot_addr_hash_table_find(
node_list->node_table, rpt_h->sta_mac);
if (node) {
goto update;
}
node = (iot_brm_tsfm_info_desc_t *)iot_addr_hash_table_alloc(
node_list->node_table);
if (!node) {
node = iot_brm_same_tsfm_find_min_snr();
if (!node) {
IOT_ASSERT(0);
goto out;
}
iot_addr_hash_table_remove(p_brm_tsfm_glb->node_list.node_table,
&node->entry);
os_mem_set(node, 0, sizeof(*node));
is_replace = 1;
addr = node->entry.addr;
iot_brm_printf("%s - buffer full, replace %02x%02x%02x%02x%02x%02x\n",
__FUNCTION__, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
}
iot_mac_addr_cpy(node->entry.addr, rpt_h->sta_mac);
iot_addr_hash_table_add(node_list->node_table, &node->entry);
node->snr = IOT_BRM_INVALID_SNR;
p_brm_tsfm_glb->update_ts = 0;
if (is_replace) {
goto update;
}
for (i = 0; i < IOT_BRM_TSFM_ADDR_LIST_MAX; i++) {
if (node_list->entry[i] == NULL) {
node_list->entry[i] = node;
break;
}
}
IOT_ASSERT(i < IOT_BRM_TSFM_ADDR_LIST_MAX);
node_list->node_cnt++;
update:
node->snr = iot_brm_calc_nw_snr(node->snr, snr);
node->pro_type = rpt_h->pro_type;
node->dev_type = rpt_h->dev_type;
node->phase_1 = rpt_h->phase_1;
node->phase_2 = rpt_h->phase_2;
node->phase_3 = rpt_h->phase_3;
iot_brm_printf("%s - sta_addr: %02x%02x%02x%02x%02x%02x, node count: %lu\n",
__FUNCTION__, rpt_h->sta_mac[5], rpt_h->sta_mac[4], rpt_h->sta_mac[3],
rpt_h->sta_mac[2], rpt_h->sta_mac[1], rpt_h->sta_mac[0],
node_list->node_cnt);
out:
return;
}
void iot_brm_same_tsfm_info_collect_handle(uint8_t *data, uint16_t len,
iot_pkt_t *pkt)
{
proto_conn_less_tsfm_info_rpt_t *rpt_h =
(proto_conn_less_tsfm_info_rpt_t *)data;
uint8_t *ptr = iot_pkt_data(pkt);
iot_plc_msdu_recv_t *msdu_h =
(iot_plc_msdu_recv_t *)(ptr - sizeof(*msdu_h));
uint8_t local_cco_addr[IOT_MAC_ADDR_LEN];
uint8_t reason;
if (p_brm_tsfm_glb == NULL) {
reason = 1;
goto drop;
}
if (len < sizeof(proto_conn_less_tsfm_info_rpt_t)) {
reason = 2;
goto drop;
}
if (p_brm_tsfm_glb->is_collecting == 0) {
reason = 3;
goto drop;
}
if (!iot_mac_addr_valid(iot_brm_get_cco_addr())) {
reason = 4;
goto drop;
}
iot_mac_addr_cpy(local_cco_addr, iot_brm_get_cco_addr());
iot_mac_addr_reverse(local_cco_addr);
/* Only save the sta with the same tsfm address as the local but different
* cco address.
*/
if (!iot_mac_addr_cmp(rpt_h->cco_mac, local_cco_addr) &&
iot_mac_addr_cmp(rpt_h->tsfm_mac, p_brm_tsfm_glb->cco_mac)) {
iot_brm_same_tsfm_node_add(msdu_h->snr, rpt_h);
}
goto out;
drop:
iot_brm_printf("%s drop reason %lu\n", __FUNCTION__, reason);
out:
if (pkt) {
iot_pkt_free(pkt);
}
return;
}
void iot_brm_same_tsfm_collect_clear(void)
{
if (p_brm_tsfm_glb == NULL) {
IOT_ASSERT(0);
}
iot_addr_hash_table_loop(p_brm_tsfm_glb->node_list.node_table,
iot_brm_tsfm_hash_table_clear_handler, NULL);
p_brm_tsfm_glb->node_list.node_cnt = 0;
os_mem_set(p_brm_tsfm_glb->node_list.entry, 0x0,
sizeof(p_brm_tsfm_glb->node_list.entry));
}
uint32_t iot_brm_same_tsfm_collect_trigger(uint8_t * cco_addr)
{
uint32_t ret;
if (p_brm_tsfm_glb == NULL) {
ret = ERR_NOMEM;
goto out;
}
if (p_brm_tsfm_glb->is_collecting) {
if (!iot_mac_addr_cmp(cco_addr, p_brm_tsfm_glb->cco_mac)) {
/* receive new hardware tsfm info (the address is different from the
* last receive), restart collection.
*/
iot_mac_addr_cpy(p_brm_tsfm_glb->cco_mac, cco_addr);
iot_brm_same_tsfm_collect_clear();
}
} else {
iot_mac_addr_cpy(p_brm_tsfm_glb->cco_mac, cco_addr);
iot_brm_same_tsfm_collect_clear();
p_brm_tsfm_glb->is_collecting = 1;
}
p_brm_tsfm_glb->update_ts = 0;
iot_brm_printf("%s - cco_addr: %2x %2x %2x %2x %2x %2x\n", __FUNCTION__,
cco_addr[5], cco_addr[4], cco_addr[3], cco_addr[2], cco_addr[1],
cco_addr[0]);
ret = ERR_OK;
out:
return ret;
}
void iot_brm_same_tsfm_collect_timeout(void)
{
if (p_brm_tsfm_glb == NULL) {
return;
}
if (p_brm_tsfm_glb->is_collecting == 1) {
p_brm_tsfm_glb->update_ts++;
if (p_brm_tsfm_glb->update_ts > IOT_BRM_TSFM_COLLECT_TIMEOUT) {
p_brm_tsfm_glb->update_ts = 0;
p_brm_tsfm_glb->is_collecting = 0;
iot_brm_printf("%s timeout\n", __FUNCTION__);
}
}
}
uint32_t iot_brm_same_tsfm_fill_node_info(
iot_sg_ext_cus_same_tsfm_node_resp_t *resp)
{
uint32_t ret = ERR_OK;
uint16_t index;
iot_brm_tsfm_info_desc_t **node_list;
uint16_t i;
uint16_t node_count;
uint8_t list_sn;
if (resp == NULL || p_brm_tsfm_glb == NULL) {
IOT_ASSERT(0);
ret = ERR_FAIL;
goto out;
}
node_list = p_brm_tsfm_glb->node_list.entry;
list_sn = resp->req_info.list_sn;
resp->follow_flag = 0;
resp->node_cnt = 0;
if (p_brm_tsfm_glb->is_collecting == 0) {
resp->done = 1;
} else {
resp->done = 0;
}
if (list_sn == 0) {
goto out;
}
index = (list_sn - 1) * IOT_BRM_TSFM_FRAME_ENTRY_MAX;
if (index >= p_brm_tsfm_glb->node_list.node_cnt) {
goto out;
}
node_count = p_brm_tsfm_glb->node_list.node_cnt - index;
if (node_count > IOT_BRM_TSFM_FRAME_ENTRY_MAX) {
node_count = IOT_BRM_TSFM_FRAME_ENTRY_MAX;
resp->follow_flag = 1;
}
resp->node_cnt = node_count;
for (i = 0; i < node_count; i++) {
iot_mac_addr_cpy(resp->node_list[i].addr, node_list[index]->entry.addr);
resp->node_list[i].dev_type = node_list[index]->dev_type;
resp->node_list[i].pro_type = node_list[index]->pro_type;
index++;
}
out:
return ret;
}
uint32_t iot_brm_tsfm_init(void)
{
uint32_t ret = ERR_OK;
p_brm_tsfm_glb = os_mem_malloc(IOT_BRM_MID, sizeof(*p_brm_tsfm_glb));
if (p_brm_tsfm_glb == NULL) {
ret = ERR_NOMEM;
goto out;
}
p_brm_tsfm_glb->node_list.node_table = iot_addr_hash_table_create(
IOT_BRM_MID, IOT_BRM_TSFM_ADDR_LIST_MAX,
sizeof(iot_brm_tsfm_info_desc_t), IOT_BRM_TSFM_HASH_TABLE_SIZE);
if (p_brm_tsfm_glb->node_list.node_table == NULL) {
ret = ERR_NOMEM;
goto out_list_fail;
}
p_brm_tsfm_glb->update_ts = 0;
p_brm_tsfm_glb->is_collecting = 0;
os_mem_set(p_brm_tsfm_glb->cco_mac, 0xFF, IOT_MAC_ADDR_LEN);
p_brm_tsfm_glb->node_list.node_cnt = 0;
os_mem_set(p_brm_tsfm_glb->node_list.entry, 0x0,
sizeof(p_brm_tsfm_glb->node_list.entry));
goto out;
out_list_fail:
iot_brm_tsfm_deinit();
out:
iot_brm_printf("%s - ret: %d\n", __FUNCTION__, ret);
return ret;
}
void iot_brm_tsfm_deinit(void)
{
if (p_brm_tsfm_glb == NULL) {
goto out;
}
if (p_brm_tsfm_glb->node_list.node_table != NULL) {
iot_addr_hash_table_delete(p_brm_tsfm_glb->node_list.node_table);
}
os_mem_free(p_brm_tsfm_glb);
p_brm_tsfm_glb = NULL;
out:
iot_brm_printf("%s\n", __FUNCTION__);
return;
}
#endif /* IOT_BRM_ENABLE */