1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063 |
- /**************************************************************************************************
- Filename: ZDNwkMgr.c
- Revised: $Date: 2007-10-17 15:38:45 -0700 (Wed, 17 Oct 2007) $
- Revision: $Revision: 15716 $
- Description: The ZigBee Network Manager.
- Copyright 2007 Texas Instruments Incorporated. All rights reserved.
- IMPORTANT: Your use of this Software is limited to those specific rights
- granted under the terms of a software license agreement between the user
- who downloaded the software, his/her employer (which must be your employer)
- and Texas Instruments Incorporated (the "License"). You may not use this
- Software unless you agree to abide by the terms of the License. The License
- limits your use, and you acknowledge, that the Software may not be modified,
- copied or distributed unless embedded on a Texas Instruments microcontroller
- or used solely and exclusively in conjunction with a Texas Instruments radio
- frequency transceiver, which is integrated into your product. Other than for
- the foregoing purpose, you may not use, reproduce, copy, prepare derivative
- works of, modify, distribute, perform, display or sell this Software and/or
- its documentation for any purpose.
- YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
- PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
- INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
- NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
- TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
- NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
- LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
- INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
- OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
- OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
- (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
- Should you have any questions regarding your right to use this Software,
- contact Texas Instruments Incorporated at www.TI.com.
- **************************************************************************************************/
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- /******************************************************************************
- * INCLUDES
- */
- #include "ZComdef.h"
- #include "nwk_util.h"
- #include "ZDApp.h"
- #include "ZDObject.h"
- #include "ZGlobals.h"
- #include "ZDNwkMgr.h"
- #if defined( MT_ZDO_FUNC )
- #include "MT_ZDO.h"
- #endif
-
- #if defined ( LCD_SUPPORTED )
- #include "OnBoard.h"
- #endif
- /* HAL */
- #include "hal_lcd.h"
-
- /******************************************************************************
- * CONSTANTS
- */
- #define ONE_MINUTE 60000 // 1(m) * 60(s) * 1000(ms)
- #if defined ( LCD_SUPPORTED )
- const char NwkMgrStr_1[] = "NM-fail not hi";
- const char NwkMgrStr_2[] = "NM-cur<last fail";
- const char NwkMgrStr_3[] = "NM-energy too hi";
- const char NwkMgrStr_4[] = "NM-energy not up";
- #endif
-
- /******************************************************************************
- * TYPEDEFS
- */
- /*********************************************************************
- * GLOBAL VARIABLES
- */
-
- // Task ID for internal task/event processing. This variable will be
- // received when ZDNwkMgr_Init() is called.
- uint8 ZDNwkMgr_TaskID = 0;
- /******************************************************************************
- * LOCAL VARIABLES
- */
- // Frequency Agility variables
- uint8 ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq = 0;
- zAddrType_t ZDNwkMgr_MgmtNwkUpdateNotifyAddr;
- uint16 ZDNwkMgr_UpdateNotifyTimer = 0;
- uint8 ZDNwkMgr_NumUpdateNotifySent = 0;
- uint8 ZDNwkMgr_WaitingForNotifyConfirm = FALSE;
- uint16 ZDNwkMgr_TotalTransmissions;
- uint16 ZDNwkMgr_TxFailures;
- ZDO_MgmtNwkUpdateReq_t ZDNwkMgr_MgmtNwkUpdateReq;
-
- #if defined ( NWK_MANAGER )
- uint16 ZDNwkMgr_UpdateRequestTimer = 0;
- uint8 ZDNwkMgr_LastChannelEnergy = 0;
- uint16 ZDNwkMgr_LastChannelFailureRate = 0;
- #endif // NWK_MANAGER
- uint8 ZDNwkMgr_NewChannel;
- // PAN ID Conflict variables
- #if defined ( NWK_MANAGER )
- uint8 ZDNwkMgr_PanIdUpdateInProgress = FALSE;
- #endif // NWK_MANAGER
- /*********************************************************************
- * GLOBAL FUNCTIONS
- */
- // Freguency Agility functions
- void (*pZDNwkMgr_ReportChannelInterference)( NLME_ChanInterference_t *chanInterference ) = NULL;
- void (*pZDNwkMgr_ProcessDataConfirm)( afDataConfirm_t *afDataConfirm ) = NULL;
- void (*pZDNwkMgr_EDScanConfirmCB)( NLME_EDScanConfirm_t *EDScanConfirm ) = NULL;
- // PAN ID Conflict functions
- void (*pZDNwkMgr_NetworkReportCB)( ZDNwkMgr_NetworkReport_t *pReport ) = NULL;
- void (*pZDNwkMgr_NetworkUpdateCB)( ZDNwkMgr_NetworkUpdate_t *pUpdate ) = NULL;
- /******************************************************************************
- * LOCAL FUNCTIONS
- */
- void ZDNwkMgr_ProcessServerDiscRsp( zdoIncomingMsg_t *inMsg );
- void ZDNwkMgr_SetNwkManagerAddr( uint16 nwkManagerAddr );
- // Frequency Agility functions
- static void ZDNwkMgr_ProcessMsgCBs( zdoIncomingMsg_t *inMsg );
- static void ZDNwkMgr_ProcessMgmtNwkUpdateReq( zdoIncomingMsg_t *inMsg );
- static void ZDNwkMgr_ProcessChannelInterference( ZDNwkMgr_ChanInterference_t *pChanInterference );
- static void ZDNwkMgr_ProcessEDScanConfirm( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm );
- static void ZDNwkMgr_CheckForChannelInterference( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm );
- static void ZDNwkMgr_BuildAndSendUpdateNotify( uint8 TransSeq, zAddrType_t *dstAddr,
- uint16 totalTransmissions, uint16 txFailures,
- ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm, uint8 txOptions );
- void ZDNwkMgr_EDScanConfirmCB( NLME_EDScanConfirm_t *EDScanConfirm );
- void ZDNwkMgr_ProcessDataConfirm( afDataConfirm_t *afDataConfirm );
- void ZDNwkMgr_ReportChannelInterference( NLME_ChanInterference_t *chanInterference );
- #if defined ( NWK_MANAGER )
- static void ZDNwkMgr_ProcessMgmtNwkUpdateNotify( zdoIncomingMsg_t *inMsg );
- static void ZDNwkMgr_CheckForChannelChange( ZDO_MgmtNwkUpdateNotify_t *pNotify );
- #endif // NWK_MANAGER
- // PAN ID Conflict functions
- #if defined ( NWK_MANAGER )
- void ZDNwkMgr_NetworkReportCB( ZDNwkMgr_NetworkReport_t *pReport );
- void ZDNwkMgr_NetworkUpdateCB( ZDNwkMgr_NetworkUpdate_t *pUpdate );
- void ZDNwkMgr_ProcessNetworkReport( ZDNwkMgr_NetworkReport_t *pNetworkReport );
- void ZDNwkMgr_ProcessNetworkUpdate( ZDNwkMgr_NetworkUpdate_t *pNetworkUpdate );
- #endif // NWK_MANAGER
- /*********************************************************************
- * @fn ZDNwkMgr_Init
- *
- * @brief Initialization function for the Network Manager Task.
- * This is called during initialization and should contain
- * any application specific initialization (ie. hardware
- * initialization/setup, table initialization, power up
- * notificaiton ... ).
- *
- * @param task_id - the ID assigned by OSAL. This ID should be
- * used to send messages and set timers.
- *
- * @return none
- */
- void ZDNwkMgr_Init( byte task_id )
- {
- // Save the task ID
- ZDNwkMgr_TaskID = task_id;
- ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Server_Discovery_rsp );
- // Frequecy Agility initialization
- ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Mgmt_NWK_Update_req );
- #if defined ( NWK_MANAGER )
- ZDO_RegisterForZDOMsg( ZDNwkMgr_TaskID, Mgmt_NWK_Update_notify );
- #endif // NWK_MANAGER
- pZDNwkMgr_EDScanConfirmCB = ZDNwkMgr_EDScanConfirmCB;
- pZDNwkMgr_ProcessDataConfirm = ZDNwkMgr_ProcessDataConfirm;
- pZDNwkMgr_ReportChannelInterference = ZDNwkMgr_ReportChannelInterference;
-
- // PAN ID Conflict initialization
- #if defined ( NWK_MANAGER )
- pZDNwkMgr_NetworkReportCB = ZDNwkMgr_NetworkReportCB;
- pZDNwkMgr_NetworkUpdateCB = ZDNwkMgr_NetworkUpdateCB;
- #endif // NWK_MANAGER
-
- ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addrMode = Addr16Bit;
- ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = INVALID_NODE_ADDR;
- }
- /*********************************************************************
- * @fn ZDNwkMgr_event_loop
- *
- * @brief Main event loop for the Network Manager task. This function
- * is called to process all events for the task. Events
- * include timers, messages and any other user defined events.
- *
- * @param task_id - The OSAL assigned task ID.
- * @param events - events to process. This is a bit map and can
- * contain more than one event.
- *
- * @return none
- */
- UINT16 ZDNwkMgr_event_loop( byte task_id, UINT16 events )
- {
- osal_event_hdr_t *msgPtr;
- (void)task_id; // Intentionally unreferenced parameter
- if ( events & SYS_EVENT_MSG )
- {
- msgPtr = (osal_event_hdr_t *)osal_msg_receive( ZDNwkMgr_TaskID );
- while ( msgPtr )
- {
- switch ( msgPtr->event )
- {
- case ZDO_CB_MSG:
- // ZDO sends the message that we registered for
- ZDNwkMgr_ProcessMsgCBs( (zdoIncomingMsg_t *)msgPtr );
- break;
-
- case NM_CHANNEL_INTERFERE:
- // NWK layer sends the message when it detectes Channel Interference
- ZDNwkMgr_ProcessChannelInterference( (ZDNwkMgr_ChanInterference_t *)msgPtr );
- break;
-
- case NM_ED_SCAN_CONFIRM:
- // NWK layer sends the message when it receives an ED scan confirmation
- ZDNwkMgr_ProcessEDScanConfirm( (ZDNwkMgr_EDScanConfirm_t *)msgPtr );
- break;
- #if defined ( NWK_MANAGER )
- case ZDO_NETWORK_REPORT:
- // NWK layer sends this message when it receives a Network Report message
- ZDNwkMgr_ProcessNetworkReport( (ZDNwkMgr_NetworkReport_t *)msgPtr );
- break;
-
- case ZDO_NETWORK_UPDATE:
- // NKW layer sends this message when it receives a Network Update message
- ZDNwkMgr_ProcessNetworkUpdate( (ZDNwkMgr_NetworkUpdate_t *)msgPtr );
- break;
- #endif // NWK_MANAGER
- default:
- break;
- }
- // Release the memory
- osal_msg_deallocate( (uint8 *)msgPtr );
- // Next
- msgPtr = (osal_event_hdr_t *)osal_msg_receive( ZDNwkMgr_TaskID );
- }
-
- // Return unprocessed events
- return (events ^ SYS_EVENT_MSG);
- }
- if ( events & ZDNWKMGR_CHANNEL_CHANGE_EVT )
- {
- // Switch channel
- _NIB.nwkLogicalChannel = ZDNwkMgr_NewChannel;
- ZMacSetReq( ZMacChannel, &ZDNwkMgr_NewChannel );
-
- // Our Channel has been changed -- notify to save info into NV
- ZDApp_NwkStateUpdateCB();
-
- // Reset the total transmit count and the transmit failure counters
- _NIB.nwkTotalTransmissions = 0;
- nwkTransmissionFailures( TRUE );
-
- return ( events ^ ZDNWKMGR_CHANNEL_CHANGE_EVT );
- }
- if ( events & ZDNWKMGR_UPDATE_NOTIFY_EVT )
- {
- // Update the Update Notify timer
- if ( ZDNwkMgr_UpdateNotifyTimer > 0 )
- {
- ZDNwkMgr_UpdateNotifyTimer--;
- osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_NOTIFY_EVT, ONE_MINUTE );
- }
- else
- {
- ZDNwkMgr_NumUpdateNotifySent = 0;
- }
-
- return ( events ^ ZDNWKMGR_UPDATE_NOTIFY_EVT );
- }
-
- #if defined ( NWK_MANAGER )
- if ( events & ZDNWKMGR_UPDATE_REQUEST_EVT )
- {
- // Update the Update Request timer
- if ( ZDNwkMgr_UpdateRequestTimer > 0 )
- {
- ZDNwkMgr_UpdateRequestTimer--;
- osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_REQUEST_EVT, ONE_MINUTE );
- }
-
- return ( events ^ ZDNWKMGR_UPDATE_REQUEST_EVT );
- }
- #endif // NWK_MANAGER
-
- if ( events & ZDNWKMGR_SCAN_REQUEST_EVT )
- {
- if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount > 0 )
- {
- if ( NLME_EDScanRequest( ZDNwkMgr_MgmtNwkUpdateReq.channelMask,
- ZDNwkMgr_MgmtNwkUpdateReq.scanDuration ) == ZSuccess )
- {
- ZDNwkMgr_MgmtNwkUpdateReq.scanCount--;
- }
- }
-
- return ( events ^ ZDNWKMGR_SCAN_REQUEST_EVT );
- }
-
- // Discard or make more handlers
- return 0;
- }
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessMsgCBs
- *
- * @brief Process the incoming messages.
- *
- * @param msgPtr - message to process
- *
- * @return TRUE if message to be freed. FALSE otherwise.
- */
- static void ZDNwkMgr_ProcessMsgCBs( zdoIncomingMsg_t *inMsg )
- {
- switch ( inMsg->clusterID )
- {
- case Mgmt_NWK_Update_req:
- ZDNwkMgr_ProcessMgmtNwkUpdateReq( inMsg );
- break;
- #if defined ( NWK_MANAGER )
- case Mgmt_NWK_Update_notify:
- ZDNwkMgr_ProcessMgmtNwkUpdateNotify( inMsg );
- break;
- #endif // NWK_MANAGER
- case Server_Discovery_rsp:
- ZDNwkMgr_ProcessServerDiscRsp( inMsg );
- break;
-
- default:
- // Unknown message
- break;
- }
- }
- /*********************************************************************
- * Frequency Agility Routines
- */
- #if defined ( NWK_MANAGER )
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessMgmtNwkUpdateNotify
- *
- * @brief This function processes the incoming Management
- * Network Update notify.
- *
- * @param pUpdateNotify - notify message
- *
- * @return TRUE if message to be freed. FALSE otherwise.
- */
- static void ZDNwkMgr_ProcessMgmtNwkUpdateNotify( zdoIncomingMsg_t *inMsg )
- {
- if ( zgNwkMgrMode == ZDNWKMGR_ENABLE )
- {
- ZDO_MgmtNwkUpdateNotify_t *pNotify = ZDO_ParseMgmtNwkUpdateNotify( inMsg );
- if ( pNotify )
- {
- ZDNwkMgr_CheckForChannelChange( pNotify );
- osal_mem_free( pNotify );
- }
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_CheckForChannelChange
- *
- * @brief This function processes the incoming Management Network
- * Update notify and starts an Update Request if a channel
- * change is needed.
- *
- * @param pUpdateNotify - notify message
- *
- * @return none
- */
- static void ZDNwkMgr_CheckForChannelChange( ZDO_MgmtNwkUpdateNotify_t *pNotify )
- {
- uint8 i;
- uint16 failureRate;
- uint8 lowestEnergyIndex;
- uint8 lowestEnergyValue = 0xFF;
-
- // If any device has more than 50% transmission failures, a channel
- // change should be considered
- failureRate = ( pNotify->transmissionFailures * 100 ) / pNotify->totalTransmissions;
- if ( failureRate < ZDNWKMGR_CC_TX_FAILURE )
- {
- #if defined ( LCD_SUPPORTED )
- HalLcdWriteString( (char*)NwkMgrStr_1, HAL_LCD_LINE_1 );
- HalLcdWriteStringValueValue( ": ", failureRate, 10, ZDNWKMGR_CC_TX_FAILURE, 10, HAL_LCD_LINE_2 );
- #endif
- return;
- }
- // If the current failure rate is higher than the last failure rate,
- // a channel change should be considered
- if ( failureRate < ZDNwkMgr_LastChannelFailureRate )
- {
- #if defined ( LCD_SUPPORTED )
- HalLcdWriteString( (char*)NwkMgrStr_2, HAL_LCD_LINE_1 );
- HalLcdWriteStringValueValue( ": ", failureRate, 10,
- ZDNwkMgr_LastChannelFailureRate, 10, HAL_LCD_LINE_2 );
- #endif
- return;
- }
-
- // Select a single channel based on the Mgmt_NWK_Update_notify based on
- // the lowest energy. This is the proposed new channel.
- for ( i = 0; i < pNotify->listCount; i++ )
- {
- if ( pNotify->energyValues[i] < lowestEnergyValue )
- {
- lowestEnergyIndex = i;
- lowestEnergyValue = pNotify->energyValues[i];
- }
- }
-
- // If this new channel does not have an energy level below an acceptable
- // threshold, a channel change should not be done.
- if ( lowestEnergyValue > ZDNWKMGR_ACCEPTABLE_ENERGY_LEVEL )
- {
- #if defined ( LCD_SUPPORTED )
- HalLcdWriteString( (char*)NwkMgrStr_3, HAL_LCD_LINE_1 );
- HalLcdWriteStringValueValue( ": ", lowestEnergyValue, 10,
- ZDNWKMGR_ACCEPTABLE_ENERGY_LEVEL, 10, HAL_LCD_LINE_2 );
- #endif
- return;
- }
- // Channel change should be done -- find out the new active channel
- for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
- {
- if ( ( (uint32)1 << i ) & pNotify->scannedChannels )
- {
- if ( lowestEnergyIndex == 0 )
- break;
- lowestEnergyIndex--;
- }
- }
-
- if ( ( _NIB.nwkLogicalChannel != i ) && ( ZDNwkMgr_UpdateRequestTimer == 0 ) )
- {
- uint32 channelMask;
- zAddrType_t dstAddr;
-
- // The new channel
- ZDNwkMgr_NewChannel = i;
-
- // Prior to changing channels, the network manager should store the
- // energy scan value as the last energy scan value and the failure
- // rate from the existing channel as the last failure rate. These
- // values are useful to allow comparison of the failure rate and energy
- // level on the previous channel to evaluate if the network is causing
- // its own interference.
- ZDNwkMgr_LastChannelEnergy = lowestEnergyValue;
- ZDNwkMgr_LastChannelFailureRate = failureRate;
-
- // The network manager should broadcast a Mgmt_NWK_Update_req notifying
- // devices of the new channel. The broadcast shall be to all routers
- // and coordinator.
- dstAddr.addrMode = AddrBroadcast;
- dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR_DEVRXON;
- channelMask = (uint32)1 << i;
-
- // Increment the nwkUpdateId parameter and set the updateID in the beacon
- NLME_SetUpdateID(_NIB.nwkUpdateId + 1);
-
- ZDP_MgmtNwkUpdateReq( &dstAddr, channelMask, 0xfe, 0, _NIB.nwkUpdateId, 0 );
-
- // The network manager shall set a timer based on the value of
- // apsChannelTimer upon issue of a Mgmt_NWK_Update_req that changes
- // channels and shall not issue another such command until this
- // timer expires.
- ZDNwkMgr_UpdateRequestTimer = ZDNWKMGR_UPDATE_REQUEST_TIMER;
- osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_REQUEST_EVT, ONE_MINUTE );
-
- // Upon receipt of a Mgmt_NWK_Update_req with a change of channels,
- // the local network manager shall set a timer equal to the
- // nwkNetworkBroadcastDeliveryTime and shall switch channels upon
- // expiration of this timer. NOTE: since we won't recevied our own
- // broadcasted Update Request, we start the channel change timer here.
- osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_CHANNEL_CHANGE_EVT,
- ZDNWKMGR_BCAST_DELIVERY_TIME );
- }
- }
- #endif // NWK_MANAGER
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessMgmtNwkUpdateReq
- *
- * @brief This function processes the incoming Management
- * Network Update request and starts the request (if needed).
- *
- * @param Request message
- *
- * @return none
- */
- static void ZDNwkMgr_ProcessMgmtNwkUpdateReq( zdoIncomingMsg_t *inMsg )
- {
- ZDO_MgmtNwkUpdateReq_t Req;
-
- ZDO_ParseMgmtNwkUpdateReq( inMsg, &Req );
-
- if ( Req.scanDuration <= 0x05 )
- {
- // Request is to scan over channelMask. The result will be reported by Confirm
- if ( ( !inMsg->wasBroadcast ) &&
- ( Req.scanCount > ZDNWKMGR_MIN_SCAN_COUNT ) &&
- ( Req.scanCount <= ZDNWKMGR_MAX_SCAN_COUNT ) )
- {
- if ( NLME_EDScanRequest( Req.channelMask, Req.scanDuration ) == ZSuccess )
- {
- // Save off the information to be used for the notify
- ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq = inMsg->TransSeq;
- ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = inMsg->srcAddr.addr.shortAddr;
-
- Req.scanCount--;
-
- // Save off scan info for the subsequent scans
- ZDNwkMgr_MgmtNwkUpdateReq = Req;
- }
- }
- }
- else if ( Req.scanDuration == 0xFE )
- {
- // Request is to change Channel. The command provide a new active
- // channel as a single channel in the channelMask.
- if ( Req.nwkUpdateId > _NIB.nwkUpdateId )
- {
- uint8 i;
-
- // Set update ID in the Beacon
- NLME_SetUpdateID(Req.nwkUpdateId);
-
- // Find out the new active channel
- for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
- {
- if ( ( (uint32)1 << i ) & Req.channelMask )
- {
- break;
- }
- }
- if ( _NIB.nwkLogicalChannel != i )
- {
- ZDNwkMgr_NewChannel = i;
-
- // Upon receipt of a Mgmt_NWK_Update_req with a change of channels,
- // the local network manager shall set a timer equal to the
- // nwkNetworkBroadcastDeliveryTime and shall switch channels upon
- // expiration of this timer. Each node shall also increment the
- // nwkUpdateId parameter and also reset the total transmit count
- // and the transmit failure counters.
- osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_CHANNEL_CHANGE_EVT,
- ZDNWKMGR_BCAST_DELIVERY_TIME );
- }
- }
- }
- else if ( Req.scanDuration == 0xFF )
- {
- // Request is to change apsChannelMask and nwkManagerAddr
- if ( Req.nwkUpdateId > _NIB.nwkUpdateId )
- {
- NLME_SetUpdateID(Req.nwkUpdateId); // Set the updateID in the beacon
-
- if ( ( Req.channelMask != 0 ) && ( _NIB.channelList != Req.channelMask ) )
- {
- _NIB.channelList = Req.channelMask;
-
- // Our Channel List has been changed -- notify to save info into NV
- ZDApp_NwkStateUpdateCB();
- }
-
- ZDNwkMgr_SetNwkManagerAddr( Req.nwkManagerAddr );
- }
- }
- else // 0x06-0xFD
- {
- // Request is invalid
- if ( !inMsg->wasBroadcast )
- {
- ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = inMsg->srcAddr.addr.shortAddr;
- ZDP_MgmtNwkUpdateNotify( inMsg->TransSeq, &ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
- ZDP_INVALID_REQTYPE, 0, 0, 0, 0, NULL, AF_TX_OPTIONS_NONE, false );
- }
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessServerDiscRsp
- *
- * @brief Process the incoming System Server Discovery Response
- *
- * @param pRsp - Structure containing Server Discovery response
- *
- * @return none
- */
- void ZDNwkMgr_ProcessServerDiscRsp( zdoIncomingMsg_t *inMsg )
- {
- ZDO_ServerDiscRsp_t Rsp;
-
- ZDO_ParseServerDiscRsp( inMsg, &Rsp );
-
- if ( Rsp.status == ZSuccess )
- {
- // Is the Network Manager bit set in the response?
- if ( Rsp.serverMask & NETWORK_MANAGER )
- {
- // Set the Remote Device's NWK Address as the Network Manager Address
- ZDNwkMgr_SetNwkManagerAddr( inMsg->srcAddr.addr.shortAddr );
- }
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessChannelInterference
- *
- * @brief This function processes the incoming Channel Interference
- * detection message and sends out a notify (if needed).
- *
- * @param pChannelInterference - interference message
- *
- * @return none
- */
- static void ZDNwkMgr_ProcessChannelInterference( ZDNwkMgr_ChanInterference_t *pChanInterference )
- {
- // To avoid a device with communication problems from constantly
- // sending reports to the network manager, the device should not
- // send a Mgmt_NWK_Update_notify more than 4 times per hour.
- if ( ZDNwkMgr_NumUpdateNotifySent < 4 )
- {
- // Conduct an energy scan on all channels.
- if ( NLME_EDScanRequest( MAX_CHANNELS_24GHZ, _NIB.scanDuration ) == ZSuccess )
- {
- // Save the counters for the Update Notify message to be sent
- ZDNwkMgr_TotalTransmissions = pChanInterference->totalTransmissions;
- ZDNwkMgr_TxFailures = pChanInterference->txFailures;
- // Mark scan as channel inetrference check
- ZDNwkMgr_MgmtNwkUpdateReq.scanCount = 0xFF;
- }
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessEDScanConfirm
- *
- * @brief This function processes the incoming ED Scan Confirm
- * message and sends out a notify (if needed).
- *
- * @param pEDScanConfirm - SD Scan Confirmation message
- *
- * @return none
- */
- static void ZDNwkMgr_ProcessEDScanConfirm( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm )
- {
- if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount == 0xFF )
- {
- // Confirm to scan all channels for channel interference check
- ZDNwkMgr_CheckForChannelInterference( pEDScanConfirm );
-
- ZDNwkMgr_MgmtNwkUpdateReq.scanCount = 0;
- }
- else
- {
- // Confirm to the requested scan
- uint16 txFailures = nwkTransmissionFailures( FALSE );
-
- ZDNwkMgr_BuildAndSendUpdateNotify( ZDNwkMgr_MgmtNwkUpdateNotifyTransSeq,
- &ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
- _NIB.nwkTotalTransmissions, txFailures,
- pEDScanConfirm, AF_TX_OPTIONS_NONE );
- // More scans needed?
- if ( ZDNwkMgr_MgmtNwkUpdateReq.scanCount > 0 )
- {
- osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_SCAN_REQUEST_EVT, 50 );
- }
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_CheckForChannelInterference
- *
- * @brief This function processes the incoming ED Scan Confirm
- * message and sends out an Update Notify (if needed).
- *
- * @param pEDScanConfirm - SD Scan Confirmation message
- *
- * @return none
- */
- static void ZDNwkMgr_CheckForChannelInterference( ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm )
- {
- uint8 i;
- uint8 channelEnergy = 0;
- uint8 energyIncreased = FALSE;
-
- // Get the current channel energy
- if ( ( (uint32)1 << _NIB.nwkLogicalChannel ) & pEDScanConfirm->scannedChannels )
- {
- channelEnergy = pEDScanConfirm->energyDetectList[_NIB.nwkLogicalChannel];
- }
-
- // If this energy scan does not indicate higher energy on the current
- // channel then other channels, no action is taken. The device should
- // continue to operate as normal and the message counters are not reset.
- for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
- {
- if ( ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels ) &&
- ( channelEnergy > pEDScanConfirm->energyDetectList[i] ) )
- {
- energyIncreased = TRUE;
- break;
- }
- }
-
- // If the energy scan does indicate increased energy on the channel
- // in use, a Mgmt_NWK_Update_notify should be sent to the Network
- // Manager to indicate interference is present.
- if ( energyIncreased )
- {
- // Send a Management Network Update notify to the Network Manager
- ZDNwkMgr_MgmtNwkUpdateNotifyAddr.addr.shortAddr = _NIB.nwkManagerAddr;
- ZDNwkMgr_BuildAndSendUpdateNotify( 0, &ZDNwkMgr_MgmtNwkUpdateNotifyAddr,
- ZDNwkMgr_TotalTransmissions, ZDNwkMgr_TxFailures,
- pEDScanConfirm, AF_MSG_ACK_REQUEST );
- ZDNwkMgr_WaitingForNotifyConfirm = TRUE; // Confirm will clear the counters
-
- if ( ZDNwkMgr_NumUpdateNotifySent == 0 )
- {
- // First notify message sent within this hour. Start the Update Notify timer.
- ZDNwkMgr_UpdateNotifyTimer = ZDNWKMGR_UPDATE_NOTIFY_TIMER;
- osal_start_timerEx( ZDNwkMgr_TaskID, ZDNWKMGR_UPDATE_NOTIFY_EVT, ONE_MINUTE );
- }
-
- ZDNwkMgr_NumUpdateNotifySent++;
- }
- #if defined ( LCD_SUPPORTED )
- else
- {
- // HalLcdWriteString( (char*)NwkMgrStr_4, HAL_LCD_LINE_1 );
- //HalLcdWriteStringValueValue( ": ", _NIB.nwkLogicalChannel, 10, channelEnergy, 10, HAL_LCD_LINE_2 );
- }
- #endif
- }
- /*********************************************************************
- * @fn ZDNwkMgr_BuildAndSendUpdateNotify
- *
- * @brief This builds and send a Mgmt_NWK_Update_notify message. This
- * function sends a unicast message.
- *
- * @param TransSeq - transaction sequence number
- * @param dstAddr - destination address of the message
- * @param pEDScanConfirm - update notify info
- *
- * @return afStatus_t
- */
- static void ZDNwkMgr_BuildAndSendUpdateNotify( uint8 TransSeq, zAddrType_t *dstAddr,
- uint16 totalTransmissions, uint16 txFailures,
- ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm,
- uint8 txOptions )
- {
- uint8 i;
- uint8 listCount = 0;
- uint8 *energyValues = NULL;
-
- // Count number of energy detects
- for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
- {
- if ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels )
- listCount++;
- }
-
- if ( listCount > 0 )
- {
- energyValues = (uint8 *)osal_mem_alloc( listCount );
- if ( energyValues )
- {
- uint8 j = 0;
- for ( i = 0; i < ED_SCAN_MAXCHANNELS; i++ )
- {
- if ( ( (uint32)1 << i ) & pEDScanConfirm->scannedChannels )
- energyValues[j++] = pEDScanConfirm->energyDetectList[i];
- }
- }
- }
-
- // Send a Management Network Update notify back
- ZDP_MgmtNwkUpdateNotify( TransSeq, dstAddr, pEDScanConfirm->status,
- pEDScanConfirm->scannedChannels,
- totalTransmissions, txFailures,
- listCount, energyValues, txOptions, false );
- if ( energyValues )
- osal_mem_free( energyValues );
- }
- #if defined ( NWK_MANAGER )
- /*********************************************************************
- * @fn NwkMgr_SetNwkManager
- *
- * @brief Set the local device as the Network Manager
- *
- * @param none
- *
- * @return none
- */
- void NwkMgr_SetNwkManager( void )
- {
- if ( zgNwkMgrMode == ZDNWKMGR_ENABLE )
- {
- // We're the Network Manager. Set our address as the Network Manager Address
- ZDNwkMgr_SetNwkManagerAddr( _NIB.nwkDevAddress );
-
- // Set the Network Manager bit of the Server Mask
- ZDO_Config_Node_Descriptor.ServerMask |= NETWORK_MANAGER;
- }
- }
- #endif // NWK_MANAGER
- /*********************************************************************
- * @fn ZDApp_SetNwkManagerAddr()
- *
- * @brief Sets the nwkManagerAddr in NIB.
- *
- * @param nwkManagerAddr
- *
- * @return none
- */
- void ZDNwkMgr_SetNwkManagerAddr( uint16 nwkManagerAddr )
- {
- if ( _NIB.nwkManagerAddr != nwkManagerAddr )
- {
- // Update the Network Manager Address
- _NIB.nwkManagerAddr = nwkManagerAddr;
-
- // Our Network Manger Address has been changed -- notify to save info into NV
- ZDApp_NwkStateUpdateCB();
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_ReportChannelInterference
- *
- * @brief This function builds a Channel Interference detection
- * message and then forwards it to the Network Manager.
- *
- * @param chanInterference
- *
- * @return none
- */
- void ZDNwkMgr_ReportChannelInterference( NLME_ChanInterference_t *chanInterference )
- {
- ZDNwkMgr_ChanInterference_t *pChanInterference;
- // Send Channel Interference message to the Network Manager task
- pChanInterference = (ZDNwkMgr_ChanInterference_t *)osal_msg_allocate( sizeof( ZDNwkMgr_ChanInterference_t ) );
- if ( pChanInterference )
- {
- pChanInterference->hdr.event = NM_CHANNEL_INTERFERE;
-
- // Build the structure
- pChanInterference->totalTransmissions = chanInterference->totalTransmissions;
- pChanInterference->txFailures = chanInterference->txFailures;
-
- osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pChanInterference );
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_EDScanConfirmCB
- *
- * @brief Handle Energy Scan confirm callback
- *
- * @param scannedChannels - scanned channels
- * @param energyDetectList - measured energy for channels
- *
- * @return none
- */
- void ZDNwkMgr_EDScanConfirmCB( NLME_EDScanConfirm_t *EDScanConfirm )
- {
- ZDNwkMgr_EDScanConfirm_t *pEDScanConfirm;
- // Send ED Confirm to the Network Manager task
- pEDScanConfirm = (ZDNwkMgr_EDScanConfirm_t *)osal_msg_allocate( sizeof( ZDNwkMgr_EDScanConfirm_t ) );
- if ( pEDScanConfirm )
- {
- pEDScanConfirm->hdr.event = NM_ED_SCAN_CONFIRM;
-
- // Build the structure
- pEDScanConfirm->status = EDScanConfirm->status;
- pEDScanConfirm->scannedChannels = EDScanConfirm->scannedChannels;
- osal_memcpy( pEDScanConfirm->energyDetectList, EDScanConfirm->energyDetectList, ED_SCAN_MAXCHANNELS );
-
- osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pEDScanConfirm );
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessDataConfirm
- *
- * @brief Process received Confirmation for Mgmt NWK Update Notify message
- *
- * @param none
- *
- * @return none
- */
- void ZDNwkMgr_ProcessDataConfirm( afDataConfirm_t *afDataConfirm )
- {
- if ( ZDNwkMgr_WaitingForNotifyConfirm &&
- ( afDataConfirm->transID == 0 ) &&
- ( afDataConfirm->hdr.status == ZSuccess ) )
- {
- // The Mgmt NWK Update Notify was sent as an APS Unicast with
- // acknowledgement and once the acknowledgment is received the
- // total transmit and transmit failure counters are reset to zero.
- _NIB.nwkTotalTransmissions = 0;
- nwkTransmissionFailures( TRUE );
-
- ZDNwkMgr_WaitingForNotifyConfirm = FALSE;
- }
- }
- /*********************************************************************
- * PAN ID Conflict Routines
- */
- #if defined ( NWK_MANAGER )
- /*********************************************************************
- * @fn ZDNwkMgr_NetworkReportCB
- *
- * @brief Handle the Network Report Command
- *
- * @param srcAddr - Source Address of the message.
- * @param status - ZSuccess.
- * @param serverMask - Bit mask of services matching the req serverMask.
- * @param securityUse -
- *
- * @return none
- */
- void ZDNwkMgr_NetworkReportCB( ZDNwkMgr_NetworkReport_t *pReport )
- {
- // Send Network Report message to the Network Manager task
- osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pReport );
- }
- /*********************************************************************
- * @fn ZDNwkMgr_NetworkUpdateCB
- *
- * @brief Handle the Network Update Command
- *
- * @param srcAddr - Source Address of the message.
- * @param status - ZSuccess.
- * @param serverMask - Bit mask of services matching the req serverMask.
- * @param securityUse -
- *
- * @return none
- */
- void ZDNwkMgr_NetworkUpdateCB( ZDNwkMgr_NetworkUpdate_t *pUpdate )
- {
- // Send Network Update message to the Network Manager task
- osal_msg_send( ZDNwkMgr_TaskID, (uint8 *)pUpdate );
- }
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessNetworkReport
- *
- * @brief Process the incoming Network Report message
- *
- * @param pNetworkReport - Structure containing Network Report message
- *
- * @return none
- */
- void ZDNwkMgr_ProcessNetworkReport( ZDNwkMgr_NetworkReport_t *pNetworkReport )
- {
- uint8 i;
- uint16 newPID;
- uint8 unique = TRUE;
- if ( pNetworkReport->reportType == NWKREPORT_PANID_CONFLICT )
- {
- if ( ZDNwkMgr_PanIdUpdateInProgress == FALSE )
- {
- do
- {
- // select a new PAN ID
- newPID = (uint16)osal_rand();
-
- // Make sure that the chosen PAN ID is not already in use in the
- // local neighborhood and also not contained within the Report
- // Information field of the Network Report Command frame
- for ( i = 0; i < pNetworkReport->reportInfoCnt; i++ )
- {
- if ( pNetworkReport->panIDs[i] == newPID )
- {
- unique = FALSE;
- break;
- }
- }
- } while ( !unique );
-
- // Send out a Network Update command.
- NLME_SendNetworkUpdate( NWK_BROADCAST_SHORTADDR, NWKUPDATE_PANID_UPDATE,
- _NIB.extendedPANID, _NIB.nwkUpdateId+1, newPID );
-
- ZDNwkMgr_PanIdUpdateInProgress = TRUE;
- }
- }
- }
- /*********************************************************************
- * @fn ZDNwkMgr_ProcessNetworkUpdate
- *
- * @brief Process the incoming Network Update message
- *
- * @param pNetworkReport - Structure containing Network Update message
- *
- * @return none
- */
- void ZDNwkMgr_ProcessNetworkUpdate( ZDNwkMgr_NetworkUpdate_t *pNetworkUpdate )
- {
- if ( pNetworkUpdate->updateType == NWKUPDATE_PANID_UPDATE )
- {
- // Our PAN ID has been changed -- notify to save info into NV
- ZDApp_NwkStateUpdateCB();
-
- ZDNwkMgr_PanIdUpdateInProgress = FALSE;
- }
- }
- #endif // NWK_MANAGER
- /*********************************************************************
- *********************************************************************/
|