12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227 |
- /**************************************************************************************************
- Filename: ZDObject.c
- Revised: $Date: 2011-07-13 10:55:53 -0700 (Wed, 13 Jul 2011) $
- Revision: $Revision: 26766 $
- Description: This is the Zigbee Device Object.
- Copyright 2004-2011 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.
- **************************************************************************************************/
- /*********************************************************************
- * INCLUDES
- */
- #include "ZComdef.h"
- #include "OSAL.h"
- #include "OSAL_Nv.h"
- #include "rtg.h"
- #include "NLMEDE.h"
- #include "nwk_globals.h"
- #include "APS.h"
- #include "APSMEDE.h"
- #include "AssocList.h"
- #include "BindingTable.h"
- #include "AddrMgr.h"
- #include "AF.h"
- #include "ZDObject.h"
- #include "ZDProfile.h"
- #include "ZDConfig.h"
- #include "ZDSecMgr.h"
- #include "ZDApp.h"
- #include "nwk_util.h" // NLME_IsAddressBroadcast()
- #include "ZGlobals.h"
- #if defined MT_ZDO_CB_FUNC
- #include "MT.h"
- #endif
- #if defined( LCD_SUPPORTED )
- #include "OnBoard.h"
- #endif
- /* HAL */
- #include "hal_lcd.h"
- /*********************************************************************
- * MACROS
- */
- /*********************************************************************
- * CONSTANTS
- */
- // NLME Stub Implementations
- #define ZDO_ProcessMgmtPermitJoinTimeout NLME_PermitJoiningTimeout
- // Status fields used by ZDO_ProcessMgmtRtgReq
- #define ZDO_MGMT_RTG_ENTRY_ACTIVE 0x00
- #define ZDO_MGMT_RTG_ENTRY_DISCOVERY_UNDERWAY 0x01
- #define ZDO_MGMT_RTG_ENTRY_DISCOVERY_FAILED 0x02
- #define ZDO_MGMT_RTG_ENTRY_INACTIVE 0x03
- /*********************************************************************
- * TYPEDEFS
- */
- #if defined ( REFLECTOR )
- typedef struct
- {
- byte SrcTransSeq;
- zAddrType_t SrcAddr;
- uint16 LocalCoordinator;
- byte epIntf;
- uint16 ProfileID;
- byte numInClusters;
- uint16 *inClusters;
- byte numOutClusters;
- uint16 *outClusters;
- byte SecurityUse;
- byte status;
- } ZDO_EDBind_t;
- #endif // defined ( REFLECTOR )
- enum
- {
- ZDMATCH_INIT, // Initialized
- ZDMATCH_WAIT_REQ, // Received first request, waiting for second
- ZDMATCH_SENDING_BINDS // Received both requests, sending unbind/binds
- };
- enum
- {
- ZDMATCH_SENDING_NOT,
- ZDMATCH_SENDING_UNBIND,
- ZDMATCH_SENDING_BIND
- };
- /*********************************************************************
- * GLOBAL VARIABLES
- */
- /*********************************************************************
- * EXTERNAL VARIABLES
- */
- /*********************************************************************
- * EXTERNAL FUNCTIONS
- */
- /*********************************************************************
- * LOCAL VARIABLES
- */
- static uint16 ZDOBuildBuf[26]; // temp area to build data without allocation
- #if defined ( REFLECTOR )
- static ZDO_EDBind_t *ZDO_EDBind; // Null when not used
- #endif
- #if defined ( MANAGED_SCAN )
- uint32 managedScanNextChannel = 0;
- uint32 managedScanChannelMask = 0;
- uint8 managedScanTimesPerChannel = 0;
- #endif
- ZDMatchEndDeviceBind_t *matchED = (ZDMatchEndDeviceBind_t *)NULL;
- uint32 apsChannelMask = 0;
- /*********************************************************************
- * LOCAL FUNCTIONS
- */
- static void ZDODeviceSetup( void );
- #if defined ( MANAGED_SCAN )
- static void ZDOManagedScan_Next( void );
- #endif
- #if defined ( REFLECTOR )
- static void ZDO_RemoveEndDeviceBind( void );
- static void ZDO_SendEDBindRsp( byte TransSeq, zAddrType_t *dstAddr, byte Status, byte secUse );
- #endif
- static byte ZDO_CompareClusterLists( byte numList1, uint16 *list1,
- byte numList2, uint16 *list2, uint16 *pMatches );
- static void ZDO_RemoveMatchMemory( void );
- static uint8 ZDO_CopyMatchInfo( ZDEndDeviceBind_t *destReq, ZDEndDeviceBind_t *srcReq );
- static void ZDO_EndDeviceBindMatchTimeoutCB( void );
- uint8 *ZDO_ConvertOTAClusters( uint8 cnt, uint8 *inBuf, uint16 *outList );
- static void zdoSendStateChangeMsg(uint8 state, uint8 taskId);
- /*********************************************************************
- * @fn ZDO_Init
- *
- * @brief ZDObject and ZDProfile initialization.
- *
- * @param none
- *
- * @return none
- */
- void ZDO_Init( void )
- {
- // Initialize ZD items
- #if defined ( REFLECTOR )
- ZDO_EDBind = NULL;
- #endif
- // Initialize default ZDO_UseExtendedPANID to the APS one.
- osal_cpyExtAddr( ZDO_UseExtendedPANID, AIB_apsUseExtendedPANID );
- // Setup the device - type of device to create.
- ZDODeviceSetup();
- }
- #if defined ( MANAGED_SCAN )
- /*********************************************************************
- * @fn ZDOManagedScan_Next()
- *
- * @brief Setup a managed scan.
- *
- * @param none
- *
- * @return none
- */
- static void ZDOManagedScan_Next( void )
- {
- // Is it the first time
- if ( managedScanNextChannel == 0 && managedScanTimesPerChannel == 0 )
- {
- // Setup the defaults
- managedScanNextChannel = 1;
- while( managedScanNextChannel && (zgDefaultChannelList & managedScanNextChannel) == 0 )
- managedScanNextChannel <<= 1;
- managedScanChannelMask = managedScanNextChannel;
- managedScanTimesPerChannel = MANAGEDSCAN_TIMES_PRE_CHANNEL;
- }
- else
- {
- // Do we need to go to the next channel
- if ( managedScanTimesPerChannel == 0 )
- {
- // Find next active channel
- managedScanChannelMask = managedScanNextChannel;
- managedScanTimesPerChannel = MANAGEDSCAN_TIMES_PRE_CHANNEL;
- }
- else
- {
- managedScanTimesPerChannel--;
- if ( managedScanTimesPerChannel == 0 )
- {
- managedScanNextChannel <<= 1;
- while( managedScanNextChannel && (zgDefaultChannelList & managedScanNextChannel) == 0 )
- managedScanNextChannel <<= 1;
- if ( managedScanNextChannel == 0 )
- zdoDiscCounter = NUM_DISC_ATTEMPTS + 1; // Stop
- }
- }
- }
- }
- #endif // MANAGED_SCAN
- /*********************************************************************
- * @fn ZDODeviceSetup()
- *
- * @brief Call set functions depending on the type of device compiled.
- *
- * @param none
- *
- * @return none
- */
- static void ZDODeviceSetup( void )
- {
- if ( ZG_BUILD_COORDINATOR_TYPE )
- {
- NLME_CoordinatorInit();
- }
- #if defined ( REFLECTOR )
- APS_ReflectorInit( (ZG_DEVICE_COORDINATOR_TYPE) ? APS_REFLECTOR_PUBLIC : APS_REFLECTOR_PRIVATE );
- #endif
- if ( ZG_BUILD_JOINING_TYPE )
- {
- NLME_DeviceJoiningInit();
- }
- }
- /*********************************************************************
- * @fn ZDO_StartDevice
- *
- * @brief This function starts a device in a network.
- *
- * @param logicalType - Device type to start
- * startMode - indicates mode of device startup
- * beaconOrder - indicates time betwen beacons
- * superframeOrder - indicates length of active superframe
- *
- * @return none
- */
- void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder )
- {
- ZStatus_t ret;
- #if defined ( ZIGBEE_FREQ_AGILITY )
- static uint8 discRetries = 0;
- #endif
- #if defined ( ZIGBEE_COMMISSIONING )
- static uint8 scanCnt = 0;
- #endif
- ret = ZUnsupportedMode;
- if ( ZG_BUILD_COORDINATOR_TYPE && logicalType == NODETYPE_COORDINATOR )
- {
- if ( startMode == MODE_HARD )
- {
- devState = DEV_COORD_STARTING;
- ret = NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList,
- zgDefaultStartingScanDuration, beaconOrder,
- superframeOrder, false );
- }
- else if ( startMode == MODE_RESUME )
- {
- // Just start the coordinator
- devState = DEV_COORD_STARTING;
- ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false );
- }
- else
- {
- #if defined( LCD_SUPPORTED )
- //HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
- #endif
- }
- }
- if ( ZG_BUILD_JOINING_TYPE && (logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE) )
- {
- if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )
- {
- devState = DEV_NWK_DISC;
- #if defined( MANAGED_SCAN )
- ZDOManagedScan_Next();
- ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask, BEACON_ORDER_15_MSEC );
- #else
- ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );
- #if defined ( ZIGBEE_FREQ_AGILITY )
- if ( !( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE ) &&
- ( ret == ZSuccess ) && ( ++discRetries == 4 ) )
- {
- // For devices with RxOnWhenIdle equals to FALSE, any network channel
- // change will not be recieved. On these devices or routers that have
- // lost the network, an active scan shall be conducted on the Default
- // Channel list using the extended PANID to find the network. If the
- // extended PANID isn't found using the Default Channel list, an scan
- // should be completed using all channels.
- zgDefaultChannelList = MAX_CHANNELS_24GHZ;
- }
- #endif // ZIGBEE_FREQ_AGILITY
- #if defined ( ZIGBEE_COMMISSIONING )
- if (startMode == MODE_REJOIN && scanCnt++ >= 5 )
- {
- // When ApsUseExtendedPanID is commissioned to a non zero value via
- // application specific means, the device shall conduct an active scan
- // on the Default Channel list and join the PAN with the same
- // ExtendedPanID. If the PAN is not found, an scan should be completed
- // on all channels.
- // When devices rejoin the network and the PAN is not found from
- zgDefaultChannelList = MAX_CHANNELS_24GHZ;
- }
- #endif // ZIGBEE_COMMISSIONING
- #endif
- }
- else if ( startMode == MODE_RESUME )
- {
- if ( logicalType == NODETYPE_ROUTER )
- {
- ZMacScanCnf_t scanCnf;
- devState = DEV_NWK_ORPHAN;
- /* if router and nvram is available, fake successful orphan scan */
- scanCnf.hdr.Status = ZSUCCESS;
- scanCnf.ScanType = ZMAC_ORPHAN_SCAN;
- scanCnf.UnscannedChannels = 0;
- scanCnf.ResultListSize = 0;
- nwk_ScanJoiningOrphan(&scanCnf);
- ret = ZSuccess;
- }
- else
- {
- devState = DEV_NWK_ORPHAN;
- ret = NLME_OrphanJoinRequest( zgDefaultChannelList,
- zgDefaultStartingScanDuration );
- }
- }
- else
- {
- #if defined( LCD_SUPPORTED )
- //HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
- #endif
- }
- }
- if ( ret != ZSuccess )
- {
- osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );
- }
- }
- /**************************************************************************************************
- * @fn zdoSendStateChangeMsg
- *
- * @brief Helper function for ZDO_UpdateNwkStatus.
- *
- * input parameters
- *
- * @param taskId - The OSAL task identifier to which to send the ZDO_STATE_CHANGE_EVT.
- * @param state - The current device state.
- *
- * output parameters
- *
- * None.
- *
- * @return None.
- **************************************************************************************************
- */
- static void zdoSendStateChangeMsg(uint8 state, uint8 taskId)
- {
- osal_event_hdr_t *pMsg = (osal_event_hdr_t *)osal_msg_find(taskId, ZDO_STATE_CHANGE);
- if (NULL == pMsg)
- {
- if (NULL == (pMsg = (osal_event_hdr_t *)osal_msg_allocate(sizeof(osal_event_hdr_t))))
- {
- // Upon failure to notify any EndPoint of the state change, re-set the ZDO event to
- // try again later when more Heap may be available.
- osal_set_event(ZDAppTaskID, ZDO_STATE_CHANGE_EVT);
- }
- else
- {
- pMsg->event = ZDO_STATE_CHANGE;
- pMsg->status = state;
- (void)osal_msg_send(taskId, (uint8 *)pMsg);
- }
- }
- else
- {
- // Modify in place the status of an existing ZDO_STATE_CHANGE message to the EndPoint.
- pMsg->status = state;
- }
- }
- /**************************************************************************************************
- * @fn ZDO_UpdateNwkStatus
- *
- * @brief This function sends a ZDO_STATE_CHANGE message to the task of every EndPoint
- * registered with AF (except, of course, the ZDO_EP). Even if a single task has more
- * than one registered EndPoint, it will only receive one notification per state
- * change. Although the device may go through a sequence of state changes, the
- * Application task may only receive notification of the final, steady-state state
- * because it has the lowest priority and never even runs to receive the intermediate
- * state change notifications.
- *
- * input parameters
- *
- * @param state - The current device state.
- *
- * output parameters
- *
- * None.
- *
- * @return None.
- **************************************************************************************************
- */
- void ZDO_UpdateNwkStatus(devStates_t state)
- {
- epList_t *pItem = epList;
- while (pItem != NULL)
- {
- if (pItem->epDesc->endPoint != ZDO_EP)
- {
- zdoSendStateChangeMsg(state, *(pItem->epDesc->task_id));
- }
- pItem = pItem->nextDesc;
- }
- #if defined MT_ZDO_CB_FUNC
- zdoSendStateChangeMsg(state, MT_TaskID);
- #endif
- ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
- (void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.
- }
- #if defined ( REFLECTOR )
- /*********************************************************************
- * @fn ZDO_RemoveEndDeviceBind
- *
- * @brief Remove the end device bind
- *
- * @param none
- *
- * @return none
- */
- static void ZDO_RemoveEndDeviceBind( void )
- {
- if ( ZDO_EDBind != NULL )
- {
- // Free the RAM
- if ( ZDO_EDBind->inClusters != NULL )
- {
- osal_mem_free( ZDO_EDBind->inClusters );
- }
- if ( ZDO_EDBind->outClusters != NULL )
- {
- osal_mem_free( ZDO_EDBind->outClusters );
- }
- osal_mem_free( ZDO_EDBind );
- ZDO_EDBind = NULL;
- }
- }
- #endif // REFLECTOR
- #if defined ( REFLECTOR )
- /*********************************************************************
- * @fn ZDO_RemoveEndDeviceBind
- *
- * @brief Remove the end device bind
- *
- * @param none
- *
- * @return none
- */
- static void ZDO_SendEDBindRsp( byte TransSeq, zAddrType_t *dstAddr, byte Status, byte secUse )
- {
- ZDP_EndDeviceBindRsp( TransSeq, dstAddr, Status, secUse );
- #if defined( LCD_SUPPORTED )
- //HalLcdWriteString( "End Device Bind", HAL_LCD_LINE_1 );
- if ( Status == ZDP_SUCCESS )
- {
- // HalLcdWriteString( "Success Sent", HAL_LCD_LINE_2 );
- }
- else
- {
- // HalLcdWriteString( "Timeout", HAL_LCD_LINE_2 );
- }
- #endif
- }
- #endif // REFLECTOR
- /*********************************************************************
- * @fn ZDO_CompareClusterLists
- *
- * @brief Compare one list to another list
- *
- * @param numList1 - number of items in list 1
- * @param list1 - first list of cluster IDs
- * @param numList2 - number of items in list 2
- * @param list2 - second list of cluster IDs
- * @param pMatches - buffer to put matches
- *
- * @return number of matches
- */
- static byte ZDO_CompareClusterLists( byte numList1, uint16 *list1,
- byte numList2, uint16 *list2, uint16 *pMatches )
- {
- byte x, y;
- uint16 z;
- byte numMatches = 0;
- // Check the first in against the seconds out
- for ( x = 0; x < numList1; x++ )
- {
- for ( y = 0; y < numList2; y++ )
- {
- z = list2[y];
- if ( list1[x] == z )
- {
- pMatches[numMatches++] = z;
- }
- }
- }
- return ( numMatches );
- }
- /*********************************************************************
- * Utility functions
- */
- /*********************************************************************
- * @fn ZDO_CompareByteLists
- *
- * @brief Compares two lists for matches.
- *
- * @param ACnt - number of entries in list A
- * @param AList - List A
- * @param BCnt - number of entries in list B
- * @param BList - List B
- *
- * @return true if a match is found
- */
- byte ZDO_AnyClusterMatches( byte ACnt, uint16 *AList, byte BCnt, uint16 *BList )
- {
- byte x, y;
- for ( x = 0; x < ACnt; x++ )
- {
- for ( y = 0; y < BCnt; y++ )
- {
- if ( AList[x] == BList[y] )
- {
- return true;
- }
- }
- }
- return false;
- }
- /*********************************************************************
- * Callback functions from ZDProfile
- */
- /*********************************************************************
- * @fn ZDO_ProcessNodeDescReq
- *
- * @brief This function processes and responds to the
- * Node_Desc_req message.
- *
- * @param inMsg - incoming message
- *
- * @return none
- */
- void ZDO_ProcessNodeDescReq( zdoIncomingMsg_t *inMsg )
- {
- uint16 aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
- NodeDescriptorFormat_t *desc = NULL;
- if ( aoi == ZDAppNwkAddr.addr.shortAddr )
- {
- desc = &ZDO_Config_Node_Descriptor;
- }
- if ( desc != NULL )
- {
- ZDP_NodeDescMsg( inMsg, aoi, desc );
- }
- else
- {
- ZDP_GenericRsp( inMsg->TransSeq, &(inMsg->srcAddr),
- ZDP_INVALID_REQTYPE, aoi, Node_Desc_rsp, inMsg->SecurityUse );
- }
- }
- /*********************************************************************
- * @fn ZDO_ProcessPowerDescReq
- *
- * @brief This function processes and responds to the
- * Node_Power_req message.
- *
- * @param inMsg - incoming request
- *
- * @return none
- */
- void ZDO_ProcessPowerDescReq( zdoIncomingMsg_t *inMsg )
- {
- uint16 aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
- NodePowerDescriptorFormat_t *desc = NULL;
- if ( aoi == ZDAppNwkAddr.addr.shortAddr )
- {
- desc = &ZDO_Config_Power_Descriptor;
- }
- if ( desc != NULL )
- {
- ZDP_PowerDescMsg( inMsg, aoi, desc );
- }
- else
- {
- ZDP_GenericRsp( inMsg->TransSeq, &(inMsg->srcAddr),
- ZDP_INVALID_REQTYPE, aoi, Power_Desc_rsp, inMsg->SecurityUse );
- }
- }
- /*********************************************************************
- * @fn ZDO_ProcessSimpleDescReq
- *
- * @brief This function processes and responds to the
- * Simple_Desc_req message.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessSimpleDescReq( zdoIncomingMsg_t *inMsg )
- {
- SimpleDescriptionFormat_t *sDesc = NULL;
- uint16 aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
- byte endPoint = inMsg->asdu[2];
- byte free = false;
- byte stat = ZDP_SUCCESS;
- if ( (endPoint == ZDO_EP) || (endPoint > MAX_ENDPOINTS) )
- {
- stat = ZDP_INVALID_EP;
- }
- else if ( aoi == ZDAppNwkAddr.addr.shortAddr )
- {
- free = afFindSimpleDesc( &sDesc, endPoint );
- if ( sDesc == NULL )
- {
- stat = ZDP_NOT_ACTIVE;
- }
- }
- else
- {
- if ( ZSTACK_ROUTER_BUILD )
- {
- stat = ZDP_DEVICE_NOT_FOUND;
- }
- else if ( ZSTACK_END_DEVICE_BUILD )
- {
- stat = ZDP_INVALID_REQTYPE;
- }
- }
- ZDP_SimpleDescMsg( inMsg, stat, sDesc );
- if ( free && sDesc )
- {
- osal_mem_free( sDesc );
- }
- }
- /*********************************************************************
- * @fn ZDO_ProcessActiveEPReq
- *
- * @brief This function processes and responds to the
- * Active_EP_req message.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessActiveEPReq( zdoIncomingMsg_t *inMsg )
- {
- byte cnt = 0;
- uint16 aoi;
- byte stat = ZDP_SUCCESS;
- aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
- if ( aoi == NLME_GetShortAddr() )
- {
- cnt = afNumEndPoints() - 1; // -1 for ZDO endpoint descriptor
- afEndPoints( (uint8 *)ZDOBuildBuf, true );
- }
- else
- {
- stat = ZDP_INVALID_REQTYPE;
- }
- ZDP_ActiveEPRsp( inMsg->TransSeq, &(inMsg->srcAddr), stat,
- aoi, cnt, (uint8 *)ZDOBuildBuf, inMsg->SecurityUse );
- }
- /*********************************************************************
- * @fn ZDO_ConvertOTAClusters
- *
- * @brief This function will convert the over-the-air cluster list
- * format to an internal format.
- *
- * @param inMsg - incoming message (request)
- *
- * @return pointer to incremented inBuf
- */
- uint8 *ZDO_ConvertOTAClusters( uint8 cnt, uint8 *inBuf, uint16 *outList )
- {
- uint8 x;
- for ( x = 0; x < cnt; x++ )
- {
- // convert ota format to internal
- outList[x] = BUILD_UINT16( inBuf[0], inBuf[1] );
- inBuf += sizeof( uint16 );
- }
- return ( inBuf );
- }
- /*********************************************************************
- * @fn ZDO_ProcessMatchDescReq
- *
- * @brief This function processes and responds to the
- * Match_Desc_req message.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessMatchDescReq( zdoIncomingMsg_t *inMsg )
- {
- uint8 epCnt = 0;
- uint8 numInClusters;
- uint16 *inClusters = NULL;
- uint8 numOutClusters;
- uint16 *outClusters = NULL;
- epList_t *epDesc;
- SimpleDescriptionFormat_t *sDesc = NULL;
- uint8 allocated;
- uint8 *msg;
- uint16 aoi;
- uint16 profileID;
- // Parse the incoming message
- msg = inMsg->asdu;
- aoi = BUILD_UINT16( msg[0], msg[1] );
- profileID = BUILD_UINT16( msg[2], msg[3] );
- msg += 4;
- if ( ADDR_BCAST_NOT_ME == NLME_IsAddressBroadcast(aoi) )
- {
- ZDP_MatchDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZDP_INVALID_REQTYPE,
- ZDAppNwkAddr.addr.shortAddr, 0, NULL, inMsg->SecurityUse );
- return;
- }
- else if ( (ADDR_NOT_BCAST == NLME_IsAddressBroadcast(aoi)) && (aoi != ZDAppNwkAddr.addr.shortAddr) )
- {
- ZDP_MatchDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZDP_INVALID_REQTYPE,
- ZDAppNwkAddr.addr.shortAddr, 0, NULL, inMsg->SecurityUse );
- return;
- }
- if ((numInClusters = *msg++) &&
- (inClusters = (uint16*)osal_mem_alloc( numInClusters * sizeof( uint16 ) )))
- {
- msg = ZDO_ConvertOTAClusters( numInClusters, msg, inClusters );
- }
- else
- {
- numInClusters = 0;
- }
- if ((numOutClusters = *msg++) &&
- (outClusters = (uint16 *)osal_mem_alloc( numOutClusters * sizeof( uint16 ) )))
- {
- msg = ZDO_ConvertOTAClusters( numOutClusters, msg, outClusters );
- }
- else
- {
- numOutClusters = 0;
- }
- // First count the number of endpoints that match.
- epDesc = epList;
- while ( epDesc )
- {
- // Don't search endpoint 0 and check if response is allowed
- if ( epDesc->epDesc->endPoint != ZDO_EP && (epDesc->flags&eEP_AllowMatch) )
- {
- if ( epDesc->pfnDescCB )
- {
- sDesc = (SimpleDescriptionFormat_t *)epDesc->pfnDescCB( AF_DESCRIPTOR_SIMPLE, epDesc->epDesc->endPoint );
- allocated = TRUE;
- }
- else
- {
- sDesc = epDesc->epDesc->simpleDesc;
- allocated = FALSE;
- }
- if ( sDesc && sDesc->AppProfId == profileID )
- {
- uint8 *uint8Buf = (uint8 *)ZDOBuildBuf;
- // Are there matching input clusters?
- if ((ZDO_AnyClusterMatches( numInClusters, inClusters,
- sDesc->AppNumInClusters, sDesc->pAppInClusterList )) ||
- // Are there matching output clusters?
- (ZDO_AnyClusterMatches( numOutClusters, outClusters,
- sDesc->AppNumOutClusters, sDesc->pAppOutClusterList )))
- {
- // Notify the endpoint of the match.
- uint8 bufLen = sizeof( ZDO_MatchDescRspSent_t ) + (numOutClusters + numInClusters) * sizeof(uint16);
- ZDO_MatchDescRspSent_t *pRspSent = (ZDO_MatchDescRspSent_t *) osal_msg_allocate( bufLen );
- if (pRspSent)
- {
- pRspSent->hdr.event = ZDO_MATCH_DESC_RSP_SENT;
- pRspSent->nwkAddr = inMsg->srcAddr.addr.shortAddr;
- pRspSent->numInClusters = numInClusters;
- pRspSent->numOutClusters = numOutClusters;
- if (numInClusters)
- {
- pRspSent->pInClusters = (uint16*) (pRspSent + 1);
- osal_memcpy(pRspSent->pInClusters, inClusters, numInClusters * sizeof(uint16));
- }
- else
- {
- pRspSent->pInClusters = NULL;
- }
- if (numOutClusters)
- {
- pRspSent->pOutClusters = (uint16*)(pRspSent + 1) + numInClusters;
- osal_memcpy(pRspSent->pOutClusters, outClusters, numOutClusters * sizeof(uint16));
- }
- else
- {
- pRspSent->pOutClusters = NULL;
- }
- osal_msg_send( *epDesc->epDesc->task_id, (uint8 *)pRspSent );
- }
- uint8Buf[epCnt++] = sDesc->EndPoint;
- }
- }
- if ( allocated )
- {
- osal_mem_free( sDesc );
- }
- }
- epDesc = epDesc->nextDesc;
- }
- if ( epCnt )
- {
- // Send the message if at least one match found.
- if ( ZSuccess == ZDP_MatchDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZDP_SUCCESS,
- ZDAppNwkAddr.addr.shortAddr, epCnt, (uint8 *)ZDOBuildBuf, inMsg->SecurityUse ) )
- {
- #if defined( LCD_SUPPORTED )
- //HalLcdWriteScreen( "Match Desc Req", "Rsp Sent" );
- #endif
- }
- }
- else
- {
- // No match found
- if (ADDR_NOT_BCAST == NLME_IsAddressBroadcast(aoi))
- {
- // send response message with match length = 0
- ZDP_MatchDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZDP_SUCCESS,
- ZDAppNwkAddr.addr.shortAddr, 0, (uint8 *)ZDOBuildBuf, inMsg->SecurityUse );
- #if defined( LCD_SUPPORTED )
- // HalLcdWriteScreen( "Match Desc Req", "Rsp Non Matched" );
- #endif
- }
- else
- {
- // no response mesage for broadcast message
- #if defined( LCD_SUPPORTED )
- // HalLcdWriteScreen( "Match Desc Req", "Non Matched" );
- #endif
- }
- }
- if ( inClusters != NULL )
- {
- osal_mem_free( inClusters );
- }
- if ( outClusters != NULL )
- {
- osal_mem_free( outClusters );
- }
- }
- /*********************************************************************
- * @fn ZDO_ProcessBindUnbindReq()
- *
- * @brief Called to process a Bind or Unbind Request message.
- *
- * @param inMsg - incoming message (request)
- * @param pReq - place to put parsed information
- *
- * @return none
- */
- void ZDO_ProcessBindUnbindReq( zdoIncomingMsg_t *inMsg, ZDO_BindUnbindReq_t *pReq )
- {
- zAddrType_t SourceAddr; // Binding Source addres
- byte bindStat;
- SourceAddr.addrMode = Addr64Bit;
- osal_cpyExtAddr( SourceAddr.addr.extAddr, pReq->srcAddress );
- // If the local device is not the primary binding cache
- // check the src address of the bind request.
- // If it is not the local device's extended address
- // discard the request.
- if ( !osal_ExtAddrEqual( SourceAddr.addr.extAddr, NLME_GetExtAddr()) ||
- (pReq->dstAddress.addrMode != Addr64Bit &&
- pReq->dstAddress.addrMode != AddrGroup) )
- {
- bindStat = ZDP_NOT_SUPPORTED;
- }
- else
- {
- // Check source & destination endpoints
- if ( (pReq->srcEndpoint == 0 || pReq->srcEndpoint > MAX_ENDPOINTS)
- || (( pReq->dstAddress.addrMode == Addr64Bit ) &&
- (pReq->dstEndpoint == 0 || pReq->dstEndpoint > MAX_ENDPOINTS)) )
- {
- bindStat = ZDP_INVALID_EP;
- }
- else
- {
- if ( inMsg->clusterID == Bind_req )
- {
- // Assume the table is full
- bindStat = ZDP_TABLE_FULL;
- #if defined( APP_TP ) || defined( APP_TP2 )
- // For ZigBee Conformance Testing
- if ( bindNumOfEntries() < gNWK_MAX_BINDING_ENTRIES )
- #endif
- {
- if ( APSME_BindRequest( pReq->srcEndpoint, pReq->clusterID,
- &(pReq->dstAddress), pReq->dstEndpoint ) == ZSuccess )
- {
- uint16 nwkAddr;
- // valid entry
- bindStat = ZDP_SUCCESS;
- // Notify to save info into NV
- ZDApp_NVUpdate();
- // Check for the destination address
- if ( pReq->dstAddress.addrMode == Addr64Bit )
- {
- if ( APSME_LookupNwkAddr( pReq->dstAddress.addr.extAddr, &nwkAddr ) == FALSE )
- {
- ZDP_NwkAddrReq( pReq->dstAddress.addr.extAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
- }
- }
- }
- }
- }
- else // Unbind_req
- {
- if ( APSME_UnBindRequest( pReq->srcEndpoint, pReq->clusterID,
- &(pReq->dstAddress), pReq->dstEndpoint ) == ZSuccess )
- {
- bindStat = ZDP_SUCCESS;
- // Notify to save info into NV
- ZDApp_NVUpdate();
- }
- else
- bindStat = ZDP_NO_ENTRY;
- }
- }
- }
- // Send back a response message
- ZDP_SendData( &(inMsg->TransSeq), &(inMsg->srcAddr),
- (inMsg->clusterID | ZDO_RESPONSE_BIT), 1, &bindStat,
- inMsg->SecurityUse );
- }
- /*********************************************************************
- * @fn ZDO_UpdateAddrManager
- *
- * @brief Update the Address Manager.
- *
- * @param nwkAddr - network address
- * @param extAddr - extended address
- *
- * @return none
- */
- void ZDO_UpdateAddrManager( uint16 nwkAddr, uint8 *extAddr )
- {
- AddrMgrEntry_t addrEntry;
- // Update the address manager
- addrEntry.user = ADDRMGR_USER_DEFAULT;
- addrEntry.nwkAddr = nwkAddr;
- AddrMgrExtAddrSet( addrEntry.extAddr, extAddr );
- AddrMgrEntryUpdate( &addrEntry );
- }
- /*********************************************************************
- * @fn ZDO_ProcessServerDiscReq
- *
- * @brief Process the Server_Discovery_req message.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessServerDiscReq( zdoIncomingMsg_t *inMsg )
- {
- uint16 serverMask = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
- uint16 matchMask = serverMask & ZDO_Config_Node_Descriptor.ServerMask;
- if ( matchMask )
- {
- ZDP_ServerDiscRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZSUCCESS,
- ZDAppNwkAddr.addr.shortAddr, matchMask, inMsg->SecurityUse );
- }
- }
- /*********************************************************************
- * Call Back Functions from APS - API
- */
- /*********************************************************************
- * @fn ZDO_EndDeviceTimeoutCB
- *
- * @brief This function handles the binding timer for the End
- * Device Bind command.
- *
- * @param none
- *
- * @return none
- */
- void ZDO_EndDeviceTimeoutCB( void )
- {
- #if defined ( REFLECTOR )
- byte stat;
- if ( ZDO_EDBind )
- {
- stat = ZDO_EDBind->status;
- // Send the response message to the first sent
- ZDO_SendEDBindRsp( ZDO_EDBind->SrcTransSeq, &(ZDO_EDBind->SrcAddr),
- stat, ZDO_EDBind->SecurityUse );
- ZDO_RemoveEndDeviceBind();
- }
- #endif // REFLECTOR
- }
- /*********************************************************************
- * Optional Management Messages
- */
- /*********************************************************************
- * @fn ZDO_ProcessMgmtLqiReq
- *
- * @brief This function handles parsing the incoming Management
- * LQI request and generate the response.
- *
- * Note: This function will limit the number of items returned
- * to ZDO_MAX_LQI_ITEMS items.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessMgmtLqiReq( zdoIncomingMsg_t *inMsg )
- {
- byte x;
- byte index;
- byte numItems;
- byte maxItems;
- ZDP_MgmtLqiItem_t* table = NULL;
- ZDP_MgmtLqiItem_t* item;
- neighborEntry_t entry;
- byte aItems;
- associated_devices_t *aDevice;
- AddrMgrEntry_t nwkEntry;
- uint8 StartIndex = inMsg->asdu[0];
- // Get the number of neighbor items
- NLME_GetRequest( nwkNumNeighborTableEntries, 0, &maxItems );
- // Get the number of associated items
- aItems = (uint8)AssocCount( PARENT, CHILD_FFD_RX_IDLE );
- // Total number of items
- maxItems += aItems;
- // Start with the supplied index
- if ( maxItems > StartIndex )
- {
- numItems = maxItems - StartIndex;
- // limit the size of the list
- if ( numItems > ZDO_MAX_LQI_ITEMS )
- numItems = ZDO_MAX_LQI_ITEMS;
- // Allocate the memory to build the table
- table = (ZDP_MgmtLqiItem_t*)osal_mem_alloc( (short)
- ( numItems * sizeof( ZDP_MgmtLqiItem_t ) ) );
- if ( table != NULL )
- {
- x = 0;
- item = table;
- index = StartIndex;
- // Loop through associated items and build list
- for ( ; x < numItems; x++ )
- {
- if ( index < aItems )
- {
- // get next associated device
- aDevice = AssocFindDevice( index++ );
- // set basic fields
- item->panID = _NIB.nwkPanId;
- osal_cpyExtAddr( item->extPanID, _NIB.extendedPANID );
- item->nwkAddr = aDevice->shortAddr;
- item->permit = ZDP_MGMT_BOOL_UNKNOWN;
- item->depth = 0xFF;
- item->lqi = aDevice->linkInfo.rxLqi;
- // set extented address
- nwkEntry.user = ADDRMGR_USER_DEFAULT;
- nwkEntry.nwkAddr = aDevice->shortAddr;
- if ( AddrMgrEntryLookupNwk( &nwkEntry ) == TRUE )
- {
- osal_cpyExtAddr( item->extAddr, nwkEntry.extAddr );
- }
- else
- {
- osal_memset( item->extAddr, 0xFF, Z_EXTADDR_LEN );
- }
- // use association info to set other fields
- if ( aDevice->nodeRelation == PARENT )
- {
- if ( aDevice->shortAddr == 0 )
- {
- item->devType = ZDP_MGMT_DT_COORD;
- item->depth = 0;
- }
- else
- {
- item->devType = ZDP_MGMT_DT_ROUTER;
- item->depth = _NIB.nodeDepth - 1;
- }
- item->rxOnIdle = ZDP_MGMT_BOOL_UNKNOWN;
- item->relation = ZDP_MGMT_REL_PARENT;
- }
- else
- {
- // If not parent, then it's a child
- item->depth = _NIB.nodeDepth + 1;
- if ( aDevice->nodeRelation < CHILD_FFD )
- {
- item->devType = ZDP_MGMT_DT_ENDDEV;
- if ( aDevice->nodeRelation == CHILD_RFD )
- {
- item->rxOnIdle = FALSE;
- }
- else
- {
- item->rxOnIdle = TRUE;
- }
- }
- else
- {
- item->devType = ZDP_MGMT_DT_ROUTER;
- if ( aDevice->nodeRelation == CHILD_FFD )
- {
- item->rxOnIdle = FALSE;
- }
- else
- {
- item->rxOnIdle = TRUE;
- }
- }
- item->relation = ZDP_MGMT_REL_CHILD;
- }
- item++;
- }
- else
- {
- if ( StartIndex <= aItems )
- // Start with 1st neighbor
- index = 0;
- else
- // Start with >1st neighbor
- index = StartIndex - aItems;
- break;
- }
- }
- // Loop through neighbor items and finish list
- for ( ; x < numItems; x++ )
- {
- // Add next neighbor table item
- NLME_GetRequest( nwkNeighborTable, index++, &entry );
- // set ZDP_MgmtLqiItem_t fields
- item->panID = entry.panId;
- osal_cpyExtAddr( item->extPanID, _NIB.extendedPANID );
- osal_memset( item->extAddr, 0xFF, Z_EXTADDR_LEN );
- item->nwkAddr = entry.neighborAddress;
- item->rxOnIdle = ZDP_MGMT_BOOL_UNKNOWN;
- item->relation = ZDP_MGMT_REL_UNKNOWN;
- item->permit = ZDP_MGMT_BOOL_UNKNOWN;
- item->depth = 0xFF;
- item->lqi = entry.linkInfo.rxLqi;
- if ( item->nwkAddr == 0 )
- {
- item->devType = ZDP_MGMT_DT_COORD;
- }
- else
- {
- item->devType = ZDP_MGMT_DT_ROUTER;
- }
- item++;
- }
- }
- }
- else
- {
- numItems = 0;
- }
- // Send response
- ZDP_MgmtLqiRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZSuccess, maxItems,
- StartIndex, numItems, table, false );
- if ( table )
- {
- osal_mem_free( table );
- }
- }
- /*********************************************************************
- * @fn ZDO_ProcessMgmtNwkDiscReq
- *
- * @brief This function handles parsing the incoming Management
- * Network Discover request and starts the request.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessMgmtNwkDiscReq( zdoIncomingMsg_t *inMsg )
- {
- NLME_ScanFields_t scan;
- uint8 index;
- uint8 *msg;
- msg = inMsg->asdu;
- scan.channels = osal_build_uint32( msg, 4 );
- msg += 4;
- scan.duration = *msg++;
- index = *msg;
- scan.scanType = ZMAC_ACTIVE_SCAN;
- scan.scanApp = NLME_DISC_SCAN;
- // Save off the information to be used for the response
- zdappMgmtNwkDiscReqInProgress = true;
- zdappMgmtNwkDiscRspAddr.addrMode = Addr16Bit;
- zdappMgmtNwkDiscRspAddr.addr.shortAddr = inMsg->srcAddr.addr.shortAddr;
- zdappMgmtNwkDiscStartIndex = index;
- zdappMgmtNwkDiscRspTransSeq = inMsg->TransSeq;
- if ( NLME_NwkDiscReq2( &scan ) != ZSuccess )
- {
- NLME_NwkDiscTerm();
- // zdappMgmtNwkDiscReqInProgress will be reset in the confirm callback
- }
- }
- #if defined ( ZDO_MGMT_NWKDISC_RESPONSE )
- /*********************************************************************
- * @fn ZDO_FinishProcessingMgmtNwkDiscReq
- *
- * @brief This function finishes the processing of the Management
- * Network Discover Request and generates the response.
- *
- * Note: This function will limit the number of items returned
- * to ZDO_MAX_NWKDISC_ITEMS items.
- *
- * @param ResultCountSrcAddr - source of the request
- * @param msg - pointer to incoming message
- * @param SecurityUse -
- *
- * @return none
- */
- void ZDO_FinishProcessingMgmtNwkDiscReq( void )
- {
- byte count, i, ResultCount = 0;
- networkDesc_t *newDesc = NULL, *pList, *NetworkList;
- NetworkList = nwk_getNwkDescList();
- // Count the number of nwk descriptors in the list
- pList = nwk_getNwkDescList();
- while (pList)
- {
- ResultCount++;
- pList = pList->nextDesc;
- }
- if ( ZSTACK_ROUTER_BUILD )
- {
- // Look for my PanID.
- pList = nwk_getNwkDescList();
- while ( pList )
- {
- if ( pList->panId == _NIB.nwkPanId )
- {
- break;
- }
- if ( !pList->nextDesc )
- {
- break;
- }
- pList = pList->nextDesc;
- }
- // If my Pan not present (query to a star network ZC or an isolated ZR?),
- // prepend it.
- if ( !pList || (pList->panId != _NIB.nwkPanId) )
- {
- newDesc = (networkDesc_t *)osal_mem_alloc( sizeof( networkDesc_t ) );
- if ( newDesc )
- {
- byte pJoin;
- newDesc->panId = _NIB.nwkPanId;
- newDesc->logicalChannel = _NIB.nwkLogicalChannel;
- newDesc->version = NLME_GetProtocolVersion();
- newDesc->stackProfile = zgStackProfile;
- //Extended PanID
- osal_cpyExtAddr( newDesc->extendedPANID, _NIB.extendedPANID);
- ZMacGetReq( ZMacAssociationPermit, &pJoin );
- newDesc->chosenRouter = ((pJoin) ? ZDAppNwkAddr.addr.shortAddr :
- INVALID_NODE_ADDR);
- newDesc->nextDesc = NetworkList;
- NetworkList = newDesc;
- ResultCount++;
- }
- }
- }
- // Calc the count and apply a max count.
- if ( zdappMgmtNwkDiscStartIndex > ResultCount )
- {
- count = 0;
- }
- else
- {
- count = ResultCount - zdappMgmtNwkDiscStartIndex;
- if ( count > ZDO_MAX_NWKDISC_ITEMS )
- {
- count = ZDO_MAX_NWKDISC_ITEMS;
- }
- // Move the list pointer up to the start index.
- for ( i = 0; i < zdappMgmtNwkDiscStartIndex; i++ )
- {
- NetworkList = NetworkList->nextDesc;
- }
- }
- ZDP_MgmtNwkDiscRsp( zdappMgmtNwkDiscRspTransSeq,
- &zdappMgmtNwkDiscRspAddr, ZSuccess, ResultCount,
- zdappMgmtNwkDiscStartIndex,
- count,
- NetworkList,
- false );
- if ( ZSTACK_ROUTER_BUILD )
- {
- if ( newDesc != NULL )
- {
- osal_mem_free( newDesc );
- }
- }
- NLME_NwkDiscTerm();
- }
- #endif
- /*********************************************************************
- * @fn ZDO_ProcessMgmtRtgReq
- *
- * @brief This function finishes the processing of the Management
- * Routing Request and generates the response.
- *
- * Note: This function will limit the number of items returned
- * to ZDO_MAX_RTG_ITEMS items.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessMgmtRtgReq( zdoIncomingMsg_t *inMsg )
- {
- byte x;
- byte maxNumItems;
- byte numItems = 0;
- uint8 *pBuf = NULL;
- rtgItem_t *pList;
- uint8 StartIndex = inMsg->asdu[0];
- // Get the number of table items
- NLME_GetRequest( nwkNumRoutingTableEntries, 0, &maxNumItems );
- if ( maxNumItems > StartIndex )
- {
- numItems = maxNumItems - StartIndex; // Start at the passed in index
- // limit the size of the list
- if ( numItems > ZDO_MAX_RTG_ITEMS )
- {
- numItems = ZDO_MAX_RTG_ITEMS;
- }
- // Allocate the memory to build the table
- pBuf = osal_mem_alloc( (short)(sizeof( rtgItem_t ) * numItems) );
- if ( pBuf != NULL )
- {
- // Convert buffer to list
- pList = (rtgItem_t *)pBuf;
- // Loop through items and build list
- for ( x = 0; x < numItems; x++ )
- {
- NLME_GetRequest( nwkRoutingTable, (uint16)(x + StartIndex), (void*)pList );
- // Remap the status to the RoutingTableList Record Format defined in the ZigBee spec
- switch( pList->status )
- {
- case RT_ACTIVE:
- pList->status = ZDO_MGMT_RTG_ENTRY_ACTIVE;
- break;
- case RT_DISC:
- pList->status = ZDO_MGMT_RTG_ENTRY_DISCOVERY_UNDERWAY;
- break;
- case RT_LINK_FAIL:
- pList->status = ZDO_MGMT_RTG_ENTRY_DISCOVERY_FAILED;
- break;
- case RT_INIT:
- case RT_REPAIR:
- default:
- pList->status = ZDO_MGMT_RTG_ENTRY_INACTIVE;
- break;
- }
- // Increment pointer to next record
- pList++;
- }
- }
- else
- {
- numItems = 0;
- }
- }
- // Send response
- ZDP_MgmtRtgRsp( inMsg->TransSeq, &(inMsg->srcAddr), ZSuccess, maxNumItems, StartIndex, numItems,
- (rtgItem_t *)pBuf, false );
- if ( pBuf != NULL )
- {
- osal_mem_free( pBuf );
- }
- }
- /*********************************************************************
- * @fn ZDO_ProcessMgmtBindReq
- *
- * @brief This function finishes the processing of the Management
- * Bind Request and generates the response.
- *
- * Note: This function will limit the number of items returned
- * to ZDO_MAX_BIND_ITEMS items.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessMgmtBindReq( zdoIncomingMsg_t *inMsg )
- {
- #if defined ( REFLECTOR )
- byte x;
- uint16 maxNumItems;
- uint16 numItems;
- uint8 *pBuf = NULL;
- apsBindingItem_t *pList;
- uint8 StartIndex = inMsg->asdu[0];
- uint8 status;
- // Get the number of table items
- APSME_GetRequest( apsNumBindingTableEntries, 0, (byte*)(&maxNumItems) );
- if ( maxNumItems > StartIndex )
- {
- numItems = maxNumItems - StartIndex; // Start at the passed in index
- }
- else
- {
- numItems = 0;
- }
- // limit the size of the list
- if ( numItems > ZDO_MAX_BIND_ITEMS )
- {
- numItems = ZDO_MAX_BIND_ITEMS;
- }
- // Allocate the memory to build the table
- if ( numItems && (pBuf = osal_mem_alloc( sizeof( apsBindingItem_t ) * numItems )) )
- {
- status = ZSuccess;
- // Convert buffer to list
- pList = (apsBindingItem_t *)pBuf;
- // Loop through items and build list
- for ( x = 0; x < numItems; x++ )
- {
- APSME_GetRequest( apsBindingTable, (x + StartIndex), (void*)pList );
- pList++;
- }
- }
- else
- {
- status = ZDP_NOT_PERMITTED;
- numItems = 0;
- }
- // Send response
- ZDP_MgmtBindRsp( inMsg->TransSeq, &(inMsg->srcAddr), status, (byte)maxNumItems, StartIndex,
- (byte)numItems, (apsBindingItem_t *)pBuf, false );
- if ( pBuf )
- {
- osal_mem_free( pBuf );
- }
- #else
- (void)inMsg;
- #endif
- }
- /*********************************************************************
- * @fn ZDO_ProcessMgmtDirectJoinReq
- *
- * @brief This function finishes the processing of the Management
- * Direct Join Request and generates the response.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessMgmtDirectJoinReq( zdoIncomingMsg_t *inMsg )
- {
- uint8 *deviceAddr;
- uint8 capInfo;
- uint8 stat;
- // Parse the message
- deviceAddr = inMsg->asdu;
- capInfo = inMsg->asdu[Z_EXTADDR_LEN];
- stat = (byte) NLME_DirectJoinRequest( deviceAddr, capInfo );
- ZDP_MgmtDirectJoinRsp( inMsg->TransSeq, &(inMsg->srcAddr), stat, false );
- }
- /*********************************************************************
- * @fn ZDO_ProcessMgmtLeaveReq
- *
- * @brief This function processes a Management Leave Request
- * and generates the response.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessMgmtLeaveReq( zdoIncomingMsg_t *inMsg )
- {
- NLME_LeaveReq_t req;
- ZStatus_t status;
- uint8 option;
- uint8 *msg = inMsg->asdu;
- if ( ( AddrMgrExtAddrValid( msg ) == FALSE ) ||
- ( osal_ExtAddrEqual( msg, NLME_GetExtAddr() ) == TRUE ) )
- {
- // Remove this device
- req.extAddr = NULL;
- }
- else
- {
- // Remove child device
- req.extAddr = msg;
- }
- option = msg[Z_EXTADDR_LEN];
- if ( option & ZDP_MGMT_LEAVE_REQ_RC )
- {
- req.removeChildren = TRUE;
- }
- if ( option & ZDP_MGMT_LEAVE_REQ_REJOIN )
- {
- req.rejoin = TRUE;
- }
- req.silent = FALSE;
- status = NLME_LeaveReq( &req );
- ZDP_MgmtLeaveRsp( inMsg->TransSeq, &(inMsg->srcAddr), status, FALSE );
- }
- /*********************************************************************
- * @fn ZDO_ProcessMgmtPermitJoinReq
- *
- * @brief This function processes a Management Permit Join Request
- * and generates the response.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessMgmtPermitJoinReq( zdoIncomingMsg_t *inMsg )
- {
- uint8 stat;
- uint8 duration;
- uint8 tcsig;
- duration = inMsg->asdu[ZDP_MGMT_PERMIT_JOIN_REQ_DURATION];
- tcsig = inMsg->asdu[ZDP_MGMT_PERMIT_JOIN_REQ_TC_SIG];
- // Set the network layer permit join duration
- stat = (byte) NLME_PermitJoiningRequest( duration );
- // Handle the Trust Center Significance
- if ( ZG_SECURE_ENABLED && ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
- {
- if ( tcsig == TRUE )
- {
- ZDSecMgrPermitJoining( duration );
- }
- }
- // Send a response if unicast
- if ( !inMsg->wasBroadcast )
- {
- ZDP_MgmtPermitJoinRsp( inMsg->TransSeq, &(inMsg->srcAddr), stat, false );
- }
- }
- /*
- * This function stub allows the next higher layer to be notified of
- * a permit joining timeout.
- */
- /*********************************************************************
- * @fn ZDO_ProcessMgmtPermitJoinTimeout
- *
- * @brief This function stub allows the next higher layer to be
- * notified of a permit joining timeout. Currently, this
- * directly bypasses the APS layer.
- *
- * @param none
- *
- * @return none
- */
- void ZDO_ProcessMgmtPermitJoinTimeout( void )
- {
- #if defined( ZDO_MGMT_PERMIT_JOIN_RESPONSE )
- // Currently, only the ZDSecMgr needs to be notified
- if ( ZG_SECURE_ENABLED && ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
- {
- ZDSecMgrPermitJoiningTimeout();
- }
- #endif
- }
- /*********************************************************************
- * @fn ZDO_ProcessUserDescReq
- *
- * @brief This function finishes the processing of the User
- * Descriptor Request and generates the response.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessUserDescReq( zdoIncomingMsg_t *inMsg )
- {
- uint16 aoi = BUILD_UINT16( inMsg->asdu[0], inMsg->asdu[1] );
- UserDescriptorFormat_t userDesc;
- if ( (aoi == ZDAppNwkAddr.addr.shortAddr) && (ZSUCCESS == osal_nv_read(
- ZCD_NV_USERDESC, 0, sizeof(UserDescriptorFormat_t), &userDesc )) )
- {
- ZDP_UserDescRsp( inMsg->TransSeq, &(inMsg->srcAddr), aoi, &userDesc, false );
- }
- else
- {
- ZDP_GenericRsp(inMsg->TransSeq, &(inMsg->srcAddr),
- ZDP_NOT_SUPPORTED, aoi, User_Desc_rsp, inMsg->SecurityUse );
- }
- }
- /*********************************************************************
- * @fn ZDO_ProcessUserDescSet
- *
- * @brief This function finishes the processing of the User
- * Descriptor Set and generates the response.
- *
- * @param inMsg - incoming message (request)
- *
- * @return none
- */
- void ZDO_ProcessUserDescSet( zdoIncomingMsg_t *inMsg )
- {
- uint8 *msg;
- uint16 aoi;
- UserDescriptorFormat_t userDesc;
- uint8 outMsg[3];
- uint8 status;
- msg = inMsg->asdu;
- aoi = BUILD_UINT16( msg[0], msg[1] );
- if ( aoi == ZDAppNwkAddr.addr.shortAddr )
- {
- userDesc.len = (msg[2] < AF_MAX_USER_DESCRIPTOR_LEN) ? msg[2] : AF_MAX_USER_DESCRIPTOR_LEN;
- msg ++; // increment one for the length field
- osal_memcpy( userDesc.desc, &msg[2], userDesc.len );
- osal_nv_write( ZCD_NV_USERDESC, 0, sizeof(UserDescriptorFormat_t), &userDesc );
- if ( userDesc.len != 0 )
- {
- ZDO_Config_Node_Descriptor.UserDescAvail = TRUE;
- }
- else
- {
- ZDO_Config_Node_Descriptor.UserDescAvail = FALSE;
- }
- status = ZDP_SUCCESS;
- }
- else
- {
- status = ZDP_NOT_SUPPORTED;
- }
- outMsg[0] = status;
- outMsg[1] = LO_UINT16( aoi );
- outMsg[2] = LO_UINT16( aoi );
- ZDP_SendData( &(inMsg->TransSeq), &(inMsg->srcAddr), User_Desc_conf, 3, outMsg,
- inMsg->SecurityUse );
- }
- /*********************************************************************
- * @fn ZDO_ProcessDeviceAnnce
- *
- * @brief This function processes a device annouce message.
- *
- * @param inMsg - incoming message
- *
- * @return none
- */
- void ZDO_ProcessDeviceAnnce( zdoIncomingMsg_t *inMsg )
- {
- ZDO_DeviceAnnce_t Annce;
- AddrMgrEntry_t addrEntry;
- uint8 parentExt[Z_EXTADDR_LEN];
- // Parse incoming message
- ZDO_ParseDeviceAnnce( inMsg, &Annce );
- if ( ZSTACK_END_DEVICE_BUILD )
- {
- // Make sure the message didn't come from myself - end device only
- if ( osal_ExtAddrEqual( NLME_GetExtAddr(), Annce.extAddr ) && Annce.nwkAddr == NLME_GetShortAddr() )
- {
- return;
- }
- }
- #if defined ( ZIGBEE_STOCHASTIC_ADDRESSING )
- // Clean up the neighbor table
- nwkNeighborRemoveAllStranded();
- // If address conflict is detected, no need to update the address manager
- if ( NLME_CheckNewAddrSet( Annce.nwkAddr, Annce.extAddr )== ZFailure )
- {
- return;
- }
- #endif
- #if defined ( ZIGBEE_STOCHASTIC_ADDRESSING )
- // Check for parent's address
- NLME_GetCoordExtAddr( parentExt );
- if ( osal_ExtAddrEqual( parentExt, Annce.extAddr ) )
- {
- if ( Annce.nwkAddr != NLME_GetCoordShortAddr() )
- {
- // Set the Parent's MAC's new short address
- _NIB.nwkCoordAddress = Annce.nwkAddr;
- ZMacSetReq( ZMacCoordShortAddress, (byte*)&(_NIB.nwkCoordAddress) );
- }
- }
- if ( ZSTACK_ROUTER_BUILD )
- {
- // If the device annce comes from a end device child that has moved
- // to another parent, remove it from associated device list
- // If the dev annce is coming from other device's children,
- // (The dev annce from its own children shall be unicast to itself,
- // So check the mac destination address)
- // Remove it from the associated device list. If it is not
- // a child, no action will be taken in AssocRemove() anyway.
- if ( inMsg->macDestAddr != NLME_GetShortAddr() )
- {
- associated_devices_t *dev_ptr;
- // If it's an end device child
- dev_ptr = AssocGetWithExt( Annce.extAddr );
- if ( dev_ptr )
- {
- if ( dev_ptr->nodeRelation == CHILD_RFD ||
- dev_ptr->nodeRelation == CHILD_RFD_RX_IDLE )
- {
- AssocRemove( Annce.extAddr );
- }
- }
- }
- if ( Annce.nwkAddr != NLME_GetShortAddr() )
- {
- // If an associated device is found with matched extended Address,
- // update its short address
- if ( AssocChangeNwkAddr( Annce.nwkAddr, Annce.extAddr ) )
- {
- // Set event to save NV
- ZDApp_NVUpdate();
- }
- }
- }
- // Update the neighbor table
- nwkNeighborUpdateNwkAddr( Annce.nwkAddr, Annce.extAddr );
- // Assume that the device has moved, remove existing routing entries
- RTG_RemoveRtgEntry( Annce.nwkAddr, 0 );
- #endif // ZIGBEE_STOCHASTIC_ADDRESSING
- // Fill in the extended address in address manager if we don't have it already.
- addrEntry.user = ADDRMGR_USER_DEFAULT;
- addrEntry.nwkAddr = Annce.nwkAddr;
- if ( AddrMgrEntryLookupNwk( &addrEntry ) )
- {
- osal_memset( parentExt, 0, Z_EXTADDR_LEN );
- if ( osal_ExtAddrEqual( parentExt, addrEntry.extAddr ) )
- {
- AddrMgrExtAddrSet( addrEntry.extAddr, Annce.extAddr );
- AddrMgrEntryUpdate( &addrEntry );
- }
- }
- // Update the short address in address manager if it's been changed
- AddrMgrExtAddrSet( addrEntry.extAddr, Annce.extAddr );
- if ( AddrMgrEntryLookupExt( &addrEntry ) )
- {
- if ( addrEntry.nwkAddr != Annce.nwkAddr )
- {
- addrEntry.nwkAddr = Annce.nwkAddr;
- AddrMgrEntryUpdate( &addrEntry );
- }
- }
- }
- /*********************************************************************
- * @fn ZDO_BuildSimpleDescBuf
- *
- * @brief Build a byte sequence representation of a Simple Descriptor.
- *
- * @param buf - pointer to a byte array big enough for data.
- * @param desc - SimpleDescriptionFormat_t *
- *
- * @return none
- */
- void ZDO_BuildSimpleDescBuf( uint8 *buf, SimpleDescriptionFormat_t *desc )
- {
- byte cnt;
- uint16 *ptr;
- *buf++ = desc->EndPoint;
- *buf++ = HI_UINT16( desc->AppProfId );
- *buf++ = LO_UINT16( desc->AppProfId );
- *buf++ = HI_UINT16( desc->AppDeviceId );
- *buf++ = LO_UINT16( desc->AppDeviceId );
- *buf++ = (byte)(desc->AppDevVer << 4);
- *buf++ = desc->AppNumInClusters;
- ptr = desc->pAppInClusterList;
- for ( cnt = 0; cnt < desc->AppNumInClusters; ptr++, cnt++ )
- {
- *buf++ = HI_UINT16( *ptr );
- *buf++ = LO_UINT16( *ptr );
- }
- *buf++ = desc->AppNumOutClusters;
- ptr = desc->pAppOutClusterList;
- for ( cnt = 0; cnt < desc->AppNumOutClusters; ptr++, cnt++ )
- {
- *buf++ = HI_UINT16( *ptr );
- *buf++ = LO_UINT16( *ptr );
- }
- }
- /*********************************************************************
- * @fn ZDO_MatchEndDeviceBind()
- *
- * @brief
- *
- * Called to match end device binding requests
- *
- * @param bindReq - binding request information
- * @param SecurityUse - Security enable/disable
- *
- * @return none
- */
- void ZDO_MatchEndDeviceBind( ZDEndDeviceBind_t *bindReq )
- {
- zAddrType_t dstAddr;
- uint8 sendRsp = FALSE;
- uint8 status;
- // Is this the first request?
- if ( matchED == NULL )
- {
- // Create match info structure
- matchED = (ZDMatchEndDeviceBind_t *)osal_mem_alloc( sizeof ( ZDMatchEndDeviceBind_t ) );
- if ( matchED )
- {
- // Clear the structure
- osal_memset( (uint8 *)matchED, 0, sizeof ( ZDMatchEndDeviceBind_t ) );
- // Copy the first request's information
- if ( !ZDO_CopyMatchInfo( &(matchED->ed1), bindReq ) )
- {
- status = ZDP_NO_ENTRY;
- sendRsp = TRUE;
- }
- }
- else
- {
- status = ZDP_NO_ENTRY;
- sendRsp = TRUE;
- }
- if ( !sendRsp )
- {
- // Set into the correct state
- matchED->state = ZDMATCH_WAIT_REQ;
- // Setup the timeout
- APS_SetEndDeviceBindTimeout( AIB_MaxBindingTime, ZDO_EndDeviceBindMatchTimeoutCB );
- }
- }
- else
- {
- matchED->state = ZDMATCH_SENDING_BINDS;
- // Copy the 2nd request's information
- if ( !ZDO_CopyMatchInfo( &(matchED->ed2), bindReq ) )
- {
- status = ZDP_NO_ENTRY;
- sendRsp = TRUE;
- }
- // Make a source match for ed1
- matchED->ed1numMatched = ZDO_CompareClusterLists(
- matchED->ed1.numOutClusters, matchED->ed1.outClusters,
- matchED->ed2.numInClusters, matchED->ed2.inClusters, ZDOBuildBuf );
- if ( matchED->ed1numMatched )
- {
- // Save the match list
- matchED->ed1Matched = osal_mem_alloc( (short)(matchED->ed1numMatched * sizeof ( uint16 )) );
- if ( matchED->ed1Matched )
- {
- osal_memcpy( matchED->ed1Matched, ZDOBuildBuf, (matchED->ed1numMatched * sizeof ( uint16 )) );
- }
- else
- {
- // Allocation error, stop
- status = ZDP_NO_ENTRY;
- sendRsp = TRUE;
- }
- }
- // Make a source match for ed2
- matchED->ed2numMatched = ZDO_CompareClusterLists(
- matchED->ed2.numOutClusters, matchED->ed2.outClusters,
- matchED->ed1.numInClusters, matchED->ed1.inClusters, ZDOBuildBuf );
- if ( matchED->ed2numMatched )
- {
- // Save the match list
- matchED->ed2Matched = osal_mem_alloc( (short)(matchED->ed2numMatched * sizeof ( uint16 )) );
- if ( matchED->ed2Matched )
- {
- osal_memcpy( matchED->ed2Matched, ZDOBuildBuf, (matchED->ed2numMatched * sizeof ( uint16 )) );
- }
- else
- {
- // Allocation error, stop
- status = ZDP_NO_ENTRY;
- sendRsp = TRUE;
- }
- }
- if ( (sendRsp == FALSE) && (matchED->ed1numMatched || matchED->ed2numMatched) )
- {
- // Do the first unbind/bind state
- ZDMatchSendState( ZDMATCH_REASON_START, ZDP_SUCCESS, 0 );
- }
- else
- {
- status = ZDP_NO_MATCH;
- sendRsp = TRUE;
- }
- }
- if ( sendRsp )
- {
- // send response to this requester
- dstAddr.addrMode = Addr16Bit;
- dstAddr.addr.shortAddr = bindReq->srcAddr;
- ZDP_EndDeviceBindRsp( bindReq->TransSeq, &dstAddr, status, bindReq->SecurityUse );
- if ( matchED->state == ZDMATCH_SENDING_BINDS )
- {
- // send response to first requester
- dstAddr.addrMode = Addr16Bit;
- dstAddr.addr.shortAddr = matchED->ed1.srcAddr;
- ZDP_EndDeviceBindRsp( matchED->ed1.TransSeq, &dstAddr, status, matchED->ed1.SecurityUse );
- }
- // Process ended - release memory used
- ZDO_RemoveMatchMemory();
- }
- }
- /*********************************************************************
- * @fn ZDO_RemoveMatchMemory()
- *
- * @brief Called to clear the memory used for the end device bind.
- *
- * @param none
- *
- * @return none
- */
- static void ZDO_RemoveMatchMemory( void )
- {
- if ( matchED != NULL )
- {
- if ( matchED->ed2Matched != NULL )
- {
- osal_mem_free( matchED->ed2Matched );
- }
- if ( matchED->ed1Matched != NULL )
- {
- osal_mem_free( matchED->ed1Matched );
- }
- if ( matchED->ed1.inClusters != NULL )
- {
- osal_mem_free( matchED->ed1.inClusters );
- }
- if ( matchED->ed1.outClusters != NULL )
- {
- osal_mem_free( matchED->ed1.outClusters );
- }
- if ( matchED->ed2.inClusters != NULL )
- {
- osal_mem_free( matchED->ed2.inClusters );
- }
- if ( matchED->ed2.outClusters != NULL )
- {
- osal_mem_free( matchED->ed2.outClusters );
- }
- osal_mem_free( matchED );
- matchED = (ZDMatchEndDeviceBind_t *)NULL;
- }
- }
- /*********************************************************************
- * @fn ZDO_CopyMatchInfo()
- *
- * @brief Called to copy memory used for the end device bind.
- *
- * @param srcReq - source information
- * @param dstReq - destination location
- *
- * @return TRUE if copy was successful.
- */
- static uint8 ZDO_CopyMatchInfo( ZDEndDeviceBind_t *destReq, ZDEndDeviceBind_t *srcReq )
- {
- uint8 allOK = TRUE;
- // Copy bind information into the match info structure
- osal_memcpy( (uint8 *)destReq, srcReq, sizeof ( ZDEndDeviceBind_t ) );
- // Initialize the destination cluster pointers
- destReq->inClusters = NULL;
- destReq->outClusters = NULL;
- // Copy input cluster IDs
- if ( srcReq->numInClusters )
- {
- destReq->inClusters = osal_mem_alloc( (short)(srcReq->numInClusters * sizeof ( uint16 )) );
- if ( destReq->inClusters )
- {
- // Copy the clusters
- osal_memcpy( (uint8*)(destReq->inClusters), (uint8 *)(srcReq->inClusters),
- (srcReq->numInClusters * sizeof ( uint16 )) );
- }
- else
- {
- allOK = FALSE;
- }
- }
- // Copy output cluster IDs
- if ( srcReq->numOutClusters )
- {
- destReq->outClusters = osal_mem_alloc( (short)(srcReq->numOutClusters * sizeof ( uint16 )) );
- if ( destReq->outClusters )
- {
- // Copy the clusters
- osal_memcpy( (uint8 *)(destReq->outClusters), (uint8 *)(srcReq->outClusters),
- (srcReq->numOutClusters * sizeof ( uint16 )) );
- }
- else
- {
- allOK = FALSE;
- }
- }
- if ( allOK == FALSE )
- {
- if ( destReq->inClusters != NULL )
- {
- osal_mem_free( destReq->inClusters );
- }
- if ( destReq->outClusters != NULL )
- {
- osal_mem_free( destReq->outClusters );
- }
- }
- return ( allOK );
- }
- /*********************************************************************
- * @fn ZDMatchSendState()
- *
- * @brief State machine for the End device match message algorithm.
- *
- * @param reason - state of algoritm
- * @param status - initial message status
- * @param TransSeq - next transaction sequence number
- *
- * @return FALSE if error and we are not currently matching, TRUE
- * if success.
- */
- uint8 ZDMatchSendState( uint8 reason, uint8 status, uint8 TransSeq )
- {
- uint8 *dstIEEEAddr = NULL;
- uint8 dstEP = 0xFF;
- zAddrType_t dstAddr;
- zAddrType_t destinationAddr;
- uint16 msgType;
- uint16 clusterID = 0xFFFF;
- ZDEndDeviceBind_t *ed = NULL;
- uint8 rspStatus = ZDP_SUCCESS;
- if ( matchED == NULL )
- {
- return ( FALSE );
- }
- // Check sequence number
- if ( reason == ZDMATCH_REASON_BIND_RSP || reason == ZDMATCH_REASON_UNBIND_RSP )
- {
- if ( TransSeq != matchED->transSeq )
- {
- return( FALSE ); // ignore the message
- }
- }
- // turn off timer
- APS_SetEndDeviceBindTimeout( 0, ZDO_EndDeviceBindMatchTimeoutCB );
- if ( reason == ZDMATCH_REASON_TIMEOUT )
- {
- rspStatus = ZDP_TIMEOUT; // The process will stop
- }
- if ( reason == ZDMATCH_REASON_START || reason == ZDMATCH_REASON_BIND_RSP )
- {
- matchED->sending = ZDMATCH_SENDING_UNBIND;
- if ( reason == ZDMATCH_REASON_BIND_RSP && status != ZDP_SUCCESS )
- {
- rspStatus = status;
- }
- }
- else if ( reason == ZDMATCH_REASON_UNBIND_RSP )
- {
- if ( status == ZDP_SUCCESS )
- {
- matchED->sending = ZDMATCH_SENDING_UNBIND;
- }
- else
- {
- matchED->sending = ZDMATCH_SENDING_BIND;
- }
- }
- if ( reason != ZDMATCH_REASON_START && matchED->sending == ZDMATCH_SENDING_UNBIND )
- {
- // Move to the next cluster ID
- if ( matchED->ed1numMatched )
- {
- matchED->ed1numMatched--;
- }
- else if ( matchED->ed2numMatched )
- {
- matchED->ed2numMatched--;
- }
- }
- // What message do we send now
- if ( matchED->ed1numMatched )
- {
- ed = &(matchED->ed1);
- clusterID = matchED->ed1Matched[matchED->ed1numMatched-1];
- dstIEEEAddr = matchED->ed2.ieeeAddr;
- dstEP = matchED->ed2.endpoint;
- }
- else if ( matchED->ed2numMatched )
- {
- ed = &(matchED->ed2);
- clusterID = matchED->ed2Matched[matchED->ed2numMatched-1];
- dstIEEEAddr = matchED->ed1.ieeeAddr;
- dstEP = matchED->ed1.endpoint;
- }
- dstAddr.addrMode = Addr16Bit;
- // Send the next message
- if ( (rspStatus == ZDP_SUCCESS) && ed )
- {
- // Send unbind/bind message to source
- if ( matchED->sending == ZDMATCH_SENDING_UNBIND )
- {
- msgType = Unbind_req;
- }
- else
- {
- msgType = Bind_req;
- }
- dstAddr.addr.shortAddr = ed->srcAddr;
- // Save off the transaction sequence number
- matchED->transSeq = ZDP_TransID;
- destinationAddr.addrMode = Addr64Bit;
- osal_cpyExtAddr( destinationAddr.addr.extAddr, dstIEEEAddr );
- ZDP_BindUnbindReq( msgType, &dstAddr, ed->ieeeAddr, ed->endpoint, clusterID,
- &destinationAddr, dstEP, ed->SecurityUse );
- // Set timeout for response
- APS_SetEndDeviceBindTimeout( AIB_MaxBindingTime, ZDO_EndDeviceBindMatchTimeoutCB );
- }
- else
- {
- // Send the response messages to requesting devices
- // send response to first requester
- dstAddr.addr.shortAddr = matchED->ed1.srcAddr;
- ZDP_EndDeviceBindRsp( matchED->ed1.TransSeq, &dstAddr, rspStatus, matchED->ed1.SecurityUse );
- // send response to second requester
- if ( matchED->state == ZDMATCH_SENDING_BINDS )
- {
- dstAddr.addr.shortAddr = matchED->ed2.srcAddr;
- ZDP_EndDeviceBindRsp( matchED->ed2.TransSeq, &dstAddr, rspStatus, matchED->ed2.SecurityUse );
- }
- // Process ended - release memory used
- ZDO_RemoveMatchMemory();
- }
- return ( TRUE );
- }
- /*********************************************************************
- * @fn ZDO_EndDeviceBindMatchTimeoutCB()
- *
- * @brief End device bind timeout.
- *
- * @param none
- *
- * @return none
- */
- static void ZDO_EndDeviceBindMatchTimeoutCB( void )
- {
- ZDMatchSendState( ZDMATCH_REASON_TIMEOUT, ZDP_TIMEOUT, 0 );
- }
- /*********************************************************************
- * ZDO MESSAGE PARSING API FUNCTIONS
- */
- /*********************************************************************
- * @fn ZDO_ParseEndDeviceBindReq
- *
- * @brief This function parses the End_Device_Bind_req message.
- *
- * NOTE: The clusters lists in bindReq are allocated in this
- * function and must be freed by that calling function.
- *
- * @param inMsg - incoming message (request)
- * @param bindReq - pointer to place to parse message to
- *
- * @return none
- */
- void ZDO_ParseEndDeviceBindReq( zdoIncomingMsg_t *inMsg, ZDEndDeviceBind_t *bindReq )
- {
- uint8 *msg;
- // Parse the message
- bindReq->TransSeq = inMsg->TransSeq;
- bindReq->srcAddr = inMsg->srcAddr.addr.shortAddr;
- bindReq->SecurityUse = inMsg->SecurityUse;
- msg = inMsg->asdu;
- bindReq->localCoordinator = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- osal_cpyExtAddr( bindReq->ieeeAddr, msg );
- msg += Z_EXTADDR_LEN;
- bindReq->endpoint = *msg++;
- bindReq->profileID = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- bindReq->inClusters = NULL;
- bindReq->outClusters = NULL;
- if ((bindReq->numInClusters = *msg++) &&
- (bindReq->inClusters = (uint16*)osal_mem_alloc( (bindReq->numInClusters * sizeof( uint16 )))))
- {
- msg = ZDO_ConvertOTAClusters( bindReq->numInClusters, msg, bindReq->inClusters );
- }
- else
- {
- bindReq->numInClusters = 0;
- }
- if ((bindReq->numOutClusters = *msg++) &&
- (bindReq->outClusters = (uint16*)osal_mem_alloc((bindReq->numOutClusters * sizeof(uint16)))))
- {
- msg = ZDO_ConvertOTAClusters( bindReq->numOutClusters, msg, bindReq->outClusters );
- }
- else
- {
- bindReq->numOutClusters = 0;
- }
- }
- /*********************************************************************
- * @fn ZDO_ParseBindUnbindReq
- *
- * @brief This function parses the Bind_req or Unbind_req message.
- *
- * @param inMsg - incoming message (request)
- * @param pReq - place to put parsed information
- *
- * @return none
- */
- void ZDO_ParseBindUnbindReq( zdoIncomingMsg_t *inMsg, ZDO_BindUnbindReq_t *pReq )
- {
- uint8 *msg;
- msg = inMsg->asdu;
- osal_cpyExtAddr( pReq->srcAddress, msg );
- msg += Z_EXTADDR_LEN;
- pReq->srcEndpoint = *msg++;
- pReq->clusterID = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- pReq->dstAddress.addrMode = *msg++;
- if ( pReq->dstAddress.addrMode == Addr64Bit )
- {
- osal_cpyExtAddr( pReq->dstAddress.addr.extAddr, msg );
- msg += Z_EXTADDR_LEN;
- pReq->dstEndpoint = *msg;
- }
- else
- {
- // copy group address
- pReq->dstAddress.addr.shortAddr = BUILD_UINT16( msg[0], msg[1] );
- }
- }
- /*********************************************************************
- * @fn ZDO_ParseAddrRsp
- *
- * @brief Turns the inMsg (incoming message) into the out parsed
- * structure.
- *
- * @param inMsg - incoming message
- *
- * @return pointer to parsed structures. This structure was
- * allocated using osal_mem_alloc, so it must be freed
- * by the calling function [osal_mem_free()].
- */
- ZDO_NwkIEEEAddrResp_t *ZDO_ParseAddrRsp( zdoIncomingMsg_t *inMsg )
- {
- ZDO_NwkIEEEAddrResp_t *rsp;
- uint8 *msg;
- byte cnt = 0;
- // Calculate the number of items in the list
- if ( inMsg->asduLen > (1 + Z_EXTADDR_LEN + 2) )
- {
- cnt = inMsg->asdu[1 + Z_EXTADDR_LEN + 2];
- }
- else
- {
- cnt = 0;
- }
- // Make buffer
- rsp = (ZDO_NwkIEEEAddrResp_t *)osal_mem_alloc( sizeof(ZDO_NwkIEEEAddrResp_t) + (cnt * sizeof ( uint16 )) );
- if ( rsp )
- {
- msg = inMsg->asdu;
- rsp->status = *msg++;
- if ( rsp->status == ZDO_SUCCESS )
- {
- osal_cpyExtAddr( rsp->extAddr, msg );
- msg += Z_EXTADDR_LEN;
- rsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- rsp->numAssocDevs = 0;
- // StartIndex field is only present if NumAssocDev field is non-zero.
- if ( cnt > 0 )
- {
- uint16 *pList = &(rsp->devList[0]);
- byte n = cnt;
- rsp->numAssocDevs = *msg++;
- rsp->startIndex = *msg++;
- while ( n != 0 )
- {
- *pList++ = BUILD_UINT16( msg[0], msg[1] );
- msg += sizeof( uint16 );
- n--;
- }
- }
- }
- }
- return ( rsp );
- }
- /*********************************************************************
- * @fn ZDO_ParseNodeDescRsp
- *
- * @brief This function parses the Node_Desc_rsp message.
- *
- * @param inMsg - incoming message
- * @param pNDRsp - place to parse the message into
- *
- * @return none
- */
- void ZDO_ParseNodeDescRsp( zdoIncomingMsg_t *inMsg, ZDO_NodeDescRsp_t *pNDRsp )
- {
- uint8 *msg;
- msg = inMsg->asdu;
- pNDRsp->status = *msg++;
- pNDRsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
- if ( pNDRsp->status == ZDP_SUCCESS )
- {
- msg += 2;
- pNDRsp->nodeDesc.LogicalType = *msg & 0x07;
- pNDRsp->nodeDesc.ComplexDescAvail = ( *msg & 0x08 ) >> 3;
- pNDRsp->nodeDesc.UserDescAvail = ( *msg & 0x10 ) >> 4;
- msg++; // Reserved bits.
- pNDRsp->nodeDesc.FrequencyBand = (*msg >> 3) & 0x1f;
- pNDRsp->nodeDesc.APSFlags = *msg++ & 0x07;
- pNDRsp->nodeDesc.CapabilityFlags = *msg++;
- pNDRsp->nodeDesc.ManufacturerCode[0] = *msg++;
- pNDRsp->nodeDesc.ManufacturerCode[1] = *msg++;
- pNDRsp->nodeDesc.MaxBufferSize = *msg++;
- pNDRsp->nodeDesc.MaxInTransferSize[0] = *msg++;
- pNDRsp->nodeDesc.MaxInTransferSize[1] = *msg++;
- pNDRsp->nodeDesc.ServerMask = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- pNDRsp->nodeDesc.MaxOutTransferSize[0] = *msg++;
- pNDRsp->nodeDesc.MaxOutTransferSize[1] = *msg++;
- pNDRsp->nodeDesc.DescriptorCapability = *msg;
- }
- }
- /*********************************************************************
- * @fn ZDO_ParesPowerDescRsp
- *
- * @brief This function parses the Power_Desc_rsp message.
- *
- * @param inMsg - incoming message
- * @param pNPRsp - place to parse the message into
- *
- * @return none
- */
- void ZDO_ParsePowerDescRsp( zdoIncomingMsg_t *inMsg, ZDO_PowerRsp_t *pNPRsp )
- {
- uint8 *msg;
- msg = inMsg->asdu;
- pNPRsp->status = *msg++;
- pNPRsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
- if ( pNPRsp->status == ZDP_SUCCESS )
- {
- msg += 2;
- pNPRsp->pwrDesc.AvailablePowerSources = *msg >> 4;
- pNPRsp->pwrDesc.PowerMode = *msg++ & 0x0F;
- pNPRsp->pwrDesc.CurrentPowerSourceLevel = *msg >> 4;
- pNPRsp->pwrDesc.CurrentPowerSource = *msg++ & 0x0F;
- }
- }
- /*********************************************************************
- * @fn ZDO_ParseSimpleDescRsp
- *
- * @brief This function parse the Simple_Desc_rsp message.
- *
- * NOTE: The pAppInClusterList and pAppOutClusterList fields
- * in the SimpleDescriptionFormat_t structure are allocated
- * and the calling function needs to free [osal_msg_free()]
- * these buffers.
- *
- * @param inMsg - incoming message
- * @param pSimpleDescRsp - place to parse the message into
- *
- * @return none
- */
- void ZDO_ParseSimpleDescRsp( zdoIncomingMsg_t *inMsg, ZDO_SimpleDescRsp_t *pSimpleDescRsp )
- {
- uint8 *msg;
- msg = inMsg->asdu;
- pSimpleDescRsp->status = *msg++;
- pSimpleDescRsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
- msg += sizeof ( uint16 );
- msg++; // Skip past the length field.
- if ( pSimpleDescRsp->status == ZDP_SUCCESS )
- {
- ZDO_ParseSimpleDescBuf( msg, &(pSimpleDescRsp->simpleDesc) );
- }
- }
- /*********************************************************************
- * @fn ZDO_ParseEPListRsp
- *
- * @brief This parse the Active_EP_rsp or Match_Desc_rsp message.
- *
- * @param inMsg - incoming message
- *
- * @return none
- */
- ZDO_ActiveEndpointRsp_t *ZDO_ParseEPListRsp( zdoIncomingMsg_t *inMsg )
- {
- ZDO_ActiveEndpointRsp_t *pRsp;
- uint8 *msg;
- uint8 Status;
- uint8 cnt;
- msg = inMsg->asdu;
- Status = *msg++;
- cnt = msg[2];
- pRsp = (ZDO_ActiveEndpointRsp_t *)osal_mem_alloc( sizeof( ZDO_ActiveEndpointRsp_t ) + cnt );
- if ( pRsp )
- {
- pRsp->status = Status;
- pRsp->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
- msg += sizeof( uint16 );
- pRsp->cnt = cnt;
- msg++; // pass cnt
- osal_memcpy( pRsp->epList, msg, cnt );
- }
- return ( pRsp );
- }
- /*********************************************************************
- * @fn ZDO_ParseServerDiscRsp
- *
- * @brief Parse the Server_Discovery_rsp message.
- *
- * @param inMsg - incoming message.
- * @param pRsp - place to put the parsed information.
- *
- * @return none
- */
- void ZDO_ParseServerDiscRsp( zdoIncomingMsg_t *inMsg, ZDO_ServerDiscRsp_t *pRsp )
- {
- pRsp->status = inMsg->asdu[0];
- pRsp->serverMask = BUILD_UINT16( inMsg->asdu[1], inMsg->asdu[2] );
- }
- /*********************************************************************
- * @fn ZDO_ParseMgmtLqiRsp
- *
- * @brief This function parses the incoming Management
- * LQI response
- *
- * @param inMsg - incoming message
- *
- * @return a pointer to parsed response structure (NULL if not allocated).
- * This structure was allocated using osal_mem_alloc, so it must be freed
- * by the calling function [osal_mem_free()].
- */
- ZDO_MgmtLqiRsp_t *ZDO_ParseMgmtLqiRsp( zdoIncomingMsg_t *inMsg )
- {
- ZDO_MgmtLqiRsp_t *pRsp;
- uint8 status;
- uint8 startIndex = 0;
- uint8 neighborLqiCount = 0;
- uint8 neighborLqiEntries = 0;
- uint8 *msg;
- msg = inMsg->asdu;
- status = *msg++;
- if ( status == ZSuccess )
- {
- neighborLqiEntries = *msg++;
- startIndex = *msg++;
- neighborLqiCount = *msg++;
- }
- // Allocate a buffer big enough to handle the list.
- pRsp = (ZDO_MgmtLqiRsp_t *)osal_mem_alloc(
- sizeof( ZDO_MgmtLqiRsp_t ) + (neighborLqiCount * sizeof( neighborLqiItem_t )) );
- if ( pRsp )
- {
- uint8 x;
- neighborLqiItem_t *pList = pRsp->list;
- pRsp->status = status;
- pRsp->neighborLqiEntries = neighborLqiEntries;
- pRsp->startIndex = startIndex;
- pRsp->neighborLqiCount = neighborLqiCount;
- for ( x = 0; x < neighborLqiCount; x++ )
- {
- osal_cpyExtAddr(pList->extPANId, msg); //Copy extended PAN ID
- msg += Z_EXTADDR_LEN;
- msg += Z_EXTADDR_LEN; // Throwing away IEEE.
- pList->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
- msg += 2 + 1 + 1 + 1; // Skip DeviceType, RxOnIdle, Rlationship, PermitJoining and Depth
- pList->rxLqi = *msg++;
- pList->txQuality = 0; // This is not specified OTA by ZigBee 1.1.
- pList++;
- }
- }
- return ( pRsp );
- }
- /*********************************************************************
- * @fn ZDO_ParseMgmNwkDiscRsp
- *
- * @brief This function parses the incoming Management
- * Network Discover response.
- *
- * @param inMsg - incoming message
- *
- * @return pointer to parsed response. This structure was
- * allocated using osal_mem_alloc, so it must be freed
- * by the calling function [osal_mem_free()].
- */
- ZDO_MgmNwkDiscRsp_t *ZDO_ParseMgmNwkDiscRsp( zdoIncomingMsg_t *inMsg )
- {
- ZDO_MgmNwkDiscRsp_t *pRsp;
- uint8 status;
- uint8 networkCount = 0;
- uint8 startIndex = 0;
- uint8 networkListCount = 0;
- uint8 *msg;
- msg = inMsg->asdu;
- status = *msg++;
- if ( status == ZSuccess )
- {
- networkCount = *msg++;
- startIndex = *msg++;
- networkListCount = *msg++;
- }
- // Allocate a buffer big enough to handle the list.
- pRsp = (ZDO_MgmNwkDiscRsp_t *)osal_mem_alloc( sizeof( ZDO_MgmNwkDiscRsp_t )
- + (networkListCount * sizeof( mgmtNwkDiscItem_t )) );
- if ( pRsp )
- {
- uint8 x;
- mgmtNwkDiscItem_t *pList;
- pRsp->status = status;
- pRsp->networkCount = networkCount;
- pRsp->startIndex = startIndex;
- pRsp->networkListCount = networkListCount;
- pList = pRsp->list;
- for ( x = 0; x < networkListCount; x++ )
- {
- osal_cpyExtAddr(pList->extendedPANID, msg); //Copy extended PAN ID
- pList->PANId = BUILD_UINT16( msg[0], msg[1] );
- msg += Z_EXTADDR_LEN;
- pList->logicalChannel = *msg++;
- pList->stackProfile = (*msg) & 0x0F;
- pList->version = (*msg++ >> 4) & 0x0F;
- pList->beaconOrder = (*msg) & 0x0F;
- pList->superFrameOrder = (*msg++ >> 4) & 0x0F;
- pList->permitJoining = *msg++;
- pList++;
- }
- }
- return ( pRsp );
- }
- /*********************************************************************
- * @fn ZDO_ParseMgmtRtgRsp
- *
- * @brief This function parses the incoming Management
- * Routing response.
- *
- * @param inMsg - incoming message
- *
- * @return a pointer to parsed response structure (NULL if not allocated).
- * This structure was allocated using osal_mem_alloc, so it must be freed
- * by the calling function [osal_mem_free()].
- */
- ZDO_MgmtRtgRsp_t *ZDO_ParseMgmtRtgRsp( zdoIncomingMsg_t *inMsg )
- {
- ZDO_MgmtRtgRsp_t *pRsp;
- uint8 status;
- uint8 rtgCount = 0;
- uint8 startIndex = 0;
- uint8 rtgListCount = 0;
- uint8 *msg;
- msg = inMsg->asdu;
- status = *msg++;
- if ( status == ZSuccess )
- {
- rtgCount = *msg++;
- startIndex = *msg++;
- rtgListCount = *msg++;
- }
- // Allocate a buffer big enough to handle the list
- pRsp = (ZDO_MgmtRtgRsp_t *)osal_mem_alloc(
- sizeof( ZDO_MgmtRtgRsp_t ) + (rtgListCount * sizeof( rtgItem_t )) );
- if ( pRsp )
- {
- uint8 x;
- rtgItem_t *pList = pRsp->list;
- pRsp->status = status;
- pRsp->rtgCount = rtgCount;
- pRsp->startIndex = startIndex;
- pRsp->rtgListCount = rtgListCount;
- for ( x = 0; x < rtgListCount; x++ )
- {
- pList->dstAddress = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- pList->status = *msg++;
- pList->nextHopAddress = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- pList++;
- }
- }
- return ( pRsp );
- }
- /*********************************************************************
- * @fn ZDO_ParseMgmtBindRsp
- *
- * @brief This function parses the incoming Management
- * Binding response.
- *
- * @param inMsg - pointer to message to parse
- *
- * @return a pointer to parsed response structure (NULL if not allocated).
- * This structure was allocated using osal_mem_alloc, so it must be freed
- * by the calling function [osal_mem_free()].
- */
- ZDO_MgmtBindRsp_t *ZDO_ParseMgmtBindRsp( zdoIncomingMsg_t *inMsg )
- {
- ZDO_MgmtBindRsp_t *pRsp;
- uint8 status;
- uint8 bindingCount = 0;
- uint8 startIndex = 0;
- uint8 bindingListCount = 0;
- uint8 *msg;
- msg = inMsg->asdu;
- status = *msg++;
- if ( status == ZSuccess )
- {
- bindingCount = *msg++;
- startIndex = *msg++;
- bindingListCount = *msg++;
- }
- // Allocate a buffer big enough to handle the list
- pRsp = (ZDO_MgmtBindRsp_t *)osal_mem_alloc(
- (sizeof ( ZDO_MgmtBindRsp_t ) + (bindingListCount * sizeof( apsBindingItem_t ))) );
- if ( pRsp )
- {
- uint8 x;
- apsBindingItem_t *pList = pRsp->list;
- pRsp->status = status;
- pRsp->bindingCount = bindingCount;
- pRsp->startIndex = startIndex;
- pRsp->bindingListCount = bindingListCount;
- for ( x = 0; x < bindingListCount; x++ )
- {
- osal_cpyExtAddr( pList->srcAddr, msg );
- msg += Z_EXTADDR_LEN;
- pList->srcEP = *msg++;
- // Get the Cluster ID
- pList->clusterID = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- pList->dstAddr.addrMode = *msg++;
- if ( pList->dstAddr.addrMode == Addr64Bit )
- {
- osal_cpyExtAddr( pList->dstAddr.addr.extAddr, msg );
- msg += Z_EXTADDR_LEN;
- pList->dstEP = *msg++;
- }
- else
- {
- pList->dstAddr.addr.shortAddr = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- }
- pList++;
- }
- }
- return ( pRsp );
- }
- /*********************************************************************
- * @fn ZDO_ParseUserDescRsp
- *
- * @brief This function parses the incoming User
- * Descriptor Response.
- *
- * @param inMsg - incoming response message
- *
- * @return a pointer to parsed response structure (NULL if not allocated).
- * This structure was allocated using osal_mem_alloc, so it must be freed
- * by the calling function [osal_mem_free()].
- */
- ZDO_UserDescRsp_t *ZDO_ParseUserDescRsp( zdoIncomingMsg_t *inMsg )
- {
- ZDO_UserDescRsp_t *pRsp;
- uint8 *msg;
- uint8 descLen = 0;
- msg = inMsg->asdu;
- if ( msg[0] == ZSuccess )
- {
- descLen = msg[3];
- }
- pRsp = (ZDO_UserDescRsp_t *)osal_mem_alloc( sizeof ( ZDO_UserDescRsp_t ) + descLen );
- if ( pRsp )
- {
- pRsp->status = msg[0];
- pRsp->nwkAddr = BUILD_UINT16( msg[1], msg[2] );
- pRsp->length = descLen;
- if ( descLen )
- {
- osal_memcpy( pRsp->desc, &msg[4], descLen );
- }
- }
- return ( pRsp );
- }
- /*********************************************************************
- * @fn ZDO_ParseSimpleDescBuf
- *
- * @brief Parse a byte sequence representation of a Simple Descriptor.
- *
- * @param buf - pointer to a byte array representing a Simple Desc.
- * @param desc - SimpleDescriptionFormat_t *
- *
- * This routine allocates storage for the cluster IDs because
- * they are 16-bit and need to be aligned to be properly processed.
- * This routine returns non-zero if an allocation fails.
- *
- * NOTE: This means that the caller or user of the input structure
- * is responsible for freeing the memory
- *
- * @return 0: success
- * 1: failure due to malloc failure.
- */
- uint8 ZDO_ParseSimpleDescBuf( uint8 *buf, SimpleDescriptionFormat_t *desc )
- {
- uint8 num, i;
- desc->EndPoint = *buf++;
- desc->AppProfId = BUILD_UINT16( buf[0], buf[1] );
- buf += 2;
- desc->AppDeviceId = BUILD_UINT16( buf[0], buf[1] );
- buf += 2;
- desc->AppDevVer = *buf >> 4;
- desc->Reserved = 0;
- buf++;
- // move in input cluster list (if any). allocate aligned memory.
- num = desc->AppNumInClusters = *buf++;
- if ( num )
- {
- if (!(desc->pAppInClusterList = (uint16 *)osal_mem_alloc(num*sizeof(uint16))))
- {
- // malloc failed. we're done.
- return 1;
- }
- for (i=0; i<num; ++i)
- {
- desc->pAppInClusterList[i] = BUILD_UINT16( buf[0], buf[1] );
- buf += 2;
- }
- }
- // move in output cluster list (if any). allocate aligned memory.
- num = desc->AppNumOutClusters = *buf++;
- if (num)
- {
- if (!(desc->pAppOutClusterList = (uint16 *)osal_mem_alloc(num*sizeof(uint16))))
- {
- // malloc failed. free input cluster list memory if there is any
- if ( desc->pAppInClusterList != NULL )
- {
- osal_mem_free(desc->pAppInClusterList);
- desc->pAppInClusterList = NULL;
- }
- return 1;
- }
- for (i=0; i<num; ++i)
- {
- desc->pAppOutClusterList[i] = BUILD_UINT16( buf[0], buf[1] );
- buf += 2;
- }
- }
- return 0;
- }
- /*********************************************************************
- * @fn ZDO_ParseDeviceAnnce
- *
- * @brief Parse a Device Announce message.
- *
- * @param inMsg - Incoming message
- * @param pAnnce - place to put the parsed information
- *
- * @return none
- */
- void ZDO_ParseDeviceAnnce( zdoIncomingMsg_t *inMsg, ZDO_DeviceAnnce_t *pAnnce )
- {
- uint8 *msg;
- // Parse incoming message
- msg = inMsg->asdu;
- pAnnce->nwkAddr = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- osal_cpyExtAddr( pAnnce->extAddr, msg );
- msg += Z_EXTADDR_LEN;
- pAnnce->capabilities = *msg;
- }
- /*********************************************************************
- * @fn ZDO_ParseMgmtNwkUpdateNotify
- *
- * @brief This function handles parsing of the incoming Management
- * Network Update notify.
- *
- * @param inMsg - incoming message (request)
- *
- * @return a pointer to parsed response structure (NULL if not allocated).
- * This structure was allocated using osal_mem_alloc, so it must be freed
- * by the calling function [osal_mem_free()].
- */
- ZDO_MgmtNwkUpdateNotify_t *ZDO_ParseMgmtNwkUpdateNotify( zdoIncomingMsg_t *inMsg )
- {
- uint8 status;
- uint32 scannedChannels = 0;
- uint16 totalTransmissions = 0;
- uint16 transmissionFailures = 0;
- uint8 listCount = 0;
- uint8 *msg = inMsg->asdu;
- ZDO_MgmtNwkUpdateNotify_t *pRsp;
- status = *msg++;
- if ( status == ZSuccess )
- {
- scannedChannels = osal_build_uint32( msg, 4 );
- msg += 4;
- totalTransmissions = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- transmissionFailures = BUILD_UINT16( msg[0], msg[1] );
- msg += 2;
- listCount = *msg++;
- }
- pRsp = (ZDO_MgmtNwkUpdateNotify_t *)osal_mem_alloc( sizeof ( ZDO_MgmtNwkUpdateNotify_t ) + listCount );
- if ( pRsp )
- {
- pRsp->status = status;
- pRsp->scannedChannels = scannedChannels;
- pRsp->totalTransmissions = totalTransmissions;
- pRsp->transmissionFailures = transmissionFailures;
- pRsp->listCount = listCount;
- // Allocate a buffer big enough to handle the list.
- if ( listCount > 0 )
- {
- osal_memcpy( pRsp->energyValues, msg, listCount );
- }
- }
- return ( pRsp );
- }
- /*********************************************************************
- * @fn ZDO_ParseMgmtNwkUpdateReq
- *
- * @brief This function handles parsing the incoming Management
- * Network Update request and starts the request (if needed).
- *
- * @param inMsg - incoming message (request)
- * @param pReq - pointer to place to parse message to
- *
- * @return none
- */
- void ZDO_ParseMgmtNwkUpdateReq( zdoIncomingMsg_t *inMsg, ZDO_MgmtNwkUpdateReq_t *pReq )
- {
- uint8 *msg = inMsg->asdu;
- pReq->channelMask = osal_build_uint32( msg, 4 );
- msg += 4;
- pReq->scanDuration = *msg++;
- if ( pReq->scanDuration <= 0x05 )
- {
- // Request is to scan over channelMask
- pReq->scanCount = *msg;
- }
- else if ( ( pReq->scanDuration == 0xFE ) || ( pReq->scanDuration == 0xFF ) )
- {
- // Request is to change Channel (0xFE) or apsChannelMask and NwkManagerAddr (0xFF)
- pReq->nwkUpdateId = *msg++;
- if ( pReq->scanDuration == 0xFF )
- {
- pReq->nwkManagerAddr = BUILD_UINT16( msg[0], msg[1] );
- }
- }
- }
- /*********************************************************************
- *********************************************************************/
|