afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP, uint16 cID, uint16 len, uint8 *buf, uint8 *transID, uint8 options, uint8 radius ) { pDescCB pfnDescCB; ZStatus_t stat; APSDE_DataReq_t req; afDataReqMTU_t mtu; // Verify source end point if ( srcEP == NULL ) { return afStatus_INVALID_PARAMETER; } #if !defined( REFLECTOR ) if ( dstAddr->addrMode == afAddrNotPresent ) { return afStatus_INVALID_PARAMETER; } #endif // 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; req.profileID = ZDO_PROFILE_ID; if ( (pfnDescCB = afGetDescCB( srcEP )) ) { uint16 *pID = (uint16 *)(pfnDescCB( AF_DESCRIPTOR_PROFILE_ID, srcEP->endPoint )); if ( pID ) { req.profileID = *pID; osal_mem_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; } mtu.kvp = FALSE; req.transID = *transID; req.srcEP = srcEP->endPoint; req.dstEP = dstAddr->endPoint; req.clusterID = cID; req.asduLen = len; req.asdu = buf; req.discoverRoute = AF_DataRequestDiscoverRoute;//(uint8)((options & AF_DISCV_ROUTE) ? 1 : 0); req.radiusCounter = radius; #if defined ( INTER_PAN ) req.dstPanId = dstAddr->panId; if ( StubAPS_InterPan( dstAddr->panId, dstAddr->endPoint ) ) { if ( len > INTERP_DataReqMTU() ) { stat = afStatus_INVALID_PARAMETER; } else { stat = INTERP_DataReq( &req ); } } else #endif // INTER_PAN { if (len > afDataReqMTU( &mtu ) ) { if (apsfSendFragmented) { stat = (*apsfSendFragmented)( &req ); } else { stat = afStatus_INVALID_PARAMETER; } } else { stat = APSDE_DataReq( &req ); } } /* * 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()) ) { afDataConfirm( srcEP->endPoint, *transID, stat ); } if ( stat == afStatus_SUCCESS ) { (*transID)++; } return (afStatus_t)stat; }
afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP, uint16 cID, uint16 len, uint8 *buf, uint8 *transID, uint8 options, uint8 radius ) { pDescCB pfnDescCB; ZStatus_t stat; APSDE_DataReq_t req; afDataReqMTU_t mtu; epList_t *pList; // Verify source end point if ( srcEP == NULL ) { return afStatus_INVALID_PARAMETER; } #if !defined( REFLECTOR ) if ( dstAddr->addrMode == afAddrNotPresent ) { return afStatus_INVALID_PARAMETER; } #endif // 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 *pID = (uint16 *)(pfnDescCB( AF_DESCRIPTOR_PROFILE_ID, srcEP->endPoint )); if ( pID ) { req.profileID = *pID; osal_mem_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 ) req.dstPanId = dstAddr->panId; #endif // INTER_PAN // 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 ) if ( StubAPS_InterPan( dstAddr->panId, dstAddr->endPoint ) ) { if ( len > INTERP_DataReqMTU() ) { stat = afStatus_INVALID_PARAMETER; } else { stat = INTERP_DataReq( &req ); } } else #endif // INTER_PAN { if (len > afDataReqMTU( &mtu ) ) { if (apsfSendFragmented) { stat = (*apsfSendFragmented)( &req ); } else { stat = afStatus_INVALID_PARAMETER; } } else { stat = APSDE_DataReq( &req ); } } /* * 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()) ) { afDataConfirm( srcEP->endPoint, *transID, stat ); } if ( stat == afStatus_SUCCESS ) { (*transID)++; } return (afStatus_t)stat; }