⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zdcache.c

📁 Zigbee2006入门(源代码+文档讲解+系统推荐)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************
    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 + -