📄 zdcache.c
字号:
switch ( state )
{
case eCacheWait:
state = eCacheClean;
msgAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
cmd = Find_node_cache_req;
cacheCnt = 0;
reqIdx = 0;
break;
case eCacheClean:
if ( reqIdx < cacheCnt )
{
msgAddr.addr.shortAddr = cacheFindAddr[reqIdx++];
cmd = Remove_node_cache_req;
}
else
{
strtFind = TRUE;
radius = 0;
}
break;
case eCacheFind:
if ( cacheCnt != 0 )
{
state = eCacheRequest;
reqIdx = 0;
}
else
{
strtFind = TRUE;
}
break;
case eCacheRequest:
if ( (cacheRsp == ZDP_SUCCESS) && (reqIdx != 0) )
{
cmd = Node_Desc_store_req;
len += sizeof( NodeDescriptorFormat_t );
ptr = osal_memcpy( ptr, &ZDO_Config_Node_Descriptor,
sizeof( NodeDescriptorFormat_t ) );
state = eNodeDescStore;
}
else if ( reqIdx < cacheCnt )
{
EPCnt = afNumEndPoints() - 1; // -1 for ZDO endpoint descriptor.
if ( EPCnt < CACHE_EP_MAX )
{
byte idx;
afEndPoints( EPArr, true );
msgAddr.addr.shortAddr = cacheFindAddr[reqIdx++];
cmd = Discovery_store_req;
len += (4 + EPCnt);
*ptr++ = sizeof( NodeDescriptorFormat_t );
*ptr++ = sizeof( NodePowerDescriptorFormat_t );
*ptr++ = EPCnt + 1; // NOT -1 for size in bytes of EP list.
*ptr++ = EPCnt;
for ( idx = 0; idx < EPCnt; idx++ )
{
SimpleDescriptionFormat_t *sDesc;
byte free = afFindSimpleDesc( &sDesc, EPArr[idx] );
if ( sDesc != NULL )
{
*ptr++ = 8 + sDesc->AppNumInClusters + sDesc->AppNumOutClusters;
if ( free )
{
osal_mem_free( sDesc );
}
}
else
{
*ptr++ = 8;
}
}
}
}
else
{
strtFind = TRUE;
}
break;
case eNodeDescStore:
if ( cacheRsp == ZDP_SUCCESS )
{
cmd = Power_Desc_store_req;
len += sizeof( NodePowerDescriptorFormat_t );
ptr = osal_memcpy( ptr, &ZDO_Config_Power_Descriptor,
sizeof( NodePowerDescriptorFormat_t ) );
state = ePwrDescStore;
}
else
{
strtFind = TRUE;
}
break;
case ePwrDescStore:
if ( cacheRsp == ZDP_SUCCESS )
{
cmd = Active_EP_store_req;
len += EPCnt + 1;
*ptr++ = EPCnt;
afEndPoints( ptr, true );
state = eActiveEPStore;
}
else
{
strtFind = TRUE;
}
break;
case eActiveEPStore:
if ( cacheRsp == ZDP_SUCCESS )
{
state = eSimpDescStore;
reqIdx = 0;
}
else
{
strtFind = TRUE;
}
break;
case eSimpDescStore:
if ( (cacheRsp == ZDP_SUCCESS) || (reqIdx == 0) )
{
if ( reqIdx >= EPCnt )
{
state = eCacheDone;
}
else
{
SimpleDescriptionFormat_t *sDesc;
byte free = afFindSimpleDesc( &sDesc, EPArr[reqIdx++] );
if ( sDesc != NULL )
{
cmd = Simple_Desc_store_req;
len += 1 + 8 + sDesc->AppNumInClusters + sDesc->AppNumOutClusters;
*ptr++ = 8 + sDesc->AppNumInClusters + sDesc->AppNumOutClusters;
*ptr++ = sDesc->EndPoint;
*ptr++ = LO_UINT16( sDesc->AppProfId );
*ptr++ = HI_UINT16( sDesc->AppProfId );
*ptr++ = LO_UINT16( sDesc->AppDeviceId );
*ptr++ = HI_UINT16( sDesc->AppDeviceId );
*ptr++ = (sDesc->Reserved << 4) | sDesc->AppDevVer;
*ptr++ = sDesc->AppNumInClusters;
ptr = osal_memcpy( ptr, sDesc->pAppInClusterList,
sDesc->AppNumInClusters );
*ptr++ = sDesc->AppNumOutClusters;
osal_memcpy(ptr, sDesc->pAppOutClusterList, sDesc->AppNumOutClusters);
if ( free )
{
osal_mem_free( sDesc );
}
}
}
}
else
{
strtFind = TRUE;
}
break;
case eCacheDone:
#if !defined( NWK_AUTO_POLL )
NLME_SetPollRate( 0 ); // Stop the timer to allow max power savings.
#endif
break;
default:
break;
} // switch ( state )
if ( strtFind )
{
if ( state >= eNodeDescStore )
{
SendMsg( Remove_node_cache_req, 2+Z_EXTADDR_LEN, msg );
}
state = eCacheFind;
if ( ++radius > (2 * _NIB.MaxDepth) )
{
radius = 1;
}
msgAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
cacheCnt = 0;
cmd = Discovery_Register_req;
}
cacheRsp = ZDP_TIMEOUT;
wCnt = 0;
if ( cmd != 0 )
{
SendMsg( cmd, len, msg );
}
osal_mem_free( msg );
#endif
}
#if ( CACHE_DEV_MAX > 0 )
/*********************************************************************
* @fn ZDCacheProcessReq
*
* @brief Build and send a response to a Discovery Cache request.
*
*/
void ZDCacheProcessReq( zAddrType_t *src, byte *msg, byte len,
byte cmd, byte seq, byte sty )
{
byte status = ZDP_SUCCESS;
byte sent = FALSE;
msgAddr.addr.shortAddr = src->addr.shortAddr;
tranSeq = seq;
secUse = sty;
if ( !CACHE_SERVER )
{
// Broadcast reqs without a negative response specified.
if ( (cmd == Discovery_Register_req) || (cmd == Find_node_cache_req) )
{
sent = TRUE;
}
else
{
status = ZDP_NOT_SUPPORTED;
}
}
else if ( cmd == Discovery_Register_req )
{
if ( getIdx( INVALID_NODE_ADDR ) == CACHE_DEV_MAX )
{
status = ZDP_TABLE_FULL;
}
}
else if ( cmd == Discovery_store_req )
{
status = processDiscoveryStoreReq( msg );
}
else if ( cmd == Find_node_cache_req )
{
processFindNodeCacheReq( msg );
sent = TRUE;
}
else if ( cmd == Mgmt_Cache_req )
{
processMgmtCacheReq( *msg );
sent = TRUE;
}
else
{
uint16 aoi = BUILD_UINT16( msg[0], msg[1] );
byte idx = getIdx( aoi );
if ( cmd == Remove_node_cache_req )
{
if ( (purgeAddr( aoi ) + purgeIEEE( msg+2 )) == 0 )
{
status = ZDP_NOT_PERMITTED;
}
}
else if ( idx == CACHE_DEV_MAX )
{
status = ZDP_NOT_PERMITTED;
}
else
{
msg += (2 + Z_EXTADDR_LEN);
switch ( cmd )
{
case Node_Desc_store_req:
osal_memcpy( NodeDesc+idx, msg, sizeof( NodeDescriptorFormat_t ) );
break;
case Power_Desc_store_req:
osal_memcpy( NodePwr+idx, msg, sizeof( NodePowerDescriptorFormat_t ) );
break;
case Active_EP_store_req:
if ( *msg < CACHE_EP_MAX )
{
EPCnt[idx] = *msg++;
osal_memcpy( EPArr+idx, msg, EPCnt[idx] );
}
else
{
status = ZDP_INSUFFICIENT_SPACE;
}
break;
case Simple_Desc_store_req:
status = processSimpleDescStoreReq( msg, idx );
break;
}
}
}
if ( !sent )
{
SendMsg( (cmd | ZDO_RESPONSE_BIT ), 1, &status );
}
}
/*********************************************************************
* @fn ZDCacheProcessMatchDescReq
*
* @brief Build and send a response to a Broadcast Discovery Cache request.
*
* @return None.
*/
void ZDCacheProcessMatchDescReq( byte seq, zAddrType_t *src,
byte inCnt, uint16 *inClusters, byte outCnt, uint16 *outClusters,
uint16 profileID, uint16 aoi, byte sty )
{
byte buf[ 1 + 2 + 1 + CACHE_EP_MAX ]; // Status + AOI + Len + EP list.
byte aoiMatch = (aoi == NWK_BROADCAST_SHORTADDR) ? TRUE : FALSE;
SimpleDescriptionFormat_t *sDesc;
byte idx, epIdx, epCnt;
secUse = sty;
if ( !CACHE_SERVER )
{
return;
}
buf[0] = ZDP_SUCCESS;
buf[1] = LO_UINT16( aoi );
buf[2] = HI_UINT16( aoi );
buf[3] = 0;
msgAddr.addr.shortAddr = src->addr.shortAddr;
// Respond by proxy for all devices that have registered an endpoint.
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( ((aoi == NWK_BROADCAST_SHORTADDR) &&
(NwkAddr[idx] != INVALID_NODE_ADDR)) || (aoi == NwkAddr[idx]) )
{
sDesc = SimpDesc[idx];
epCnt = 4;
for ( epIdx = 0; epIdx < EPCnt[idx]; epIdx++, sDesc++ )
{
if ( sDesc->AppProfId == profileID )
{
// If there are no search input/ouput clusters - respond.
if ( ((inCnt == 0) && (outCnt == 0)) ||
ZDO_AnyClusterMatches( inCnt, inClusters,
sDesc->AppNumInClusters, sDesc->pAppInClusterList ) ||
ZDO_AnyClusterMatches( outCnt, outClusters,
sDesc->AppNumOutClusters, sDesc->pAppOutClusterList ))
{
buf[epCnt++] = sDesc->EndPoint;
}
}
}
if ( epCnt > 4 )
{
buf[1] = LO_UINT16( NwkAddr[idx] );
buf[2] = HI_UINT16( NwkAddr[idx] );
buf[3] = epCnt-4;
SendMsg( Match_Desc_rsp, epCnt, buf );
}
if ( aoi == NwkAddr[idx] )
{
aoiMatch = TRUE;
if ( epCnt == 4 )
{
buf[0] = ZDP_NO_MATCH;
SendMsg( Match_Desc_rsp, 4, buf );
}
break;
}
}
}
if ( !aoiMatch )
{
buf[0] = ZDP_DEVICE_NOT_FOUND;
SendMsg( Match_Desc_rsp, 4, buf );
}
}
/*********************************************************************
* @fn ZDCacheGetDesc
*
* @brief Return the cached descriptor requested.
*
* @param aoi - NWK AddrOfInterest
*
* @return The corresponding descriptor *, if the aoi is found,
* NULL otherwise.
*/
void *ZDCacheGetDesc( uint16 aoi, eDesc_t type, byte *stat )
{
byte epIdx, idx = getIdx( aoi );
void *rtrn = NULL;
byte *ptr;
if ( idx != CACHE_DEV_MAX )
{
byte cnt;
*stat = ZDP_SUCCESS;
switch ( type )
{
case eNodeDesc:
rtrn = (void *)(NodeDesc+idx);
break;
case ePowerDesc:
rtrn = (void *)(NodePwr+idx);
break;
case eActEPDesc:
/* Tricky overload of return values:
* if rtrn val is zero (NULL), status is put in stat[0] -
* either ZDP_DEVICE_NOT_FOUND or ZDP_SUCCESS.
* otherwise, w/ rtrn val > 0, stat is loaded byte for byte w/
* all active endpts other than ZDO. Thus, stat must be pointing to
* an array of at least CACHE_EP_MAX bytes.
*/
ptr = EPArr[ idx ];
for ( cnt = 0, idx = 0; idx < CACHE_EP_MAX; idx++ )
{
if ( ptr[idx] == 0xff )
break;
else if ( ptr[idx] == ZDO_EP )
continue;
else
{
*stat++ = ptr[idx];
cnt++;
}
}
rtrn = (void *)cnt;
break;
case eSimpDesc:
// Tricky re-use of status parameter as endPoint to find.
epIdx = getIdxEP( idx, *stat );
if ( epIdx == CACHE_EP_MAX )
{
*stat = ZDP_DEVICE_NOT_FOUND;
}
else
{
rtrn = (void *)(&SimpDesc[idx][epIdx]);
}
break;
default:
*stat = ZDP_INVALID_REQTYPE;
break;
}
}
else
{
*stat = ZDP_DEVICE_NOT_FOUND;
}
return rtrn;
}
/*********************************************************************
* @fn ZDCacheGetNwkAddr
*
* @brief Find the Network Address of a discovery cache entry that
* corresponds to the given IEEE address.
*
* @param byte * - a valid buffer containing an extended IEEE address.
*
* @return If address found, return the nwk addr, else INVALIDE_NODE_ADDR.
*
*/
uint16 ZDCacheGetNwkAddr( byte *ieee )
{
uint16 addr = INVALID_NODE_ADDR;
byte idx;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( osal_ExtAddrEqual( ieee, ExtAddr[idx] ) &&
(NwkAddr[idx] != INVALID_NODE_ADDR) )
{
addr = NwkAddr[idx];
break;
}
}
return addr;
}
/*********************************************************************
* @fn ZDCacheGetExtAddr
*
* @brief Find the Extended Address of a discovery cache entry that
* corresponds to the given Network address.
*
* @param aoi - the Network Address of interest.
*
* @return If address found, return a ptr to the extended ieee addr, else NULL.
*
*/
byte * ZDCacheGetExtAddr( uint16 aoi )
{
byte *ieee = NULL;
byte idx;
for ( idx = 0; idx < CACHE_DEV_MAX; idx++ )
{
if ( aoi == NwkAddr[idx] )
{
ieee = ExtAddr[idx];
break;
}
}
return ieee;
}
#endif
#if ( CACHE_DEV_MAX == 0 )
/*********************************************************************
* @fn ZDCacheProcessRsp
*
* @brief Process a response to a Discovery Cache request.
*
* @return none
*/
void ZDCacheProcessRsp(
zAddrType_t *src, byte *msg, byte len, byte cmd, byte seq )
{
if ( ((cmd==Find_node_cache_rsp) && (*msg==ZDP_NOT_SUPPORTED) && (len==3)) ||
((cmd!=Find_node_cache_rsp) &&
((*msg != ZDP_SUCCESS) || (seq != (tranSeq-1)))) )
{
return;
}
cacheRsp = ZDP_SUCCESS;
switch ( cmd )
{
case Discovery_Register_rsp:
case Find_node_cache_rsp:
if ( cacheCnt < FIND_RSP_MAX )
{
byte idx;
// Only log unique response addresses.
for ( idx = 0; idx < cacheCnt; idx++ )
{
if ( cacheFindAddr[idx] == src->addr.shortAddr )
{
break;
}
}
if ( idx == cacheCnt )
{
cacheFindAddr[cacheCnt++] = src->addr.shortAddr;
}
}
break;
default:
break;
}
}
#endif
/*********************************************************************
*********************************************************************/
#endif //#if defined( ZDO_CACHE )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -