/*-------------------- Power_Desc_store_req -------------------- 2.4.3.1.16 Power_Desc_store_req. (ClusterID=0x0018) The Power_Desc_store_req is provided to enable ZigBee end devices on the network to request storage of their Power Descriptor on a Primary Discovery Cache device which has previously received a SUCCESS status from a Discovery_store_req to the same Primary Discovery Cache device. Included in this request is the Power Descriptor the Local Device wishes to cache. IN/OUT: The destination address where to send the request. OUT: The size in bytes of the request payload. */ zbSize_t Power_Desc_store_req ( zbNwkAddr_t aNwkAddress /* IN/OUT: The destination address where to send the request. */ ) { if (gDiscoveryCacheResponse) Copy2Bytes(aNwkAddress, gDiscoveryCacheSuccess.aNwkAddress); return sizeof(zbPowerDescriptorStoreRequest_t); }
/*-------------------- Node_Desc_store_req -------------------- 2.4.3.1.15 Node_Desc_store_req. (ClusterID=0x0017) The Node_Desc_store_req is provided to enable ZigBee end devices on the network to request storage of their Node Descriptor on a Primary Discovery Cache device which has previously received a SUCCESS status from a Discovery_store_req to the same Primary Discovery Cache device. Included in this request is the Node Descriptor the Local Device wishes to cache. IN/OUT: The destination address where to send the request. OUT: The size in bytes of the request payload. */ zbStatus_t Node_Desc_store_req ( uint8_t *pAddress /* IN/OUT: The destination address where to send the request. */ ) { if (gDiscoveryCacheResponse) Copy2Bytes(pAddress, gDiscoveryCacheSuccess.aNwkAddress); return sizeof(zbNodeDescriptorStoreRequest_t); }
/*-------------------- Active_EP_store_req -------------------- 2.4.3.1.17 Active_EP_store_req. (ClusterID=0x0019) The Active_EP_store_req is provided to enable ZigBee end devices on the network to request storage of their list of Active Endpoints on a Primary Discovery Cache device which has previously received a SUCCESS status from a Discovery_store_req to the same Primary Discovery Cache device. Included in this request is the count of Active Endpoints the Local Device wishes to cache and the endpoint list itself. IN/OUT: The destination address where to send the request. IN: The package with the request information. OUT: The size in bytes of the request payload. */ zbSize_t Active_EP_store_req ( zbNwkAddr_t aAddress, /* IN/OUT: The destination address where to send the request. */ zbActiveEPStoreRequest_t *pMessageGoingOut /* IN: The package with the request information. */ ) { if (gDiscoveryCacheResponse) Copy2Bytes(aAddress, gDiscoveryCacheSuccess.aNwkAddress); return (MbrOfs(zbActiveEPStoreRequest_t, activeEPList[0]) + pMessageGoingOut->activeEPCount); }
void OnOffLight_AppSetLightState ( zbEndPoint_t endPoint, /* IN: APP endpoint */ zclCmd_t command /* IN: */ ) { zclOnOffReq_t req; /* set up address info for a unicast to ourselves */ req.addrInfo.dstAddrMode = gZbAddrMode16Bit_c; Copy2Bytes(req.addrInfo.dstAddr.aNwkAddr, NlmeGetRequest(gNwkShortAddress_c)); req.addrInfo.dstEndPoint = endPoint; Set2Bytes(req.addrInfo.aClusterId, gZclClusterOnOff_c); req.addrInfo.srcEndPoint = endPoint; req.addrInfo.txOptions = gZclTxOptions; req.addrInfo.radiusCounter = afDefaultRadius_c; /* send the command */ req.command = command; (void)ASL_ZclOnOffReq(&req); }
/*-------------------- Simple_Desc_store_req -------------------- 2.4.3.1.18 Simple_Desc_store_req. (ClusterID=0x001a) The Simple_desc_store_req is provided to enable ZigBee end devices on the network to request storage of their list of Simple Descriptors on a Primary Discovery Cache device which has previously received a SUCCESS status from a Discovery_store_req to the same Primary Discovery Cache device. Note that each Simple Descriptor for every active endpoint on the Local Device must be individually uploaded to the Primary Discovery Cache device via this command to enable cached discovery. Included in this request is the length of the Simple Descriptor the Local Device wishes to cache and the Simple Descriptor itself. The endpoint is a field within the Simple Descriptor and is accessed by the Remote Device to manage the discovery cache information for the Local Device. IN/OUT: The buffer where the request data will be filled in. IN: The package with the request information. IN: The destination address where to send the request. OUT: The size in bytes of the request payload. */ zbSize_t Simple_Desc_store_req ( uint8_t *pkgPayload, /* IN/OUT: The buffer where the request data will be filled in. */ zbSimpleDescriptorStoreRequest_t *pMessageComingIn, /* IN: The package with the request information. */ zbNwkAddr_t aDestAddr /* IN: The destination address where to send the request. */ ) { zbSize_t payloadLength; if (gDiscoveryCacheResponse) Copy2Bytes(aDestAddr, gDiscoveryCacheSuccess.aNwkAddress); FLib_MemCpy(pkgPayload, pMessageComingIn,MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters)); payloadLength = MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters) + ZDP_CopyClusterListPairToFrame(pkgPayload + MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters), &(pMessageComingIn->simpleDescriptor.inputClusters)); Zdp_GenerateDataReq(gSimple_Desc_store_req_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload - SapHandlerDataStructureOffSet) , payloadLength ); return gZdpAlreadyHanlded_c; }
/******************************************************************************* * State machine to send the next report. If it can't get the memory, tries * again later. * * This will concatinate all of the reportable attributes in a single cluster *******************************************************************************/ void ZCL_SendReport(void) { afDeviceDef_t *pDevice; uint8_t payloadLen; uint8_t reportLen; afToApsdeMessage_t *pMsg; /* a message for sending the report */ afAddrInfo_t addrInfo; afClusterDef_t *pCluster; zclFrame_t *pFrame; uint8_t i; zclReportAttr_t *pReportList; BeeUtilZeroMemory(&addrInfo, sizeof(addrInfo)); /* starting over? reset indexes */ if(gfZclReportRestart) { gZclReportDeviceIndex = gZclReportClusterIndex = gAsynchronousClusterIndex = 0; gfZclReportRestart = FALSE; } /* get a buffer to build the next report */ pMsg = AF_MsgAlloc(); if(!pMsg) { gfZclReportRestart = FALSE; ZLC_StartShortReportingTimer(); return; } /* walk through all devices */ while(gZclReportDeviceIndex < gNum_EndPoints_c) { /* make sure this app endpoint is a ZCL device */ pDevice = (afDeviceDef_t *) endPointList[gZclReportDeviceIndex].pDevice; /* report list */ pReportList = pDevice->pReportList; if(!pDevice || !pDevice->pfnZCL) { ++gZclReportDeviceIndex; continue; } /* Find if any attribute are a asynchronous, then update the attribute */ do { for(i=0; i<pDevice->reportCount; ++i) { zclAttrDef_t *pAttrDef; zclReportAttr_t *pCurrentReportList = &pReportList[i]; /* only looking for this one cluster, to see if it's in the reportinglist */ if(!IsEqual2Bytes(pCurrentReportList->aClusterId, pDevice->pClusterDef[gAsynchronousClusterIndex].aClusterId)) continue; // If the cluster is on the reporting list, find the reporting attribute pAttrDef = ZCL_FindAttr(&pDevice->pClusterDef[gAsynchronousClusterIndex], pCurrentReportList->attrId); if(pAttrDef) { /* It's a asynchronous attribute, update before reporting */ if(ZclAttrIsAsynchronous_c(pAttrDef->flags)) { ++gAsynchronousClusterIndex; BeeAppUpdateDevice(0, gZclUI_SendReportingAttributeRequest_c, pAttrDef->id, pCurrentReportList->aClusterId, NULL); //Free the message, because we return from here MSG_Free(pMsg); return; } } } ++gAsynchronousClusterIndex; }while(gAsynchronousClusterIndex < pDevice->clusterCount); /* check each cluster for reporting attributes */ while(gZclReportClusterIndex < pDevice->clusterCount) { pCluster = &pDevice->pClusterDef[gZclReportClusterIndex]; pFrame = (void *)(&((uint8_t *)pMsg)[ApsmeGetAsduOffset()]); /* build the report for the next cluster */ reportLen = ZCL_BuildAttrReport( (zclCmdReportAttr_t *)(pFrame + 1), /* ptr to report frame */ pDevice, /* ptr to device */ pCluster ); /* no reporting attributes this cluster */ if(!reportLen) { ++gZclReportClusterIndex; continue; } /* set up the address info */ addrInfo.dstAddrMode = gZbAddrModeIndirect_c; addrInfo.srcEndPoint = endPointList[gZclReportDeviceIndex].pEndpointDesc->pSimpleDesc->endPoint; addrInfo.txOptions = gZclTxOptions; addrInfo.radiusCounter = afDefaultRadius_c; /* determine which cluster to send it to */ Copy2Bytes(addrInfo.aClusterId, pCluster->aClusterId); /* set up frame */ pFrame->frameControl = gZclFrameControl_FrameTypeGeneral | gZclFrameControl_DisableDefaultRsp; pFrame->transactionId = gZclTransactionId++; pFrame->command = gZclCmdReportAttr_c; /* send the report */ payloadLen = sizeof(zclFrame_t) + reportLen; (void)ZCL_DataRequestNoCopy(&addrInfo, payloadLen, pMsg); ++gZclReportClusterIndex; /* start a short timer between reporting clusters */ gfZclReportRestart = FALSE; ZLC_StartShortReportingTimer(); return; } /* try next device */ ++gZclReportDeviceIndex; gZclReportClusterIndex=0; gAsynchronousClusterIndex=0; } /* end of while(gZclReportDeviceIndex < gNum_EndPoints_c) */ if(pMsg) MSG_Free(pMsg); /* start up a new timer if needed */ if(gZclReportingSetup.reportTimeout != 0 && gZclReportingSetup.reportTimeout != 0xFFFF) { gZclReportingSetup.reportCounter = gZclReportingSetup.reportTimeout; ZLC_StartReportingTimer(); } }
void HcOutgoingZtcTaskEventMonitor(OepOutgoingMessage_t *message) { hcZtcMessage_t* pMsgFromSAPHandler; /* cleaner access to the 11073 apdu */ oepGenericApdu_t *pApdu = (oepGenericApdu_t *)message->pApdu; uint8_t* pSrcDataPtr; uint8_t* pDstDataPtr; /* first fragment flag is initially set to True */ uint8_t firstFragment = TRUE; uint16_t apduLen = message->length - MbrSizeof(oepGenericApdu_t, apduLen); uint8_t dataCopyLen; /* iterate the fragments */ do { /* allocate a new buffer as the ZTC frames are quite different from the actual 11073 frames */ pMsgFromSAPHandler = (hcZtcMessage_t *) MSG_Alloc(mSapHandlerMsgTotalLen_c); if (firstFragment) { oepMsgType_t oepMsgType; firstFragment = FALSE; /* is it a cfg, prst, other kind of frame? */ oepMsgType = GetOepMsgType(pApdu); /* get ZTC opcode id for the frame */ pMsgFromSAPHandler->msgType = GetMsgZtcOpCode(pApdu); /* frame is an object configuration frame */ if (oepMsgType == msgType_ObjCfgMsg) { hcZtcObjCfgFrame_t* pHcZtcObjCfgFrame = (hcZtcObjCfgFrame_t *)pMsgFromSAPHandler->data; apduLen -= MbrSizeof(oepGenericApdu_t, choice); if (apduLen > mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame)) { dataCopyLen = mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame); apduLen -= dataCopyLen; pHcZtcObjCfgFrame->nextFragmentPresent = TRUE; } else { dataCopyLen = (uint8_t)apduLen; apduLen = 0; pHcZtcObjCfgFrame->nextFragmentPresent = FALSE; } pMsgFromSAPHandler->msgLen = dataCopyLen + MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame); pSrcDataPtr = (uint8_t *)pApdu->payload; pDstDataPtr = (uint8_t *)pHcZtcObjCfgFrame->objCfgFrame; pHcZtcObjCfgFrame->endPoint = message->srcEndPoint; } else { /* Aarq, Aars, Prst, etc type of frame */ hcZtcFrame_t* pZtcFrameGeneric = (hcZtcFrame_t *)pMsgFromSAPHandler->data; if (apduLen > mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFrame_t, apdu)) { dataCopyLen = mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFrame_t, apdu); apduLen -= dataCopyLen; pZtcFrameGeneric->nextFragmentPresent = TRUE; } else { dataCopyLen = (uint8_t)apduLen; apduLen = 0; pZtcFrameGeneric->nextFragmentPresent = FALSE; } pMsgFromSAPHandler->msgLen = dataCopyLen + MbrOfs(hcZtcFrame_t, apdu); pSrcDataPtr = (uint8_t *)&pApdu->choice; pDstDataPtr = (uint8_t *)pZtcFrameGeneric->apdu; Copy2Bytes(pZtcFrameGeneric->aSrcDstAddr, message->aDstAddr); pZtcFrameGeneric->dstEndPoint = message->dstEndPoint; pZtcFrameGeneric->srcEndPoint = message->srcEndPoint; } } else { /* this is not the first fragment; */ hcZtcFragmentContinuationFrame_t* pZtcFragmentCont = (hcZtcFragmentContinuationFrame_t *)pMsgFromSAPHandler->data; /* set fragment continuation opcode */ pMsgFromSAPHandler->msgType = gHcZtcOpcode_FragmentContinuation_d; if (apduLen > mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFragmentContinuationFrame_t, fragmentData)) { dataCopyLen = mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFragmentContinuationFrame_t, fragmentData); apduLen -= dataCopyLen; pZtcFragmentCont->nextFragmentPresent = TRUE; } else { dataCopyLen = (uint8_t)apduLen; apduLen = 0; pZtcFragmentCont->nextFragmentPresent = FALSE; } pMsgFromSAPHandler->msgLen = dataCopyLen + MbrSizeof(hcZtcFragmentContinuationFrame_t, fragmentData); pDstDataPtr = (uint8_t *)pZtcFragmentCont->fragmentData; } FLib_MemCpy(pDstDataPtr, pSrcDataPtr, dataCopyLen); pSrcDataPtr += dataCopyLen; /* send message to ZTC */ #ifndef gHostApp_d ZTC_TaskEventMonitor(gHcApp_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c); #else ZTC_TaskEventMonitor(gpHostAppUart, gHcApp_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c); #endif /* free the message if ZTC hasn't already done that */ if (pMsgFromSAPHandler) MSG_Free(pMsgFromSAPHandler); } while (apduLen > 0); }
void HcIncomingZtcTaskEventMonitor(OepFragmentedApdu_t *message) { hcZtcMessage_t* pMsgFromSAPHandler; /* pCurrentFragment points initially to the fragment in OepFragmentedApdu_t */ OepApduFragment_t* pCurrentFragment = &message->fragment; /* cleaner access to the 11073 apdu */ oepGenericApdu_t *pApdu = (oepGenericApdu_t *)pCurrentFragment->data; /* first fragment flag is initially set to True */ uint8_t firstFragment = TRUE; /* iterate the fragments */ do { uint8_t srcOffset, dstOffset, dataCopyLen; /* allocate a new buffer as the ZTC frames are quite different from the actual 11073 frames */ pMsgFromSAPHandler = (hcZtcMessage_t *) MSG_Alloc(mSapHandlerMsgTotalLen_c); /* set default values for mem copy offsets and length */ /* by default copy data beginning with the choice member in the apdu */ srcOffset = MbrOfs(oepGenericApdu_t, choice); /* by default copy data to the apdu member in the ztc frame*/ dstOffset = MbrOfs(hcZtcFrame_t, apdu); /* data copy length adjusted to omit apduLen field */ dataCopyLen = pCurrentFragment->len - MbrOfs(oepGenericApdu_t, choice); if (firstFragment) { oepMsgType_t oepMsgType; firstFragment = FALSE; /* is it a cfg, prst, other kind of frame? */ oepMsgType = GetOepMsgType(pApdu); /* get ZTC opcode id for the frame */ pMsgFromSAPHandler->msgType = GetMsgZtcOpCode(pApdu); /* frame is an object configuration frame */ if (oepMsgType == msgType_ObjCfgMsg) { /* msgLen is the length of the ZTC payload; this includes the actual apdu payload, without the choice and apduLen as well as the src/dstEndPoint and nextFragmentPresent bytes */ pMsgFromSAPHandler->msgLen = (uint8_t)(pCurrentFragment->len - MbrOfs(oepGenericApdu_t, payload) + MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame)); /* adjust source offset for data copy to not include choice */ srcOffset = MbrOfs(oepGenericApdu_t, payload); /* adjust dst offset for data copy as srcAddress and an endpoint are no longer included */ dstOffset = MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame); /* adjust data length for data copy as choice is no longer included */ dataCopyLen -= MbrSizeof(oepGenericApdu_t, choice); /* set destination endpoint as second byte in the ZTC packet based on frame direction */ pMsgFromSAPHandler->data[1] = message->dstEndPoint; } else { /* Aarq, Aars, Prst, etc type of frame */ hcZtcFrame_t* pZtcFrameGeneric = (hcZtcFrame_t *)pMsgFromSAPHandler->data; /* msgLen is the length of the ZTC payload; this includes the actual apdu payload, without the apduLen as well as the addressing information and nextFragmentPresent bytes */ pMsgFromSAPHandler->msgLen = pCurrentFragment->len - MbrOfs(oepGenericApdu_t, choice) + MbrOfs(hcZtcFrame_t, apdu); /* copy addressing info */ Copy2Bytes(pZtcFrameGeneric->aSrcDstAddr, message->aSrcAddr); pZtcFrameGeneric->dstEndPoint = message->dstEndPoint; pZtcFrameGeneric->srcEndPoint = message->srcEndPoint; } } else { /* this is not the first fragment; */ /* set data copy and copy size accordingly */ srcOffset = 0; dstOffset = 1; dataCopyLen = pCurrentFragment->len; pApdu = (oepGenericApdu_t *)pCurrentFragment->data; /* set fragment continuation opcode */ pMsgFromSAPHandler->msgType = gHcZtcOpcode_FragmentContinuation_d; /* msgLen includes the actualapdu payload and the nextFragmentPresent byte */ pMsgFromSAPHandler->msgLen = pCurrentFragment->len + MbrSizeof(hcZtcFrame_t, nextFragmentPresent); } /* nextFragmentPresent */ pMsgFromSAPHandler->data[0] = FALSE; /* set nextFramgentPresent byte in ZTC frame to 1 if there is another fragment to be processed */ if (pCurrentFragment->nextFragment != NULL) pMsgFromSAPHandler->data[0] = TRUE; /* do the fragment iteration */ pCurrentFragment = pCurrentFragment->nextFragment; /* copy payload data */ FLib_MemCpy((uint8_t*)pMsgFromSAPHandler->data + dstOffset, (uint8_t*)pApdu + srcOffset, dataCopyLen); /* send message to ZTC */ #ifndef gHostApp_d ZTC_TaskEventMonitor(gAppHc_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c); #else ZTC_TaskEventMonitor(gpHostAppUart, gAppHc_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c); #endif /* free the message if ZTC hasn't already done that */ if (pMsgFromSAPHandler) MSG_Free(pMsgFromSAPHandler); } while (pCurrentFragment != NULL); }
/************************************************************************************ * Using the default values of the ApsCahnnelMask and ScandDuration, Generates an * Nlme command to discover the ZigBee networks that may exist on the current * channel list. * * Interface assumptions: * Uses APS channel mask (gApsChannelMask_c) * * Return value: * NONE. * * Revison history: * Date Author Comments * ------ ------ -------- * 280208 MN Updated ************************************************************************************/ void ZdoNwkMng_GenerateNetworkFormation ( void /*IN: No Input Parameters*/ ) { nlmeNetworkFormationReq_t *pNwkFormationReq; zdoNlmeMessage_t *pNwkMsg; uint8_t *pChannelList = (uint8_t *)ApsmeGetRequest(gApsChannelMask_c); #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) != gCoordinator_c) return; #endif /* every single command needs it own buffer to be passed down to next layer. */ pNwkMsg = MSG_AllocType(zdoNlmeMessage_t); /* If the buffer allocation fails for any reason, that is it, no further processing is needed. */ if ( !pNwkMsg ) return; /* Create the network formation request and sent to the network Layer. */ pNwkMsg->msgType = gNlmeNetworkFormationRequest_c; /* Fast access to the memory where the */ pNwkFormationReq = &pNwkMsg->msgData.networkFormationReq; #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gCoordinator_c) #endif { /* We will use the list from the ED if and only if it is a valid list other wise use the current APS channel mask. */ if ((*(uint32_t *)gaScanChannels) != 0) { /* Use only the channels with the best energy levels for the active scan. */ pChannelList = gaScanChannels; } } /* Using the default channel mask, generate the Formation command. */ FLib_MemCpy(pNwkFormationReq->aScanChannels, pChannelList, sizeof(ApsmeGetRequest(gApsChannelMask_c))); /* Get all the parameters neede for this command. */ pNwkFormationReq->scanDuration = gScanDuration_c; FLib_MemCpy(&pNwkFormationReq->beaconOrder, &gBeeStackConfig.beaconOrder, 2); Copy2Bytes(pNwkFormationReq->aPanId, NlmeGetRequest(gNwkPanId_c)); pNwkFormationReq->batteryLifeExtension = gBeeStackConfig.batteryLifeExtn; if (ZDO_NLME_SapHandler( pNwkMsg )) { /* Catch the error if needed. */ } }