/***************************************************************************** This Function store to the Information Base in BlackBox and Host. *****************************************************************************/ void ZtcMsgSetIBReq(uint8_t msgType, uint8_t attrId, uint8_t index, uint8_t *pValue) { index_t i; uint8_t entrySize; /* Search attribute in table */ for (i = 0; i < NumberOfElements(maZtcIBData); ++i) { if (attrId == maZtcIBData[i].id) { break; } } if (i == NumberOfElements(maZtcIBData)) { return; } entrySize = maZtcIBData[i].entrySize; if((maZtcIBData[i].access == mZtcIBRWUseFunc)) { ztcIBAccessTbl_t const *pZtcIBAccessFuncTbl = NULL; uint8_t j; /* Find the entry in maZtcIBAccessFuncTbl */ for (j = 0; j < NumberOfElements(maZtcIBAccessFuncTbl); ++j) { if (maZtcIBData[i].id == maZtcIBAccessFuncTbl[j].id) { pZtcIBAccessFuncTbl = &maZtcIBAccessFuncTbl[j]; break; } } if (pZtcIBAccessFuncTbl) (void)(pZtcIBAccessFuncTbl)->pSetTblEntry(index, pValue); } else { /* Set the IB attribute locally and sent it over the UART (to BlackBox) */ FLib_MemCpy((uint8_t *) maZtcIBData[i].pTable + (uint16_t) (entrySize * index), pValue, entrySize); } gZtcPacketToClient.structured.header.opcodeGroup = gZtcReqOpcodeGroup_c; gZtcPacketToClient.structured.header.msgType = msgType; gZtcPacketToClient.structured.payload[0] = attrId; gZtcPacketToClient.structured.payload[1] = index; gZtcPacketToClient.structured.payload[2] = 0x01; /* Update one entry each time */ gZtcPacketToClient.structured.payload[3] = entrySize; FLib_MemCpy(&gZtcPacketToClient.structured.payload[4], pValue, entrySize); gZtcPacketToClient.structured.header.len = 4 + entrySize; ZtcComm_WritePacketToClient((gZtcPacketToClient.structured.header.len + sizeof(gZtcPacketToClient.structured.header))); }
/************************************************************************************ * Does a local energy scan, pass the confirm to the application using the ZDP_APP * Sap handler. Not available to ZEDs * * Interface assumptions: * The parameter aChannelList, is a valid channel list and is on little endian. * The parameter duration, is a non zero value. * * Return value: * NONE. * * Revison history: * Date Author Comments * ------ ------ -------- * 180208 MN Created ************************************************************************************/ void ZdoNwkMng_EnergyScanRequest ( zbChannels_t aChannelList, uint8_t duration ) { uintn32_t localList = 0; zdoNlmeMessage_t *pEnergyScan; nlmeEnergyScanReq_t *pEnergyRequest; pEnergyScan = MSG_Alloc(sizeof(nlmeEnergyScanReq_t) + sizeof(zbMsgId_t)); if (!pEnergyScan) return; /* NOTE: this function is used on FA and on regular ZDO state machine some times it receives the parameter on little endian and some times on big endian. */ /* Check if it's a valid channel list */ if( aChannelList[0] & 0xFF || aChannelList[1] & 0x07 || aChannelList[3] & 0xF8 ) { #ifdef __IAR_SYSTEMS_ICC__ FLib_MemCpyReverseOrder(&localList, aChannelList, sizeof(uint32_t)); #else localList = *((uint32_t *)aChannelList); localList = Native2OTA32(localList); #endif } pEnergyScan->msgType = gNlmeEnergyScanRequest_c; pEnergyRequest = &pEnergyScan->msgData.EnergyScanReq; if (localList) { FLib_MemCpy(pEnergyRequest->aScanChannels, &localList, sizeof(localList)); } else { FLib_MemCpy(pEnergyRequest->aScanChannels, aChannelList, sizeof(localList)); } pEnergyRequest->scanDuration = duration; if(ZDO_NLME_SapHandler(pEnergyScan)) { } }
zbSize_t Mgmt_Direct_Join_req ( zbMgmtDirectJoinRequest_t *pMsgComingIn ) { zdoNlmeMessage_t *pZdoNlmeMsg; #if ((gStandardSecurity_d || gHighSecurity_d) && gApsMaxEntriesForPermissionsTable_c) nlmeZdoMessage_t zdoMsg; #endif #if ((gStandardSecurity_d || gHighSecurity_d) && gApsMaxEntriesForPermissionsTable_c) if (!CommandHasPermission(NlmeGetRequest(gNwkShortAddress_c), gNetworkSettingsPermission_c)) { zdoMsg.msgData.directJoinConf.status = gZdpNotAuthorized_c; Zdp_Mgmt_Direct_Join_conf((void *)&zdoMsg); return 0; } #endif pZdoNlmeMsg = MSG_Alloc(MbrSizeof(zdoNlmeMessage_t, msgType) + sizeof(nlmeDirectJoinReq_t)); if (pZdoNlmeMsg) { pZdoNlmeMsg->msgType = gNlmeDirectJoinRequest_c; FLib_MemCpy(&pZdoNlmeMsg->msgData.directJoinReq, pMsgComingIn, sizeof(nlmeDirectJoinReq_t)); ZDO_SendEvent(gZdoEvent_ManagementCommand_c); (void)ZDO_NLME_SapHandler((void *)pZdoNlmeMsg); } return 0; }
/******************************************************************************* * Build the report for this cluster. May be empty. * * Returns 0 if nothing to report. Returns length of report if one or more * attributes to report. *******************************************************************************/ uint8_t ZCL_BuildAttrReport ( zclCmdReportAttr_t *pAttrRecord, /* IN: buffer to build report */ afDeviceDef_t *pDevice, /* IN: device for building report */ afClusterDef_t *pCluster /* IN: cluster definition */ ) { uint8_t i; uint8_t attrLen; uint8_t reportLen; zclReportAttr_t *pReportList; uint8_t * pAttrData; zclAttrDef_t * pAttrDef; /* no reportable attributes on this endpoint */ if(!pDevice->reportCount) return 0; /* report list */ pReportList = pDevice->pReportList; /* prepare for building the attribute list from the clusters */ /* look through attributes on this cluster */ reportLen = 0; for(i=0; i<pDevice->reportCount; ++i) { zclReportAttr_t *pCurrentReportList = &pReportList[i]; /* only looking for this one cluster */ if(!IsEqual2Bytes(pCurrentReportList->aClusterId, pCluster->aClusterId)) continue; /* report the attribute if being reported */ /* although it's reportable, is it being reported? */ if(BeeUtilGetIndexedBit(pDevice->pData, i)) { /* add the attribute to the list */ pAttrRecord->attrId = pCurrentReportList->attrId; pAttrDef = ZCL_FindAttr(pCluster, pAttrRecord->attrId); if (pAttrDef) pAttrRecord->attrType = pAttrDef->type; /* get a pointer to the data */ pAttrData = ZCL_GetAttributePtr(pDevice, pCluster, pCurrentReportList->attrId, &attrLen); FLib_MemCpy(pAttrRecord->aData, pAttrData, attrLen); /* on to next record */ attrLen += (sizeof(zclCmdReportAttr_t) - MbrSizeof(zclCmdReportAttr_t,aData)); pAttrRecord = (zclCmdReportAttr_t *)(((uint8_t *)pAttrRecord) + attrLen); reportLen += attrLen; } /* end of if being reported */ } /* end of for loop */ return reportLen; }
/*-------------------- User_Desc_set -------------------- 2.4.3.1.12 User_Desc_set. (ClusterID=0x0014) The User_Desc_set command is generated from a local device wishing to configure the user descriptor on a remote device. This command shall be unicast either to the remote device itself or to an alternative device that contains the discovery information of the remote device. The local device shall generate the User_Desc_set command using the format illustrated in Table 2.52. The NWKAddrOfInterest field shall contain the network address of the remote device for which the user descriptor is to be configured and the UserDescription field shall contain the ASCII character string that is to be configured in the user descriptor. IN: The buffer where the request data will be filled in. IN: The package with the request information. IN: The destination address where the message will be send. */ zbSize_t User_Desc_set ( uint8_t *pkgPayload, /* IN: The buffer where the request data will be filled in. */ zbUserDescriptorSet_t *pMessageComingIn, /* IN: The package with the request information. */ zbNwkAddr_t aDestAddr /* IN: The destination address where the message will be send. */ ) { zbSize_t payloadLength; FLib_MemSet(pkgPayload, 0x20, sizeof(zbUserDescriptorSet_t)); payloadLength = (MbrOfs(zbUserDescriptorSet_t, descriptor.aUserDescription[0]) + pMessageComingIn->descriptor.length); FLib_MemCpy(pkgPayload, pMessageComingIn,payloadLength); Zdp_GenerateDataReq( gUser_Desc_set_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload -SapHandlerDataStructureOffSet), sizeof(zbUserDescriptorSet_t) ); return gZdpAlreadyHanlded_c; }
/*-------------------- End_Device_Bind_req -------------------- 2.4.3.2.1 End_Device_Bind_req. (ClusterID=0x0020) The End_Device_Bind_req is generated from a Local Device wishing to perform End Device Bind with a Remote Device. The End_Device_Bind_req is generated, typically based on some user action like a button press. The destination addressing on this command shall be unicast and the destination address shall be that of the ZigBee Coordinator. 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 End_Device_Bind_req ( uint8_t *pkgPayload, /* IN/OUT: The buffer where the request data will be filled in. */ zbEndDeviceBindRequest_t *pMessageComingIn, /* IN: The package with the request information. */ zbNwkAddr_t aDestAddr /* IN: The destination address where to send the request. */ ) { zbSize_t payloadLength; FLib_MemCpy(pkgPayload, pMessageComingIn, MbrOfs(zbEndDeviceBindRequest_t, inputClusterList)); payloadLength = MbrOfs(zbEndDeviceBindRequest_t, inputClusterList) + ZDP_CopyClusterListPairToFrame(pkgPayload + MbrOfs(zbEndDeviceBindRequest_t, inputClusterList), &pMessageComingIn->inputClusterList); Zdp_GenerateDataReq( gEnd_Device_Bind_req_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload - SapHandlerDataStructureOffSet) , payloadLength ); return gZdpAlreadyHanlded_c; }
/*-------------------- Match_Desc_req -------------------- 2.4.3.1.7 Match_Desc_req. (ClusterID=0x0006) The Match_Desc_req command is generated from a local device wishing to find remote devices supporting a specific simple descriptor match criterion. This command shall either be broadcast to all RxOnWhenIdle devices or unicast. If the command is unicast, it shall be directed either to the remote device itself or to an alternative device that contains the discovery information of the remote device. The local device shall generate the Match_Desc_req command using the format illustrated in Table 2.47. The NWKAddrOfInterest field shall contain the broadcast to all RxOnWhenIdle devices network address (0xfffd), if the command is to be broadcast, or the network address of the remote device for which the match is required. IN: The buffer where the request will be generated. IN: The package with the request data. IN: The Address of the destination node. OUT: The Size of the payload for the request. */ zbSize_t Match_Desc_req ( uint8_t *pkgPayload, /* IN: The buffer where the request will be generated. */ zbMatchDescriptorRequestPtr_t *pMessageComingIn, /* IN: The package with the request data. */ zbNwkAddr_t aDestAddr /* IN: The Address of the destination node. */ ) { zbSize_t payloadLength; FLib_MemCpy(pkgPayload , pMessageComingIn, MbrOfs(zbMatchDescriptorRequestPtr_t, inputClusterList)); payloadLength = MbrOfs(zbMatchDescriptorRequestPtr_t, inputClusterList) + ZDP_CopyClusterListPairToFrame(pkgPayload + MbrOfs(zbMatchDescriptorRequestPtr_t, inputClusterList), (void *)&pMessageComingIn->inputClusterList); Zdp_GenerateDataReq(gMatch_Desc_req_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload - SapHandlerDataStructureOffSet), payloadLength ); return gZdpAlreadyHanlded_c; }
/* Start the ZC or ZR. Turns on the radio. Calls NLME-START-ROUTER.request */ void ZdoNwkMng_GenerateStartRouterReq ( void /*IN: No Input Parameters*/ ) { zdoNlmeMessage_t *pMsg; nlmeStartRouterReq_t sStartRouterReq; /*Create the Start as Router request and sent to the network Layer*/ pMsg = MSG_AllocType(zdoNlmeMessage_t); if(NULL == pMsg) return; pMsg->msgType = gNlmeStartRouterRequest_c; sStartRouterReq.beaconOrder = sStartRouterReq.superframeOrder = gBeeStackConfig.beaconOrder; sStartRouterReq.batteryLifeExtension = gBeeStackConfig.batteryLifeExtn; FLib_MemCpy(&pMsg->msgData.startRouterReq,&sStartRouterReq,sizeof(nlmeStartRouterReq_t)); ( void ) ZDO_NLME_SapHandler(pMsg); }
/*-------------------- 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; }
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 ApsChannelMask and ScanDuration, generates an * Nlme command to discover the ZigBee networks that may exist on the current * channel list (issues beacon requests and listens to beacon responses). * * Interface assumptions: * NONE. * * Return value: * NONE. * * Revison history: * Date Author Comments * ------ ------ -------- * 140708 DG Updated ************************************************************************************/ void ZdoNwkMng_GenerateNwkDiscoveryReq ( void /* IN: No Input Parameters. */ ) { zdoNlmeMessage_t *pNwkMsg; nlmeNetworkDiscoveryReq_t *pNwkDiscoveryReq; uint8_t *pChannelList = (uint8_t *)ApsmeGetRequest(gApsChannelMask_c); /* We need to generate a message to Nwk layer, a buffer needs to be allocated. */ pNwkMsg = MSG_AllocType( zdoNlmeMessage_t ); /* For some reason we fail to allocate the memory, no further processing can be done. */ if (!pNwkMsg) return; /* We are about to do what in the network layer is named active scan, we need the right list depending on the device type. */ #if gCoordinatorCapability_d || gComboDeviceCapability_d #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; } } #endif /* Create the network descovery request and sent to the network Layer. */ pNwkMsg->msgType = gNlmeNetworkDiscoveryRequest_c ; /* Fast access to the memory where the message is build, also is less code. */ pNwkDiscoveryReq = &pNwkMsg->msgData.networkDiscoveryReq; /* Set the current and active ApsChannelMask, remember this can be updated during the FA process. */ FLib_MemCpy(pNwkDiscoveryReq->aScanChannels, pChannelList, sizeof(ApsmeGetRequest(gApsChannelMask_c))); /* Get the default duration to use during the scan, remember that is trasnformed to a milliseconds time, down in the Nwk Layer. */ pNwkDiscoveryReq->scanDuration = gScanDuration_c; /* Pass the command down to the Nwk layer. */ if (ZDO_NLME_SapHandler( pNwkMsg )) { /* Catch the error if needed. */ } }
/* Store information to the Information Base. * * On entry * pRequest->iId ID of the IB entry to set, * pRequest->iIndex Index of the first element to set, and * pRequest->iEntries Number of elements to set. * pRequest->pData Not actually a pointer; replaced by the start of the * data. * * Note that this code treats everything as an array. Scalar values are * considered arrays that have a maximum of one element. */ void ZtcMsgSetIBReqFunc(void) { #define pRequest ((getIBRequest_t *) gZtcPacketFromClient.structured.payload) index_t entriesToSet = pRequest->iEntries; index_t entrySize; index_t firstEntry = pRequest->iIndex; index_t i; ztcIBData_t const *pIBData; index_t totalDataSize; for (i = 0, pIBData = NULL; i < NumberOfElements(maZtcIBData); ++i) { if (pRequest->iId == maZtcIBData[i].id) { pIBData = &maZtcIBData[i]; break; } } if (!pIBData) { ZtcError(gZtcUnknownIBIdentifier_c); return; } if ((pIBData->access != mZtcIBRW) && (pIBData->access != mZtcIBRWUseFunc)) { gZtcPacketToClient.structured.payload[0] = gZtcReadOnly_c; return; } entrySize = pIBData->entrySize; totalDataSize = (index_t) (entriesToSet * entrySize); /* Check each of these conditions separately, to catch overflows. */ if ( (firstEntry >= pIBData->maxEntries) || (firstEntry + entriesToSet > pIBData->maxEntries) || (totalDataSize > gZtcPacketFromClient.structured.header.len)) { gZtcPacketToClient.structured.payload[0] = gZtcTooBig_c; return; } if (pIBData->access == mZtcIBRWUseFunc) { ztcIBAccessTbl_t const *pZtcIBAccessFuncTbl = NULL; /* Find the entry in maZtcIBAccessFuncTbl */ for (i = 0; i < NumberOfElements(maZtcIBAccessFuncTbl); ++i) { if (pIBData->id == maZtcIBAccessFuncTbl[i].id) { pZtcIBAccessFuncTbl = &maZtcIBAccessFuncTbl[i]; break; } } if (pZtcIBAccessFuncTbl) { uint8_t *pEntries = (void *) &pRequest->pData; for(i = firstEntry; i < (firstEntry + entriesToSet); i++) { (void)(pZtcIBAccessFuncTbl)->pSetTblEntry(i, pEntries); pEntries = pEntries + entrySize; } return; } } FLib_MemCpy((uint8_t *) pIBData->pTable + ((uint16_t)entrySize * firstEntry), (void *) &pRequest->pData, totalDataSize); #undef pRequest } /* ZtcMsgSetIBReqFunc() */
/* Retrieve information from the Information Base. * * On entry * pRequest->iId ID of the IB entry to get, * pRequest->iIndex Index of the first element to get, and * pRequest->iEntries Number of elements to get. * pRequest->pData Ignored * * Return * pRequest->iEntries Actual number of elements returned, * pRequest->pData Reused as the total data returned, in bytes. * * Note that this code treats everything as an array. Scalar values are * considered arrays that have a maximum of one element. */ void ZtcMsgGetIBReqFunc(void) { #define pRequest ((getIBRequest_t *) gZtcPacketFromClient.structured.payload) getIBRequest_t *pResponse = ((getIBRequest_t *) &gZtcPacketToClient.structured.payload[sizeof(clientPacketStatus_t)]); index_t entriesReturned = pRequest->iEntries; index_t entrySize; index_t firstEntry = pRequest->iIndex; index_t i; ztcIBData_t const *pIBData; index_t totalDataSize; for (i = 0, pIBData = NULL; i < NumberOfElements(maZtcIBData); ++i) { if (pRequest->iId == maZtcIBData[i].id) { pIBData = &maZtcIBData[i]; break; } } if (!pIBData) { ZtcError(gZtcUnknownIBIdentifier_c); return; } /* The Test Tool is used by humans, who make mistakes. Be forgiving. */ if (firstEntry >= pIBData->maxEntries) { firstEntry = pIBData->maxEntries - 1; } if (firstEntry + entriesReturned > pIBData->maxEntries) { entriesReturned = pIBData->maxEntries - firstEntry; } if (!entriesReturned) { entriesReturned = 1; } /* points to the "To" client packet. They don't overlap. */ FLib_MemCpy((uint8_t *) pResponse, (void *) pRequest, sizeof(getIBRequest_t)); pResponse->iEntries = entriesReturned; pResponse->iEntrySize = entrySize = pIBData->entrySize; totalDataSize = (index_t) (entriesReturned * entrySize); if (totalDataSize > sizeof(gZtcPacketFromClient.structured.payload) - sizeof(getIBRequest_t)) { gZtcPacketToClient.structured.payload[0] = gZtcTooBig_c; return; } /* Note that pRequest points to the "From" client packet, and pResponse */ /* totalDataSize is shifted because Test Tool has to receive it little endian */ *((uint16_t *) &pResponse->pData) = totalDataSize << 8; gZtcPacketToClient.structured.header.len = sizeof(getIBRequest_t) + totalDataSize + sizeof(clientPacketStatus_t); if (pIBData->access == mZtcIBRWUseFunc) { ztcIBAccessTbl_t const *pZtcIBAccessFuncTbl = NULL; /* Find the entry in maZtcIBAccessFuncTbl */ for (i = 0; i < NumberOfElements(maZtcIBAccessFuncTbl); ++i) { if (pIBData->id == maZtcIBAccessFuncTbl[i].id) { pZtcIBAccessFuncTbl = &maZtcIBAccessFuncTbl[i]; break; } } if (pZtcIBAccessFuncTbl) { uint8_t *pEntries = ((uint8_t *) &pResponse->pData) + sizeof(pResponse->pData); for(i = firstEntry; i < (firstEntry+entriesReturned); i++) { (void)(pZtcIBAccessFuncTbl)->pGetTblEntry(i, pEntries); pEntries = pEntries + entrySize; } return; } } FLib_MemCpy(((uint8_t *) &pResponse->pData) + sizeof(pResponse->pData), (void *) (((uint8_t *) pIBData->pTable) + ((uint16_t)entrySize * firstEntry)), totalDataSize); #undef pRequest } /* ZtcMsgGetIBReqFunc() */
void OepAgentSetAddressInfo(Oep11073AddressInfo_t *addrInfo) { FLib_MemCpy(&mAgentAddrInfo, addrInfo, sizeof(Oep11073AddressInfo_t)); }
static void CopyAgentAddrInfoToMsg(OepOutgoingMessage_t *pOutMsg) { pOutMsg->dstAddrMode = mAgentAddrInfo.dstAddrMode; pOutMsg->srcEndPoint = mAgentAddrInfo.srcEndPoint; pOutMsg->dstEndPoint = mAgentAddrInfo.dstEndPoint; FLib_MemCpy(&pOutMsg->aDstAddr, mAgentAddrInfo.aDstAddr, 8); }
/*! ********************************************************************************* * \brief Initialize the RNG HW module * * \return Status of the RNG initialization sequence * ********************************************************************************** */ uint8_t RNG_Init(void) { #if FSL_FEATURE_SOC_RNG_COUNT const rnga_user_config_t config = { .isIntMasked = 1, .highAssuranceEnable = 0 }; RNGA_DRV_Init(0, &config); if( kStatus_RNGA_Success != RNGA_DRV_GetRandomData(0, &mRandomNumber, sizeof(uint32_t)) ) { return gRngInternalError_d; } #elif FSL_FEATURE_SOC_TRNG_COUNT trng_user_config_t config; TRNG_DRV_InitUserConfigDefault(&config); config.frequencyCountLimit.minimum = 0x00000100; config.frequencyCountLimit.maximum = 0x000F0000; config.ringOscDiv = kTRNGRingOscDiv0; config.entropyDelay = 1200; OSA_InstallIntHandler(g_trngIrqId[0], TRNG_ISR); if( kStatus_TRNG_Success != TRNG_DRV_Init(0, &config) ) { return gRngInternalError_d; } if( kStatus_TRNG_Success != TRNG_DRV_GetRandomData(0, &mRandomNumber, sizeof(uint32_t)) ) { return gRngInternalError_d; } #else #if gRNG_UsePhyRngForInitialSeed_d /* Use 802.15.4 PHY to generate the initial seed */ PhyGetRandomNo(&mRandomNumber); #else /* Use MCU unique Id for initial seed */ mRandomNumber = SIM_UIDL; #endif #endif /* Init Successfull */ return gRngSuccess_d; } /*! ********************************************************************************* * \brief Read a random number from the HW RNG module. * If the HW fails, the SW PRNG is used as backup. * * \param[out] pRandomNo - pointer to location where the value will be stored * * \return status of the RNG module * ********************************************************************************** */ static uint8_t RNG_HwGetRandomNo(uint32_t* pRandomNo) { #if FSL_FEATURE_SOC_RNG_COUNT if( kStatus_RNGA_Success == RNGA_DRV_GetRandomData(0, pRandomNo, sizeof(uint32_t)) ) { return gRngSuccess_d; } #elif FSL_FEATURE_SOC_TRNG_COUNT if( TRNG_HAL_GetEntropyValidCmd(g_trngBase[0]) && (kStatus_TRNG_Success == TRNG_DRV_GetRandomData(0, pRandomNo, sizeof(uint32_t))) ) { return gRngSuccess_d; } #endif mRandomNumber = (mRandomNumber * 6075) + 1283; FLib_MemCpy(pRandomNo, &mRandomNumber, sizeof(uint32_t)); return gRngSuccess_d; } /*! ********************************************************************************* * \brief Generate a random number * * \param[out] pRandomNo - pointer to location where the value will be stored * ********************************************************************************** */ void RNG_GetRandomNo(uint32_t* pRandomNo) { /* Check for NULL pointers */ if (NULL != pRandomNo) { (void)RNG_HwGetRandomNo(pRandomNo); } } /*! ********************************************************************************* * \brief Initialize seed for the PRNG algorithm. * * \param[in] pSeed - pointer to a buffer containing 20 bytes (160 bits). * Can be set using the RNG_GetRandomNo() function. * ********************************************************************************** */ void RNG_SetPseudoRandomNoSeed(uint8_t* pSeed) { mPRNG_Requests = 1; FLib_MemCpy( XKEY, pSeed, mPRNG_NoOfBytes_c ); }
/************************************************************************************ * 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. */ } }
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); }
/* Call on the network layer to (re)join the network. Includes orphan join, associate join, etc... */ void ZdoNwkMng_GenerateNwkJoinRequest(zbNwkJoinMode_t joinMode) { zdoNlmeMessage_t *pMsg; nlmeJoinReq_t *pJoinReq; uint8_t *pExtendedPan = (uint8_t *)NlmeGetRequest(gNwkExtendedPanId_c); /* allocate the request */ pMsg = MSG_AllocType(zdoNlmeMessage_t); if (!pMsg) { return; } /* Create the network Join request and sent to the network Layer */ pMsg->msgType = gNlmeJoinRequest_c; pJoinReq = &pMsg->msgData.joinReq; FLib_MemCpy(pJoinReq->aScanChannels, ApsmeGetRequest(gApsChannelMask_c), sizeof(ApsmeGetRequest(gApsChannelMask_c))); gZDO_SecureRejoin = ApsmeGetRequest(gApsUseInsecureJoin_c); /* By default the node will try to keep the behavior established by the SAS attribute, The SAS attribute canbe override by the application through the IB Set and Get. */ pJoinReq->securityEnable = ApsmeGetRequest(gApsUseInsecureJoin_c)? FALSE : TRUE; #if gStandardSecurity_d || gHighSecurity_d /* If we are trying to send a secure packet, then, check if we have a valid Nwk key. */ if (pJoinReq->securityEnable) { pJoinReq->securityEnable = SSP_NwkGotValidKey(); } /* If the rejoin is allowed unsecured then change the APSIB until authentication has arrive. */ if (!pJoinReq->securityEnable) { ApsmeSetRequest(gApsUseInsecureJoin_c, TRUE); } #endif #if gComboDeviceCapability_d pJoinReq->joinAsRouter = (NlmeGetRequest( gDevType_c ) == gRouter_c)? TRUE : FALSE; #elif ( gRouterCapability_d ) pJoinReq->joinAsRouter = TRUE; #else /*gRouterCapability_d*/ pJoinReq->joinAsRouter = FALSE; #endif /*gRouterCapability_d*/ pJoinReq->rejoinNetwork = joinMode; if (joinMode == gZdoStartMode_NwkRejoin_c) { pExtendedPan = (uint8_t *)ApsmeGetRequest(gApsUseExtendedPANID_c); } Copy8Bytes( pJoinReq->aExtendedPanId, pExtendedPan); pJoinReq->scanDuration = gScanDuration_c; pJoinReq->powerSource = ((gBeeStackConfig.currPowerSourceAndLevel & 0x01)? 0 : 1); pJoinReq->rxOnWhenIdle = ((IsLocalDeviceReceiverOnWhenIdle())? TRUE : FALSE); ( void ) ZDO_NLME_SapHandler( pMsg ); }