📄 zdcache.c
字号:
/*********************************************************************
Filename: ZDCache.c
Revised: $Date: 2007-02-15 15:11:28 -0800 (Thu, 15 Feb 2007) $
Revision: $Revision: 13481 $
Description: Implementation of the ZDO Discovery Cache functionality.
Notes:
Copyright (c) 2006 by Texas Instruments, Inc.
All Rights Reserved. Permission to use, reproduce, copy, prepare
derivative works, modify, distribute, perform, display or sell this
software and/or its documentation for any purpose is prohibited
without the express written consent of Texas Instruments, Inc.
*********************************************************************/
#if defined( ZDO_CACHE )
/*********************************************************************
* INCLUDES
*/
#include "AF.h"
#include "nwk_globals.h"
#include "nwk_util.h"
#include "OSAL.h"
#include "ZDCache.h"
#include "ZDConfig.h"
#include "ZDObject.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
#define MAX_PKT_LEN (MAX_DATA_PACKET_LEN - NWK_HDR_LEN)
#if ( CACHE_DEV_MAX == 0 )
#define WAIT_ON_RESP_CACHE 5
#define FIND_RSP_MAX 16
#endif
#define SendMsg( CMD, LEN, DATA ) \
afAddOrSendMessage( &msgAddr, /* *DestAddr */\
ZDO_EP, /* Endpoint */\
(CMD), /* ClusterId */\
SEND_MESSAGE, /* TransCount */\
FRAMETYPE_MSG, /* FrameType */\
&tranSeq, /* *TransSeqNumber */\
NULL, /* CommandType */\
NULL, /* AttribDataType */\
NULL, /* AttribId */\
NULL, /* ErrorCode */\
(LEN), /* DataLength */\
(DATA), /* *Data */\
AF_TX_OPTIONS_NONE, \
FALSE, /* Discover route */\
radius )
/*********************************************************************
* TYPEDEFS
*/
#if ( CACHE_DEV_MAX == 0 )
typedef enum {
eCacheWait,
eCacheClean,
eCacheFind,
eCacheRequest,
eNodeDescStore,
ePwrDescStore,
eActiveEPStore,
eSimpDescStore,
eCacheDone
} eCacheState;
#endif
/*********************************************************************
* GLOBAL VARIABLES
*/
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL FUNCTIONS
*/
#if ( CACHE_DEV_MAX > 0 )
static byte processDiscoveryStoreReq ( byte *data );
static byte processSimpleDescStoreReq ( byte *data, byte idx );
static void processFindNodeCacheReq ( byte *data );
static byte getCnt ( void );
static byte getIdx ( uint16 addr );
static byte getNth ( byte Nth );
static byte getIdxExt ( byte *ieee );
static byte getIdxEP ( byte idx, byte ep );
static byte purgeAddr ( uint16 addr );
static byte purgeIEEE ( byte *ieee );
#endif
/*********************************************************************
* LOCAL VARIABLES
*/
static afAddrType_t msgAddr;
static byte radius;
static byte tranSeq;
static byte secUse;
#if ( CACHE_DEV_MAX > 0 )
static uint16 NwkAddr[CACHE_DEV_MAX];
static byte ExtAddr[CACHE_DEV_MAX][Z_EXTADDR_LEN];
static uint32 Expiry[CACHE_DEV_MAX];
static NodeDescriptorFormat_t NodeDesc[CACHE_DEV_MAX];
static NodePowerDescriptorFormat_t NodePwr[CACHE_DEV_MAX];
static byte EPCnt[CACHE_DEV_MAX];
static byte EPArr[CACHE_DEV_MAX][CACHE_EP_MAX];
static SimpleDescriptionFormat_t SimpDesc[CACHE_DEV_MAX][CACHE_EP_MAX];
static uint16 InClusters[CACHE_DEV_MAX][CACHE_EP_MAX][CACHE_CR_MAX];
static uint16 OutClusters[CACHE_DEV_MAX][CACHE_EP_MAX][CACHE_CR_MAX];
#elif ( CACHE_DEV_MAX == 0 )
static uint16 cacheFindAddr[FIND_RSP_MAX];
static byte EPArr[CACHE_EP_MAX];
static byte EPCnt;
static byte cacheCnt; // Count of responding cache devices.
static byte cacheRsp; // Results of last discovery cache request.
#endif
#if ( CACHE_DEV_MAX > 0 )
/*********************************************************************
* @fn processDiscoveryStoreReq
*
* @brief Process a Discovery_store_req
*
* @return none
*/
static byte processDiscoveryStoreReq( byte *data )
{
uint16 aoi = BUILD_UINT16( data[0], data[1] );
byte rtrn = ZDP_INSUFFICIENT_SPACE;
byte idx;
data += 2;
// First purge any outdated cache with this network address or IEEE.
purgeAddr( aoi );
purgeIEEE( data );
// If an invalid addr cannot be found, the cache arrays are full.
if ( (idx = getIdx( INVALID_NODE_ADDR )) != CACHE_DEV_MAX )
{
osal_cpyExtAddr( ExtAddr[idx], data );
data += Z_EXTADDR_LEN;
if ( (*data++ == sizeof( NodeDescriptorFormat_t )) &&
(*data++ == sizeof( NodePowerDescriptorFormat_t )) &&
(*data++ <= CACHE_EP_MAX) &&
(*data < CACHE_EP_MAX) )
{
rtrn = ZDP_SUCCESS;
NwkAddr[idx] = aoi;
Expiry[idx] = 0; //TBD - what value & how to keep alive?
EPCnt[idx] = 0;
}
}
return rtrn;
}
/*********************************************************************
* @fn processSimpleDescStoreReq
*
* @brief Process a Simple_Desc_store_req
*
* @return none
*/
static byte processSimpleDescStoreReq( byte *data, byte idx )
{
byte rtrn = ZDP_INSUFFICIENT_SPACE;
SimpleDescriptionFormat_t desc;
// Skip first byte == total length of descriptor.
if (ZDO_ParseSimpleDescBuf( data+1, &desc )) {
// malloc failed -- we can't do this...
return ZDP_NOT_PERMITTED;
}
if ( (desc.AppNumInClusters <= CACHE_CR_MAX) &&
(desc.AppNumOutClusters <= CACHE_CR_MAX) )
{
byte epIdx = getIdxEP( idx, desc.EndPoint );
if ( epIdx == CACHE_EP_MAX )
{
rtrn = ZDP_NOT_PERMITTED;
}
else
{
SimpleDescriptionFormat_t *pDesc = &(SimpDesc[idx][epIdx]);
osal_memcpy( pDesc->pAppInClusterList, desc.pAppInClusterList,
desc.AppNumInClusters*sizeof(uint16) );
osal_memcpy( pDesc->pAppOutClusterList, desc.pAppOutClusterList,
desc.AppNumOutClusters*sizeof(uint16) );
pDesc->EndPoint = desc.EndPoint;
pDesc->AppProfId = desc.AppProfId;
pDesc->AppDeviceId = desc.AppDeviceId;
pDesc->AppDevVer = desc.AppDevVer;
pDesc->Reserved = desc.Reserved;
pDesc->AppNumInClusters = desc.AppNumInClusters;
pDesc->AppNumOutClusters = desc.AppNumOutClusters;
rtrn = ZDP_SUCCESS;
}
}
// free up the malloc'ed cluster lists
if (desc.AppNumInClusters) {
osal_mem_free(desc.pAppInClusterList);
}
if (desc.AppNumOutClusters) {
osal_mem_free(desc.pAppOutClusterList);
}
return rtrn;
}
/*********************************************************************
* @fn processFindNodeCacheReq
*
* @brief Process a Find_node_cache_req
*
* @return none
*/
static void processFindNodeCacheReq( byte *data )
{
uint16 aoi = BUILD_UINT16( data[0], data[1] );
byte idx = getIdx( aoi );
if ( idx == CACHE_DEV_MAX )
{
idx = getIdxExt ( data+2 );
}
if ( idx != CACHE_DEV_MAX )
{
byte buf[2+2+Z_EXTADDR_LEN];
buf[0] = LO_UINT16( ZDAppNwkAddr.addr.shortAddr );
buf[1] = HI_UINT16( ZDAppNwkAddr.addr.shortAddr );
buf[2] = LO_UINT16( NwkAddr[idx] );
buf[3] = HI_UINT16( NwkAddr[idx] );
osal_cpyExtAddr( buf+4, ExtAddr[idx] );
SendMsg( Find_node_cache_rsp, 2+2+Z_EXTADDR_LEN, buf );
}
}
/*********************************************************************
* @fn processMgmtCacheReq
*
* @brief Process a Mgmt_cache_req
*
* @return none
*/
static void processMgmtCacheReq( byte idx )
{
const byte max =
(((CACHE_DEV_MAX-idx) * (2 + Z_EXTADDR_LEN) + 1) < MAX_PKT_LEN) ?
((CACHE_DEV_MAX-idx) * (2 + Z_EXTADDR_LEN) + 1) : MAX_PKT_LEN;
byte *buf = osal_mem_alloc( max );
byte status = ZDP_INSUFFICIENT_SPACE;
byte cnt = 1;
if ( buf == NULL )
{
buf = &status;
}
else
{
byte *ptr = buf;
*ptr++ = ZDP_SUCCESS;
*ptr++ = getCnt();
*ptr++ = idx;
*ptr++ = 0;
for ( idx = getNth( idx ); idx < CACHE_DEV_MAX; idx++ )
{
if ( cnt >= (max - (2 + Z_EXTADDR_LEN)) )
{
break;
}
if ( NwkAddr[idx] != INVALID_NODE_ADDR )
{
ptr = osal_cpyExtAddr( ptr, ExtAddr[idx] );
*ptr++ = LO_UINT16( NwkAddr[idx] );
*ptr++ = HI_UINT16( NwkAddr[idx] );
cnt += (2 + Z_EXTADDR_LEN);
buf[3]++;
}
}
}
SendMsg( Mgmt_Cache_rsp, cnt, buf );
if ( buf != NULL )
{
osal_mem_free( buf );
}
}
/*********************************************************************
* @fn getCnt
*
* @return The count of valid cache entries.
*
*/
static byte getCnt( void )
{
byte cnt = 0;
byte idx;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( NwkAddr[idx] != INVALID_NODE_ADDR )
{
cnt++;
}
}
return cnt;
}
/*********************************************************************
* @fn getIdx
*
* @brief Find the idx into the Discovery Cache Arrays corresponding to
* the given short address.
*
* @param uint16 - a valid 16 bit short address.
*
* @return If address found, return the valid index, else CACHE_DEV_MAX.
*
*/
static byte getIdx( uint16 addr )
{
byte idx;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( addr == NwkAddr[idx] )
{
break;
}
}
return idx;
}
/*********************************************************************
* @fn getNth
*
* @param byte - the Nth idx sought.
*
* @return If N or more entries exist, return the index of the Nth entry,
* else CACHE_DEV_MAX.
*
*/
static byte getNth( byte Nth )
{
byte cnt = 0;
byte idx;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( NwkAddr[idx] != INVALID_NODE_ADDR )
{
if ( cnt++ >= Nth )
{
break;
}
}
}
return idx;
}
/*********************************************************************
* @fn getIdxExt
*
* @brief Find the idx into the Discovery Cache Arrays corresponding to
* the given IEEE address.
*
* @param byte * - a valid buffer containing an extended IEEE address.
*
* @return If address found, return the valid index, else CACHE_DEV_MAX.
*
*/
static byte getIdxExt( byte *ieee )
{
byte idx;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( osal_ExtAddrEqual( ieee, ExtAddr[idx] ) &&
(NwkAddr[idx] != INVALID_NODE_ADDR) )
{
break;
}
}
return idx;
}
/*********************************************************************
* @fn getIdxEP
*
* @brief Find the idx into the EndPoint Array corresponding to the idx of a
* cached short address.
*
* @param byte - a valid index of a cached 16 bit short address.
* @param byte - the EndPoint of interest.
*
* @return If EndPoint found, return the valid index, else CACHE_EP_MAX.
*
*/
static byte getIdxEP( byte idx, byte ep )
{
byte epIdx;
for ( epIdx = 0; epIdx < EPCnt[idx]; epIdx++ )
{
if ( ep == EPArr[idx][epIdx] )
{
break;
}
}
if ( epIdx == EPCnt[idx] )
{
epIdx = CACHE_EP_MAX;
}
return epIdx;
}
/*********************************************************************
* @fn purgeAddr
*
* @brief Purge every instance of given network address from Discovery Cache.
*
* @param uint16 - a 16-bit network address.
*
*/
static byte purgeAddr( uint16 addr )
{
byte idx, cnt = 0;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( NwkAddr[idx] == addr )
{
NwkAddr[idx] = INVALID_NODE_ADDR;
cnt++;
}
}
return cnt;
}
/*********************************************************************
* @fn purgeIEEE
*
* @brief Purge every instance of given IEEE from Discovery Cache.
*
* @param ZLongAddr_t - a valid IEEE address.
*
*/
static byte purgeIEEE( byte *ieee )
{
byte idx, cnt = 0;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( osal_ExtAddrEqual( ieee, ExtAddr[idx] ) &&
(NwkAddr[idx] != INVALID_NODE_ADDR) )
{
NwkAddr[idx] = INVALID_NODE_ADDR;
cnt++;
}
}
return cnt;
}
#endif
/*********************************************************************
* @fn ZDCacheInit
*
* @brief Initialize ZDO Cache environment.
*
*/
void ZDCacheInit( void )
{
msgAddr.endPoint = ZDO_EP;
msgAddr.addrMode = afAddr16Bit;
msgAddr.addr.shortAddr = INVALID_NODE_ADDR;
radius = AF_DEFAULT_RADIUS;
(void)secUse;
#if ( CACHE_DEV_MAX > 0 )
byte idx;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
byte epIdx;
NwkAddr[idx] = INVALID_NODE_ADDR;
for ( epIdx = 0; epIdx < CACHE_EP_MAX; epIdx++ )
{
SimpDesc[idx][epIdx].pAppInClusterList = InClusters[idx][epIdx];
SimpDesc[idx][epIdx].pAppOutClusterList= OutClusters[idx][epIdx];
}
}
#elif ( CACHE_DEV_MAX == 0 )
// Client cache work done by ZDCacheTimerEvent, driven by NWK_AUTO_POLL_EVT.
#endif
}
/*********************************************************************
* @fn ZDCacheTimerEvent
*
* @brief ZDP maintenance, aging discovery cache.
* Invoked at RTG_TIMER_INTERVAL.
*/
void ZDCacheTimerEvent( void )
{
#if ( CACHE_DEV_MAX > 0 )
byte idx;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( NwkAddr[idx] != INVALID_NODE_ADDR )
{
if ( --Expiry[idx] == 0 )
{
NwkAddr[idx] = INVALID_NODE_ADDR;
}
}
}
#elif ( CACHE_DEV_MAX == 0 )
static eCacheState state = eCacheWait;
static byte reqIdx = 0;
static byte wCnt = 0;
byte strtFind = FALSE;
byte cmd = 0;
byte len = 2 + Z_EXTADDR_LEN;
byte *msg, *ptr;
wCnt++;
if ( state == eCacheWait )
{
if ( wCnt < WAIT_TO_STORE_CACHE )
{
return;
}
}
else if ( wCnt < WAIT_ON_RESP_CACHE )
{
return;
}
msg = osal_mem_alloc( MAX_PKT_LEN );
if ( msg == NULL )
{
return;
}
msg[0] = LO_UINT16( ZDAppNwkAddr.addr.shortAddr );
msg[1] = HI_UINT16( ZDAppNwkAddr.addr.shortAddr );
osal_cpyExtAddr( msg+2, saveExtAddr );
ptr = msg+2+Z_EXTADDR_LEN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -