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

📄 zdcache.c

📁 Zigbee2006入门(源代码+文档讲解+系统推荐)
💻 C
📖 第 1 页 / 共 2 页
字号:

  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 + -