请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
部件号:CC2652P GitHub: https://github.com/zigbee-luo/z_stack_2022.git
修复af.c.
/*********************************************************************
* MACROS
*/
#ifndef NWK_MAX_DATABUFS_TOTAL
#define NWK_MAX_DATABUFS_TOTAL 24 // same with nwk_global.c, luoyiming 2022-04-08
#endif
/*********************************************************************
* TYPEDEF
*/
typedef struct
{
void* next;
uint8_t endpoint;
uint8_t transID;
uint16_t clusterID;
bool apsAck;
void* cnfParam;
pfnAfCnfCB afCnfCB;
} afDataCnfList_t;
typedef struct
{
uint8_t endPoint;
uint8_t transID;
uint16_t clusterID;
} afDataConfirmParam_t;
/*********************************************************************
* @fn afSend
*
* @brief Helper macro for V1 API to invoke V2 API.
*
* input parameters
*
* @param *dstAddr - Full ZB destination address: Nwk Addr + End Point.
* @param srcEP - Origination (i.e. respond to or ack to) End Point.
* @param cID - A valid cluster ID as specified by the Profile.
* @param len - Number of bytes of data pointed to by next param.
* @param *buf - A pointer to the data bytes to send.
* @param options - Valid bit mask of AF Tx Options as defined in af.h.
* @param *transID - A pointer to a byte which can be modified and which will
* be used as the transaction sequence number of the msg.
*
* output parameters
*
* @param *transID - Incremented by one if the return value is success.
*
* @return afStatus_t - See previous definition of afStatus_... types.
*/
#define afSend( dstAddr, srcEP, cID, len, buf, transID, options, radius ) \
AF_DataRequest( (dstAddr), afFindEndPointDesc( (srcEP) ), \
(cID), (len), (buf), (transID), (options), (radius) )
/*********************************************************************
* GLOBAL VARIABLES
*/
epList_t *epList;
/*********************************************************************
* LOCAL VARIABLES
*/
afDataCnfList_t *afDataCnfList;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void afBuildMSGIncoming( aps_FrameFormat_t *aff, endPointDesc_t *epDesc,
zAddrType_t *SrcAddress, uint16_t SrcPanId, NLDE_Signal_t *sig,
uint8_t nwkSeqNum, uint8_t SecurityUse, uint32_t timestamp, uint8_t radius );
static epList_t *afFindEndPointDescList( uint8_t EndPoint );
static pDescCB afGetDescCB( endPointDesc_t *epDesc );
static bool afAddCnfItem(afDataCnfList_t* cnfItem);
static afDataCnfList_t* afGetCnfItem(uint8_t endpoint, uint8_t transID);
static afDataCnfList_t* afFindCnfItem(uint8_t endpoint, uint8_t transID);
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn afInit
*
* @brief Initialization function for the AF.
*
* @param none
*
* @return none
void afInit( void )
{
}
*/
/*********************************************************************
* @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
* @param applFn - pointer to the Application 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, pApplCB applFn )
{
epList_t *ep = OsalPort_malloc(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.
ep->pfnApplCB = applFn;
#if (BDB_FINDING_BINDING_CAPABILITY_ENABLED==1)
//Make sure we add at least one application endpoint
if ((epDesc->endPoint != 0) && (epDesc->endPoint < BDB_ZIGBEE_RESERVED_ENDPOINTS_START))
{
bdb_HeadEpDescriptorList = epList;
ep->epDesc->epType = bdb_zclFindingBindingEpType(ep->epDesc);
}
#endif
#if defined ( BDB_TL_INITIATOR ) || defined ( BDB_TL_TARGET )
// find the first empty entry in the device info table
for ( uint8_t i = 0; i < TOUCHLINK_NUM_DEVICE_INFO_ENTRIES; i++ )
{
if ( touchLinkSubDevicesTbl[i] == NULL )
{
touchLinkSubDevicesTbl[i] = OsalPort_malloc(sizeof(bdbTLDeviceInfo_t));
if ( touchLinkSubDevicesTbl[i] != NULL )
{
touchLinkSubDevicesTbl[i]->deviceID = epDesc->simpleDesc->AppDeviceId;
touchLinkSubDevicesTbl[i]->endpoint = epDesc->simpleDesc->EndPoint;
touchLinkSubDevicesTbl[i]->profileID = epDesc->simpleDesc->AppProfId;
touchLinkSubDevicesTbl[i]->version = epDesc->simpleDesc->AppDevVer;
break;
}
}
}
#endif // BDB_TL_INITIATOR || BDB_TL_TARGET
}
return ep;
}
/*********************************************************************
* @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, NULL)) ? afStatus_MEM_FAIL : afStatus_SUCCESS);
}
/*********************************************************************
* @fn afDelete
*
* @brief Delete an Application's EndPoint descriptor and frees the memory
*
* @param EndPoint - Application Endpoint to delete
*
* @return afStatus_SUCCESS - endpoint deleted
* afStatus_INVALID_PARAMETER - endpoint not found
* afStatus_FAILED - endpoint list empty
*/
afStatus_t afDelete( uint8_t EndPoint )
{
epList_t *epCurrent;
epList_t *epPrevious;
if ( epList != NULL )
{
epPrevious = epCurrent = epList;
// first element of the list matches
if ( epCurrent->epDesc->endPoint == EndPoint )
{
epList = epCurrent->nextDesc;
OsalPort_free( epCurrent );
return ( afStatus_SUCCESS );
}
else
{
// search the list
for ( epCurrent = epPrevious->nextDesc;
epCurrent != NULL;
epCurrent = epCurrent->nextDesc )
{
if ( epCurrent->epDesc->endPoint == EndPoint )
{
epPrevious->nextDesc = epCurrent->nextDesc;
OsalPort_free( epCurrent );
// delete the entry and free the memory
return ( afStatus_SUCCESS );
}
epPrevious = epCurrent;
}
}
// no endpoint found
return ( afStatus_INVALID_PARAMETER );
}
else
{
// epList is empty
return ( afStatus_FAILED );
}
}
/*********************************************************************
* @fn afDataConfirm
*
* @brief This function will generate the Data Confirm back to
* the application.
*
* @param endPoint - confirm end point
* @param transID - transaction ID from APSDE_DATA_REQUEST
* @param status - status of APSDE_DATA_REQUEST
*
* @return none
*/
void afDataConfirm( uint8_t endPoint, uint8_t transID, uint16_t clusterID, ZStatus_t status )
{
endPointDesc_t *epDesc;
afDataConfirm_t *msgPtr;
//get the confirm callbakck and run
pfnAfCnfCB afCnfCB = NULL;
void* cnfParam = NULL;
afDataCnfList_t* cnfItem = afGetCnfItem( endPoint, transID );
if(cnfItem)
{
afCnfCB = cnfItem->afCnfCB;
cnfParam = cnfItem->cnfParam;
OsalPort_free(cnfItem);
}
// Find the endpoint description
epDesc = afFindEndPointDesc( endPoint );
if ( epDesc == NULL )
return;
// Determine the incoming command type
msgPtr = (afDataConfirm_t *)OsalPort_msgAllocate( sizeof(afDataConfirm_t) );
if ( msgPtr )
{
// Build the Data Confirm message
msgPtr->hdr.event = AF_DATA_CONFIRM_CMD;
msgPtr->hdr.status = status;
msgPtr->endpoint = endPoint;
msgPtr->clusterID = clusterID;
msgPtr->transID = transID;
//add new menber for confirm
msgPtr->afCnfCB = afCnfCB;
msgPtr->cnfParam = cnfParam;
#if defined ( MT_AF_CB_FUNC )
/* If MT has subscribed for this callback, don't send as a message. */
if ( AFCB_CHECK(CB_ID_AF_DATA_CNF,*(epDesc->task_id)) )
{
/* Send callback if it's subscribed */
MT_AfDataConfirm ((void *)msgPtr);
/* Release the memory. */
OsalPort_msgDeallocate( (void *)msgPtr );
}
else
#endif
{
/* send message through task message */
OsalPort_msgSend( *(epDesc->task_id), (uint8_t *)msgPtr );
}
}
}
/*********************************************************************
* @fn afReflectError
*
* @brief This function will generate the Reflect Error message to
* the application.
*
* @param srcEP - Source Endpoint
* @param dstAddrMode - mode of dstAdd - 0 - normal short addr, 1 - group Address
* @param dstAddr - intended destination
* @param dstEP - Destination Endpoint
* @param transID - transaction ID from APSDE_DATA_REQUEST
* @param status - status of APSDE_DATA_REQUEST
*
* @return none
*/
void afReflectError( uint8_t srcEP, uint8_t dstAddrMode, uint16_t dstAddr, uint8_t dstEP,
uint8_t transID, ZStatus_t status )
{
endPointDesc_t *epDesc;
afReflectError_t *msgPtr;
//get the confirm param
void* cnfParam = NULL;
afDataCnfList_t* cnfFind = afFindCnfItem(srcEP, transID);
if(cnfFind)
{
cnfParam = cnfFind->cnfParam;
}
// Find the endpoint description
epDesc = afFindEndPointDesc( srcEP );
if ( epDesc == NULL )
return;
// Determine the incoming command type
msgPtr = (afReflectError_t *)OsalPort_msgAllocate( sizeof(afReflectError_t) );
if ( msgPtr )
{
// Build the Data Confirm message
msgPtr->hdr.event = AF_REFLECT_ERROR_CMD;
msgPtr->hdr.status = status;
msgPtr->endpoint = srcEP; //As the error is internal the dst endpoint is the endpoint generating the frame (srcEp)
msgPtr->transID = transID;
msgPtr->dstAddrMode = dstAddrMode;
msgPtr->dstAddr = dstAddr;
msgPtr->dstEP = dstEP;
msgPtr->cnfParam = cnfParam;
#if defined ( MT_AF_CB_FUNC )
/* If MT has subscribed for this callback, don't send as a message. */
if ( AFCB_CHECK( CB_ID_AF_REFLECT_ERROR, *(epDesc->task_id) ) )
{
/* Send callback if it's subscribed */
MT_AfReflectError( (void *)msgPtr );
/* Release the memory. */
OsalPort_msgDeallocate( (void *)msgPtr );
}
else
#endif
{
/* send message through task message */
OsalPort_msgSend( *(epDesc->task_id), (uint8_t *)msgPtr );
}
}
}
/*********************************************************************
* @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.
* @param radius - incoming messages received radius
*
* @return none
*/
void afIncomingData( aps_FrameFormat_t *aff, zAddrType_t *SrcAddress, uint16_t SrcPanId,
NLDE_Signal_t *sig, uint8_t nwkSeqNum, uint8_t SecurityUse,
uint32_t timestamp, uint8_t radius )
{
endPointDesc_t *epDesc = NULL;
epList_t *pList = epList;
#if !defined ( APS_NO_GROUPS )
uint8_t 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 )
{
epDesc = pList->epDesc;
}
}
else if ( (epDesc = afFindEndPointDesc( aff->DstEndPoint )) )
{
pList = afFindEndPointDescList( epDesc->endPoint );
}
while ( epDesc )
{
uint16_t epProfileID = 0xFFFE; // Invalid Profile ID
if ( pList->pfnDescCB )
{
uint16_t *pID = (uint16_t *)(pList->pfnDescCB(
AF_DESCRIPTOR_PROFILE_ID, epDesc->endPoint ));
if ( pID )
{
epProfileID = *pID;
OsalPort_free( pID );
}
}
else if ( epDesc->simpleDesc )
{
epProfileID = epDesc->simpleDesc->AppProfId;
}
// First part of verification is to make sure that:
// the local Endpoint ProfileID matches the received ProfileID OR
// the message is specifically send to ZDO (this excludes the broadcast endpoint) OR
// if the Wildcard ProfileID is received the message should not be sent to ZDO endpoint
if ( (aff->ProfileID == epProfileID) ||
((epDesc->endPoint == ZDO_EP) && (aff->ProfileID == ZDO_PROFILE_ID)) ||
((epDesc->endPoint != ZDO_EP) && ( aff->ProfileID == ZDO_WILDCARD_PROFILE_ID )) )
{
// Save original endpoint
uint8_t endpoint = aff->DstEndPoint;
// overwrite with descriptor's endpoint
aff->DstEndPoint = epDesc->endPoint;
afBuildMSGIncoming( aff, epDesc, SrcAddress, SrcPanId, sig,
nwkSeqNum, SecurityUse, timestamp, radius );
// 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;
}
}
/*********************************************************************
* @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_t SrcPanId, NLDE_Signal_t *sig,
uint8_t nwkSeqNum, uint8_t SecurityUse, uint32_t timestamp, uint8_t radius )
{
afIncomingMSGPacket_t *MSGpkt;
const uint8_t len = sizeof( afIncomingMSGPacket_t ) + aff->asduLength;
uint8_t *asdu = aff->asdu;
MSGpkt = (afIncomingMSGPacket_t *)OsalPort_msgAllocate( 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->macSrcAddr = aff->macSrcAddr;
MSGpkt->macDestAddr = aff->macDestAddr;
MSGpkt->srcAddr.panId = SrcPanId;
MSGpkt->cmd.DataLength = aff->asduLength;
MSGpkt->radius = radius;
if ( MSGpkt->cmd.DataLength )
{
MSGpkt->cmd.Data = (uint8_t *)(MSGpkt + 1);
OsalPort_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.
OsalPort_msgDeallocate( (void *)MSGpkt );
}
else
#endif
{
// Send message through task message.
OsalPort_msgSend( *(epDesc->task_id), (uint8_t *)MSGpkt );
}
}
/*********************************************************************
* @fn AF_DataRequest
*
* @brief Common functionality for invoking APSDE_DataReq() for both
* SendMulti and MSG-Send.
*
* input parameters
*
* @param *dstAddr - Full ZB destination address: Nwk Addr + End Point.
* @param *srcEP - Origination (i.e. respond to or ack to) End Point Descr.
* @param cID - A valid cluster ID as specified by the Profile.
* @param len - Number of bytes of data pointed to by next param.
* @param *buf - A pointer to the data bytes to send.
* @param *transID - A pointer to a byte which can be modified and which will
* be used as the transaction sequence number of the msg.
* @param options - Valid bit mask of Tx options.
* @param radius - Normally set to AF_DEFAULT_RADIUS.
* @param afCnfCB - Callback function for data confirm
* @param cnfParam - Parameter of data confirm callback function
*
* output parameters
*
* @param *transID - Incremented by one if the return value is success.
*
* @return afStatus_t - See previous definition of afStatus_... types.
*/
uint8_t AF_DataRequestDiscoverRoute = DISC_ROUTE_NETWORK;
afStatus_t AF_DataRequestExt( afAddrType_t *dstAddr, endPointDesc_t *srcEP,
uint16_t cID, uint16_t len, uint8_t *buf, uint8_t *transID,
uint8_t options, uint8_t radius, pfnAfCnfCB afCnfCB, void* cnfParam )
{
pDescCB pfnDescCB;
ZStatus_t stat;
APSDE_DataReq_t req;
afDataReqMTU_t mtu;
epList_t *pList;
//confirm param
afDataCnfList_t* cnfItem = NULL;
// Verify source end point
if ( srcEP == NULL )
{
return afStatus_INVALID_PARAMETER;
}
// Match end point and trans ID if are busy, luoyiming fixed at 2021-09-02
if ( afFindCnfItem( srcEP->endPoint, *transID ) != NULL )
{
return afStatus_INVALID_PARAMETER;
}
// copy the addressing mode, to get the length of the packet
mtu.aps.addressingMode = dstAddr->addrMode;
// Check if route is available before sending data
if ( options & AF_LIMIT_CONCENTRATOR )
{
if ( dstAddr->addrMode != afAddr16Bit )
{
return ( afStatus_INVALID_PARAMETER );
}
// First, make sure the destination is not its self, then check for an existing route.
if ( (dstAddr->addr.shortAddr != NLME_GetShortAddr())
&& (RTG_CheckRtStatus( dstAddr->addr.shortAddr, RT_ACTIVE, (MTO_ROUTE | NO_ROUTE_CACHE) ) != RTG_SUCCESS) )
{
// A valid route to a concentrator wasn't found
return ( afStatus_NO_ROUTE );
}
}
// Validate broadcasting
if ( ( dstAddr->addrMode == afAddr16Bit ) ||
( dstAddr->addrMode == afAddrBroadcast ) )
{
// Check for valid broadcast values
if( ADDR_NOT_BCAST != NLME_IsAddressBroadcast( dstAddr->addr.shortAddr ) )
{
// Force mode to broadcast
dstAddr->addrMode = afAddrBroadcast;
}
else
{
// Address is not a valid broadcast type
if ( dstAddr->addrMode == afAddrBroadcast )
{
return afStatus_INVALID_PARAMETER;
}
}
}
else if ( dstAddr->addrMode != afAddr64Bit &&
dstAddr->addrMode != afAddrGroup &&
dstAddr->addrMode != afAddrNotPresent )
{
return afStatus_INVALID_PARAMETER;
}
// Set destination address
req.dstAddr.addrMode = dstAddr->addrMode;
if ( dstAddr->addrMode == afAddr64Bit )
{
osal_cpyExtAddr( req.dstAddr.addr.extAddr, dstAddr->addr.extAddr );
}
else
{
req.dstAddr.addr.shortAddr = dstAddr->addr.shortAddr;
}
// This option is to use Wildcard ProfileID in outgoing packets
if ( options & AF_WILDCARD_PROFILEID )
{
req.profileID = ZDO_WILDCARD_PROFILE_ID;
}
else
{
req.profileID = ZDO_PROFILE_ID;
if ( (pfnDescCB = afGetDescCB( srcEP )) )
{
uint16_t *pID = (uint16_t *)(pfnDescCB(
AF_DESCRIPTOR_PROFILE_ID, srcEP->endPoint ));
if ( pID )
{
req.profileID = *pID;
OsalPort_free( pID );
}
}
else if ( srcEP->simpleDesc )
{
req.profileID = srcEP->simpleDesc->AppProfId;
}
}
req.txOptions = 0;
if ( ( options & AF_ACK_REQUEST ) &&
( req.dstAddr.addrMode != AddrBroadcast ) &&
( req.dstAddr.addrMode != AddrGroup ) )
{
req.txOptions |= APS_TX_OPTIONS_ACK;
}
if ( options & AF_SKIP_ROUTING )
{
req.txOptions |= APS_TX_OPTIONS_SKIP_ROUTING;
}
if ( options & AF_EN_SECURITY )
{
req.txOptions |= APS_TX_OPTIONS_SECURITY_ENABLE;
mtu.aps.secure = TRUE;
}
else
{
mtu.aps.secure = FALSE;
}
if ( options & AF_PREPROCESS )
{
req.txOptions |= APS_TX_OPTIONS_PREPROCESS;
}
mtu.kvp = FALSE;
if ( options & AF_SUPRESS_ROUTE_DISC_NETWORK )
{
req.discoverRoute = DISC_ROUTE_INITIATE;
}
else
{
req.discoverRoute = AF_DataRequestDiscoverRoute;
}
req.transID = *transID;
req.srcEP = srcEP->endPoint;
req.dstEP = dstAddr->endPoint;
req.clusterID = cID;
req.asduLen = len;
req.asdu = buf;
req.radiusCounter = radius;
#if defined ( INTER_PAN ) || defined ( BDB_TL_INITIATOR ) || defined ( BDB_TL_TARGET )
req.dstPanId = dstAddr->panId;
#endif // INTER_PAN || BDB_TL_INITIATOR || BDB_TL_TARGET
//set confirm callback and confirm param before send, add by luoyiming
if( ( afCnfCB ) || ( cnfParam ) )
{
cnfItem = OsalPort_malloc( sizeof(afDataCnfList_t) );
if( cnfItem == NULL )
{
return afStatus_MEM_FAIL;
}
//add confirm callback and param into queue, fix by luoyiming 2019-3-11
cnfItem->endpoint = req.srcEP;
cnfItem->transID = req.transID;
cnfItem->clusterID = req.clusterID;
cnfItem->afCnfCB = afCnfCB;
cnfItem->cnfParam = cnfParam;
if( req.txOptions & APS_TX_OPTIONS_ACK )
{
cnfItem->apsAck = true;
}
afAddCnfItem( cnfItem );
}
// Look if there is a Callback function registered for this endpoint
// The callback is used to control the AF Transaction ID used when sending messages
pList = afFindEndPointDescList( srcEP->endPoint );
if ( ( pList != NULL ) && ( pList->pfnApplCB != NULL ) )
{
pList->pfnApplCB( &req );
}
#if defined ( INTER_PAN ) || defined ( BDB_TL_INITIATOR ) || defined ( BDB_TL_TARGET )
if ( StubAPS_InterPan( dstAddr->panId, dstAddr->endPoint ) )
{
if ( len > INTERP_DataReqMTU() )
{
stat = afStatus_INVALID_PARAMETER;
}
else
{
stat = INTERP_DataReq( &req );
}
}
else
#endif // INTER_PAN || BDB_TL_INITIATOR || BDB_TL_TARGET
{
if (len > afDataReqMTU( &mtu ) )
{
if (apsfSendFragmented)
{
stat = (*apsfSendFragmented)( &req );
}
else
{
stat = afStatus_INVALID_PARAMETER;
}
}
else
{
stat = APSDE_DataReq( &req );
}
}
//release confirm message if send fail
if( stat!= afStatus_SUCCESS )
{
afDataCnfList_t* item = afGetCnfItem( req.srcEP, req.transID );
if( item != NULL ) //only free for valid pointer, fix by luoyiming 2019-05-14.
{
OsalPort_free( item );
}
}
/*
* If this is an EndPoint-to-EndPoint message on the same device, it will not
* get added to the NWK databufs. So it will not go OTA and it will not get
* a MACCB_DATA_CONFIRM_CMD callback. Thus it is necessary to generate the
* AF_DATA_CONFIRM_CMD here. Note that APSDE_DataConfirm() only generates one
* message with the first in line TransSeqNumber, even on a multi message.
* Also note that a reflected msg will not have its confirmation generated
* here.
*/
if ( (req.dstAddr.addrMode == Addr16Bit) &&
(req.dstAddr.addr.shortAddr == NLME_GetShortAddr()) &&
(stat == afStatus_SUCCESS) ) //if APSDE_DataReq return not success, don't trigger afDataComfirm, add by luoyiming 2019-10-27.
{
afDataConfirm( srcEP->endPoint, *transID, cID, stat );
}
if ( stat == afStatus_SUCCESS )
{
(*transID)++;
}
return (afStatus_t)stat;
}
/**************************************************************************************************
* @fn afStopConfirmWaitting
*
* @brief stop confirm waitting when orphan. luoyiming add at 2022-04-08
*
* input parameters
*
* @param none
*
* None.
*
* @return none
*/
void afStopConfirmWaitting( void )
{
afDataConfirmParam_t tmpBuf[NWK_MAX_DATABUFS_TOTAL] = {0};
uint8_t num = 0;
uint8_t n;
afDataCnfList_t* find = afDataCnfList;
// find the aps-ack enabled item, luoyiming 2022-04-08
while( find )
{
if( find->apsAck )
{
tmpBuf[num].endPoint = find->endpoint;
tmpBuf[num].transID = find->transID;
tmpBuf[num].clusterID = find->transID;
num ++;
}
find = find->next;
}
// call aps-ack enabled item, luoyiming 2022-04-08
for( n = 0; n < num; n++ )
{
afDataConfirm(tmpBuf[n].endPoint, tmpBuf[n].transID, tmpBuf[n].clusterID, ZNwkNoNetworks);
}
}
/**************************************************************************************************
* @fn afAddCnfItem
*
* @brief add a data confirm callback function into data confirm list.
*
* input parameters
*
* @param cbItem - a callback function with its parameter.
*
* output parameters
*
* None.
*
* @return TRUE if success, FALSE if add list fail
*/
static bool afAddCnfItem( afDataCnfList_t* cnfItem )
{
if( NULL != cnfItem )
{
cnfItem->next = NULL;
if( NULL == afDataCnfList )
{
afDataCnfList = cnfItem;
}
else
{
afDataCnfList_t* findEnd = afDataCnfList;
while( findEnd->next )
{
findEnd = findEnd->next;
}
findEnd->next = cnfItem;
}
return TRUE;
}
return FALSE;
}
/**************************************************************************************************
* @fn afGetCnfItem
*
* @brief get the callback fuction from confirm list with transID an Endpoint, the found item
* will be removed from list.
*
* input parameters
*
* @param endpoint - filt callback function by endpoint.
* @param transID - filt callback function by transID.
*
* output parameters
*
* None.
*
* @return callback function item form data confirm list
*/
static afDataCnfList_t* afGetCnfItem( uint8_t endpoint, uint8_t transID )
{
afDataCnfList_t* find = afDataCnfList;
afDataCnfList_t* pre = NULL;
while(find)
{
if( (endpoint == find->endpoint) && (transID == find->transID) )
{
if(pre)
{
pre->next = find->next;
}
else
{
afDataCnfList = afDataCnfList->next;
}
break;
}
pre = find;
find = pre->next;
}
return find;
}
/**************************************************************************************************
* @fn afFindCnfItem
*
* @brief find the param pointer in confirm list with transID an Endpoint, the found item
* won't be removed.
*
* input parameters
*
* @param endpoint - filt callback function by endpoint.
* @param transID - filt callback function by transID.
*
* output parameters
*
* None.
*
* @return confirm callback & param item form data confirm list
*/
static afDataCnfList_t* afFindCnfItem( uint8_t endpoint, uint8_t transID )
{
afDataCnfList_t* find = afDataCnfList;
while(find)
{
if( (endpoint == find->endpoint) && (transID == find->transID) )
{
return find;
}
find = find->next;
}
return NULL;
}
/*********************************************************************
* @fn AF_DataRequestSrcRtg
*
* @brief Common functionality for invoking APSDE_DataReq() for both
* SendMulti and MSG-Send.
*
* input parameters
*
* @param *dstAddr - Full ZB destination address: Nwk Addr + End Point.
* @param *srcEP - Origination (i.e. respond to or ack to) End Point Descr.
* @param cID - A valid cluster ID as specified by the Profile.
* @param len - Number of bytes of data pointed to by next param.
* @param *buf - A pointer to the data bytes to send.
* @param *transID - A pointer to a byte which can be modified and which will
* be used as the transaction sequence number of the msg.
* @param options - Valid bit mask of Tx options.
* @param radius - Normally set to AF_DEFAULT_RADIUS.
* @param relayCnt - Number of devices in the relay list
* @param pRelayList - Pointer to the relay list
* @param afCnfCB - Callback function for data confirm
* @param cnfParam - Parameter of data confirm callback function
*
* output parameters
*
* @param *transID - Incremented by one if the return value is success.
*
* @return afStatus_t - See previous definition of afStatus_... types.
*/
afStatus_t AF_DataRequestSrcRtgExt( afAddrType_t *dstAddr, endPointDesc_t *srcEP, uint16_t cID,
uint16_t len, uint8_t *buf, uint8_t *transID, uint8_t options, uint8_t radius,
uint8_t relayCnt, uint16_t* pRelayList, pfnAfCnfCB afCnfCB, void* cnfParam )
{
uint8_t status;
/* Add the source route to the source routing table */
status = RTG_AddSrcRtgEntry_Guaranteed( dstAddr->addr.shortAddr, relayCnt,
pRelayList );
if( status == RTG_SUCCESS)
{
/* Call AF_DataRequest to send the data */
status = AF_DataRequestExt( dstAddr, srcEP, cID, len, buf, transID, options, radius, afCnfCB, cnfParam );
}
else if( status == RTG_INVALID_PATH )
{
/* The source route relay count is exceeding the network limit */
status = afStatus_INVALID_PARAMETER;
}
else
{
/* The guaranteed adding entry fails due to memory failure */
status = afStatus_MEM_FAIL;
}
return status;
}
/*********************************************************************
* @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_t EndPoint )
{
epList_t *epSearch;
for (epSearch = epList; epSearch != NULL; epSearch = epSearch->nextDesc)
{
if (epSearch->epDesc->endPoint == EndPoint)
{
break;
}
}
return epSearch;
}
/*********************************************************************
* @fn afFindEndPointDesc
*
* @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
*/
endPointDesc_t *afFindEndPointDesc( uint8_t EndPoint )
{
epList_t *epSearch;
// Look for the endpoint
epSearch = afFindEndPointDescList( EndPoint );
if ( epSearch )
return ( epSearch->epDesc );
else
return ( (endPointDesc_t *)NULL );
}
/*********************************************************************
* @fn afFindSimpleDesc
*
* @brief Find the Simple Descriptor from the endpoint number.
*
* @param EP - Application Endpoint to look for.
*
* @return Non-zero to indicate that the descriptor memory must be freed.
*/
uint8_t afFindSimpleDesc( SimpleDescriptionFormat_t **ppDesc, uint8_t EP )
{
epList_t *epItem = afFindEndPointDescList( EP );
uint8_t rtrn = FALSE;
if ( epItem )
{
if ( epItem->pfnDescCB )
{
*ppDesc = epItem->pfnDescCB( AF_DESCRIPTOR_SIMPLE, EP );
rtrn = TRUE;
}
else
{
*ppDesc = epItem->epDesc->simpleDesc;
}
}
else
{
*ppDesc = NULL;
}
return rtrn;
}
/*********************************************************************
* @fn afGetDescCB
*
* @brief Get the Descriptor callback function.
*
* @param epDesc - pointer to the endpoint descriptor
*
* @return function pointer or NULL
*/
static pDescCB afGetDescCB( endPointDesc_t *epDesc )
{
epList_t *epSearch;
// Start at the beginning
epSearch = epList;
// Look through the list until the end
while ( epSearch )
{
// Is there a match?
if ( epSearch->epDesc == epDesc )
{
return ( epSearch->pfnDescCB );
}
else
epSearch = epSearch->nextDesc; // Next entry
}
return ( (pDescCB)NULL );
}
/*********************************************************************
* @fn afDataReqMTU
*
* @brief Get the Data Request MTU(Max Transport Unit).
*
* @param fields - afDataReqMTU_t
*
* @return uint8_t(MTU)
*/
uint8_t afDataReqMTU( afDataReqMTU_t* fields )
{
uint8_t len;
uint8_t hdr;
if ( fields->kvp == TRUE )
{
hdr = AF_HDR_KVP_MAX_LEN;
}
else
{
hdr = AF_HDR_V1_1_MAX_LEN;
}
len = (uint8_t)(APSDE_DataReqMTU(&fields->aps) - hdr);
return len;
}
/*********************************************************************
* @fn afGetMatch
*
* @brief Set the allow response flag.
*
* @param ep - Application Endpoint to look for
* @param action - true - allow response, false - no response
*
* @return TRUE allow responses, FALSE no response
*/
uint8_t afGetMatch( uint8_t ep )
{
epList_t *epSearch;
// Look for the endpoint
epSearch = afFindEndPointDescList( ep );
if ( epSearch )
{
if ( epSearch->flags & eEP_AllowMatch )
return ( TRUE );
else
return ( FALSE );
}
else
return ( FALSE );
}
/*********************************************************************
* @fn afSetMatch
*
* @brief Set the allow response flag.
*
* @param ep - Application Endpoint to look for
* @param action - true - allow response, false - no response
*
* @return TRUE if success, FALSE if endpoint not found
*/
uint8_t afSetMatch( uint8_t ep, uint8_t action )
{
epList_t *epSearch;
// Look for the endpoint
epSearch = afFindEndPointDescList( ep );
if ( epSearch )
{
if ( action )
{
epSearch->flags |= eEP_AllowMatch;
}
else
{
epSearch->flags &= (eEP_AllowMatch ^ 0xFFFF);
}
return ( TRUE );
}
else
return ( FALSE );
}
/*********************************************************************
* @fn afNumEndPoints
*
* @brief Returns the number of endpoints defined (including 0)
*
* @param none
*
* @return number of endpoints
*/
uint8_t afNumEndPoints( void )
{
epList_t *epSearch;
uint8_t endpoints;
// Start at the beginning
epSearch = epList;
endpoints = 0;
while ( epSearch )
{
endpoints++;
epSearch = epSearch->nextDesc;
}
return ( endpoints );
}
/*********************************************************************
* @fn afEndPoints
*
* @brief Fills in the passed in buffer with the endpoint (numbers).
* Use afNumEndPoints to find out how big a buffer to supply.
*
* @param epBuf - pointer to mem used
*
* @return void
*/
void afEndPoints( uint8_t *epBuf, uint8_t skipZDO )
{
epList_t *epSearch;
uint8_t endPoint;
// Start at the beginning
epSearch = epList;
while ( epSearch )
{
endPoint = epSearch->epDesc->endPoint;
if ( !skipZDO || endPoint != 0 )
*epBuf++ = endPoint;
epSearch = epSearch->nextDesc;
}
}
/*********************************************************************
* @fn afCopyAddress
*
* @brief Fills in the passed in afAddrType_t parameter with the corresponding information
* from the zAddrType_t parameter.
*
* @param epBuf - pointer to mem used
*
* @return void
*/
void afCopyAddress( afAddrType_t *afAddr, zAddrType_t *zAddr )
{
afAddr->addrMode = (afAddrMode_t)zAddr->addrMode;
if ( zAddr->addrMode == Addr64Bit )
{
(void)osal_cpyExtAddr( afAddr->addr.extAddr, zAddr->addr.extAddr );
}
else
{
afAddr->addr.shortAddr = zAddr->addr.shortAddr;
}
// Since zAddrType_t has no INTER-PAN information, set the panId member to zero.
afAddr->panId = 0;
}
/**************************************************************************************************
* @fn afAPSF_ConfigGet
*
* @brief This function ascertains the fragmentation configuration that corresponds to
* the specified EndPoint.
*
* input parameters
*
* @param endPoint - The source EP of a Tx or destination EP of a Rx fragmented message.
*
* output parameters
*
* @param pCfg - A pointer to an APSF configuration structure to fill with values.
*
* @return None.
*/
void afAPSF_ConfigGet(uint8_t endPoint, afAPSF_Config_t *pCfg)
{
epList_t *pList = afFindEndPointDescList(endPoint);
if (pList == NULL)
{
pCfg->frameDelay = APSF_DEFAULT_INTERFRAME_DELAY;
pCfg->windowSize = APSF_DEFAULT_WINDOW_SIZE;
}
else
{
(void)OsalPort_memcpy(pCfg, &pList->apsfCfg, sizeof(afAPSF_Config_t));
}
}
/**************************************************************************************************
* @fn afAPSF_ConfigSet
*
* @brief This function attempts to set the fragmentation configuration that corresponds to
* the specified EndPoint.
*
* input parameters
*
* @param endPoint - The specific EndPoint for which to set the fragmentation configuration.
* @param pCfg - A pointer to an APSF configuration structure to fill with values.
*
* output parameters
*
* None.
*
* @return afStatus_SUCCESS for success.
* afStatus_INVALID_PARAMETER if the specified EndPoint is not registered.
*/
afStatus_t afAPSF_ConfigSet(uint8_t endPoint, afAPSF_Config_t *pCfg)
{
epList_t *pList = afFindEndPointDescList(endPoint);
if (pList == NULL)
{
return afStatus_INVALID_PARAMETER;
}
(void)OsalPort_memcpy(&pList->apsfCfg, pCfg, sizeof(afAPSF_Config_t));
return afStatus_SUCCESS;
}
/**************************************************************************************************
* @fn afSetApplCB
*
* @brief Sets the pointer to the Application Callback function for a
* specific EndPoint.
*
* input parameters
*
* @param endPoint - The specific EndPoint for which to set Application Callback.
* @param pApplFn - A pointer to the Application Callback function.
*
* output parameters
*
* None.
*
* @return TRUE if success, FALSE if endpoint not found
*/
uint8_t afSetApplCB( uint8_t endPoint, pApplCB pApplFn )
{
if ( pApplFn != NULL )
{
epList_t *epSearch;
// Look for the endpoint
epSearch = afFindEndPointDescList( endPoint );
if ( epSearch )
{
epSearch->pfnApplCB = pApplFn;
return ( TRUE );
}
}
return ( FALSE );
}
修复af.h
#define AF_BROADCAST_ENDPOINT 0xFF
#define AF_WILDCARD_PROFILEID 0x02 // Will force the message to use Wildcard ProfileID
#define AF_PREPROCESS 0x04 // Will force APS to callback to preprocess before calling NWK layer
#define AF_LIMIT_CONCENTRATOR 0x08
#define AF_ACK_REQUEST 0x10
#define AF_SUPRESS_ROUTE_DISC_NETWORK 0x20 // Supress Route Discovery for intermediate routes
// (route discovery preformed for initiating device)
#define AF_EN_SECURITY 0x40
#define AF_SKIP_ROUTING 0x80
#define AF_DISCV_ROUTE 0x00 // This option is no longer available, and is included for backwards compatibility
// Backwards support for afAddOrSendMessage / afFillAndSendMessage.
#define AF_TX_OPTIONS_NONE 0
#define AF_MSG_ACK_REQUEST AF_ACK_REQUEST
// Default Radius Count value
#define AF_DEFAULT_RADIUS DEF_NWK_RADIUS
/*********************************************************************
* Node Descriptor
*/
#define AF_MAX_USER_DESCRIPTOR_LEN 16
#define AF_USER_DESCRIPTOR_FILL 0x20
typedef struct
{
uint8_t len; // Length of string descriptor
uint8_t desc[AF_MAX_USER_DESCRIPTOR_LEN];
} UserDescriptorFormat_t;
// Node Logical Types
#define NODETYPE_COORDINATOR 0x00
#define NODETYPE_ROUTER 0x01
#define NODETYPE_DEVICE 0x02
// Node Frequency Band - bit map
#define NODEFREQ_800 0x01 // 868 - 868.6 MHz
#define NODEFREQ_900 0x04 // 902 - 928 MHz
#define NODEFREQ_2400 0x08 // 2400 - 2483.5 MHz
// Node MAC Capabilities - bit map
// Use CAPINFO_ALTPANCOORD, CAPINFO_DEVICETYPE_FFD,
// CAPINFO_DEVICETYPE_RFD, CAPINFO_POWER_AC,
// and CAPINFO_RCVR_ON_IDLE from nl_mede.h
// Node Descriptor format structure
typedef struct
{
uint8_t LogicalType:3;
uint8_t ComplexDescAvail:1; /* AF_V1_SUPPORT - reserved bit. */
uint8_t UserDescAvail:1; /* AF_V1_SUPPORT - reserved bit. */
uint8_t Reserved:3;
uint8_t APSFlags:3;
uint8_t FrequencyBand:5;
uint8_t CapabilityFlags;
uint8_t ManufacturerCode[2];
uint8_t MaxBufferSize;
uint8_t MaxInTransferSize[2];
uint16_t ServerMask;
uint8_t MaxOutTransferSize[2];
uint8_t DescriptorCapability;
} NodeDescriptorFormat_t;
// Bit masks for the ServerMask.
#define PRIM_TRUST_CENTER 0x01
#define BKUP_TRUST_CENTER 0x02
#define PRIM_BIND_TABLE 0x04
#define BKUP_BIND_TABLE 0x08
#define PRIM_DISC_TABLE 0x10
#define BKUP_DISC_TABLE 0x20
#define NETWORK_MANAGER 0x40
/*********************************************************************
* Node Power Descriptor
*/
// Node Current Power Modes (CURPWR)
// Receiver permanently on or sync with coordinator beacon.
#define NODECURPWR_RCVR_ALWAYS_ON 0x00
// Receiver automatically comes on periodically as defined by the
// Node Power Descriptor.
#define NODECURPWR_RCVR_AUTO 0x01
// Receiver comes on when simulated, eg by a user pressing a button.
#define NODECURPWR_RCVR_STIM 0x02
// Node Available Power Sources (AVAILPWR) - bit map
// Can be used for AvailablePowerSources or CurrentPowerSource
#define NODEAVAILPWR_MAINS 0x01 // Constant (Mains) power
#define NODEAVAILPWR_RECHARGE 0x02 // Rechargeable Battery
#define NODEAVAILPWR_DISPOSE 0x04 // Disposable Battery
// Power Level
#define NODEPOWER_LEVEL_CRITICAL 0x00 // Critical
#define NODEPOWER_LEVEL_33 0x04 // 33%
#define NODEPOWER_LEVEL_66 0x08 // 66%
#define NODEPOWER_LEVEL_100 0x0C // 100%
// Node Power Descriptor format structure
typedef struct
{
unsigned int PowerMode:4;
unsigned int AvailablePowerSources:4;
unsigned int CurrentPowerSource:4;
unsigned int CurrentPowerSourceLevel:4;
} NodePowerDescriptorFormat_t;
/*********************************************************************
* Simple Descriptor
*/
// AppDevVer values
#define APPDEVVER_1 0x01
// AF_V1_SUPPORT AppFlags - bit map
#define APPFLAG_NONE 0x00 // Backwards compatibility to AF_V1.
// AF-AppFlags - bit map
#define AF_APPFLAG_NONE 0x00
#define AF_APPFLAG_COMPLEXDESC 0x01 // Complex Descriptor Available
#define AF_APPFLAG_USERDESC 0x02 // User Descriptor Available
typedef uint16_t cId_t;
// Simple Description Format Structure
typedef struct
{
uint8_t EndPoint;
uint16_t AppProfId;
uint16_t AppDeviceId;
uint8_t AppDevVer:4;
uint8_t Reserved:4; // AF_V1_SUPPORT uses for AppFlags:4.
uint8_t AppNumInClusters;
cId_t *pAppInClusterList;
uint8_t AppNumOutClusters;
cId_t *pAppOutClusterList;
} SimpleDescriptionFormat_t;
/*********************************************************************
* AF Message Format
*/
// Frame Types
#define FRAMETYPE_KVP 0x01 // 0001
#define FRAMETYPE_MSG 0x02 // 0010
#define ERRORCODE_SUCCESS 0x00
#define AF_HDR_KVP_MAX_LEN 0x08 // Max possible AF KVP header.
#define AF_HDR_V1_0_MAX_LEN 0x03 // Max possible AF Ver 1.0 header.
#define AF_HDR_V1_1_MAX_LEN 0x00 // Max possible AF Ver 1.1 header.
// Generalized MSG Command Format
typedef struct
{
uint16_t DataLength; // Number of bytes in TransData
uint8_t *Data;
} afMSGCommandFormat_t;
typedef enum
{
noLatencyReqs,
fastBeacons,
slowBeacons
} afNetworkLatencyReq_t;
/*********************************************************************
* Endpoint Descriptions
*/
typedef enum
{
afAddrNotPresent = AddrNotPresent,
afAddr16Bit = Addr16Bit,
afAddr64Bit = Addr64Bit,
afAddrGroup = AddrGroup,
afAddrBroadcast = AddrBroadcast
} afAddrMode_t;
typedef struct
{
union
{
uint16_t shortAddr;
ZLongAddr_t extAddr;
} addr;
afAddrMode_t addrMode;
uint8_t endPoint;
uint16_t panId; // used for the INTER_PAN feature
} afAddrType_t;
typedef struct
{
OsalPort_EventHdr hdr; /* OSAL Message header */
uint16_t groupId; /* Message's group ID - 0 if not set */
uint16_t clusterId; /* Message's cluster ID */
afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,
it's an InterPAN message */
uint16_t macDestAddr; /* MAC header destination short address */
uint8_t endPoint; /* destination endpoint */
uint8_t wasBroadcast; /* TRUE if network destination was a broadcast address */
uint8_t LinkQuality; /* The link quality of the received data frame */
uint8_t correlation; /* The raw correlation value of the received data frame */
int8_t rssi; /* The received RF power in units dBm */
uint8_t SecurityUse; /* deprecated */
uint32_t timestamp; /* receipt timestamp from MAC */
uint8_t nwkSeqNum; /* network header frame sequence number */
afMSGCommandFormat_t cmd; /* Application Data */
uint16_t macSrcAddr; /* MAC header source short address */
uint8_t radius;
} afIncomingMSGPacket_t;
//Typedef for callback function to control the AF Data Confirm
typedef void (*pfnAfCnfCB)(uint8_t status, uint8_t endpoint, uint8_t transID, uint16_t clusterID, void* cnfParam);
typedef struct
{
OsalPort_EventHdr hdr;
uint8_t endpoint;
uint8_t transID;
uint16_t clusterID;
pfnAfCnfCB afCnfCB;
void* cnfParam;
} afDataConfirm_t;
// Reflect Error Message - sent when there is an error occurs
// during a reflected message.
typedef struct
{
OsalPort_EventHdr hdr; // hdr.status contains the error indication (ie. ZApsNoAck)
uint8_t endpoint; // source endpoint
uint8_t transID; // transaction ID of sent message
uint8_t dstAddrMode; // destination address type: 0 - short address, 1 - group address
uint16_t dstAddr; // destination address - depends on dstAddrMode
uint8_t dstEP; // destination endpoint
void* cnfParam; // cnfParam pointer filled when AF_DataRequest
} afReflectError_t;
// Endpoint Table - this table is the device description
// or application registration.
// There will be one entry in this table for every
// endpoint defined.
typedef struct
{
uint8_t endPoint;
uint8_t epType;
uint8_t *task_id; // Pointer to location of the Application task ID.
SimpleDescriptionFormat_t *simpleDesc;
afNetworkLatencyReq_t latencyReq;
} endPointDesc_t;
// Typedef for callback function to retrieve an endpoints
// descriptors, contained in the endpoint descriptor.
// This will allow an application to dynamically change
// the descriptor and not use the RAM/ROM.
typedef void *(*pDescCB)( uint8_t type, uint8_t endpoint );
// Typedef for callback function to control the AF transaction ID
// used when sending messages.
// This allows the application to verify if the transaction ID
// is not duplicated of a pending message.
typedef void (*pApplCB)( APSDE_DataReq_t *req );
// Descriptor types used in the above callback
#define AF_DESCRIPTOR_SIMPLE 1
#define AF_DESCRIPTOR_PROFILE_ID 2
// Bit definitions for epList_t flags.
typedef enum
{
eEP_AllowMatch = 1,
eEP_NotUsed
} eEP_Flags;
typedef struct {
uint8_t frameDelay;
uint8_t windowSize;
} afAPSF_Config_t;
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;
pApplCB pfnApplCB; // Don't use it if it has not been set to a valid function pointer by the application
} epList_t;
/*********************************************************************
* TYPEDEFS
*/
#define afStatus_SUCCESS ZSuccess /* 0x00 */
#define afStatus_FAILED ZFailure /* 0x01 */
#define afStatus_INVALID_PARAMETER ZInvalidParameter /* 0x02 */
#define afStatus_MEM_FAIL ZMemError /* 0x10 */
#define afStatus_NO_ROUTE ZNwkNoRoute /* 0xCD */
typedef ZStatus_t afStatus_t;
typedef struct
{
uint8_t kvp;
APSDE_DataReqMTU_t aps;
} afDataReqMTU_t;
/*********************************************************************
* Globals
*/
extern epList_t *epList;
/*********************************************************************
* FUNCTIONS
*/
/*
* afInit - Initialize the AF.
*/
//extern void afInit( void );
#define afInit() // No work to do for now.
/*
* afRegisterExtended - Register an Application's EndPoint description
* with a callback function for descriptors and
* with an Application callback function to control
* the AF transaction ID.
*
*/
extern epList_t *afRegisterExtended( endPointDesc_t *epDesc, pDescCB descFn, pApplCB applFn );
/*
* afRegister - Register an Application's EndPoint description.
*
*/
extern afStatus_t afRegister( endPointDesc_t *epDesc );
/*
* afDelete - Delete an Application's EndPoint descriptor and frees the memory.
*
*/
extern afStatus_t afDelete( uint8_t EndPoint );
/*
* afDataConfirm - APS will call this function after a data message
* has been sent.
*/
extern void afDataConfirm( uint8_t endPoint, uint8_t transID, uint16_t clusterID, ZStatus_t status );
/*
* afReflectError - APS will call this function for an error with a reflected data message.
*/
extern void afReflectError( uint8_t srcEP, uint8_t dstAddrMode, uint16_t dstAddr, uint8_t dstEP,
uint8_t transID, ZStatus_t status );
/*
* afIncomingData - APS will call this function when an incoming
* message is received.
*/
extern void afIncomingData( aps_FrameFormat_t *aff, zAddrType_t *SrcAddress, uint16_t SrcPanId,
NLDE_Signal_t *sig, uint8_t nwkSeqNum, uint8_t SecurityUse, uint32_t timestamp, uint8_t radius );
#define AF_DataRequest( dstAddr, srcEP, cID, len, buf, transID, options, radius ) \
AF_DataRequestExt( dstAddr, srcEP, cID, len, buf, transID, options, radius, NULL, NULL )
afStatus_t AF_DataRequestExt( afAddrType_t *dstAddr, endPointDesc_t *srcEP,
uint16_t cID, uint16_t len, uint8_t *buf, uint8_t *transID,
uint8_t options, uint8_t radius, pfnAfCnfCB afCnfCB, void* cnfParam );
/*
* afStopConfirmWaitting - stop APS-ack waitting when orphan
*/
extern void afStopConfirmWaitting( void );
/*********************************************************************
* @fn AF_DataRequestSrcRtg
*
* @brief Common functionality for invoking APSDE_DataReq() for both
* SendMulti and MSG-Send.
*
* input parameters
*
* @param *dstAddr - Full ZB destination address: Nwk Addr + End Point.
* @param *srcEP - Origination (i.e. respond to or ack to) End Point Descr.
* @param cID - A valid cluster ID as specified by the Profile.
* @param len - Number of bytes of data pointed to by next param.
* @param *buf - A pointer to the data bytes to send.
* @param *transID - A pointer to a byte which can be modified and which will
* be used as the transaction sequence number of the msg.
* @param options - Valid bit mask of Tx options.
* @param radius - Normally set to AF_DEFAULT_RADIUS.
* @param relayCnt - Number of devices in the relay list
* @param pRelayList - Pointer to the relay list
*
* output parameters
*
* @param *transID - Incremented by one if the return value is success.
*
* @return afStatus_t - See previous definition of afStatus_... types.
*/
#define AF_DataRequestSrcRtg( dstAddr, srcEP, cID, len, buf, transID, options, radius, relayCnt, pRelayList )\
AF_DataRequestSrcRtgExt( dstAddr, srcEP, cID, len, buf, transID, options, radius, relayCnt, pRelayList, NULL, NULL )
afStatus_t AF_DataRequestSrcRtgExt( afAddrType_t *dstAddr, endPointDesc_t *srcEP, uint16_t cID,
uint16_t len, uint8_t *buf, uint8_t *transID, uint8_t options, uint8_t radius,
uint8_t relayCnt, uint16_t* pRelayList, pfnAfCnfCB afCnfCB, void* cnfParam );
/*********************************************************************
* Direct Access Functions - ZigBee Device Object
*/
/*
* afFindEndPointDesc - Find the endpoint description entry from the
* endpoint number.
*/
extern endPointDesc_t *afFindEndPointDesc( uint8_t endPoint );
/*
* afFindSimpleDesc - Find the Simple Descriptor from the endpoint number.
* If return value is not zero, the descriptor memory must be freed.
*/
extern uint8_t afFindSimpleDesc( SimpleDescriptionFormat_t **ppDesc, uint8_t EP );
/*
* afDataReqMTU - Get the Data Request MTU(Max Transport Unit)
*/
extern uint8_t afDataReqMTU( afDataReqMTU_t* fields );
/*
* afGetMatch - Get the action for the Match Descriptor Response
* TRUE allow match descriptor response
*/
extern uint8_t afGetMatch( uint8_t ep );
/*
* afSetMatch - Set the action for the Match Descriptor Response
* TRUE allow match descriptor response
*/
extern uint8_t afSetMatch( uint8_t ep, uint8_t action );
/*
* afNumEndPoints - returns the number of endpoints defined.
*/
extern uint8_t afNumEndPoints( void );
/*
* afEndPoints - builds an array of endpoints.
*/
extern void afEndPoints( uint8_t *epBuf, uint8_t skipZDO );
/*
* afCopyAddress
*/
extern void afCopyAddress (afAddrType_t *afAddr, zAddrType_t *zAddr);
/*
* afAPSF_ConfigGet - ascertain the fragmentation configuration for the specified EndPoint.
*/
void afAPSF_ConfigGet(uint8_t endPoint, afAPSF_Config_t *pCfg);
/*
* afAPSF_ConfigSet - set the fragmentation configuration for the specified EndPoint.
*/
afStatus_t afAPSF_ConfigSet(uint8_t endPoint, afAPSF_Config_t *pCfg);
/*
* afSetApplCB - Sets the pointer to the Application Callback function for a
* specific EndPoint.
*/
uint8_t afSetApplCB( uint8_t endPoint, pApplCB pApplFn );
修复ZD_APP.c
void ZDO_SyncIndicationCB( uint8_t type, uint16_t shortAddr )
{
(void)shortAddr; // Remove this line if this parameter is used.
if ( ZSTACK_END_DEVICE_BUILD
|| (ZSTACK_ROUTER_BUILD && BUILD_FLEXABLE && ((_NIB.CapabilityFlags & ZMAC_ASSOC_CAPINFO_FFD_TYPE) == 0)))
{
if ( type == 1 && retryCnt == 0 )
{
// We lost contact with our parent. Clear the neighbor Table.
nwkNeighborInitTable();
//If we are Factory new, then report fail on association
if(!bdb_isDeviceNonFactoryNew())
{
bdb_nwkAssocAttemt(FALSE);
}
#if (ZG_BUILD_ENDDEVICE_TYPE)
else
{
//We lost our parent
bdb_parentLost();
afStopConfirmWaitting();
}
#endif
}
}
}