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

📄 af.c

📁 Zigbee2006入门源代码,包括了Zigbee的入门介绍,和源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        epDesc = pList->epDesc;
      else
        epDesc = NULL;
    }
    else
      epDesc = NULL;
  }
}

#if ( AF_KVP_SUPPORT )
/*********************************************************************
 * @fn          afBuildKVPIncoming
 *
 * @brief       Build the message for the app
 *
 * @param
 *
 * @return
 */
static void afBuildKVPIncoming( aps_FrameFormat_t *aff, endPointDesc_t *epDesc,
                 zAddrType_t *SrcAddress, uint8 LinkQuality, byte SecurityUse )
{
  afIncomingKVPPacket_t *KVPpkt = (afIncomingKVPPacket_t *)osal_mem_alloc(
                           sizeof( afIncomingKVPPacket_t ) );
  byte *asdu = aff->asdu;
  const byte total = LO_UINT8( *asdu++ );
  byte count;

  if ( KVPpkt == NULL )
  {
    return;
  }

  KVPpkt->hdr.event = ((total > 1) ? AF_INCOMING_GRP_KVP_CMD :
                                     AF_INCOMING_KVP_CMD );
  KVPpkt->clusterId = aff->ClusterID;
  afCopyAddress( &(KVPpkt->srcAddr), SrcAddress );
  KVPpkt->srcAddr.endPoint = aff->SrcEndPoint;
  KVPpkt->endPoint = epDesc->endPoint;
  KVPpkt->wasBroadcast = aff->wasBroadcast;
  KVPpkt->LinkQuality = LinkQuality;
  KVPpkt->SecurityUse = SecurityUse;
  KVPpkt->totalTrans = total;
  KVPpkt->cmd.TransSeqNumber = *asdu++;

  for ( count = 1; count <= total; count++ )
  {
    afIncomingKVPPacket_t *msgKVPpkt;

    KVPpkt->cmd.CommandType = LO_UINT8(*asdu);
    KVPpkt->cmd.AttribDataType = HI_UINT8(*asdu++);
    KVPpkt->cmd.AttribId = BUILD_UINT16( asdu[0], asdu[1] );
    asdu += 2;

    /* ErrorCode */
    if ((KVPpkt->cmd.CommandType == CMDTYPE_GET_RESP) ||
        (KVPpkt->cmd.CommandType == CMDTYPE_SET_RESP) ||
        (KVPpkt->cmd.CommandType == CMDTYPE_EVENT_RESP))
    {
      KVPpkt->cmd.ErrorCode = *asdu++;
    }
    else
    {
      KVPpkt->cmd.ErrorCode = ERRORCODE_SUCCESS;
    }

    /* DataLength */
    if ( (KVPpkt->cmd.CommandType == CMDTYPE_GET_ACK) ||
         (KVPpkt->cmd.CommandType == CMDTYPE_SET_RESP) ||
         (KVPpkt->cmd.CommandType == CMDTYPE_EVENT_RESP ) )
    {
      KVPpkt->cmd.DataLength = 0;
    }
    else if ((KVPpkt->cmd.AttribDataType == DATATYPE_CHAR_STR) ||
             (KVPpkt->cmd.AttribDataType == DATATYPE_OCTET_STR))
    {
      KVPpkt->cmd.DataLength = *asdu++;
    }
    else
    {
      KVPpkt->cmd.DataLength = GetDataTypeLength( (byte)KVPpkt->cmd.AttribDataType );
    }

    msgKVPpkt = (afIncomingKVPPacket_t *)osal_msg_allocate( (short)
                 (sizeof( afIncomingKVPPacket_t ) + KVPpkt->cmd.DataLength) );

    if ( msgKVPpkt == NULL )
    {
      // Maybe not enought for an octet string, but next might be no data,
      // so don't return here, just continue to look at the rest.
      asdu += KVPpkt->cmd.DataLength;
      continue;
    }

    osal_memcpy( msgKVPpkt, KVPpkt, sizeof( afIncomingKVPPacket_t ) );

    msgKVPpkt->count = count;

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

#if defined ( MT_AF_CB_FUNC )
    // If MT has subscribed for this callback, don't send as a message.
    if ( _afCallbackSub & CB_ID_AF_DATA_IND )
    {
      af_MTCB_IncomingData( (void *)msgKVPpkt );
      // Release the memory.
      osal_msg_deallocate( (void *)msgKVPpkt );
    }
    else
#endif
    {
      osal_msg_send( *(epDesc->task_id), (uint8*)msgKVPpkt );
    }
  }

  osal_mem_free( KVPpkt );
}
#endif

/*********************************************************************
 * @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, uint8 LinkQuality, byte SecurityUse,
                 uint32 timestamp )
{
  afIncomingMSGPacket_t *MSGpkt;
#if ( AF_V1_SUPPORT )
  const byte proVer = NLME_GetProtocolVersion();
  const byte len = sizeof( afIncomingMSGPacket_t ) +
              ((proVer == ZB_PROT_V1_0) ? aff->asdu[2] : aff->asduLength);
  byte *asdu = aff->asdu + ((proVer == ZB_PROT_V1_0) ? 1 : 0);
#else
  const byte len = sizeof( afIncomingMSGPacket_t ) + aff->asduLength;
  byte *asdu = aff->asdu;
#endif
  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 = LinkQuality;
  MSGpkt->SecurityUse = SecurityUse;
  MSGpkt->timestamp = timestamp;

#if ( AF_V1_SUPPORT )
  if ( proVer == ZB_PROT_V1_0 )
  {
    MSGpkt->cmd.TransSeqNumber = *asdu++;
    MSGpkt->cmd.DataLength = *asdu++;
  }
  else
#endif
  {
    MSGpkt->cmd.TransSeqNumber = 0;
    MSGpkt->cmd.DataLength = aff->asduLength;
  }

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

#if defined ( MT_AF_CB_FUNC )
  // If MT has subscribed for this callback, don't send as a message.
  if ( _afCallbackSub & CB_ID_AF_DATA_IND )
  {
    af_MTCB_IncomingData( (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 );
  }
}

#if ( AF_KVP_SUPPORT )
/*********************************************************************
 * @fn      multiInit
 *
 * @brief   Initialize a multi header.
 *
 * @param   none
 *
 * @return  Pointer to the new memory allocated for the afMultiHdr_t structure.
 */
static afMultiHdr_t *multiInit( afAddrType_t *dstAddr,
                     byte srcEndPoint, uint16 clusterID, byte FrameType,
                     byte txOptions, bool DiscoverRoute, byte RadiusCounter )
{
  afMultiHdr_t *hdr = (afMultiHdr_t *)osal_mem_alloc( sizeof( afMultiHdr_t ) );

  if ( hdr == NULL )
  {
    return NULL;
  }

  hdr->clusterID = clusterID;
  hdr->transCount = 0;
  hdr->options = txOptions & AF_ACK_REQUEST;
  hdr->options |= (DiscoverRoute) ? AF_DISCV_ROUTE : 0;
  hdr->srcEP = srcEndPoint;
  hdr->dstAddr.endPoint = dstAddr->endPoint;
  hdr->dstAddr.addrMode = dstAddr->addrMode;
  hdr->dstAddr.addr.shortAddr = dstAddr->addr.shortAddr;
  hdr->msgLen = 0;
  hdr->msg = NULL;

  return hdr;
}

/*********************************************************************
 * @fn      multiAppend
 *
 * @brief   Concatenate a new KVP message too a mulit-KVP message.
 *
 * @param   none
 *
 * @return  TRUE for success, FALSE otherwise.
 */
static bool multiAppend( afMultiHdr_t *hdr, byte bufLen, byte *buf,
       byte CommandType, byte AttribDataType, uint16 AttribId, byte ErrorCode )
{
  byte len = (byte)hdr->msgLen;
  byte *msg = osal_mem_alloc( (short)(AF_HDR_KVP_MAX_LEN + bufLen + len) );

  if ( msg == NULL )
  {
    return FALSE;
  }

  if ( hdr->msg == NULL )  // Need to make space for FrameType/Count & SeqNum.
  {
    len += 5;
    hdr->msg = msg;
    msg += 2;
  }
  else                     // Need to copy existing buffer over.
  {
    len += 3;
    osal_memcpy( msg, hdr->msg, hdr->msgLen );
    osal_mem_free( hdr->msg );
    hdr->msg = msg;
    msg += hdr->msgLen;
  }

  *msg++ = BUILD_UINT8( AttribDataType, CommandType );
  *msg++ = LO_UINT16( AttribId);
  *msg++ = HI_UINT16( AttribId );

  if ((CommandType == CMDTYPE_GET_RESP) ||
      (CommandType == CMDTYPE_SET_RESP) ||
      (CommandType == CMDTYPE_EVENT_RESP) )
  {
    *msg++ = ErrorCode;
    len++;
  }

  if ( (CommandType == CMDTYPE_GET_ACK) ||
       (CommandType == CMDTYPE_SET_RESP) ||
       (CommandType == CMDTYPE_EVENT_RESP ) )
  {
    bufLen = 0;
  }
  else if ((AttribDataType == DATATYPE_CHAR_STR) ||
           (AttribDataType == DATATYPE_OCTET_STR))
  {
    *msg++ = bufLen;
    len++;
  }

  if ( buf && bufLen )
  {
    osal_memcpy( msg, buf, bufLen );
    len += bufLen;
  }

  hdr->msgLen = len;
  hdr->transCount++;

  return TRUE;
}

/*********************************************************************
 * @fn      multiSend
 *
 * @brief   Send whatever has been buffered to send multi.
 *
 * @param   none
 *
 * @return  afStatus_t
 */
static afStatus_t multiSend( afMultiHdr_t *hdr, byte *seqNum, byte radius )
{
  afStatus_t stat;

  if ( hdr == NULL )
  {
    return afStatus_MEM_FAIL;
  }

  hdr->msg[0] = BUILD_UINT8( FRAMETYPE_KVP, hdr->transCount );
  hdr->msg[1] = *seqNum;

  stat = afSend( &hdr->dstAddr, hdr->srcEP, hdr->clusterID,
                  hdr->msgLen, hdr->msg, seqNum, hdr->options, radius );

  osal_mem_free( hdr->msg );
  osal_mem_free( hdr );

  return stat;
}

/*********************************************************************
 * @fn      afAddOrSendMessage
 *
 * @brief   Fills in the cmd format structure and sends the out-going message.
 *
 * input parameters
 *
 * @param  *dstAddr         - Full ZB destination address: Nwk Addr + End Point.
 * @param   srcEndPoint     - Origination (i.e. respond to or ack to) End Point.
 * @param   clusterID       - A valid cluster ID as specified by the Profile
 *          (e.g. see CLUSTERID_... defs in HomeControlLighting.h).
 * @param   AddOrSend       - A valid afAddOrSend_t type.
 * @param   FrameType       - A valid frame type (see prev def of FRAMETYPE_...)
 * @param  *TransSeqNumber  - A pointer to a byte which can be modified and
 *          which will be used as the transaction sequence number of the msg.
 * @param   CommandType     -
 *          KVP Frame Type  : A valid command type (see prev def of CMDTYPE_...)
 *          MSG Frame Type  : Set to 0.
 * @param   AttribDataType  -
 *          KVP Frame Type  : A valid data type (see prev def of DATATYPE_...)
 *          MSG Frame Type  : Set to 0.
 * @param   AttribId        -
 *          KVP Frame Type  : A valid Attribute ID as specified by the Profile.
 *            (e.g. see OnOffSRC_OnOff in HomeControlLighting.h).
 *          MSG Frame Type  : Set to 0.
 * @param   ErrorCode       -
 *          KVP Frame Type  : A valid error code (see prev def of ERRORCODE_...)
 *          Note: Set to 0 unless the CommandType is one of the CMDTYPE_..._ACK.
 *          MSG Frame Type  : Set to 0.
 * @param   DataLength      - Number of bytes of data pointed to by next param.
 *          KVP Frame Type  : This must match value expected for the
 *          AttributeDataType specified above or the send will fail.
 *          MSG Frame Type  : No restriction or checks.
 * @param  *Data            - A pointer to the data bytes to send.
 * @param   txOptions       - A valid bit mask (see prev def of APS_TX_OPTIONS_)
 * @param   DiscoverRoute   - Normally set to FALSE. Perhaps set to TRUE after
 *          receiving an AF_DATA_CONFIRM_CMD with status other than ZSuccess.
 * @param   RadiusCounter   - Normally set to AF_DEFAULT_RADIUS.
 *
 * output parameters
 *
 * @param  *TransSeqNumber  - Incremented by one if the return value is success.
 *
 * @return  afStatus_t      - See previous definition of afStatus_... types.
 */
afStatus_t afAddOrSendMessage(
    afAddrType_t *dstAddr, byte srcEndPoint, cId_t clusterID,
    afAddOrSend_t AddOrSend, byte FrameType, byte *TransSeqNumber,
    byte CommandType, byte AttribDataType, uint16 AttribId, byte ErrorCode,
    byte DataLength, byte *Data,
    byte txOptions, byte DiscoverRoute, byte RadiusCounter )
{
  static afMultiHdr_t *hdr;
  afStatus_t stat = afStatus_FAILED;

  if ( FrameType == FRAMETYPE_MSG )
  {
    if ( AddOrSend != SEND_MESSAGE )
    {
      return afStatus_INVALID_PARAMETER;
    }

    return afFillAndSendMessage( dstAddr, srcEndPoint, clusterID,
      1, FrameType, TransSeqNumber, NULL, NULL, NULL, NULL,
      DataLength, Data, txOptions, DiscoverRoute, RadiusCounter );
  }

  if ( FrameType != FRAMETYPE_KVP )
  {
    return afStatus_INVALID_PARAMETER;
  }

  // Cannot mix Cluster ID's in aggregation packet.
  if ( (hdr != NULL) && (hdr->clusterID != clusterID) )
  {
    multiSend( hdr, TransSeqNumber, RadiusCounter );
    hdr = NULL;
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -