/***************************************************************************** OepAgent_HandleApdu Handle APDU's sent by ZCL *****************************************************************************/ void OepAgent_HandleApdu(OepFragmentedApdu_t *pApdu) { /* Add to Oep11073 queue */ MSG_Queue(&gOepAgentQueue, pApdu); /* Send event to 11073 task */ TS_SendEvent(gOepAgentTaskID, evtApduReceived_c); }
void ZDO_NwkManager ( nlmeZdoMessage_t *pZdoMsg /*IN: Message received from ZDO*/ ) { nlmeJoinIndication_t *pJoinIndication; uint8_t aNwkAddr[2]; (void)aNwkAddr; gMemoryFreedByApplication = FALSE; switch (pZdoMsg->msgType) { /************************************************************************************* NLME-Formation.confirm: Formation confirm is only available for PAN Coordinator devices or combo devices acting like coordinator. **************************************************************************************/ case gNlmeNetworkFormationConfirm_c: #if ( gCoordinatorCapability_d || gComboDeviceCapability_d) #if gComboDeviceCapability_d /* If a combo device is not acting like a PAN Coordinator should not do any further processing. */ if (NlmeGetRequest(gDevType_c) != gCoordinator_c) { break; } #endif /* Send an event to the ZDO state machine informing the fromation status. */ if (pZdoMsg->msgData.networkFormationConf.status == gZbSuccess_c) { ZDO_SendEvent(gZdoEvent_FormationSuccess_c); } else { ZDO_SendEvent(gZdoEvent_FormationFailure_c); } #endif break; /************************************************************************************* NLME-Discovery.confirm **************************************************************************************/ case gNlmeNetworkDiscoveryConfirm_c: /* If the device is trying to associate it self to a PAN, the state machine changes to be on gZdoDiscoveringNetworksState_c. */ if (ZDO_GetState() == gZdoDiscoveringNetworksState_c) { ZdoEvent_t event; /* The discovery information have already been stored by the NWK layer. Free up the confirm. */ if(pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL) { MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor ); } /* send an event to state machine task depending on the confirmation */ event = (pZdoMsg->msgData.networkDiscoveryConf.status == gZbSuccess_c)? gZdoEvent_DiscoverySuccess_c : gZdoEvent_DiscoveryFailure_c; ZDO_SendEvent(event); /* Setting this variable to FALSE means that ZDO will free the message and not the application. */ gMemoryFreedByApplication = FALSE; break; } /*********************************************************************************** For any of this cases the tables does not need to be arround so lets free up the memory. IMPORTANT: The tables need to be freed to avoid memory leaks. ************************************************************************************/ NWK_FreeUpDiscoveryTables(); /* If the device is on running state this means that it may be the application the one commanding the discovery. */ if(ZDO_IsRunningState()) { /* Reprot the discovery information to hte application. */ ( void ) ZDP_APP_SapHandler((zdpToAppMessage_t *)pZdoMsg); /* Setting this variable to TRUE means that the application is responsible of freeing the list inside the discovery message. */ gMemoryFreedByApplication = TRUE; } /* Management commands prevent the ZDO stae machine for doing anything but finishing the process of the remote command. */ else if (ZDO_GetState() == gZdoRemoteCommandsState_c) { #if gMgmt_NWK_Disc_rsp_d /* Generate the response through zdpmanager */ Zdp_Mgmt_Send_Nwk_disc_conf( pZdoMsg ); #endif ZDO_SendEvent(gZdoEvent_ManagementResponse_c); /* The information was copied in ZDP so the list inside the packet is no longer needed. */ if (pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL) { MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor ); } /* Setting this variable to FALSE means that all the buffers are free, no need to re-free it. */ gMemoryFreedByApplication = FALSE; } else { /* Clean up the discovery tables in the stack */ NWK_FreeUpDiscoveryTables(); if (pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL) { MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor ); } gMemoryFreedByApplication = FALSE; } break; /************************************************************************************* NLME-Join.confirm: We have join TO SOME ONE. **************************************************************************************/ case gNlmeJoinConfirm_c: #if gRouterCapability_d || gEndDevCapability_d || gComboDeviceCapability_d /* Make sure that the discovery tables have been freed after join request has been processed. */ NWK_FreeUpDiscoveryTables(); /* If a combo device is not router or end device should not proceed. */ #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gCoordinator_c) { break; } #endif /* If the device is already on running state the node may receive the unsolicited rejoin response because of and addressconflict, so ignore the join confirm. */ if (ZDO_IsRunningState()) break; /* If the device is not running then force it to parse the confirm. */ ZDO_SetState(gZdoJoiningState_c); /* Send an event to the ZDO state machine informing about the joining state. */ if( pZdoMsg->msgData.joinConf.status == gZbSuccess_c ) { ZDO_SendEvent(gZdoEvent_JoinSuccess_c); } else { ZDO_SendEvent(gZdoEvent_JoinFailure_c); } #endif break; /************************************************************************************* NLME-Join.indication: A device has join TO US. **************************************************************************************/ case gNlmeJoinIndication_c: /* Do the casting for the message one time and in one place, Code saving. */ pJoinIndication = &pZdoMsg->msgData.joinIndication; /* To avoid reject packets when the node join and comunicate multi ple times, the devices should flush the APS Duplicate table. */ APS_RemoveEntryFromApsDuplicateTable(pJoinIndication->aShortAddress); /* Every child joined to us must be record, to avoid lossing it in case of reset. */ ZdoNwkMng_SaveToNvm(zdoNvmObject_NeighborTable_c); #if gRnplusCapability_d #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) != gEndDevice_c) #endif { /* Remove the old routes to the joining device */ RemoveRouteEntry(pJoinIndication->aShortAddress); } #endif #endif #if gStandardSecurity_d || gHighSecurity_d /* If the joining device is associated from scratch erase previous data. */ if (pJoinIndication->rejoinNetwork == gAssociationJoin_c) { if (ApsmeGetRequest(gApsDefaultTCKeyType_c) == gTrustCenterLinkKey_c) { APS_ResetDeviceCounters(pJoinIndication->aExtendedAddress); } else { APS_RemoveSecurityMaterialEntry(pJoinIndication->aExtendedAddress); } /* Setting the last parameter to TRUE will erase APS secure material */ ZDO_SecClearDeviceData(pJoinIndication->aShortAddress, pJoinIndication->aExtendedAddress, FALSE); } /* If security is active and the joining mode is other that association join, no further processing should be done to the join indication. Consider the unsecure join. */ //else if ((pJoinIndication->rejoinNetwork == gNwkRejoin_c) && pJoinIndication->secureRejoin) //{ /* Make sure the memory will be freed */ //gMemoryFreedByApplication = FALSE; /* Do not process it further, no transport key will be needed. */ //return; //} else if (pJoinIndication->rejoinNetwork == gNwkRejoin_c && !pJoinIndication->secureRejoin) { /* Reset the Incoming frame counter of the dev that has left. */ /* Setting the last parameter to TRUE will erase APS secure material */ if (ApsmeGetRequest(gApsDefaultTCKeyType_c) == gTrustCenterLinkKey_c) { APS_ResetDeviceCounters(pJoinIndication->aExtendedAddress); } else { APS_RemoveSecurityMaterialEntry(pJoinIndication->aExtendedAddress); } /* Setting the last parameter to TRUE will erase APS secure material */ ZDO_SecClearDeviceData(pJoinIndication->aShortAddress, pJoinIndication->aExtendedAddress, FALSE); } /* The device must be set as Unauthenticated child in the NT. */ SSP_NwkSetRelationship(pJoinIndication->aExtendedAddress, gUnAuthenticatedChild_c); /* Keep the buffer around to be use in the state machine or the application. */ gMemoryFreedByApplication = TRUE; /*************************************************** Trust center specific join indication processing. ****************************************************/ #if gTrustCenter_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (gTrustCenter) #endif { /* Keep the information, we are going to start the joining state machine. */ MSG_Queue(&gJoinIndicationQueue, pZdoMsg); /* Tell the ZDO Task that we got a joining device packet and ready for action. */ TS_SendEvent(gZdoTaskID_c, gJoinIndicationArrive_c); } #endif #if !gTrustCenter_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (!gTrustCenter) #endif { uint8_t joiningType; bool_t isHighSecurity = FALSE; /* Every other device with joining capabilities should report the joining, using an APSME-UPDATE-DEVICE.request. */ isHighSecurity = (pJoinIndication->capabilityInformation & gSecurityCapability_c)? TRUE : FALSE; if (pJoinIndication->rejoinNetwork == gAssociationJoin_c) { joiningType = (isHighSecurity)? gHighSecurityDeviceUnsecuredJoin_c : gStandardDeviceUnsecuredJoin_c; } else if (pJoinIndication->rejoinNetwork == gNwkRejoin_c) { if (pJoinIndication->secureRejoin) { joiningType = (isHighSecurity)? gHighSecurityDeviceSecuredReJoin_c : gStandardDeviceSecuredReJoin_c; } else { joiningType = (isHighSecurity)? gHighSecurityDeviceUnsecuredRejoin_c : gStandardDeviceUnsecuredRejoin_c; } } // Always send the update device ZDO_APSME_Update_Device_request(pJoinIndication->aExtendedAddress, pJoinIndication->aShortAddress, joiningType, pJoinIndication->secureRejoin); (void)ZDP_APP_SapHandler((void *)pZdoMsg); } #endif /* #endif gStandardSecurity_d */ #endif break; /*break for join indication*/ /************************************************************************************* NLME-StartRouter.confirm: Every time that a Coordinator or a Router starts, genrates a start router confirm. **************************************************************************************/ case gNlmeStartRouterConfirm_c: #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d /* Combo devices acting like ZED don't need this confirm. */ #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* Indicate router has started (or not) */ if (pZdoMsg->msgData.startRouterConf.status == gZbSuccess_c) { ZDO_SendEvent(gZdoEvent_StartRouterSuccess_c); } else { ZDO_SendEvent(gZdoEvent_StartRouterFailure_c); } #endif break; /************************************************************************************* NLME-Sync.confirm **************************************************************************************/ case gNlmeSyncConfirm_c: #if gEndDevCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) != gEndDevice_c) { break; } #endif pZdoMsg->msgType = gSyncConf_c; ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* The application is responsible of freen the buffers. */ gMemoryFreedByApplication = TRUE; #endif break; /************************************************************************************* NLME-PermitJoining.confirm **************************************************************************************/ case gNlmePermitJoiningConfirm_c: #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif if(ZDO_IsRunningState()) { /* let application know about the permit join */ pZdoMsg->msgType = gPermitjoinConf_c; ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* indicate this SAP handler won't be freeing the memory */ gMemoryFreedByApplication = TRUE; } #endif break; /************************************************************************************* NLME-DirectJoin.confirm **************************************************************************************/ case gNlmeDirectJoinConfirm_c: #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* The may come because the network layer start the direct join and the confirm must be pass up to the application. */ if (ZDO_IsRunningState()) { /* Send message on to app. Tell this SAP handler not to free it. */ (void) ZDP_APP_SapHandler( (void *)pZdoMsg ); gMemoryFreedByApplication = TRUE; } else if (ZDO_GetState() == gZdoRemoteCommandsState_c) { ZDO_SendEvent(gZdoEvent_ManagementResponse_c); #if gMgmt_Direct_Join_rsp_d && (gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d) #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* Generate the response through zdpmanager */ Zdp_Mgmt_Direct_Join_conf( pZdoMsg ); /* Update the global variable to free the menory */ gMemoryFreedByApplication = TRUE; #endif } #endif break; /************************************************************************************* NLME-Leave.indication **************************************************************************************/ case gNlmeLeaveIndication_c: /* The local node is the one leaving the network. */ if (Cmp8BytesToZero(pZdoMsg->msgData.leaveIndication.aDeviceAddress)) { /* Only important to the local leave. Pick an appropiated leaving event. */ ZdoStopMode_t stopMode; /* Send event to ZDO state machine to initiate the reset procedure (r11, p272, ln31) The devices should not set the default mode to stop the node on a leave indication, the default mode send another leave.... and we just left. */ stopMode = gZdoStopModeDefault_c | gZdoStopMode; if (pZdoMsg->msgData.leaveIndication.rejoin) { /* We will come back.! */ stopMode |= gZdoStopMode_StopAndRestart_c; /* We are doing rejoin, we should not clear the tables. */ stopMode &= ~gZdoStopMode_ResetTables_c; } /* End of if (pZdoMsg->msgData.leaveIndication.rejoin) */ /* Tell ZDO to pull the breaks; */ ZDO_StopEx(stopMode); break; } /* End of if (Cmp8BytesToZero(pZdoMsg->msgData.leaveIndication.aDeviceAddress)) */ /* If we got the indiction and we are waiting for it, return to previous state. */ if (ZDO_GetState() == gZdoRemoteCommandsState_c) { ZDO_SendEvent(gZdoEvent_ManagementResponse_c); } #if gStandardSecurity_d || gHighSecurity_d #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* Reset the Incoming frame counter of the dev that has left. */ SSP_NwkResetDeviceFrameCounter( pZdoMsg->msgData.leaveIndication.aDeviceAddress ); /* If the device is Link capable remove the link key information if it exists. */ APS_RemoveSecurityMaterialEntry(pZdoMsg->msgData.leaveIndication.aDeviceAddress); /* Let the trust center know about the leaving device. */ // if (!IsSelfIeeeAddress(ApsmeGetRequest(gApsTrustCenterAddress_c))) #if !gTrustCenter_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (!gTrustCenter) #endif { ZDO_APSME_Update_Device_request(pZdoMsg->msgData.leaveIndication.aDeviceAddress, APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr), gDeviceLeft_c, 0x00); } #endif #endif #endif /* ZEDs dont porcess the removing of the children and removing of the routes. */ #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif #if gRnplusCapability_d /* Remove the old routes for the leaving device */ RemoveRouteEntry(APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr)); #endif /* Clean up address map if there is no bindings referencing address map entry consider deleting all bindings first. */ (void)APS_RemoveDeviceFromAddressMap(pZdoMsg->msgData.leaveIndication.aDeviceAddress); /* Tells the network layer to remove the leaving device from its tables. */ NWK_RemoveChildRecords(pZdoMsg->msgData.leaveIndication.aDeviceAddress); #endif /* Save the network data, to preserve that the leaving device is gone. Plus the counters for security (NWK and APS)that got reset. */ ZdoNwkMng_SaveToNvm(zdoNvmObject_All_c); break; /************************************************************************************* NLME-Leave.confirm **************************************************************************************/ case gNlmeLeaveConfirm_c: /* If we have received a management leave request, send the response */ if (ZDO_GetState() == gZdoRemoteCommandsState_c) { #if gMgmt_Leave_rsp_d Zdp_Mgmt_Send_leave_conf(pZdoMsg); /* The momery has been handled by the next higher layer. */ gMemoryFreedByApplication = TRUE; #endif ZDO_SendEvent(gZdoEvent_ManagementResponse_c); } /* The local node is the one leaving the network. */ if (Cmp8BytesToZero(pZdoMsg->msgData.leaveConf.aDeviceAddress)) { /* The self leave is handle in the indication. */ break; } #if gStandardSecurity_d || gHighSecurity_d #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* Reset the Incoming frame counter of the dev that has left. */ SSP_NwkResetDeviceFrameCounter( pZdoMsg->msgData.leaveIndication.aDeviceAddress ); /* If the device is Link capable remove the link key information if it exists. */ APS_RemoveSecurityMaterialEntry(pZdoMsg->msgData.leaveIndication.aDeviceAddress); /* Let the trust center know about the leaving device. */ ZDO_APSME_Update_Device_request(pZdoMsg->msgData.leaveIndication.aDeviceAddress, APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr), gDeviceLeft_c, 0x00); /* Tells the network layer to remove the leaving device from its tables. */ NWK_RemoveChildRecords(pZdoMsg->msgData.leaveIndication.aDeviceAddress); #endif /* #endif gStandardSecurity_d */ #endif break; /************************************************************************************* NLME-RouteDiscovery.confirm **************************************************************************************/ case gNlmeNetworkStatusCnf_c: case gNlmeRouteDiscoveryCnf_c: /* This packet will be freed by the application*/ gMemoryFreedByApplication = TRUE; /* Pass the packet to the App */ ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); break; /************************************************************************************* NLME-EnergyScan.confirm: An Energy Scan Confirm has come back. Was it due to the forming process, or due to FA/ZDP. **************************************************************************************/ case gNlmeEnergyScanConfirm_c: if(ZDO_GetState() == gZdoDiscoveringNetworksState_c) { if (pZdoMsg->msgData.EnergyScanConf.status == gZbSuccess_c) { ZDO_SendEvent(gZdoEvent_EnergyScanComplete_c); } else { ZDO_StopEx(gZdoStopModeDefault_c); } } /* Send to application layer */ ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* Update the global variable to free the memory */ gMemoryFreedByApplication = TRUE; break; case gNlmeNetworkStatusInd_c: case gNlmeTxReport_c: /* Send to application layer */ ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* Update the global variable to free the memory */ gMemoryFreedByApplication = TRUE; break; case gNwkProcessFrameConf_c: #if gStandardSecurity_d || gHighSecurity_d /* Send to application layer */ ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* Update the global variable to free the memory */ gMemoryFreedByApplication = TRUE; #else gMemoryFreedByApplication = FALSE; #endif break; default: break; } /* End of switch */ }