Zigbee 接收过程 2015-07-15

本文详细介绍了Zigbee协议栈中afBuildMSGIncoming和afIncomingData两个关键函数,用于处理接收到的数据PDU。afBuildMSGIncoming用于构建应用层消息,而afIncomingData负责将APS子层的数据传递到应用层。当接收到组播或广播消息时,会遍历已注册的端点并调用相应处理函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/*********************************************************************
 * @fn          afBuildMSGIncoming
 *
 * @brief       Build the message for the app
 *
 * @param
 *
 * @return      pointer to next in data buffer
 */
static void afBuildMSGIncoming( aps_FrameFormat_t *aff, endPointDesc_t *epDesc,
                 zAddrType_t *SrcAddress, uint16 SrcPanId, NLDE_Signal_t *sig,
                 uint8 nwkSeqNum, uint8 SecurityUse, uint32 timestamp )
{
  afIncomingMSGPacket_t *MSGpkt;
  const uint8 len = sizeof( afIncomingMSGPacket_t ) + aff->asduLength;
  uint8 *asdu = aff->asdu;
  MSGpkt = (afIncomingMSGPacket_t *)osal_msg_allocate( len );

  if ( MSGpkt == NULL )
  {
    return;
  }

  MSGpkt->hdr.event = AF_INCOMING_MSG_CMD;
  MSGpkt->groupId = aff->GroupID;
  MSGpkt->clusterId = aff->ClusterID;
  afCopyAddress( &MSGpkt->srcAddr, SrcAddress );
  MSGpkt->srcAddr.endPoint = aff->SrcEndPoint;
  MSGpkt->endPoint = epDesc->endPoint;
  MSGpkt->wasBroadcast = aff->wasBroadcast;
  MSGpkt->LinkQuality = sig->LinkQuality;
  MSGpkt->correlation = sig->correlation;
  MSGpkt->rssi = sig->rssi;
  MSGpkt->SecurityUse = SecurityUse;
  MSGpkt->timestamp = timestamp;
  MSGpkt->nwkSeqNum = nwkSeqNum;
  MSGpkt->macDestAddr = aff->macDestAddr;
  MSGpkt->srcAddr.panId = SrcPanId;
  MSGpkt->cmd.TransSeqNumber = 0;
  MSGpkt->cmd.DataLength = aff->asduLength;

  if ( MSGpkt->cmd.DataLength )
  {
    MSGpkt->cmd.Data = (uint8 *)(MSGpkt + 1);
    osal_memcpy( MSGpkt->cmd.Data, asdu, MSGpkt->cmd.DataLength );
  }
  else
  {
    MSGpkt->cmd.Data = NULL;
  }

#if defined ( MT_AF_CB_FUNC )
  // If ZDO or SAPI have registered for this endpoint, dont intercept it here
  if (AFCB_CHECK(CB_ID_AF_DATA_IND, *(epDesc->task_id)))
  {
    MT_AfIncomingMsg( (void *)MSGpkt );
    // Release the memory.
    osal_msg_deallocate( (void *)MSGpkt );
  }
  else
#endif
  {
    // Send message through task message.
    osal_msg_send( *(epDesc->task_id), (uint8 *)MSGpkt );
  }
}

 


/*********************************************************************
 * @fn          afIncomingData
 *
 * @brief       Transfer a data PDU (ASDU) from the APS sub-layer to the AF.
 *
 * @param       aff  - pointer to APS frame format
 * @param       SrcAddress  - Source address
 * @param       SrcPanId  - Source PAN ID
 * @param       sig - incoming message's link quality
 * @param       nwkSeqNum - incoming network sequence number (from nwk header frame)
 * @param       SecurityUse - Security enable/disable
 * @param       timestamp - the MAC Timer2 timestamp at Rx.
 *
 * @return      none
 */
void afIncomingData( aps_FrameFormat_t *aff, zAddrType_t *SrcAddress, uint16 SrcPanId,
                     NLDE_Signal_t *sig, uint8 nwkSeqNum, uint8 SecurityUse, uint32 timestamp )
{
  endPointDesc_t *epDesc = NULL;
  epList_t *pList = epList;
#if !defined ( APS_NO_GROUPS )
  uint8 grpEp = APS_GROUPS_EP_NOT_FOUND;
#endif

  if ( ((aff->FrmCtrl & APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP) )
  {
#if !defined ( APS_NO_GROUPS )
    // Find the first endpoint for this group
    grpEp = aps_FindGroupForEndpoint( aff->GroupID, APS_GROUPS_FIND_FIRST );
    if ( grpEp == APS_GROUPS_EP_NOT_FOUND )
      return;   // No endpoint found

    epDesc = afFindEndPointDesc( grpEp );
    if ( epDesc == NULL )
      return;   // Endpoint descriptor not found

    pList = afFindEndPointDescList( epDesc->endPoint );
#else
    return; // Not supported
#endif
  }
  else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT )
  {//广播就拿到第一个节点
    // Set the list
    if ( pList != NULL )
    {//从第一个开始,第0个是端点0么,记得好像不是,广播会播给端点0么
      //理解错了,这个端点描述符仅仅是他的一个域,所以还是第0个开始
      epDesc = pList->epDesc;
    }
  }
  else if ( (epDesc = afFindEndPointDesc( aff->DstEndPoint )) )
  {//点播,在AF注册过的端点对应的端点描述符,pList指向我们目标端点的端点描述符
    pList = afFindEndPointDescList( epDesc->endPoint );
  }

  while ( epDesc )
  {//如果有目标端点描述符
   
    uint16 epProfileID = 0xFFFF;  // Invalid Profile ID

    if ( pList->pfnDescCB )
    {
      uint16 *pID = (uint16 *)(pList->pfnDescCB(
                                 AF_DESCRIPTOR_PROFILE_ID, epDesc->endPoint ));
      if ( pID )
      {
        epProfileID = *pID;
        osal_mem_free( pID );
      }
    }
    else if ( epDesc->simpleDesc )
    {
      epProfileID = epDesc->simpleDesc->AppProfId;
    }

    if ( (aff->ProfileID == epProfileID) ||
         ((epDesc->endPoint == ZDO_EP) && (aff->ProfileID == ZDO_PROFILE_ID)) )
    {//可见端点0还是会经来
      {
        // Save original endpoint
        uint8 endpoint = aff->DstEndPoint;

        // overwrite with descriptor's endpoint
        aff->DstEndPoint = epDesc->endPoint;

        afBuildMSGIncoming( aff, epDesc, SrcAddress, SrcPanId, sig,
                           nwkSeqNum, SecurityUse, timestamp );

        // Restore with original endpoint
        aff->DstEndPoint = endpoint;
      }
    }

    if ( ((aff->FrmCtrl & APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP) )
    {//组播处理
#if !defined ( APS_NO_GROUPS )
      // Find the next endpoint for this group
      grpEp = aps_FindGroupForEndpoint( aff->GroupID, grpEp );
      if ( grpEp == APS_GROUPS_EP_NOT_FOUND )
        return;   // No endpoint found

      epDesc = afFindEndPointDesc( grpEp );
      if ( epDesc == NULL )
        return;   // Endpoint descriptor not found

      pList = afFindEndPointDescList( epDesc->endPoint );
#else
      return;
#endif
    }
    else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT )
    {//广播处理
      pList = pList->nextDesc;
      if ( pList )
        epDesc = pList->epDesc;
      else
        epDesc = NULL;
    }
    else//点播处理
      epDesc = NULL;
  }
}

 


AF.h (c:\texas instruments\...\af):375
  * afIncomingData - APS will call this function when an incoming
  *                   message is received.
  */
  extern void afIncomingData( aps_FrameFormat_t *aff, zAddrType_t *SrcAddress, uint16 SrcPanId,
                       NLDE_Signal_t *sig, uint8 nwkSeqNum, uint8 SecurityUse, uint32 timestamp );

 

epList_t *epList;在AF.c文件中

 

typedef struct _epList_t {
  struct _epList_t *nextDesc;
  endPointDesc_t *epDesc;
  pDescCB  pfnDescCB;     // Don't use if this function pointer is NULL.
  afAPSF_Config_t apsfCfg;
  eEP_Flags flags;
} epList_t;在AF.h文件中
//可以理解成把端点描述符合指针串起来一个链表,epList是这个链表中节点指针,指向表头

  // Register the endpoint description with the AF
  afRegister( &SampleApp_epDesc );
 
  /*********************************************************************
 * @fn      afRegister
 *
 * @brief   Register an Application's EndPoint description.
 *
 * @param   epDesc - pointer to the Application's endpoint descriptor.
 *
 * NOTE:  The memory that epDesc is pointing to must exist after this call.
 *
 * @return  afStatus_SUCCESS - Registered
 *          afStatus_MEM_FAIL - not enough memory to add descriptor
 *          afStatus_INVALID_PARAMETER - duplicate endpoint
 */
afStatus_t afRegister( endPointDesc_t *epDesc )
{
  if (afFindEndPointDescList(epDesc->endPoint))  // Look for duplicate endpoint.
  {//如果注册了,那么就不能注册,没有就注册,侧面证明了,每个端点只能被一个任务注册
    return afStatus_INVALID_PARAMETER;
  }

  return ((NULL == afRegisterExtended(epDesc, NULL)) ? afStatus_MEM_FAIL : afStatus_SUCCESS);
}
/*********************************************************************
 * @fn      afFindEndPointDescList
 *
 * @brief   Find the endpoint description entry from the endpoint
 *          number.
 *
 * @param   EndPoint - Application Endpoint to look for
 *
 * @return  the address to the endpoint/interface description entry
 */
static epList_t *afFindEndPointDescList( uint8 EndPoint )
{//从链表中通过端点,来在端点描述符列表中搜索,有没有这个端点对应的端点描述符被注册,有就返回,没有返回NULL
  epList_t *epSearch;

  for (epSearch = epList; epSearch != NULL; epSearch = epSearch->nextDesc)
  {
    if (epSearch->epDesc->endPoint == EndPoint)
    {
      break;
    }
  }

  return epSearch;
}

/*********************************************************************
 * @fn      afRegisterExtended
 *
 * @brief   Register an Application's EndPoint description.
 *
 * @param   epDesc - pointer to the Application's endpoint descriptor.
 * @param   descFn - pointer to descriptor callback function
 *
 * NOTE:  The memory that epDesc is pointing to must exist after this call.
 *
 * @return  Pointer to epList_t on success, NULL otherwise.
 */
epList_t *afRegisterExtended( endPointDesc_t *epDesc, pDescCB descFn )
{//从这里看建立是从右边到左边,epList头不断向新的头滑动
  epList_t *ep = osal_mem_alloc(sizeof(epList_t));

  if (ep != NULL)
  {
    ep->nextDesc = epList;
    epList = ep;
    ep->epDesc = epDesc;
    ep->pfnDescCB = descFn;
    ep->apsfCfg.frameDelay = APSF_DEFAULT_INTERFRAME_DELAY;
    ep->apsfCfg.windowSize = APSF_DEFAULT_WINDOW_SIZE;
    ep->flags = eEP_AllowMatch;  // Default to allow Match Descriptor.
  }

  return ep;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值