zcl_general.c 100 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397
  1. /**************************************************************************************************
  2. Filename: zcl_general.c
  3. Revised: $Date: 2011-12-14 16:30:16 -0800 (Wed, 14 Dec 2011) $
  4. Revision: $Revision: 28678 $
  5. Description: Zigbee Cluster Library - General. This application receives all
  6. ZCL messages and initially parses them before passing to application.
  7. Copyright 2006-2011 Texas Instruments Incorporated. All rights reserved.
  8. IMPORTANT: Your use of this Software is limited to those specific rights
  9. granted under the terms of a software license agreement between the user
  10. who downloaded the software, his/her employer (which must be your employer)
  11. and Texas Instruments Incorporated (the "License"). You may not use this
  12. Software unless you agree to abide by the terms of the License. The License
  13. limits your use, and you acknowledge, that the Software may not be modified,
  14. copied or distributed unless embedded on a Texas Instruments microcontroller
  15. or used solely and exclusively in conjunction with a Texas Instruments radio
  16. frequency transceiver, which is integrated into your product. Other than for
  17. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  18. works of, modify, distribute, perform, display or sell this Software and/or
  19. its documentation for any purpose.
  20. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  21. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  22. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  23. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  24. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  25. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  26. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  27. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  28. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  29. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  30. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  31. Should you have any questions regarding your right to use this Software,
  32. contact Texas Instruments Incorporated at www.TI.com.
  33. **************************************************************************************************/
  34. /*********************************************************************
  35. * INCLUDES
  36. */
  37. #include "ZComDef.h"
  38. #include "OSAL.h"
  39. #include "OSAL_Nv.h"
  40. #include "zcl.h"
  41. #include "zcl_general.h"
  42. #include "ZDApp.h"
  43. #if defined ( INTER_PAN )
  44. #include "stub_aps.h"
  45. #endif
  46. /*********************************************************************
  47. * MACROS
  48. */
  49. #define locationTypeAbsolute( a ) ( (a) & LOCATION_TYPE_ABSOLUTE )
  50. #define locationType2D( a ) ( (a) & LOCATION_TYPE_2_D )
  51. #define locationTypeCoordinateSystem( a ) ( (a) & LOCATION_TYPE_COORDINATE_SYSTEM )
  52. #ifdef ZCL_SCENES
  53. #define zclGeneral_ScenesRemaingCapacity() ( ZCL_GEN_MAX_SCENES - zclGeneral_CountAllScenes() )
  54. #endif // ZCL_SCENES
  55. /*********************************************************************
  56. * CONSTANTS
  57. */
  58. /*********************************************************************
  59. * TYPEDEFS
  60. */
  61. typedef struct zclGenCBRec
  62. {
  63. struct zclGenCBRec *next;
  64. uint8 endpoint; // Used to link it into the endpoint descriptor
  65. zclGeneral_AppCallbacks_t *CBs; // Pointer to Callback function
  66. } zclGenCBRec_t;
  67. typedef struct zclGenSceneItem
  68. {
  69. struct zclGenSceneItem *next;
  70. uint8 endpoint; // Used to link it into the endpoint descriptor
  71. zclGeneral_Scene_t scene; // Scene info
  72. } zclGenSceneItem_t;
  73. typedef struct zclGenAlarmItem
  74. {
  75. struct zclGenAlarmItem *next;
  76. uint8 endpoint; // Used to link it into the endpoint descriptor
  77. zclGeneral_Alarm_t alarm; // Alarm info
  78. } zclGenAlarmItem_t;
  79. // Scene NV types
  80. typedef struct
  81. {
  82. uint16 numRecs;
  83. } nvGenScenesHdr_t;
  84. typedef struct zclGenSceneNVItem
  85. {
  86. uint8 endpoint;
  87. zclGeneral_Scene_t scene;
  88. } zclGenSceneNVItem_t;
  89. /*********************************************************************
  90. * GLOBAL VARIABLES
  91. */
  92. /*********************************************************************
  93. * GLOBAL FUNCTIONS
  94. */
  95. /*********************************************************************
  96. * LOCAL VARIABLES
  97. */
  98. static zclGenCBRec_t *zclGenCBs = (zclGenCBRec_t *)NULL;
  99. static uint8 zclGenPluginRegisted = FALSE;
  100. #ifdef ZCL_SCENES
  101. static zclGenSceneItem_t *zclGenSceneTable = (zclGenSceneItem_t *)NULL;
  102. #endif // ZCL_SCENES
  103. #ifdef ZCL_ALARMS
  104. static zclGenAlarmItem_t *zclGenAlarmTable = (zclGenAlarmItem_t *)NULL;
  105. #endif // ZCL_ALARMS
  106. /*********************************************************************
  107. * LOCAL FUNCTIONS
  108. */
  109. static ZStatus_t zclGeneral_HdlIncoming( zclIncoming_t *pInMsg );
  110. static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg );
  111. static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint );
  112. // Device Configuration and Installation clusters
  113. #ifdef ZCL_BASIC
  114. static ZStatus_t zclGeneral_ProcessInBasic( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  115. #endif // ZCL_BASIC
  116. #ifdef ZCL_IDENTIFY
  117. static ZStatus_t zclGeneral_ProcessInIdentity( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  118. #endif // ZCL_IDENTIFY
  119. // Groups and Scenes clusters
  120. #ifdef ZCL_GROUPS
  121. static ZStatus_t zclGeneral_ProcessInGroupsServer( zclIncoming_t *pInMsg );
  122. static ZStatus_t zclGeneral_ProcessInGroupsClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  123. static ZStatus_t zclGeneral_AddGroup( uint8 endPoint, aps_Group_t *group, uint8 *pData );
  124. #endif // ZCL_GROUPS
  125. #ifdef ZCL_SCENES
  126. static ZStatus_t zclGeneral_ProcessInScenesServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  127. static ZStatus_t zclGeneral_ProcessInScenesClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  128. #endif // ZCL_SCENES
  129. // On/Off and Level Control Configuration clusters
  130. #ifdef ZCL_ON_OFF
  131. static ZStatus_t zclGeneral_ProcessInOnOff( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  132. #endif // ZCL_ONOFF
  133. #ifdef ZCL_LEVEL_CTRL
  134. static ZStatus_t zclGeneral_ProcessInLevelControl( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  135. #endif // ZCL_LEVEL_CTRL
  136. // Alarms cluster
  137. #ifdef ZCL_ALARMS
  138. static ZStatus_t zclGeneral_ProcessInAlarmsServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  139. static ZStatus_t zclGeneral_ProcessInAlarmsClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  140. #endif // ZCL_ALARMS
  141. // Location cluster
  142. #ifdef ZCL_LOCATION
  143. static ZStatus_t zclGeneral_ProcessInLocationServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  144. static ZStatus_t zclGeneral_ProcessInLocationClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
  145. #endif // ZCL_LOCATION
  146. #ifdef ZCL_SCENES
  147. static uint8 zclGeneral_ScenesInitNV( void );
  148. static void zclGeneral_ScenesSetDefaultNV( void );
  149. static void zclGeneral_ScenesWriteNV( void );
  150. static uint16 zclGeneral_ScenesRestoreFromNV( void );
  151. #endif // ZCL_SCENES
  152. /*********************************************************************
  153. * @fn zclGeneral_RegisterCmdCallbacks
  154. *
  155. * @brief Register an applications command callbacks
  156. *
  157. * @param endpoint - application's endpoint
  158. * @param callbacks - pointer to the callback record.
  159. *
  160. * @return ZMemError if not able to allocate
  161. */
  162. ZStatus_t zclGeneral_RegisterCmdCallbacks( uint8 endpoint, zclGeneral_AppCallbacks_t *callbacks )
  163. {
  164. zclGenCBRec_t *pNewItem;
  165. zclGenCBRec_t *pLoop;
  166. // Register as a ZCL Plugin
  167. if ( zclGenPluginRegisted == FALSE )
  168. {
  169. zcl_registerPlugin( ZCL_CLUSTER_ID_GEN_BASIC,
  170. ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC,
  171. zclGeneral_HdlIncoming );
  172. #ifdef ZCL_SCENES
  173. // Initialize NV items
  174. zclGeneral_ScenesInitNV();
  175. // Restore the Scene table
  176. zclGeneral_ScenesRestoreFromNV();
  177. #endif // ZCL_SCENES
  178. zclGenPluginRegisted = TRUE;
  179. }
  180. // Fill in the new profile list
  181. pNewItem = osal_mem_alloc( sizeof( zclGenCBRec_t ) );
  182. if ( pNewItem == NULL )
  183. return (ZMemError);
  184. pNewItem->next = (zclGenCBRec_t *)NULL;
  185. pNewItem->endpoint = endpoint;
  186. pNewItem->CBs = callbacks;
  187. // Find spot in list
  188. if ( zclGenCBs == NULL )
  189. {
  190. zclGenCBs = pNewItem;
  191. }
  192. else
  193. {
  194. // Look for end of list
  195. pLoop = zclGenCBs;
  196. while ( pLoop->next != NULL )
  197. pLoop = pLoop->next;
  198. // Put new item at end of list
  199. pLoop->next = pNewItem;
  200. }
  201. return ( ZSuccess );
  202. }
  203. #ifdef ZCL_IDENTIFY
  204. /*********************************************************************
  205. * @fn zclGeneral_SendIdentify
  206. *
  207. * @brief Call to send out an Identify Command
  208. *
  209. * @param srcEP - Sending application's endpoint
  210. * @param dstAddr - where you want the message to go
  211. * @param identifyTime - how long the device will continue to identify itself (in seconds)
  212. * @param seqNum - identification number for the transaction
  213. *
  214. * @return ZStatus_t
  215. */
  216. ZStatus_t zclGeneral_SendIdentify( uint8 srcEP, afAddrType_t *dstAddr,
  217. uint16 identifyTime, uint8 disableDefaultRsp, uint8 seqNum )
  218. {
  219. uint8 buf[2];
  220. buf[0] = LO_UINT16( identifyTime );
  221. buf[1] = HI_UINT16( identifyTime );
  222. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
  223. COMMAND_IDENTIFY, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  224. disableDefaultRsp, 0, seqNum, 2, buf );
  225. }
  226. /*********************************************************************
  227. * @fn zclGeneral_SendIdentifyQueryResponse
  228. *
  229. * @brief Call to send out an Identify Query Response Command
  230. *
  231. * @param srcEP - Sending application's endpoint
  232. * @param dstAddr - where you want the message to go
  233. * @param timeout - how long the device will continue to identify itself (in seconds)
  234. * @param seqNum - identification number for the transaction
  235. *
  236. * @return ZStatus_t
  237. */
  238. ZStatus_t zclGeneral_SendIdentifyQueryResponse( uint8 srcEP, afAddrType_t *dstAddr,
  239. uint16 timeout, uint8 disableDefaultRsp, uint8 seqNum )
  240. {
  241. uint8 buf[2];
  242. buf[0] = LO_UINT16( timeout );
  243. buf[1] = HI_UINT16( timeout );
  244. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
  245. COMMAND_IDENTIFY_QUERY_RSP, TRUE,
  246. ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, 2, buf );
  247. }
  248. #endif // ZCL_IDENTIFY
  249. #ifdef ZCL_GROUPS
  250. /*********************************************************************
  251. * @fn zclGeneral_SendGroupRequest
  252. *
  253. * @brief Send a Group Request to a device. You can also use the
  254. * appropriate macro.
  255. *
  256. * @param srcEP - Sending Apps endpoint
  257. * @param dstAddr - where to send the request
  258. * @param cmd - one of the following:
  259. * COMMAND_GROUP_VIEW
  260. * COMMAND_GROUP_REMOVE
  261. * @param groupID -
  262. *
  263. * @return ZStatus_t
  264. */
  265. ZStatus_t zclGeneral_SendGroupRequest( uint8 srcEP, afAddrType_t *dstAddr,
  266. uint8 cmd, uint16 groupID, uint8 disableDefaultRsp, uint8 seqNum )
  267. {
  268. uint8 buf[2];
  269. buf[0] = LO_UINT16( groupID );
  270. buf[1] = HI_UINT16( groupID );
  271. return ( zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
  272. cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  273. disableDefaultRsp, 0, seqNum, 2, buf ) );
  274. }
  275. /*********************************************************************
  276. * @fn zclGeneral_SendAddGroupRequest
  277. *
  278. * @brief Send the Add Group Request to a device
  279. *
  280. * @param srcEP - Sending Apps endpoint
  281. * @param dstAddr - where to send the request
  282. * @param cmd - one of the following:
  283. * COMMAND_GROUP_ADD
  284. * COMMAND_GROUP_ADD_IF_IDENTIFYING
  285. * @param groupID - pointer to the group structure
  286. * @param groupName - pointer to Group Name. This is a Zigbee
  287. * string data type, so the first byte is the length of the
  288. * name (in bytes), then the name.
  289. *
  290. * @return ZStatus_t
  291. */
  292. ZStatus_t zclGeneral_SendAddGroupRequest( uint8 srcEP, afAddrType_t *dstAddr,
  293. uint8 cmd, uint16 groupID, uint8 *groupName,
  294. uint8 disableDefaultRsp, uint8 seqNum )
  295. {
  296. uint8 *buf;
  297. uint8 *pBuf;
  298. uint8 len;
  299. ZStatus_t status;
  300. len = 2; // Group ID
  301. len += groupName[0] + 1; // String + 1 for length
  302. buf = osal_mem_alloc( len );
  303. if ( buf )
  304. {
  305. pBuf = buf;
  306. *pBuf++ = LO_UINT16( groupID );
  307. *pBuf++ = HI_UINT16( groupID );
  308. *pBuf++ = groupName[0]; // string length
  309. osal_memcpy( pBuf, &(groupName[1]), groupName[0] );
  310. status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
  311. cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  312. disableDefaultRsp, 0, seqNum, len, buf );
  313. osal_mem_free( buf );
  314. }
  315. else
  316. status = ZMemError;
  317. return ( status );
  318. }
  319. /*********************************************************************
  320. * @fn zclGeneral_SendGroupGetMembershipRequest
  321. *
  322. * @brief Send a Get Group Membership (Resposne) Command to a device
  323. *
  324. * @param srcEP - Sending Apps endpoint
  325. * @param dstAddr - where to send the request
  326. * @param cmd - one of the following:
  327. * COMMAND_GROUP_GET_MEMBERSHIP
  328. * COMMAND_GROUP_GET_MEMBERSHIP_RSP
  329. * @param groupID - pointer to the group structure
  330. * @param groupName - pointer to Group Name. This is a Zigbee
  331. * string data type, so the first byte is the length of the
  332. * name (in bytes), then the name.
  333. *
  334. * @return ZStatus_t
  335. */
  336. ZStatus_t zclGeneral_SendGroupGetMembershipRequest( uint8 srcEP, afAddrType_t *dstAddr,
  337. uint8 cmd, uint8 rspCmd, uint8 direction, uint8 capacity,
  338. uint8 grpCnt, uint16 *grpList, uint8 disableDefaultRsp, uint8 seqNum )
  339. {
  340. uint8 *buf;
  341. uint8 *pBuf;
  342. uint8 len = 0;
  343. uint8 i;
  344. ZStatus_t status;
  345. if ( rspCmd )
  346. len++; // Capacity
  347. len++; // Group Count
  348. len += sizeof ( uint16 ) * grpCnt; // Group List
  349. buf = osal_mem_alloc( len );
  350. if ( buf )
  351. {
  352. pBuf = buf;
  353. if ( rspCmd )
  354. *pBuf++ = capacity;
  355. *pBuf++ = grpCnt;
  356. for ( i = 0; i < grpCnt; i++ )
  357. {
  358. *pBuf++ = LO_UINT16( grpList[i] );
  359. *pBuf++ = HI_UINT16( grpList[i] );
  360. }
  361. status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
  362. cmd, TRUE, direction,
  363. disableDefaultRsp, 0, seqNum, len, buf );
  364. osal_mem_free( buf );
  365. }
  366. else
  367. status = ZMemError;
  368. return ( status );
  369. }
  370. /*********************************************************************
  371. * @fn zclGeneral_SendGroupResponse
  372. *
  373. * @brief Send Group Response (not Group View Response)
  374. *
  375. * @param srcEP - Sending application's endpoint
  376. * @param dstAddr - where you want the message to go
  377. * @param cmd - either COMMAND_GROUP_ADD_RSP or COMMAND_GROUP_REMOVE_RSP
  378. * @param status - group command status
  379. * @param groupID - what group
  380. *
  381. * @return ZStatus_t
  382. */
  383. ZStatus_t zclGeneral_SendGroupResponse( uint8 srcEP, afAddrType_t *dstAddr,
  384. uint8 cmd, uint8 status, uint16 groupID,
  385. uint8 disableDefaultRsp, uint8 seqNum )
  386. {
  387. uint8 buf[3];
  388. buf[0] = status;
  389. buf[1] = LO_UINT16( groupID );
  390. buf[2] = HI_UINT16( groupID );
  391. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
  392. cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
  393. disableDefaultRsp, 0, seqNum, 3, buf );
  394. }
  395. /*********************************************************************
  396. * @fn zclGeneral_SendGroupViewResponse
  397. *
  398. * @brief Call to send Group Response Command
  399. *
  400. * @param srcEP - Sending application's endpoint
  401. * @param dstAddr - where you want the message to go
  402. * @param cmd - either COMMAND_GROUP_ADD_RSP or COMMAND_GROUP_REMOVE_RSP
  403. * @param status - group command status
  404. * @param grp - group info
  405. *
  406. * @return ZStatus_t
  407. */
  408. ZStatus_t zclGeneral_SendGroupViewResponse( uint8 srcEP, afAddrType_t *dstAddr,
  409. uint8 status, aps_Group_t *grp, uint8 disableDefaultRsp, uint8 seqNum )
  410. {
  411. uint8 *buf;
  412. uint8 len;
  413. ZStatus_t stat;
  414. len = 1 + 2; // Status + Group ID
  415. if ( status == ZCL_STATUS_SUCCESS )
  416. len += grp->name[0] + 1; // String + 1 for length
  417. buf = osal_mem_alloc( len );
  418. if ( buf )
  419. {
  420. buf[0] = status;
  421. buf[1] = LO_UINT16( grp->ID );
  422. buf[2] = HI_UINT16( grp->ID );
  423. if ( status == ZCL_STATUS_SUCCESS )
  424. {
  425. buf[3] = grp->name[0]; // string length
  426. osal_memcpy( &buf[4], (&grp->name[1]), grp->name[0] );
  427. }
  428. stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
  429. COMMAND_GROUP_VIEW_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
  430. disableDefaultRsp, 0, seqNum, len, buf );
  431. osal_mem_free( buf );
  432. }
  433. else
  434. stat = ZMemError;
  435. return ( stat );
  436. }
  437. #endif // ZCL_GROUPS
  438. #ifdef ZCL_SCENES
  439. /*********************************************************************
  440. * @fn zclGeneral_SendAddScene
  441. *
  442. * @brief Send the Add Scene Request to a device
  443. *
  444. * @param srcEP - Sending Apps endpoint
  445. * @param dstAddr - where to send the request
  446. * @param scene - pointer to the scene structure
  447. *
  448. * @return ZStatus_t
  449. */
  450. ZStatus_t zclGeneral_SendAddScene( uint8 srcEP, afAddrType_t *dstAddr,
  451. zclGeneral_Scene_t *scene, uint8 disableDefaultRsp, uint8 seqNum )
  452. {
  453. uint8 *buf;
  454. uint8 *pBuf;
  455. uint8 len;
  456. ZStatus_t status;
  457. len = 2 + 1 + 2; // Group ID + Scene ID + transition time
  458. len += scene->name[0] + 1; // String + 1 for length
  459. // Add something for the extension field length
  460. len += scene->extLen;
  461. buf = osal_mem_alloc( len );
  462. if ( buf )
  463. {
  464. pBuf = buf;
  465. *pBuf++ = LO_UINT16( scene->groupID );
  466. *pBuf++ = HI_UINT16( scene->groupID );
  467. *pBuf++ = scene->ID;
  468. *pBuf++ = LO_UINT16( scene->transTime );
  469. *pBuf++ = HI_UINT16( scene->transTime );
  470. *pBuf++ = scene->name[0]; // string length
  471. osal_memcpy( pBuf, &(scene->name[1]), scene->name[0] );
  472. pBuf += scene->name[0]; // move pass name
  473. // Add the extension fields
  474. if ( scene->extLen > 0 )
  475. osal_memcpy( pBuf, scene->extField, scene->extLen );
  476. status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
  477. COMMAND_SCENE_ADD, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  478. disableDefaultRsp, 0, seqNum, len, buf );
  479. osal_mem_free( buf );
  480. }
  481. else
  482. status = ZMemError;
  483. return ( status );
  484. }
  485. /*********************************************************************
  486. * @fn zclGeneral_SendSceneRequest
  487. *
  488. * @brief Send a Scene Request to a device. You can also use the
  489. * appropriate macro.
  490. *
  491. * @param srcEP - Sending Apps endpoint
  492. * @param dstAddr - where to send the request
  493. * @param cmd - one of the following:
  494. * COMMAND_SCENE_VIEW
  495. * COMMAND_SCENE_REMOVE
  496. * COMMAND_SCENE_REMOVE_ALL
  497. * COMMAND_SCENE_STORE
  498. * COMMAND_SCENE_RECALL
  499. * COMMAND_SCENE_GET_MEMBERSHIP
  500. * @param groupID - group ID
  501. * @param sceneID - scene ID (not applicable to COMMAND_SCENE_REMOVE_ALL and
  502. * COMMAND_SCENE_GET_MEMBERSHIP)
  503. * @return ZStatus_t
  504. */
  505. ZStatus_t zclGeneral_SendSceneRequest( uint8 srcEP, afAddrType_t *dstAddr,
  506. uint8 cmd, uint16 groupID, uint8 sceneID,
  507. uint8 disableDefaultRsp, uint8 seqNum )
  508. {
  509. uint8 buf[3];
  510. uint8 len = 2;
  511. buf[0] = LO_UINT16( groupID );
  512. buf[1] = HI_UINT16( groupID );
  513. if ( cmd != COMMAND_SCENE_REMOVE_ALL && cmd != COMMAND_SCENE_GET_MEMBERSHIP )
  514. {
  515. buf[2] = sceneID;
  516. len++;
  517. }
  518. return ( zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
  519. cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  520. disableDefaultRsp, 0, seqNum, len, buf ) );
  521. }
  522. /*********************************************************************
  523. * @fn zclGeneral_SendSceneResponse
  524. *
  525. * @brief Send Group Response (not Group View Response)
  526. *
  527. * @param srcEP - Sending application's endpoint
  528. * @param dstAddr - where you want the message to go
  529. * @param cmd - either COMMAND_SCENE_ADD_RSP, COMMAND_SCENE_REMOVE_RSP
  530. * COMMAND_SCENE_STORE_RSP, or COMMAND_SCENE_REMOVE_ALL_RSP
  531. * @param status - scene command status
  532. * @param groupID - what group
  533. * @param sceneID - what scene (not applicable to COMMAND_SCENE_REMOVE_ALL_RSP)
  534. *
  535. * @return ZStatus_t
  536. */
  537. ZStatus_t zclGeneral_SendSceneResponse( uint8 srcEP, afAddrType_t *dstAddr,
  538. uint8 cmd, uint8 status, uint16 groupID,
  539. uint8 sceneID, uint8 disableDefaultRsp, uint8 seqNum )
  540. {
  541. uint8 buf[4];
  542. uint8 len = 1 + 2; // Status + Group ID
  543. buf[0] = status;
  544. buf[1] = LO_UINT16( groupID );
  545. buf[2] = HI_UINT16( groupID );
  546. if ( cmd != COMMAND_SCENE_REMOVE_ALL_RSP )
  547. {
  548. buf[3] = sceneID;
  549. len++;
  550. }
  551. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
  552. cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
  553. disableDefaultRsp, 0, seqNum, len, buf );
  554. }
  555. /*********************************************************************
  556. * @fn zclGeneral_SendSceneViewResponse
  557. *
  558. * @brief Call to send Scene Response Command
  559. *
  560. * @param srcEP - Sending application's endpoint
  561. * @param dstAddr - where you want the message to go
  562. * @param status - scene command status
  563. * @param scene - scene info
  564. *
  565. * @return ZStatus_t
  566. */
  567. ZStatus_t zclGeneral_SendSceneViewResponse( uint8 srcEP, afAddrType_t *dstAddr,
  568. uint8 status, zclGeneral_Scene_t *scene,
  569. uint8 disableDefaultRsp, uint8 seqNum )
  570. {
  571. uint8 *buf;
  572. uint8 *pBuf;
  573. uint8 len = 1 + 2 + 1; // Status + Group ID + Scene ID
  574. ZStatus_t stat;
  575. if ( status == ZCL_STATUS_SUCCESS )
  576. {
  577. len += 2; // Transition Time
  578. len += scene->name[0] + 1; // string + 1 for length
  579. // Add something for the extension field length
  580. len += scene->extLen;
  581. }
  582. buf = osal_mem_alloc( len );
  583. if ( buf )
  584. {
  585. pBuf = buf;
  586. *pBuf++ = status;
  587. *pBuf++ = LO_UINT16( scene->groupID );
  588. *pBuf++ = HI_UINT16( scene->groupID );
  589. *pBuf++ = scene->ID;
  590. if ( status == ZCL_STATUS_SUCCESS )
  591. {
  592. *pBuf++ = LO_UINT16( scene->transTime );
  593. *pBuf++ = HI_UINT16( scene->transTime );
  594. *pBuf++ = scene->name[0]; // string length
  595. if ( scene->name[0] != 0 )
  596. {
  597. osal_memcpy( pBuf, &(scene->name[1]), scene->name[0] );
  598. pBuf += scene->name[0]; // move pass name
  599. }
  600. // Add the extension fields
  601. if ( scene->extLen > 0 )
  602. osal_memcpy( pBuf, scene->extField, scene->extLen );
  603. }
  604. stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
  605. COMMAND_SCENE_VIEW_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
  606. disableDefaultRsp, 0, seqNum, len, buf );
  607. osal_mem_free( buf );
  608. }
  609. else
  610. stat = ZMemError;
  611. return ( stat );
  612. }
  613. /*********************************************************************
  614. * @fn zclGeneral_SendSceneGetMembershipResponse
  615. *
  616. * @brief Call to send Scene Get Membership Response Command
  617. *
  618. * @param srcEP - Sending application's endpoint
  619. * @param dstAddr - where you want the message to go
  620. * @param status - scene command status
  621. * @param capacity - remaining capacity of the scene table
  622. * @param sceneCnt - number of scenes in the scene list
  623. * @param sceneList - list of scene IDs
  624. * @param groupID - group ID that scene belongs to
  625. * @param seqNum - sequence number
  626. *
  627. * @return ZStatus_t
  628. */
  629. ZStatus_t zclGeneral_SendSceneGetMembershipResponse( uint8 srcEP, afAddrType_t *dstAddr,
  630. uint8 status, uint8 capacity, uint8 sceneCnt, uint8 *sceneList,
  631. uint16 groupID, uint8 disableDefaultRsp, uint8 seqNum )
  632. {
  633. uint8 *buf;
  634. uint8 *pBuf;
  635. uint8 len = 1 + 1 + 2; // Status + Capacity + Group ID;
  636. uint8 i;
  637. ZStatus_t stat;
  638. if ( status == ZCL_STATUS_SUCCESS )
  639. {
  640. len++; // Scene Count
  641. len += sceneCnt; // Scene List (Scene ID is a single octet)
  642. }
  643. buf = osal_mem_alloc( len );
  644. if ( buf )
  645. {
  646. pBuf = buf;
  647. *pBuf++ = status;
  648. *pBuf++ = capacity;
  649. *pBuf++ = LO_UINT16( groupID );
  650. *pBuf++ = HI_UINT16( groupID );
  651. if ( status == ZCL_STATUS_SUCCESS )
  652. {
  653. *pBuf++ = sceneCnt;
  654. for ( i = 0; i < sceneCnt; i++ )
  655. *pBuf++ = sceneList[i];
  656. }
  657. stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
  658. COMMAND_SCENE_GET_MEMBERSHIP_RSP, TRUE,
  659. ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
  660. osal_mem_free( buf );
  661. }
  662. else
  663. stat = ZMemError;
  664. return ( stat );
  665. }
  666. #endif // ZCL_SCENES
  667. #ifdef ZCL_LEVEL_CTRL
  668. /*********************************************************************
  669. * @fn zclGeneral_SendLevelControlMoveToLevelRequest
  670. *
  671. * @brief Call to send out a Level Control Request. You can also use
  672. * the appropriate macro.
  673. *
  674. * @param srcEP - Sending application's endpoint
  675. * @param dstAddr - where you want the message to go
  676. * @param cmd - one of the following:
  677. * COMMAND_LEVEL_MOVE_TO_LEVEL or
  678. * COMMAND_LEVEL_MOVE_TO_LEVEL_WITH_ON_OFF
  679. * @param level - what level to move to
  680. * @param transitionTime - how long to take to get to the level (in seconds)
  681. *
  682. * @return ZStatus_t
  683. */
  684. ZStatus_t zclGeneral_SendLevelControlMoveToLevelRequest( uint8 srcEP, afAddrType_t *dstAddr,
  685. uint8 cmd, uint8 level, uint16 transTime,
  686. uint8 disableDefaultRsp, uint8 seqNum )
  687. {
  688. uint8 buf[3];
  689. buf[0] = level;
  690. buf[1] = LO_UINT16( transTime );
  691. buf[2] = HI_UINT16( transTime );
  692. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
  693. cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  694. disableDefaultRsp, 0, seqNum, 3, buf );
  695. }
  696. /*********************************************************************
  697. * @fn zclGeneral_SendLevelControlMoveRequest
  698. *
  699. * @brief Call to send out a Level Control Request. You can also use
  700. * the appropriate macro.
  701. *
  702. * @param srcEP - Sending application's endpoint
  703. * @param dstAddr - where you want the message to go
  704. * @param cmd - one of the following:
  705. * COMMAND_LEVEL_MOVE or
  706. * COMMAND_LEVEL_MOVE_WITH_ON_OFF
  707. * @param moveMode - LEVEL_MOVE_UP or
  708. * LEVEL_MOVE_DOWN
  709. * @param rate - number of steps to take per second
  710. *
  711. * @return ZStatus_t
  712. */
  713. ZStatus_t zclGeneral_SendLevelControlMoveRequest( uint8 srcEP, afAddrType_t *dstAddr,
  714. uint8 cmd, uint8 moveMode, uint8 rate,
  715. uint8 disableDefaultRsp, uint8 seqNum )
  716. {
  717. uint8 buf[2];
  718. buf[0] = moveMode;
  719. buf[1] = rate;
  720. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
  721. cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  722. disableDefaultRsp, 0, seqNum, 2, buf );
  723. }
  724. /*********************************************************************
  725. * @fn zclGeneral_SendLevelControlStepRequest
  726. *
  727. * @brief Call to send out a Level Control Request. You can also use
  728. * the appropriate macro.
  729. *
  730. * @param srcEP - Sending application's endpoint
  731. * @param dstAddr - where you want the message to go
  732. * @param cmd - one of the following:
  733. * COMMAND_LEVEL_STEP
  734. * COMMAND_LEVEL_STEP_WITH_ON_OFF
  735. * @param stepMode - LEVEL_STEP_UP or
  736. * LEVEL_STEP_DOWN
  737. * @param amount - number of levels to step
  738. * @param transitionTime - time, in 1/10ths of a second, to take to perform the step
  739. *
  740. * @return ZStatus_t
  741. */
  742. ZStatus_t zclGeneral_SendLevelControlStepRequest( uint8 srcEP, afAddrType_t *dstAddr,
  743. uint8 cmd, uint8 stepMode, uint8 stepSize, uint16 transTime,
  744. uint8 disableDefaultRsp, uint8 seqNum )
  745. {
  746. uint8 buf[4];
  747. buf[0] = stepMode;
  748. buf[1] = stepSize;
  749. buf[2] = LO_UINT16( transTime );
  750. buf[3] = HI_UINT16( transTime );
  751. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
  752. cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  753. disableDefaultRsp, 0, seqNum, 4, buf );
  754. }
  755. #endif // ZCL_LEVEL_CTRL
  756. #ifdef ZCL_ALARMS
  757. /*********************************************************************
  758. * @fn zclGeneral_SendAlarmRequest
  759. *
  760. * @brief Call to send out an Alarm Request Command
  761. *
  762. * @param srcEP - Sending application's endpoint
  763. * @param dstAddr - where you want the message to go
  764. * @param cmd - either COMMAND_ALARMS_RESET or COMMAND_ALARMS_ALARM
  765. * @param alarmCode - code for the cause of the alarm
  766. * @param clusterID - cluster whose attribute generate the alarm
  767. *
  768. * @return ZStatus_t
  769. */
  770. ZStatus_t zclGeneral_SendAlarmRequest( uint8 srcEP, afAddrType_t *dstAddr,
  771. uint8 cmd, uint8 alarmCode, uint16 clusterID,
  772. uint8 disableDefaultRsp, uint8 seqNum )
  773. {
  774. uint8 buf[3];
  775. buf[0] = alarmCode;
  776. buf[1] = LO_UINT16( clusterID );
  777. buf[2] = HI_UINT16( clusterID );
  778. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
  779. cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  780. disableDefaultRsp, 0, seqNum, 3, buf );
  781. }
  782. /*********************************************************************
  783. * @fn zclGeneral_SendAlarmGetRespnose
  784. *
  785. * @brief Call to send out an Alarm Get Response Command
  786. *
  787. * @param srcEP - Sending application's endpoint
  788. * @param dstAddr - where you want the message to go
  789. * @param status - SUCCESS or NOT_FOUND
  790. * @param alarmCode - code for the cause of the alarm
  791. * @param clusterID - cluster whose attribute generate the alarm
  792. * @param timeStamp - time at which the alarm occured
  793. *
  794. * @return ZStatus_t
  795. */
  796. ZStatus_t zclGeneral_SendAlarmGetRespnose( uint8 srcEP, afAddrType_t *dstAddr,
  797. uint8 status, uint8 alarmCode, uint16 clusterID,
  798. uint32 timeStamp, uint8 disableDefaultRsp, uint8 seqNum )
  799. {
  800. uint8 buf[8];
  801. uint8 len = 1; // Status
  802. buf[0] = status;
  803. if ( status == ZCL_STATUS_SUCCESS )
  804. {
  805. len += 1 + 2 + 4; // Alarm code + Cluster ID + Time stamp
  806. buf[1] = alarmCode;
  807. buf[2] = LO_UINT16( clusterID );
  808. buf[3] = HI_UINT16( clusterID );
  809. osal_buffer_uint32( &buf[4], timeStamp );
  810. }
  811. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
  812. COMMAND_ALARMS_GET_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
  813. disableDefaultRsp, 0, seqNum, len, buf );
  814. }
  815. #ifdef SE_UK_EXT
  816. /*********************************************************************
  817. * @fn zclGeneral_SendAlarmGetEventLog
  818. *
  819. * @brief Call to send out an Alarm Get Event Log Command
  820. *
  821. * @param srcEP - Sending application's endpoint
  822. * @param dstAddr - where you want the message to go
  823. * @param pEventLog - pointer to Get Event Log Command
  824. * @param disableDefaultRsp - disable default response
  825. * @param seqNum - ZCL sequence number
  826. *
  827. * @return ZStatus_t
  828. */
  829. ZStatus_t zclGeneral_SendAlarmGetEventLog( uint8 srcEP, afAddrType_t *dstAddr,
  830. zclGetEventLog_t *pEventLog,
  831. uint8 disableDefaultRsp, uint8 seqNum )
  832. {
  833. uint8 buf[10];
  834. buf[0] = pEventLog->logID;
  835. osal_buffer_uint32( &buf[1], pEventLog->startTime );
  836. osal_buffer_uint32( &buf[5], pEventLog->endTime );
  837. buf[9] = pEventLog->numEvents;
  838. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
  839. COMMAND_ALARMS_GET_EVENT_LOG, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
  840. disableDefaultRsp, 0, seqNum, 10, buf );
  841. }
  842. /*********************************************************************
  843. * @fn zclGeneral_SendAlarmPublishEventLog
  844. *
  845. * @brief Call to send out an Alarm Publish Event Log Command
  846. *
  847. * @param srcEP - Sending application's endpoint
  848. * @param dstAddr - where you want the message to go
  849. * @param pEventLog - pointer to Publish Event Log Command
  850. * @param disableDefaultRsp - disable default response
  851. * @param seqNum - ZCL sequence number
  852. *
  853. * @return ZStatus_t
  854. */
  855. ZStatus_t zclGeneral_SendAlarmPublishEventLog( uint8 srcEP, afAddrType_t *dstAddr,
  856. zclPublishEventLog_t *pEventLog,
  857. uint8 disableDefaultRsp, uint8 seqNum )
  858. {
  859. uint8 *buf;
  860. uint8 *pBuf;
  861. uint8 bufLen;
  862. // Log ID + Command Index + Total Commands + (numSubLogs * ( Event ID + Event Time))
  863. bufLen = 1 + 1 + 1 + (pEventLog->numSubLogs * (1 + 4));
  864. buf = osal_mem_alloc( bufLen );
  865. if ( buf == NULL )
  866. {
  867. return (ZMemError);
  868. }
  869. pBuf = buf;
  870. *pBuf++ = pEventLog->logID;
  871. *pBuf++ = pEventLog->cmdIndex;
  872. *pBuf++ = pEventLog->totalCmds;
  873. for ( uint8 i = 0; i < pEventLog->numSubLogs; i++ )
  874. {
  875. zclEventLogPayload_t *pLogs = &(pEventLog->pLogs[i]);
  876. *pBuf++ = pLogs->eventId;
  877. pBuf = osal_buffer_uint32( pBuf, pLogs->eventTime );
  878. }
  879. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
  880. COMMAND_ALARMS_PUBLISH_EVENT_LOG, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
  881. disableDefaultRsp, 0, seqNum, bufLen, buf );
  882. }
  883. #endif // SE_UK_EXT
  884. #endif // ZCL_ALARMS
  885. #ifdef ZCL_LOCATION
  886. /*********************************************************************
  887. * @fn zclGeneral_SendLocationSetAbsolute
  888. *
  889. * @brief Call to send out a Set Absolute Location Command
  890. *
  891. * @param srcEP - Sending application's endpoint
  892. * @param dstAddr - where you want the message to go
  893. * @param absLoc - absolute location info
  894. *
  895. * @return ZStatus_t
  896. */
  897. ZStatus_t zclGeneral_SendLocationSetAbsolute( uint8 srcEP, afAddrType_t *dstAddr,
  898. zclLocationAbsolute_t *absLoc,
  899. uint8 disableDefaultRsp, uint8 seqNum )
  900. {
  901. uint8 buf[10]; // 5 fields (2 octects each)
  902. buf[0] = LO_UINT16( absLoc->coordinate1 );
  903. buf[1] = HI_UINT16( absLoc->coordinate1 );
  904. buf[2] = LO_UINT16( absLoc->coordinate2 );
  905. buf[3] = HI_UINT16( absLoc->coordinate2 );
  906. buf[4] = LO_UINT16( absLoc->coordinate3 );
  907. buf[5] = HI_UINT16( absLoc->coordinate3 );
  908. buf[6] = LO_UINT16( absLoc->power );
  909. buf[7] = HI_UINT16( absLoc->power );
  910. buf[8] = LO_UINT16( absLoc->pathLossExponent );
  911. buf[9] = HI_UINT16( absLoc->pathLossExponent );
  912. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  913. COMMAND_LOCATION_SET_ABSOLUTE, TRUE,
  914. ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 10, buf );
  915. }
  916. /*********************************************************************
  917. * @fn zclGeneral_SendLocationSetDevCfg
  918. *
  919. * @brief Call to send out a Set Device Configuration Command
  920. *
  921. * @param srcEP - Sending application's endpoint
  922. * @param dstAddr - where you want the message to go
  923. * @param devCfg - device configuration info
  924. *
  925. * @return ZStatus_t
  926. */
  927. ZStatus_t zclGeneral_SendLocationSetDevCfg( uint8 srcEP, afAddrType_t *dstAddr,
  928. zclLocationDevCfg_t *devCfg,
  929. uint8 disableDefaultRsp, uint8 seqNum )
  930. {
  931. uint8 buf[9]; // 4 fields (2 octects each) + 1 field with 1 octect
  932. buf[0] = LO_UINT16( devCfg->power );
  933. buf[1] = HI_UINT16( devCfg->power );
  934. buf[2] = LO_UINT16( devCfg->pathLossExponent );
  935. buf[3] = HI_UINT16( devCfg->pathLossExponent );
  936. buf[4] = LO_UINT16( devCfg->calcPeriod );
  937. buf[5] = HI_UINT16( devCfg->calcPeriod );
  938. buf[6] = devCfg->numMeasurements;
  939. buf[7] = LO_UINT16( devCfg->reportPeriod );
  940. buf[8] = HI_UINT16( devCfg->reportPeriod );
  941. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  942. COMMAND_LOCATION_SET_DEV_CFG, TRUE,
  943. ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 9, buf );
  944. }
  945. /*********************************************************************
  946. * @fn zclGeneral_SendLocationGetDevCfg
  947. *
  948. * @brief Call to send out a Get Device Configuration Command
  949. *
  950. * @param srcEP - Sending application's endpoint
  951. * @param dstAddr - where you want the message to go
  952. * @param targetAddr - device for which location parameters are being requested
  953. *
  954. * @return ZStatus_t
  955. */
  956. ZStatus_t zclGeneral_SendLocationGetDevCfg( uint8 srcEP, afAddrType_t *dstAddr,
  957. uint8 *targetAddr, uint8 disableDefaultRsp, uint8 seqNum )
  958. {
  959. uint8 buf[8];
  960. osal_cpyExtAddr( buf, targetAddr );
  961. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  962. COMMAND_LOCATION_GET_DEV_CFG, TRUE,
  963. ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 8, buf );
  964. }
  965. /*********************************************************************
  966. * @fn zclGeneral_SendLocationGetData
  967. *
  968. * @brief Call to send out a Get Location Data Command
  969. *
  970. * @param srcEP - Sending application's endpoint
  971. * @param dstAddr - where you want the message to go
  972. * @param locaData - location information and channel parameters that are requested.
  973. *
  974. * @return ZStatus_t
  975. */
  976. ZStatus_t zclGeneral_SendLocationGetData( uint8 srcEP, afAddrType_t *dstAddr,
  977. zclLocationGetData_t *locData,
  978. uint8 disableDefaultRsp, uint8 seqNum )
  979. {
  980. uint8 buf[10]; // bitmap (1) + number responses (1) + IEEE Address (8)
  981. uint8 *pBuf = buf;
  982. uint8 len = 2; // bitmap + number responses
  983. *pBuf = locData->absoluteOnly;
  984. *pBuf |= locData->recalculate << 1;
  985. *pBuf |= locData->brdcastIndicator << 2;
  986. *pBuf |= locData->brdcastResponse << 3;
  987. *pBuf |= locData->compactResponse << 4;
  988. pBuf++; // move past the bitmap field
  989. *pBuf++ = locData->numResponses;
  990. if ( locData->brdcastIndicator == 0 )
  991. {
  992. osal_cpyExtAddr( pBuf, locData->targetAddr );
  993. len += 8; // ieee addr
  994. }
  995. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  996. COMMAND_LOCATION_GET_DATA, TRUE,
  997. ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, len, buf );
  998. }
  999. /*********************************************************************
  1000. * @fn zclGeneral_SendLocationDevCfgResponse
  1001. *
  1002. * @brief Call to send out a Device Configuration Response Command
  1003. *
  1004. * @param srcEP - Sending application's endpoint
  1005. * @param dstAddr - where you want the message to go
  1006. * @param devCfg - device's location parameters that are requested
  1007. *
  1008. * @return ZStatus_t
  1009. */
  1010. ZStatus_t zclGeneral_SendLocationDevCfgResponse( uint8 srcEP, afAddrType_t *dstAddr,
  1011. zclLocationDevCfgRsp_t *devCfg,
  1012. uint8 disableDefaultRsp, uint8 seqNum )
  1013. {
  1014. uint8 buf[10]; // 4 fields (2 octects each) + 2 fields (1 octect each)
  1015. uint8 len = 1; // Status
  1016. buf[0] = devCfg->status;
  1017. if ( devCfg->status == ZCL_STATUS_SUCCESS )
  1018. {
  1019. buf[1] = LO_UINT16( devCfg->data.power );
  1020. buf[2] = HI_UINT16( devCfg->data.power );
  1021. buf[3] = LO_UINT16( devCfg->data.pathLossExponent );
  1022. buf[4] = HI_UINT16( devCfg->data.pathLossExponent );
  1023. buf[5] = LO_UINT16( devCfg->data.calcPeriod );
  1024. buf[6] = HI_UINT16( devCfg->data.calcPeriod );
  1025. buf[7] = devCfg->data.numMeasurements;
  1026. buf[8] = LO_UINT16( devCfg->data.reportPeriod );
  1027. buf[9] = HI_UINT16( devCfg->data.reportPeriod );
  1028. len += 9;
  1029. }
  1030. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  1031. COMMAND_LOCATION_DEV_CFG_RSP, TRUE,
  1032. ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
  1033. }
  1034. /*********************************************************************
  1035. * @fn zclGeneral_SendLocationData
  1036. *
  1037. * @brief Call to send out location data
  1038. *
  1039. * @param srcEP - Sending application's endpoint
  1040. * @param dstAddr - where you want the message to go
  1041. * @param status - indicates whether response to request was successful or not
  1042. * @param locData - location information and channel parameters being sent
  1043. *
  1044. * @return ZStatus_t
  1045. */
  1046. ZStatus_t zclGeneral_SendLocationData( uint8 srcEP, afAddrType_t *dstAddr, uint8 cmd,
  1047. uint8 status, zclLocationData_t *locData,
  1048. uint8 disableDefaultRsp, uint8 seqNum )
  1049. {
  1050. uint8 buf[16];
  1051. uint8 *pBuf = buf;
  1052. uint8 len = 0;
  1053. if ( cmd == COMMAND_LOCATION_DATA_RSP )
  1054. {
  1055. // Only response command includes a status field
  1056. *pBuf++ = status;
  1057. len++;
  1058. }
  1059. if ( cmd != COMMAND_LOCATION_DATA_RSP || status == ZCL_STATUS_SUCCESS )
  1060. {
  1061. // Notification or Response with successful status
  1062. *pBuf++ = locData->type;
  1063. *pBuf++ = LO_UINT16( locData->absLoc.coordinate1 );
  1064. *pBuf++ = HI_UINT16( locData->absLoc.coordinate1 );
  1065. *pBuf++ = LO_UINT16( locData->absLoc.coordinate2 );
  1066. *pBuf++ = HI_UINT16( locData->absLoc.coordinate2 );
  1067. len += 5;
  1068. if ( locationType2D(locData->type) == 0 )
  1069. {
  1070. // 2D location doesn't have coordinate 3
  1071. *pBuf++ = LO_UINT16( locData->absLoc.coordinate3 );
  1072. *pBuf++ = HI_UINT16( locData->absLoc.coordinate3 );
  1073. len += 2;
  1074. }
  1075. if ( cmd != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
  1076. {
  1077. // Compact notification doesn't include these fields
  1078. *pBuf++ = LO_UINT16( locData->absLoc.power );
  1079. *pBuf++ = HI_UINT16( locData->absLoc.power );
  1080. *pBuf++ = LO_UINT16( locData->absLoc.pathLossExponent );
  1081. *pBuf++ = HI_UINT16( locData->absLoc.pathLossExponent );
  1082. len += 4;
  1083. }
  1084. if ( locationTypeAbsolute(locData->type) == 0 )
  1085. {
  1086. // Absolute location doesn't include these fields
  1087. if ( cmd != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
  1088. {
  1089. // Compact notification doesn't include this field
  1090. *pBuf++ = locData->calcLoc.locationMethod;
  1091. len++;
  1092. }
  1093. *pBuf++ = locData->calcLoc.qualityMeasure;
  1094. *pBuf++ = LO_UINT16( locData->calcLoc.locationAge );
  1095. *pBuf++ = HI_UINT16( locData->calcLoc.locationAge );
  1096. len += 3;
  1097. }
  1098. }
  1099. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  1100. cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
  1101. disableDefaultRsp, 0, seqNum, len, buf );
  1102. }
  1103. #endif // ZCL_LOCATION
  1104. /*********************************************************************
  1105. * @fn zclGeneral_FindCallbacks
  1106. *
  1107. * @brief Find the callbacks for an endpoint
  1108. *
  1109. * @param endpoint - endpoint to find the application callbacks for
  1110. *
  1111. * @return pointer to the callbacks
  1112. */
  1113. static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint )
  1114. {
  1115. zclGenCBRec_t *pCBs;
  1116. pCBs = zclGenCBs;
  1117. while ( pCBs )
  1118. {
  1119. if ( pCBs->endpoint == endpoint )
  1120. return ( pCBs->CBs );
  1121. pCBs = pCBs->next;
  1122. }
  1123. return ( (zclGeneral_AppCallbacks_t *)NULL );
  1124. }
  1125. /*********************************************************************
  1126. * @fn zclGeneral_HdlIncoming
  1127. *
  1128. * @brief Callback from ZCL to process incoming Commands specific
  1129. * to this cluster library or Profile commands for attributes
  1130. * that aren't in the attribute list
  1131. *
  1132. *
  1133. * @param pInMsg - pointer to the incoming message
  1134. *
  1135. * @return ZStatus_t
  1136. */
  1137. static ZStatus_t zclGeneral_HdlIncoming( zclIncoming_t *pInMsg )
  1138. {
  1139. ZStatus_t stat = ZSuccess;
  1140. #if defined ( INTER_PAN )
  1141. if ( StubAPS_InterPan( pInMsg->msg->srcAddr.panId, pInMsg->msg->srcAddr.endPoint ) )
  1142. return ( stat ); // Cluster not supported thru Inter-PAN
  1143. #endif
  1144. if ( zcl_ClusterCmd( pInMsg->hdr.fc.type ) )
  1145. {
  1146. // Is this a manufacturer specific command?
  1147. if ( pInMsg->hdr.fc.manuSpecific == 0 )
  1148. {
  1149. stat = zclGeneral_HdlInSpecificCommands( pInMsg );
  1150. }
  1151. else
  1152. {
  1153. // We don't support any manufacturer specific command.
  1154. stat = ZFailure;
  1155. }
  1156. }
  1157. else
  1158. {
  1159. // Handle all the normal (Read, Write...) commands -- should never get here
  1160. stat = ZFailure;
  1161. }
  1162. return ( stat );
  1163. }
  1164. /*********************************************************************
  1165. * @fn zclGeneral_HdlInSpecificCommands
  1166. *
  1167. * @brief Callback from ZCL to process incoming Commands specific
  1168. * to this cluster library
  1169. * @param pInMsg - pointer to the incoming message
  1170. *
  1171. * @return ZStatus_t
  1172. */
  1173. static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg )
  1174. {
  1175. ZStatus_t stat;
  1176. zclGeneral_AppCallbacks_t *pCBs;
  1177. // make sure endpoint exists
  1178. pCBs = zclGeneral_FindCallbacks( pInMsg->msg->endPoint );
  1179. if ( pCBs == NULL )
  1180. return ( ZFailure );
  1181. switch ( pInMsg->msg->clusterId )
  1182. {
  1183. #ifdef ZCL_BASIC
  1184. case ZCL_CLUSTER_ID_GEN_BASIC:
  1185. stat = zclGeneral_ProcessInBasic( pInMsg, pCBs );
  1186. break;
  1187. #endif // ZCL_BASIC
  1188. #ifdef ZCL_IDENTIFY
  1189. case ZCL_CLUSTER_ID_GEN_IDENTIFY:
  1190. stat = zclGeneral_ProcessInIdentity( pInMsg, pCBs );
  1191. break;
  1192. #endif // ZCL_IDENTIFY
  1193. #ifdef ZCL_GROUPS
  1194. case ZCL_CLUSTER_ID_GEN_GROUPS:
  1195. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1196. stat = zclGeneral_ProcessInGroupsServer( pInMsg );
  1197. else
  1198. stat = zclGeneral_ProcessInGroupsClient( pInMsg, pCBs );
  1199. break;
  1200. #endif // ZCL_GROUPS
  1201. #ifdef ZCL_SCENES
  1202. case ZCL_CLUSTER_ID_GEN_SCENES:
  1203. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1204. stat = zclGeneral_ProcessInScenesServer( pInMsg, pCBs );
  1205. else
  1206. stat = zclGeneral_ProcessInScenesClient( pInMsg, pCBs );
  1207. break;
  1208. #endif // ZCL_SCENES
  1209. #ifdef ZCL_ON_OFF
  1210. case ZCL_CLUSTER_ID_GEN_ON_OFF:
  1211. stat = zclGeneral_ProcessInOnOff( pInMsg, pCBs );
  1212. break;
  1213. #endif // ZCL_ON_OFF
  1214. #ifdef ZCL_LEVEL_CTRL
  1215. case ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL:
  1216. stat = zclGeneral_ProcessInLevelControl( pInMsg, pCBs );
  1217. break;
  1218. #endif // ZCL_LEVEL_CTRL
  1219. #ifdef ZCL_ALARMS
  1220. case ZCL_CLUSTER_ID_GEN_ALARMS:
  1221. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1222. stat = zclGeneral_ProcessInAlarmsServer( pInMsg, pCBs );
  1223. else
  1224. stat = zclGeneral_ProcessInAlarmsClient( pInMsg, pCBs );
  1225. break;
  1226. #endif // ZCL_ALARMS
  1227. #ifdef ZCL_LOCATION
  1228. case ZCL_CLUSTER_ID_GEN_LOCATION:
  1229. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1230. stat = zclGeneral_ProcessInLocationServer( pInMsg, pCBs );
  1231. else
  1232. stat = zclGeneral_ProcessInLocationClient( pInMsg, pCBs );
  1233. break;
  1234. #endif // ZCL_LOCATION
  1235. case ZCL_CLUSTER_ID_GEN_POWER_CFG:
  1236. case ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG:
  1237. case ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG:
  1238. case ZCL_CLUSTER_ID_GEN_TIME:
  1239. default:
  1240. stat = ZFailure;
  1241. break;
  1242. }
  1243. return ( stat );
  1244. }
  1245. #ifdef ZCL_BASIC
  1246. /*********************************************************************
  1247. * @fn zclGeneral_ProcessInBasic
  1248. *
  1249. * @brief Process in the received Basic Command.
  1250. *
  1251. * @param pInMsg - pointer to the incoming message
  1252. *
  1253. * @return ZStatus_t
  1254. */
  1255. static ZStatus_t zclGeneral_ProcessInBasic( zclIncoming_t *pInMsg,
  1256. zclGeneral_AppCallbacks_t *pCBs )
  1257. {
  1258. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1259. {
  1260. if ( pInMsg->hdr.commandID > COMMAND_BASIC_RESET_FACT_DEFAULT )
  1261. return ( ZFailure ); // Error ignore the command
  1262. if ( pCBs->pfnBasicReset )
  1263. pCBs->pfnBasicReset();
  1264. }
  1265. // no Client command
  1266. return ( ZSuccess );
  1267. }
  1268. #endif // ZCL_BASIC
  1269. #ifdef ZCL_IDENTIFY
  1270. /*********************************************************************
  1271. * @fn zclGeneral_ProcessInIdentity
  1272. *
  1273. * @brief Process in the received Identity Command.
  1274. *
  1275. * @param pInMsg - pointer to the incoming message
  1276. *
  1277. * @return ZStatus_t
  1278. */
  1279. static ZStatus_t zclGeneral_ProcessInIdentity( zclIncoming_t *pInMsg,
  1280. zclGeneral_AppCallbacks_t *pCBs )
  1281. {
  1282. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1283. {
  1284. if ( pInMsg->hdr.commandID > COMMAND_IDENTIFY_QUERY )
  1285. return ( ZFailure ); // Error ignore the command
  1286. if ( pInMsg->hdr.commandID == COMMAND_IDENTIFY )
  1287. {
  1288. if ( pCBs->pfnIdentify )
  1289. {
  1290. zclIdentify_t cmd;
  1291. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  1292. cmd.identifyTime = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
  1293. pCBs->pfnIdentify( &cmd );
  1294. }
  1295. }
  1296. else
  1297. {
  1298. zclAttrRec_t attrRec;
  1299. uint16 identifyTime = 0;
  1300. // Retrieve Identify Time
  1301. if ( zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, ATTRID_IDENTIFY_TIME, &attrRec ) )
  1302. zclReadAttrData( (uint8 *)&identifyTime, &attrRec, NULL );
  1303. // Is device identifying itself?
  1304. if ( identifyTime > 0 )
  1305. {
  1306. zclGeneral_SendIdentifyQueryResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1307. identifyTime, true, pInMsg->hdr.transSeqNum );
  1308. }
  1309. return ( ZCL_STATUS_CMD_HAS_RSP );
  1310. }
  1311. }
  1312. else // Client Command
  1313. {
  1314. if ( pInMsg->hdr.commandID > COMMAND_IDENTIFY_QUERY_RSP )
  1315. return ( ZFailure ); // Error ignore the command
  1316. if ( pCBs->pfnIdentifyQueryRsp )
  1317. {
  1318. zclIdentifyQueryRsp_t rsp;
  1319. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  1320. rsp.timeout = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
  1321. pCBs->pfnIdentifyQueryRsp( &rsp );
  1322. }
  1323. }
  1324. return ( ZSuccess );
  1325. }
  1326. #endif // ZCL_IDENTIFY
  1327. #ifdef ZCL_GROUPS
  1328. /*********************************************************************
  1329. * @fn zclGeneral_AddGroup
  1330. *
  1331. * @brief Add a Group.
  1332. *
  1333. * @param endPoint - application endpoint
  1334. * @param group - group to be added
  1335. * @param pData - pointer to the group info
  1336. *
  1337. * @return ZStatus_t
  1338. */
  1339. static ZStatus_t zclGeneral_AddGroup( uint8 endPoint, aps_Group_t *group, uint8 *pData )
  1340. {
  1341. zclAttrRec_t attrRec;
  1342. uint8 nameLen;
  1343. uint8 nameSupport = FALSE;
  1344. pData += 2; // Move past group ID
  1345. nameLen = *pData++;
  1346. // Retrieve Name Support attribute
  1347. if ( zclFindAttrRec( endPoint, ZCL_CLUSTER_ID_GEN_GROUPS, ATTRID_GROUP_NAME_SUPPORT, &attrRec ) )
  1348. zclReadAttrData( &nameSupport, &attrRec, NULL );
  1349. if ( nameSupport )
  1350. {
  1351. if ( nameLen > (APS_GROUP_NAME_LEN-1) )
  1352. nameLen = (APS_GROUP_NAME_LEN-1);
  1353. group->name[0] = nameLen;
  1354. osal_memcpy( &(group->name[1]), pData, nameLen );
  1355. }
  1356. return ( aps_AddGroup( endPoint, group ) );
  1357. }
  1358. /*********************************************************************
  1359. * @fn zclGeneral_ProcessInGroupsServer
  1360. *
  1361. * @brief Process in the received Groups Command.
  1362. *
  1363. * @param pInMsg - pointer to the incoming message
  1364. *
  1365. * @return ZStatus_t
  1366. */
  1367. static ZStatus_t zclGeneral_ProcessInGroupsServer( zclIncoming_t *pInMsg )
  1368. {
  1369. zclAttrRec_t attrRec;
  1370. aps_Group_t group;
  1371. aps_Group_t *pGroup;
  1372. uint8 *pData;
  1373. uint8 status;
  1374. uint8 grpCnt;
  1375. uint8 grpRspCnt = 0;
  1376. uint16 *grpList;
  1377. uint16 identifyTime = 0;
  1378. uint8 i;
  1379. ZStatus_t stat = ZSuccess;
  1380. osal_memset( (uint8*)&group, 0, sizeof( aps_Group_t ) );
  1381. pData = pInMsg->pData;
  1382. group.ID = BUILD_UINT16( pData[0], pData[1] );
  1383. switch ( pInMsg->hdr.commandID )
  1384. {
  1385. case COMMAND_GROUP_ADD:
  1386. status = zclGeneral_AddGroup( pInMsg->msg->endPoint, &group, pData );
  1387. if ( status != ZSuccess )
  1388. {
  1389. if ( status == ZApsDuplicateEntry )
  1390. status = ZCL_STATUS_DUPLICATE_EXISTS;
  1391. else
  1392. status = ZCL_STATUS_INSUFFICIENT_SPACE;
  1393. }
  1394. zclGeneral_SendGroupAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1395. status, group.ID, true, pInMsg->hdr.transSeqNum );
  1396. stat = ZCL_STATUS_CMD_HAS_RSP;
  1397. break;
  1398. case COMMAND_GROUP_VIEW:
  1399. pGroup = aps_FindGroup( pInMsg->msg->endPoint, group.ID );
  1400. if ( pGroup )
  1401. {
  1402. status = ZCL_STATUS_SUCCESS;
  1403. }
  1404. else
  1405. {
  1406. // Group not found
  1407. status = ZCL_STATUS_NOT_FOUND;
  1408. pGroup = &group;
  1409. }
  1410. zclGeneral_SendGroupViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1411. status, pGroup, true, pInMsg->hdr.transSeqNum );
  1412. stat = ZCL_STATUS_CMD_HAS_RSP;
  1413. break;
  1414. case COMMAND_GROUP_GET_MEMBERSHIP:
  1415. grpCnt = *pData++;
  1416. // Allocate space for the group list
  1417. grpList = osal_mem_alloc( sizeof( uint16 ) * APS_MAX_GROUPS );
  1418. if ( grpList != NULL )
  1419. {
  1420. if ( grpCnt == 0 )
  1421. {
  1422. // Find out all the groups of which the endpoint is a member.
  1423. grpRspCnt = aps_FindAllGroupsForEndpoint( pInMsg->msg->endPoint, grpList );
  1424. }
  1425. else
  1426. {
  1427. // Find out the groups (in the list) of which the endpoint is a member.
  1428. for ( i = 0; i < grpCnt; i++ )
  1429. {
  1430. group.ID = BUILD_UINT16( pData[0], pData[1] );
  1431. pData += 2;
  1432. if ( aps_FindGroup( pInMsg->msg->endPoint, group.ID ) )
  1433. grpList[grpRspCnt++] = group.ID;
  1434. }
  1435. }
  1436. if ( grpCnt == 0 || grpRspCnt != 0 )
  1437. {
  1438. zclGeneral_SendGroupGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1439. aps_GroupsRemaingCapacity(), grpRspCnt,
  1440. grpList, true, pInMsg->hdr.transSeqNum );
  1441. }
  1442. osal_mem_free( grpList );
  1443. }
  1444. else
  1445. {
  1446. // Couldn't allocate space for the group list -- send a Default Response command back.
  1447. zclDefaultRspCmd_t defaultRspCmd;
  1448. defaultRspCmd.commandID = pInMsg->hdr.commandID;
  1449. defaultRspCmd.statusCode = ZCL_STATUS_INSUFFICIENT_SPACE;
  1450. zcl_SendDefaultRspCmd( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
  1451. pInMsg->msg->clusterId, &defaultRspCmd,
  1452. ZCL_FRAME_SERVER_CLIENT_DIR, true, 0, pInMsg->hdr.transSeqNum );
  1453. }
  1454. stat = ZCL_STATUS_CMD_HAS_RSP;
  1455. break;
  1456. case COMMAND_GROUP_REMOVE:
  1457. if ( aps_RemoveGroup( pInMsg->msg->endPoint, group.ID ) )
  1458. status = ZCL_STATUS_SUCCESS;
  1459. else
  1460. status = ZCL_STATUS_NOT_FOUND;
  1461. zclGeneral_SendGroupRemoveResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1462. status, group.ID, true, pInMsg->hdr.transSeqNum );
  1463. stat = ZCL_STATUS_CMD_HAS_RSP;
  1464. break;
  1465. case COMMAND_GROUP_REMOVE_ALL:
  1466. aps_RemoveAllGroup( pInMsg->msg->endPoint );
  1467. break;
  1468. case COMMAND_GROUP_ADD_IF_IDENTIFYING:
  1469. // Retrieve Identify Time
  1470. if ( zclFindAttrRec( pInMsg->msg->endPoint, ZCL_CLUSTER_ID_GEN_IDENTIFY, ATTRID_IDENTIFY_TIME, &attrRec ) )
  1471. zclReadAttrData( (uint8 *)&identifyTime, &attrRec, NULL );
  1472. // Is device identifying itself?
  1473. if ( identifyTime > 0 )
  1474. zclGeneral_AddGroup( pInMsg->msg->endPoint, &group, pData );
  1475. break;
  1476. default:
  1477. stat = ZFailure;
  1478. break;
  1479. }
  1480. return ( stat );
  1481. }
  1482. /*********************************************************************
  1483. * @fn zclGeneral_ProcessInGroupsClient
  1484. *
  1485. * @brief Process in the received Groups Command.
  1486. *
  1487. * @param pInMsg - pointer to the incoming message
  1488. *
  1489. * @return ZStatus_t
  1490. */
  1491. static ZStatus_t zclGeneral_ProcessInGroupsClient( zclIncoming_t *pInMsg,
  1492. zclGeneral_AppCallbacks_t *pCBs )
  1493. {
  1494. aps_Group_t group;
  1495. uint8 *pData = pInMsg->pData;
  1496. uint8 grpCnt;
  1497. uint8 nameLen;
  1498. zclGroupRsp_t rsp;
  1499. uint8 i;
  1500. ZStatus_t stat = ZSuccess;
  1501. osal_memset( (uint8*)&group, 0, sizeof( aps_Group_t ) );
  1502. osal_memset( (uint8*)&rsp, 0, sizeof( zclGroupRsp_t ) );
  1503. switch ( pInMsg->hdr.commandID )
  1504. {
  1505. case COMMAND_GROUP_ADD_RSP:
  1506. case COMMAND_GROUP_VIEW_RSP:
  1507. case COMMAND_GROUP_REMOVE_RSP:
  1508. rsp.status = *pData++;
  1509. group.ID = BUILD_UINT16( pData[0], pData[1] );
  1510. if ( rsp.status == ZCL_STATUS_SUCCESS && pInMsg->hdr.commandID == COMMAND_GROUP_VIEW_RSP )
  1511. {
  1512. pData += 2; // Move past ID
  1513. nameLen = *pData++;
  1514. if ( nameLen > (APS_GROUP_NAME_LEN-1) )
  1515. nameLen = (APS_GROUP_NAME_LEN-1);
  1516. group.name[0] = nameLen;
  1517. osal_memcpy( &(group.name[1]), pData, nameLen );
  1518. rsp.grpName = group.name;
  1519. }
  1520. if ( pCBs->pfnGroupRsp )
  1521. {
  1522. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  1523. rsp.cmdID = pInMsg->hdr.commandID;
  1524. rsp.grpCnt = 1;
  1525. rsp.grpList = &group.ID;
  1526. rsp.capacity = 0;
  1527. pCBs->pfnGroupRsp( &rsp );
  1528. }
  1529. break;
  1530. case COMMAND_GROUP_GET_MEMBERSHIP_RSP:
  1531. {
  1532. uint16 *grpList = NULL;
  1533. rsp.capacity = *pData++;
  1534. grpCnt = *pData++;
  1535. if ( grpCnt > 0 )
  1536. {
  1537. // Allocate space for the group list
  1538. grpList = osal_mem_alloc( sizeof( uint16 ) * grpCnt );
  1539. if ( grpList != NULL )
  1540. {
  1541. rsp.grpCnt = grpCnt;
  1542. for ( i = 0; i < grpCnt; i++ )
  1543. {
  1544. grpList[i] = BUILD_UINT16( pData[0], pData[1] );
  1545. pData += 2;
  1546. }
  1547. }
  1548. }
  1549. if ( pCBs->pfnGroupRsp )
  1550. {
  1551. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  1552. rsp.cmdID = pInMsg->hdr.commandID;
  1553. rsp.grpList = grpList;
  1554. pCBs->pfnGroupRsp( &rsp );
  1555. }
  1556. if ( grpList != NULL )
  1557. {
  1558. osal_mem_free( grpList );
  1559. }
  1560. }
  1561. break;
  1562. default:
  1563. stat = ZFailure;
  1564. break;
  1565. }
  1566. return ( stat );
  1567. }
  1568. #endif // ZCL_GROUPS
  1569. #ifdef ZCL_SCENES
  1570. /*********************************************************************
  1571. * @fn zclGeneral_AddScene
  1572. *
  1573. * @brief Add a scene for an endpoint
  1574. *
  1575. * @param endpoint -
  1576. * @param scene - new scene item
  1577. *
  1578. * @return ZStatus_t
  1579. */
  1580. ZStatus_t zclGeneral_AddScene( uint8 endpoint, zclGeneral_Scene_t *scene )
  1581. {
  1582. zclGenSceneItem_t *pNewItem;
  1583. zclGenSceneItem_t *pLoop;
  1584. // Fill in the new profile list
  1585. pNewItem = osal_mem_alloc( sizeof( zclGenSceneItem_t ) );
  1586. if ( pNewItem == NULL )
  1587. return ( ZMemError );
  1588. // Fill in the plugin record.
  1589. pNewItem->next = (zclGenSceneItem_t *)NULL;
  1590. pNewItem->endpoint = endpoint;
  1591. osal_memcpy( (uint8*)&(pNewItem->scene), (uint8*)scene, sizeof ( zclGeneral_Scene_t ));
  1592. // Find spot in list
  1593. if ( zclGenSceneTable == NULL )
  1594. {
  1595. zclGenSceneTable = pNewItem;
  1596. }
  1597. else
  1598. {
  1599. // Look for end of list
  1600. pLoop = zclGenSceneTable;
  1601. while ( pLoop->next != NULL )
  1602. pLoop = pLoop->next;
  1603. // Put new item at end of list
  1604. pLoop->next = pNewItem;
  1605. }
  1606. // Update NV
  1607. zclGeneral_ScenesWriteNV();
  1608. return ( ZSuccess );
  1609. }
  1610. /*********************************************************************
  1611. * @fn zclGeneral_FindScene
  1612. *
  1613. * @brief Find a scene with endpoint and sceneID
  1614. *
  1615. * @param endpoint -
  1616. * @param groupID - what group the scene belongs to
  1617. * @param sceneID - ID to look for scene
  1618. *
  1619. * @return a pointer to the scene information, NULL if not found
  1620. */
  1621. zclGeneral_Scene_t *zclGeneral_FindScene( uint8 endpoint, uint16 groupID, uint8 sceneID )
  1622. {
  1623. zclGenSceneItem_t *pLoop;
  1624. // Look for end of list
  1625. pLoop = zclGenSceneTable;
  1626. while ( pLoop )
  1627. {
  1628. if ( (pLoop->endpoint == endpoint || endpoint == 0xFF)
  1629. && pLoop->scene.groupID == groupID && pLoop->scene.ID == sceneID )
  1630. {
  1631. return ( &(pLoop->scene) );
  1632. }
  1633. pLoop = pLoop->next;
  1634. }
  1635. return ( (zclGeneral_Scene_t *)NULL );
  1636. }
  1637. /*********************************************************************
  1638. * @fn aps_FindAllScensForGroup
  1639. *
  1640. * @brief Find all the scenes with groupID
  1641. *
  1642. * @param endpoint - endpoint to look for
  1643. * @param sceneList - List to hold scene IDs (should hold APS_MAX_SCENES entries)
  1644. *
  1645. * @return number of scenes copied to sceneList
  1646. */
  1647. uint8 zclGeneral_FindAllScenesForGroup( uint8 endpoint, uint16 groupID, uint8 *sceneList )
  1648. {
  1649. zclGenSceneItem_t *pLoop;
  1650. uint8 cnt = 0;
  1651. // Look for end of list
  1652. pLoop = zclGenSceneTable;
  1653. while ( pLoop )
  1654. {
  1655. if ( pLoop->endpoint == endpoint && pLoop->scene.groupID == groupID )
  1656. sceneList[cnt++] = pLoop->scene.ID;
  1657. pLoop = pLoop->next;
  1658. }
  1659. return ( cnt );
  1660. }
  1661. /*********************************************************************
  1662. * @fn zclGeneral_RemoveScene
  1663. *
  1664. * @brief Remove a scene with endpoint and sceneID
  1665. *
  1666. * @param endpoint -
  1667. * @param groupID - what group the scene belongs to
  1668. * @param sceneID - ID to look for scene
  1669. *
  1670. * @return TRUE if removed, FALSE if not found
  1671. */
  1672. uint8 zclGeneral_RemoveScene( uint8 endpoint, uint16 groupID, uint8 sceneID )
  1673. {
  1674. zclGenSceneItem_t *pLoop;
  1675. zclGenSceneItem_t *pPrev;
  1676. // Look for end of list
  1677. pLoop = zclGenSceneTable;
  1678. pPrev = NULL;
  1679. while ( pLoop )
  1680. {
  1681. if ( pLoop->endpoint == endpoint
  1682. && pLoop->scene.groupID == groupID && pLoop->scene.ID == sceneID )
  1683. {
  1684. if ( pPrev == NULL )
  1685. zclGenSceneTable = pLoop->next;
  1686. else
  1687. pPrev->next = pLoop->next;
  1688. // Free the memory
  1689. osal_mem_free( pLoop );
  1690. // Update NV
  1691. zclGeneral_ScenesWriteNV();
  1692. return ( TRUE );
  1693. }
  1694. pPrev = pLoop;
  1695. pLoop = pLoop->next;
  1696. }
  1697. return ( FALSE );
  1698. }
  1699. /*********************************************************************
  1700. * @fn zclGeneral_RemoveAllScenes
  1701. *
  1702. * @brief Remove all scenes with endpoint and group Id
  1703. *
  1704. * @param endpoint -
  1705. * @param groupID - ID to look for group
  1706. *
  1707. * @return none
  1708. */
  1709. void zclGeneral_RemoveAllScenes( uint8 endpoint, uint16 groupID )
  1710. {
  1711. zclGenSceneItem_t *pLoop;
  1712. zclGenSceneItem_t *pPrev;
  1713. zclGenSceneItem_t *pNext;
  1714. // Look for end of list
  1715. pLoop = zclGenSceneTable;
  1716. pPrev = NULL;
  1717. while ( pLoop )
  1718. {
  1719. if ( pLoop->endpoint == endpoint && pLoop->scene.groupID == groupID )
  1720. {
  1721. if ( pPrev == NULL )
  1722. zclGenSceneTable = pLoop->next;
  1723. else
  1724. pPrev->next = pLoop->next;
  1725. pNext = pLoop->next;
  1726. // Free the memory
  1727. osal_mem_free( pLoop );
  1728. pLoop = pNext;
  1729. }
  1730. else
  1731. {
  1732. pPrev = pLoop;
  1733. pLoop = pLoop->next;
  1734. }
  1735. }
  1736. // Update NV
  1737. zclGeneral_ScenesWriteNV();
  1738. }
  1739. /*********************************************************************
  1740. * @fn zclGeneral_CountScenes
  1741. *
  1742. * @brief Count the number of scenes for an endpoint
  1743. *
  1744. * @param endpoint -
  1745. *
  1746. * @return number of scenes assigned to an endpoint
  1747. */
  1748. uint8 zclGeneral_CountScenes( uint8 endpoint )
  1749. {
  1750. zclGenSceneItem_t *pLoop;
  1751. uint8 cnt = 0;
  1752. // Look for end of list
  1753. pLoop = zclGenSceneTable;
  1754. while ( pLoop )
  1755. {
  1756. if ( pLoop->endpoint == endpoint )
  1757. cnt++;
  1758. pLoop = pLoop->next;
  1759. }
  1760. return ( cnt );
  1761. }
  1762. /*********************************************************************
  1763. * @fn zclGeneral_CountAllScenes
  1764. *
  1765. * @brief Count the total number of scenes
  1766. *
  1767. * @param none
  1768. *
  1769. * @return number of scenes
  1770. */
  1771. uint8 zclGeneral_CountAllScenes( void )
  1772. {
  1773. zclGenSceneItem_t *pLoop;
  1774. uint8 cnt = 0;
  1775. // Look for end of list
  1776. pLoop = zclGenSceneTable;
  1777. while ( pLoop )
  1778. {
  1779. cnt++;
  1780. pLoop = pLoop->next;
  1781. }
  1782. return ( cnt );
  1783. }
  1784. /*********************************************************************
  1785. * @fn zclGeneral_ReadSceneCountCB
  1786. *
  1787. * @brief Read the number of scenes currently in the device's
  1788. * scene table (i.e., the Scene Count attribute).
  1789. *
  1790. * Note: This function gets called only when the pointer
  1791. * 'dataPtr' to the Scene Count attribute value is
  1792. * NULL in the attribute database registered with
  1793. * the ZCL.
  1794. *
  1795. * @param clusterId - cluster that attribute belongs to
  1796. * @param attrId - attribute to be read
  1797. * @param oper - ZCL_OPER_LEN, ZCL_OPER_READ
  1798. * @param pValue - pointer to attribute value
  1799. * @param pLen - pointer to length of attribute value read
  1800. *
  1801. * @return status
  1802. */
  1803. ZStatus_t zclGeneral_ReadSceneCountCB( uint16 clusterId, uint16 attrId,
  1804. uint8 oper, uint8 *pValue, uint16 *pLen )
  1805. {
  1806. ZStatus_t status = ZCL_STATUS_SUCCESS;
  1807. // This callback function should only be called for the Scene Count attribute
  1808. switch ( oper )
  1809. {
  1810. case ZCL_OPER_LEN:
  1811. *pLen = 1; // uint8
  1812. break;
  1813. case ZCL_OPER_READ:
  1814. *pValue = zclGeneral_CountAllScenes();
  1815. if ( pLen != NULL )
  1816. {
  1817. *pLen = 1;
  1818. }
  1819. break;
  1820. default:
  1821. status = ZCL_STATUS_SOFTWARE_FAILURE; // should never get here!
  1822. break;
  1823. }
  1824. return ( status );
  1825. }
  1826. /*********************************************************************
  1827. * @fn zclGeneral_ProcessInScenesServer
  1828. *
  1829. * @brief Process in the received Scenes Command.
  1830. *
  1831. * @param pInMsg - pointer to the incoming message
  1832. *
  1833. * @return ZStatus_t
  1834. */
  1835. static ZStatus_t zclGeneral_ProcessInScenesServer( zclIncoming_t *pInMsg,
  1836. zclGeneral_AppCallbacks_t *pCBs )
  1837. {
  1838. zclAttrRec_t attrRec;
  1839. zclGeneral_Scene_t scene;
  1840. zclGeneral_Scene_t *pScene;
  1841. uint8 *pData = pInMsg->pData;
  1842. uint8 nameLen;
  1843. uint8 status;
  1844. uint8 sceneCnt = 0;
  1845. uint8 *sceneList = NULL;
  1846. uint8 sendRsp = FALSE;
  1847. uint8 nameSupport = FALSE;
  1848. ZStatus_t stat = ZSuccess;
  1849. osal_memset( (uint8*)&scene, 0, sizeof( zclGeneral_Scene_t ) );
  1850. scene.groupID = BUILD_UINT16( pData[0], pData[1] );
  1851. pData += 2; // Move past group ID
  1852. scene.ID = *pData++;
  1853. switch ( pInMsg->hdr.commandID )
  1854. {
  1855. case COMMAND_SCENE_ADD:
  1856. // Parse the rest of the incoming message
  1857. scene.transTime = BUILD_UINT16( pData[0], pData[1] );
  1858. pData += 2;
  1859. nameLen= *pData++; // Name length
  1860. // Retrieve Name Support attribute
  1861. if ( zclFindAttrRec( pInMsg->msg->endPoint, ZCL_CLUSTER_ID_GEN_SCENES, ATTRID_SCENES_NAME_SUPPORT, &attrRec ) )
  1862. {
  1863. zclReadAttrData( &nameSupport, &attrRec, NULL );
  1864. }
  1865. if ( nameSupport )
  1866. {
  1867. if ( nameLen > (ZCL_GEN_SCENE_NAME_LEN-1) )
  1868. {
  1869. // truncate to maximum size
  1870. scene.name[0] = ZCL_GEN_SCENE_NAME_LEN-1;
  1871. }
  1872. else
  1873. {
  1874. scene.name[0] = nameLen;
  1875. }
  1876. osal_memcpy( &(scene.name[1]), pData, scene.name[0] );
  1877. }
  1878. pData += nameLen; // move past name, use original length
  1879. scene.extLen = pInMsg->pDataLen - ( (uint16)( pData - pInMsg->pData ) );
  1880. if ( scene.extLen > 0 )
  1881. {
  1882. // Copy the extention field(s)
  1883. if ( scene.extLen > ZCL_GEN_SCENE_EXT_LEN )
  1884. {
  1885. scene.extLen = ZCL_GEN_SCENE_EXT_LEN;
  1886. }
  1887. osal_memcpy( scene.extField, pData, scene.extLen );
  1888. }
  1889. if ( scene.groupID == 0x0000 ||
  1890. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
  1891. {
  1892. // Either the Scene doesn't belong to a Group (Group ID = 0x0000) or it
  1893. // does and the corresponding Group exits
  1894. pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
  1895. if ( pScene || ( zclGeneral_CountAllScenes() < ZCL_GEN_MAX_SCENES ) )
  1896. {
  1897. status = ZCL_STATUS_SUCCESS;
  1898. if ( pScene != NULL )
  1899. {
  1900. // The Scene already exists so update it
  1901. pScene->transTime = scene.transTime;
  1902. osal_memcpy( pScene->name, scene.name, ZCL_GEN_SCENE_NAME_LEN );
  1903. // Use the new extention field(s)
  1904. osal_memcpy( pScene->extField, scene.extField, scene.extLen );
  1905. pScene->extLen = scene.extLen;
  1906. // Update NV
  1907. zclGeneral_ScenesWriteNV();
  1908. }
  1909. else
  1910. {
  1911. // The Scene doesn't exist so add it
  1912. zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
  1913. }
  1914. }
  1915. else
  1916. {
  1917. status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
  1918. }
  1919. }
  1920. else
  1921. {
  1922. status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
  1923. }
  1924. zclGeneral_SendSceneAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1925. status, scene.groupID, scene.ID,
  1926. true, pInMsg->hdr.transSeqNum );
  1927. stat = ZCL_STATUS_CMD_HAS_RSP;
  1928. break;
  1929. case COMMAND_SCENE_VIEW:
  1930. pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
  1931. if ( pScene != NULL )
  1932. {
  1933. status = ZCL_STATUS_SUCCESS;
  1934. }
  1935. else
  1936. {
  1937. // Scene not found
  1938. if ( scene.groupID != 0x0000 &&
  1939. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) == NULL )
  1940. {
  1941. status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
  1942. }
  1943. else
  1944. {
  1945. status = ZCL_STATUS_NOT_FOUND;
  1946. }
  1947. pScene = &scene;
  1948. }
  1949. zclGeneral_SendSceneViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1950. status, pScene, true, pInMsg->hdr.transSeqNum );
  1951. stat = ZCL_STATUS_CMD_HAS_RSP;
  1952. break;
  1953. case COMMAND_SCENE_REMOVE:
  1954. if ( zclGeneral_RemoveScene( pInMsg->msg->endPoint, scene.groupID, scene.ID ) )
  1955. {
  1956. status = ZCL_STATUS_SUCCESS;
  1957. }
  1958. else
  1959. {
  1960. // Scene not found
  1961. if ( aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) == NULL )
  1962. {
  1963. // The Group is not in the Group Table
  1964. status = ZCL_STATUS_INVALID_FIELD;
  1965. }
  1966. else
  1967. {
  1968. status = ZCL_STATUS_NOT_FOUND;
  1969. }
  1970. }
  1971. if ( UNICAST_MSG( pInMsg->msg ) )
  1972. {
  1973. // Addressed to this device (not to a group) - send a response back
  1974. zclGeneral_SendSceneRemoveResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1975. status, scene.groupID,
  1976. scene.ID, true, pInMsg->hdr.transSeqNum );
  1977. }
  1978. stat = ZCL_STATUS_CMD_HAS_RSP;
  1979. break;
  1980. case COMMAND_SCENE_REMOVE_ALL:
  1981. if ( scene.groupID == 0x0000 ||
  1982. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
  1983. {
  1984. zclGeneral_RemoveAllScenes( pInMsg->msg->endPoint, scene.groupID );
  1985. status = ZCL_STATUS_SUCCESS;
  1986. }
  1987. else
  1988. {
  1989. status = ZCL_STATUS_INVALID_FIELD;
  1990. }
  1991. if ( UNICAST_MSG( pInMsg->msg ) )
  1992. {
  1993. // Addressed to this device (not to a group) - send a response back
  1994. zclGeneral_SendSceneRemoveAllResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1995. status, scene.groupID, true, pInMsg->hdr.transSeqNum );
  1996. }
  1997. stat = ZCL_STATUS_CMD_HAS_RSP;
  1998. break;
  1999. case COMMAND_SCENE_STORE:
  2000. if ( scene.groupID == 0x0000 ||
  2001. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
  2002. {
  2003. // Either the Scene doesn't belong to a Group (Group ID = 0x0000) or it
  2004. // does and the corresponding Group exits
  2005. pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
  2006. if ( pScene || ( zclGeneral_CountAllScenes() < ZCL_GEN_MAX_SCENES ) )
  2007. {
  2008. uint8 sceneChanged = FALSE;
  2009. status = ZCL_STATUS_SUCCESS;
  2010. if ( pScene == NULL )
  2011. {
  2012. // Haven't been added yet
  2013. pScene = &scene;
  2014. }
  2015. if ( pCBs->pfnSceneStoreReq )
  2016. {
  2017. zclSceneReq_t req;
  2018. req.srcAddr = &(pInMsg->msg->srcAddr);
  2019. req.scene = pScene;
  2020. // Get the latest Scene info
  2021. if ( pCBs->pfnSceneStoreReq( &req ) )
  2022. {
  2023. sceneChanged = TRUE;
  2024. }
  2025. }
  2026. if ( pScene == &scene )
  2027. {
  2028. // The Scene doesn't exist so add it
  2029. zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
  2030. }
  2031. else if ( sceneChanged )
  2032. {
  2033. // The Scene already exists so update only NV
  2034. zclGeneral_ScenesWriteNV();
  2035. }
  2036. }
  2037. else
  2038. {
  2039. status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
  2040. }
  2041. }
  2042. else
  2043. {
  2044. status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
  2045. }
  2046. if ( UNICAST_MSG( pInMsg->msg ) )
  2047. {
  2048. // Addressed to this device (not to a group) - send a response back
  2049. zclGeneral_SendSceneStoreResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  2050. status, scene.groupID, scene.ID,
  2051. true, pInMsg->hdr.transSeqNum );
  2052. }
  2053. stat = ZCL_STATUS_CMD_HAS_RSP;
  2054. break;
  2055. case COMMAND_SCENE_RECALL:
  2056. pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
  2057. if ( pScene && pCBs->pfnSceneRecallReq )
  2058. {
  2059. zclSceneReq_t req;
  2060. req.srcAddr = &(pInMsg->msg->srcAddr);
  2061. req.scene = pScene;
  2062. pCBs->pfnSceneRecallReq( &req );
  2063. }
  2064. // No response
  2065. break;
  2066. case COMMAND_SCENE_GET_MEMBERSHIP:
  2067. // Find all the Scenes corresponding to the Group ID
  2068. if ( scene.groupID == 0x0000 ||
  2069. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
  2070. {
  2071. // Allocate space for the scene list
  2072. sceneList = osal_mem_alloc( ZCL_GEN_MAX_SCENES );
  2073. if ( sceneList != NULL )
  2074. {
  2075. sceneCnt = zclGeneral_FindAllScenesForGroup( pInMsg->msg->endPoint,
  2076. scene.groupID, sceneList );
  2077. status = ZCL_STATUS_SUCCESS;
  2078. if ( UNICAST_MSG( pInMsg->msg ) )
  2079. {
  2080. // Addressed only to this device - send a response back
  2081. sendRsp = TRUE;
  2082. }
  2083. else
  2084. {
  2085. // Addressed to the Group - ONLY send a response if an entry within the
  2086. // Scene Table corresponds to the Group ID
  2087. if ( sceneCnt != 0 )
  2088. {
  2089. sendRsp = TRUE;
  2090. }
  2091. }
  2092. }
  2093. else
  2094. {
  2095. // Couldn't allocate space for the scene list!
  2096. status = ZCL_STATUS_INSUFFICIENT_SPACE;
  2097. sendRsp = TRUE;
  2098. }
  2099. }
  2100. else
  2101. {
  2102. // The Group is not in the Group Table - send a response back
  2103. status = ZCL_STATUS_INVALID_FIELD;
  2104. sendRsp = TRUE;
  2105. }
  2106. if ( sendRsp )
  2107. {
  2108. zclGeneral_SendSceneGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  2109. status, zclGeneral_ScenesRemaingCapacity(), sceneCnt, sceneList,
  2110. scene.groupID, true, pInMsg->hdr.transSeqNum );
  2111. }
  2112. if ( sceneList != NULL )
  2113. {
  2114. osal_mem_free( sceneList );
  2115. }
  2116. stat = ZCL_STATUS_CMD_HAS_RSP;
  2117. break;
  2118. default:
  2119. stat = ZFailure;
  2120. break;
  2121. }
  2122. return ( stat );
  2123. }
  2124. /*********************************************************************
  2125. * @fn zclGeneral_ProcessInScenesClient
  2126. *
  2127. * @brief Process in the received Scenes Command.
  2128. *
  2129. * @param pInMsg - pointer to the incoming message
  2130. *
  2131. * @return ZStatus_t
  2132. */
  2133. static ZStatus_t zclGeneral_ProcessInScenesClient( zclIncoming_t *pInMsg,
  2134. zclGeneral_AppCallbacks_t *pCBs )
  2135. {
  2136. zclGeneral_Scene_t scene;
  2137. uint8 *pData = pInMsg->pData;
  2138. uint8 nameLen;
  2139. zclSceneRsp_t rsp;
  2140. uint8 i;
  2141. ZStatus_t stat = ZSuccess;
  2142. osal_memset( (uint8*)&scene, 0, sizeof( zclGeneral_Scene_t ) );
  2143. osal_memset( (uint8*)&rsp, 0, sizeof( zclSceneRsp_t ) );
  2144. // Get the status field first
  2145. rsp.status = *pData++;
  2146. if ( pInMsg->hdr.commandID == COMMAND_SCENE_GET_MEMBERSHIP_RSP )
  2147. {
  2148. rsp.capacity = *pData++;
  2149. }
  2150. scene.groupID = BUILD_UINT16( pData[0], pData[1] );
  2151. pData += 2; // Move past group ID
  2152. switch ( pInMsg->hdr.commandID )
  2153. {
  2154. case COMMAND_SCENE_VIEW_RSP:
  2155. // Parse the rest of the incoming message
  2156. scene.ID = *pData++; // Not applicable to Remove All Response command
  2157. scene.transTime = BUILD_UINT16( pData[0], pData[1] );
  2158. pData += 2;
  2159. nameLen = *pData++; // Name length
  2160. if ( nameLen > (ZCL_GEN_SCENE_NAME_LEN-1) )
  2161. {
  2162. // truncate to maximum size
  2163. scene.name[0] = ZCL_GEN_SCENE_NAME_LEN-1;
  2164. }
  2165. else
  2166. {
  2167. scene.name[0] = nameLen;
  2168. }
  2169. osal_memcpy( &(scene.name[1]), pData, scene.name[0] );
  2170. pData += nameLen; // move past name, use original length
  2171. //*** Do something with the extension field(s)
  2172. // Fall through to callback - break is left off intentionally
  2173. case COMMAND_SCENE_ADD_RSP:
  2174. case COMMAND_SCENE_REMOVE_RSP:
  2175. case COMMAND_SCENE_REMOVE_ALL_RSP:
  2176. case COMMAND_SCENE_STORE_RSP:
  2177. if ( pCBs->pfnSceneRsp )
  2178. {
  2179. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2180. rsp.cmdID = pInMsg->hdr.commandID;
  2181. rsp.scene = &scene;
  2182. pCBs->pfnSceneRsp( &rsp );
  2183. }
  2184. break;
  2185. case COMMAND_SCENE_GET_MEMBERSHIP_RSP:
  2186. {
  2187. uint8 *sceneList = NULL;
  2188. if ( rsp.status == ZCL_STATUS_SUCCESS )
  2189. {
  2190. uint8 sceneCnt = *pData++;
  2191. if ( sceneCnt > 0 )
  2192. {
  2193. // Allocate space for the scene list
  2194. sceneList = osal_mem_alloc( sceneCnt );
  2195. if ( sceneList != NULL )
  2196. {
  2197. rsp.sceneCnt = sceneCnt;
  2198. for ( i = 0; i < sceneCnt; i++ )
  2199. sceneList[i] = *pData++;
  2200. }
  2201. }
  2202. }
  2203. if ( pCBs->pfnSceneRsp )
  2204. {
  2205. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2206. rsp.cmdID = pInMsg->hdr.commandID;
  2207. rsp.sceneList = sceneList;
  2208. rsp.scene = &scene;
  2209. pCBs->pfnSceneRsp( &rsp);
  2210. }
  2211. if ( sceneList != NULL )
  2212. {
  2213. osal_mem_free( sceneList );
  2214. }
  2215. }
  2216. break;
  2217. default:
  2218. stat = ZFailure;
  2219. break;
  2220. }
  2221. return ( stat );
  2222. }
  2223. #endif // ZCL_SCENES
  2224. #ifdef ZCL_ON_OFF
  2225. /*********************************************************************
  2226. * @fn zclGeneral_ProcessInCmdOnOff
  2227. *
  2228. * @brief Process in the received On/Off Command.
  2229. *
  2230. * @param pInMsg - pointer to the incoming message
  2231. *
  2232. * @return ZStatus_t
  2233. */
  2234. static ZStatus_t zclGeneral_ProcessInOnOff( zclIncoming_t *pInMsg,
  2235. zclGeneral_AppCallbacks_t *pCBs )
  2236. {
  2237. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  2238. {
  2239. if ( pInMsg->hdr.commandID > COMMAND_TOGGLE )
  2240. return ( ZFailure ); // Error ignore the command
  2241. if ( pCBs->pfnOnOff )
  2242. pCBs->pfnOnOff( pInMsg->hdr.commandID );
  2243. }
  2244. // no Client command
  2245. return ( ZSuccess );
  2246. }
  2247. #endif // ZCL_ON_OFF
  2248. #ifdef ZCL_LEVEL_CTRL
  2249. /*********************************************************************
  2250. * @fn zclGeneral_ProcessInLevelControl
  2251. *
  2252. * @brief Process in the received Level Control Command.
  2253. *
  2254. * @param pInMsg - pointer to the incoming message
  2255. *
  2256. * @return ZStatus_t
  2257. */
  2258. static ZStatus_t zclGeneral_ProcessInLevelControl( zclIncoming_t *pInMsg,
  2259. zclGeneral_AppCallbacks_t *pCBs )
  2260. {
  2261. uint8 withOnOff = FALSE;
  2262. ZStatus_t stat = ZSuccess;
  2263. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  2264. {
  2265. switch ( pInMsg->hdr.commandID )
  2266. {
  2267. case COMMAND_LEVEL_MOVE_TO_LEVEL_WITH_ON_OFF:
  2268. withOnOff = TRUE;
  2269. // fall through
  2270. case COMMAND_LEVEL_MOVE_TO_LEVEL:
  2271. if ( pCBs->pfnLevelControlMoveToLevel )
  2272. {
  2273. zclLCMoveToLevel_t cmd;
  2274. cmd.level = pInMsg->pData[0];
  2275. cmd.transitionTime = BUILD_UINT16( pInMsg->pData[1], pInMsg->pData[2] );
  2276. cmd.withOnOff = withOnOff;
  2277. pCBs->pfnLevelControlMoveToLevel( &cmd );
  2278. }
  2279. break;
  2280. case COMMAND_LEVEL_MOVE_WITH_ON_OFF:
  2281. withOnOff = TRUE;
  2282. // fall through
  2283. case COMMAND_LEVEL_MOVE:
  2284. if ( pCBs->pfnLevelControlMove )
  2285. {
  2286. zclLCMove_t cmd;
  2287. cmd.moveMode = pInMsg->pData[0];
  2288. cmd.rate = pInMsg->pData[1];
  2289. cmd.withOnOff = withOnOff;
  2290. pCBs->pfnLevelControlMove( &cmd );
  2291. }
  2292. break;
  2293. case COMMAND_LEVEL_STEP_WITH_ON_OFF:
  2294. withOnOff = TRUE;
  2295. // fall through
  2296. case COMMAND_LEVEL_STEP:
  2297. if ( pCBs->pfnLevelControlStep )
  2298. {
  2299. zclLCStep_t cmd;
  2300. cmd.stepMode = pInMsg->pData[0];
  2301. cmd.amount = pInMsg->pData[1];
  2302. cmd.transitionTime = BUILD_UINT16( pInMsg->pData[2], pInMsg->pData[3] );
  2303. cmd.withOnOff = withOnOff;
  2304. pCBs->pfnLevelControlStep( &cmd );
  2305. }
  2306. break;
  2307. case COMMAND_LEVEL_STOP:
  2308. case COMMAND_LEVEL_STOP_WITH_ON_OFF:
  2309. // Both Stop commands are identical
  2310. if ( pCBs->pfnLevelControlStop )
  2311. {
  2312. pCBs->pfnLevelControlStop();
  2313. }
  2314. break;
  2315. default:
  2316. stat = ZFailure;
  2317. break;
  2318. }
  2319. }
  2320. // no Client command
  2321. return ( stat );
  2322. }
  2323. #endif // ZCL_LEVEL_CTRL
  2324. #ifdef ZCL_ALARMS
  2325. /*********************************************************************
  2326. * @fn zclGeneral_AddAlarm
  2327. *
  2328. * @brief Add an alarm for a cluster
  2329. *
  2330. * @param endpoint -
  2331. * @param alarm - new alarm item
  2332. *
  2333. * @return ZStatus_t
  2334. */
  2335. ZStatus_t zclGeneral_AddAlarm( uint8 endpoint, zclGeneral_Alarm_t *alarm )
  2336. {
  2337. zclGenAlarmItem_t *pNewItem;
  2338. zclGenAlarmItem_t *pLoop;
  2339. // Fill in the new profile list
  2340. pNewItem = osal_mem_alloc( sizeof( zclGenAlarmItem_t ) );
  2341. if ( pNewItem == NULL )
  2342. return ( ZMemError );
  2343. // Fill in the plugin record.
  2344. pNewItem->next = (zclGenAlarmItem_t *)NULL;
  2345. pNewItem->endpoint = endpoint;
  2346. osal_memcpy( (uint8*)(&pNewItem->alarm), (uint8*)alarm, sizeof ( zclGeneral_Alarm_t ) );
  2347. // Find spot in list
  2348. if ( zclGenAlarmTable == NULL )
  2349. {
  2350. zclGenAlarmTable = pNewItem;
  2351. }
  2352. else
  2353. {
  2354. // Look for end of list
  2355. pLoop = zclGenAlarmTable;
  2356. while ( pLoop->next != NULL )
  2357. pLoop = pLoop->next;
  2358. // Put new item at end of list
  2359. pLoop->next = pNewItem;
  2360. }
  2361. return ( ZSuccess );
  2362. }
  2363. /*********************************************************************
  2364. * @fn zclGeneral_FindAlarm
  2365. *
  2366. * @brief Find an alarm with alarmCode and clusterID
  2367. *
  2368. * @param endpoint -
  2369. * @param groupID - what group the scene belongs to
  2370. * @param sceneID - ID to look for scene
  2371. *
  2372. * @return a pointer to the alarm information, NULL if not found
  2373. */
  2374. zclGeneral_Alarm_t *zclGeneral_FindAlarm( uint8 endpoint, uint8 alarmCode, uint16 clusterID )
  2375. {
  2376. zclGenAlarmItem_t *pLoop;
  2377. // Look for the alarm
  2378. pLoop = zclGenAlarmTable;
  2379. while ( pLoop )
  2380. {
  2381. if ( pLoop->endpoint == endpoint &&
  2382. pLoop->alarm.code == alarmCode && pLoop->alarm.clusterID == clusterID )
  2383. {
  2384. return ( &(pLoop->alarm) );
  2385. }
  2386. pLoop = pLoop->next;
  2387. }
  2388. return ( (zclGeneral_Alarm_t *)NULL );
  2389. }
  2390. /*********************************************************************
  2391. * @fn zclGeneral_FindEarliestAlarm
  2392. *
  2393. * @brief Find an alarm with the earliest timestamp
  2394. *
  2395. * @param endpoint -
  2396. *
  2397. * @return a pointer to the alarm information, NULL if not found
  2398. */
  2399. zclGeneral_Alarm_t *zclGeneral_FindEarliestAlarm( uint8 endpoint )
  2400. {
  2401. zclGenAlarmItem_t *pLoop;
  2402. zclGenAlarmItem_t earliestAlarm;
  2403. zclGenAlarmItem_t *pEarliestAlarm = &earliestAlarm;
  2404. pEarliestAlarm->alarm.timeStamp = 0xFFFFFFFF;
  2405. // Look for alarm with earliest time
  2406. pLoop = zclGenAlarmTable;
  2407. while ( pLoop )
  2408. {
  2409. if ( pLoop->endpoint == endpoint &&
  2410. pLoop->alarm.timeStamp < pEarliestAlarm->alarm.timeStamp )
  2411. {
  2412. pEarliestAlarm = pLoop;
  2413. }
  2414. pLoop = pLoop->next;
  2415. }
  2416. if ( pEarliestAlarm->alarm.timeStamp != 0xFFFFFFFF )
  2417. return ( &(pEarliestAlarm->alarm) );
  2418. // No alarm
  2419. return ( (zclGeneral_Alarm_t *)NULL );
  2420. }
  2421. /*********************************************************************
  2422. * @fn zclGeneral_ResetAlarm
  2423. *
  2424. * @brief Remove a scene with endpoint and sceneID
  2425. *
  2426. * @param endpoint -
  2427. * @param alarmCode -
  2428. * @param clusterID -
  2429. *
  2430. * @return TRUE if removed, FALSE if not found
  2431. */
  2432. void zclGeneral_ResetAlarm( uint8 endpoint, uint8 alarmCode, uint16 clusterID )
  2433. {
  2434. zclGenAlarmItem_t *pLoop;
  2435. zclGenAlarmItem_t *pPrev;
  2436. // Look for end of list
  2437. pLoop = zclGenAlarmTable;
  2438. pPrev = NULL;
  2439. while ( pLoop )
  2440. {
  2441. if ( pLoop->endpoint == endpoint &&
  2442. pLoop->alarm.code == alarmCode && pLoop->alarm.clusterID == clusterID )
  2443. {
  2444. if ( pPrev == NULL )
  2445. zclGenAlarmTable = pLoop->next;
  2446. else
  2447. pPrev->next = pLoop->next;
  2448. // Free the memory
  2449. osal_mem_free( pLoop );
  2450. // Notify the Application so that if the alarm condition still active then
  2451. // a new notification will be generated, and a new alarm record will be
  2452. // added to the alarm log
  2453. // zclGeneral_NotifyReset( alarmCode, clusterID ); // callback function?
  2454. return;
  2455. }
  2456. pPrev = pLoop;
  2457. pLoop = pLoop->next;
  2458. }
  2459. }
  2460. /*********************************************************************
  2461. * @fn zclGeneral_ResetAllAlarms
  2462. *
  2463. * @brief Remove all alarms with endpoint
  2464. *
  2465. * @param endpoint -
  2466. * @param notifyApp -
  2467. *
  2468. * @return none
  2469. */
  2470. void zclGeneral_ResetAllAlarms( uint8 endpoint, uint8 notifyApp )
  2471. {
  2472. zclGenAlarmItem_t *pLoop;
  2473. zclGenAlarmItem_t *pPrev;
  2474. zclGenAlarmItem_t *pNext;
  2475. // Look for end of list
  2476. pLoop = zclGenAlarmTable;
  2477. pPrev = NULL;
  2478. while ( pLoop )
  2479. {
  2480. if ( pLoop->endpoint == endpoint )
  2481. {
  2482. if ( pPrev == NULL )
  2483. zclGenAlarmTable = pLoop->next;
  2484. else
  2485. pPrev->next = pLoop->next;
  2486. pNext = pLoop->next;
  2487. // Free the memory
  2488. osal_mem_free( pLoop );
  2489. pLoop = pNext;
  2490. }
  2491. else
  2492. {
  2493. pPrev = pLoop;
  2494. pLoop = pLoop->next;
  2495. }
  2496. }
  2497. if ( notifyApp )
  2498. {
  2499. // Notify the Application so that if any alarm conditions still active then
  2500. // a new notification will be generated, and a new alarm record will be
  2501. // added to the alarm log
  2502. // zclGeneral_NotifyResetAll(); // callback function?
  2503. }
  2504. }
  2505. /*********************************************************************
  2506. * @fn zclGeneral_ProcessInAlarmsServer
  2507. *
  2508. * @brief Process in the received Alarms Command.
  2509. *
  2510. * @param pInMsg - pointer to the incoming message
  2511. *
  2512. * @return ZStatus_t
  2513. */
  2514. static ZStatus_t zclGeneral_ProcessInAlarmsServer( zclIncoming_t *pInMsg,
  2515. zclGeneral_AppCallbacks_t *pCBs )
  2516. {
  2517. zclGeneral_Alarm_t *pAlarm;
  2518. uint8 *pData = pInMsg->pData;
  2519. ZStatus_t stat = ZSuccess;
  2520. switch ( pInMsg->hdr.commandID )
  2521. {
  2522. case COMMAND_ALARMS_RESET:
  2523. zclGeneral_ResetAlarm( pInMsg->msg->endPoint, pData[0],
  2524. BUILD_UINT16( pData[1], pData[2] ) );
  2525. break;
  2526. case COMMAND_ALARMS_RESET_ALL:
  2527. zclGeneral_ResetAllAlarms( pInMsg->msg->endPoint, TRUE );
  2528. break;
  2529. case COMMAND_ALARMS_GET:
  2530. pAlarm = zclGeneral_FindEarliestAlarm( pInMsg->msg->endPoint );
  2531. if ( pAlarm )
  2532. {
  2533. // Send a response back
  2534. zclGeneral_SendAlarmGetRespnose( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  2535. ZCL_STATUS_SUCCESS, pAlarm->code,
  2536. pAlarm->clusterID, pAlarm->timeStamp,
  2537. true, pInMsg->hdr.transSeqNum );
  2538. // Remove the entry from the Alarm table
  2539. zclGeneral_ResetAlarm( pInMsg->msg->endPoint, pAlarm->code, pAlarm->clusterID );
  2540. }
  2541. else
  2542. {
  2543. // Send a response back
  2544. zclGeneral_SendAlarmGetRespnose( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  2545. ZCL_STATUS_NOT_FOUND, 0, 0, 0,
  2546. true, pInMsg->hdr.transSeqNum );
  2547. }
  2548. stat = ZCL_STATUS_CMD_HAS_RSP;
  2549. break;
  2550. case COMMAND_ALARMS_RESET_LOG:
  2551. zclGeneral_ResetAllAlarms( pInMsg->msg->endPoint, FALSE );
  2552. break;
  2553. #ifdef SE_UK_EXT
  2554. case COMMAND_ALARMS_PUBLISH_EVENT_LOG:
  2555. if ( pCBs->pfnPublishEventLog )
  2556. {
  2557. zclPublishEventLog_t eventLog;
  2558. eventLog.logID = *pData++;
  2559. eventLog.cmdIndex = *pData++;
  2560. eventLog.totalCmds = *pData++;
  2561. // First try to find out number of Sub Log Payloads
  2562. eventLog.numSubLogs = (pInMsg->pDataLen-3)/(1+4); // event ID + event time
  2563. if ( eventLog.numSubLogs > 0 )
  2564. {
  2565. // Try to alloc space for Log Payload
  2566. eventLog.pLogs = (zclEventLogPayload_t *)osal_mem_alloc( sizeof( zclEventLogPayload_t ) *
  2567. eventLog.numSubLogs );
  2568. if ( eventLog.pLogs != NULL )
  2569. {
  2570. // Copy Log Payload
  2571. for ( uint8 i = 0; i < eventLog.numSubLogs; i++ )
  2572. {
  2573. eventLog.pLogs[i].eventId = *pData++;
  2574. eventLog.pLogs[i].eventTime = osal_build_uint32( pData, 4 );
  2575. pData += 4;
  2576. }
  2577. }
  2578. else
  2579. {
  2580. stat = ZCL_STATUS_SOFTWARE_FAILURE;
  2581. }
  2582. }
  2583. else
  2584. {
  2585. eventLog.pLogs = NULL;
  2586. }
  2587. if ( stat == ZSuccess )
  2588. {
  2589. pCBs->pfnPublishEventLog( &(pInMsg->msg->srcAddr), &eventLog );
  2590. }
  2591. if ( eventLog.pLogs != NULL )
  2592. {
  2593. osal_mem_free( eventLog.pLogs );
  2594. }
  2595. }
  2596. break;
  2597. #endif // SE_UK_EXT
  2598. default:
  2599. stat = ZFailure;
  2600. break;
  2601. }
  2602. return ( stat );
  2603. }
  2604. /*********************************************************************
  2605. * @fn zclGeneral_ProcessInAlarmsClient
  2606. *
  2607. * @brief Process in the received Alarms Command.
  2608. *
  2609. * @param pInMsg - pointer to the incoming message
  2610. *
  2611. * @return ZStatus_t
  2612. */
  2613. static ZStatus_t zclGeneral_ProcessInAlarmsClient( zclIncoming_t *pInMsg,
  2614. zclGeneral_AppCallbacks_t *pCBs )
  2615. {
  2616. uint8 *pData = pInMsg->pData;
  2617. zclAlarm_t alarm;
  2618. ZStatus_t stat = ZSuccess;
  2619. osal_memset( (uint8*)&alarm, 0, sizeof( zclAlarm_t ) );
  2620. switch ( pInMsg->hdr.commandID )
  2621. {
  2622. case COMMAND_ALARMS_ALARM:
  2623. if ( pCBs->pfnAlarm )
  2624. {
  2625. alarm.srcAddr = &(pInMsg->msg->srcAddr);
  2626. alarm.cmdID = pInMsg->hdr.commandID;
  2627. alarm.status = *pData++;
  2628. alarm.alarmCode = *pData++;
  2629. alarm.clusterID = BUILD_UINT16( pData[0], pData[1] );
  2630. pData += 2;
  2631. alarm.timeStamp = osal_build_uint32( pData, 4 );
  2632. pCBs->pfnAlarm( &alarm );
  2633. }
  2634. break;
  2635. case COMMAND_ALARMS_GET_RSP:
  2636. if ( pCBs->pfnAlarm )
  2637. {
  2638. alarm.srcAddr = &(pInMsg->msg->srcAddr);
  2639. alarm.cmdID = pInMsg->hdr.commandID;
  2640. alarm.alarmCode = *pData++;
  2641. alarm.clusterID = BUILD_UINT16( pData[0], pData[1] );
  2642. pCBs->pfnAlarm( &alarm );
  2643. }
  2644. break;
  2645. #ifdef SE_UK_EXT
  2646. case COMMAND_ALARMS_GET_EVENT_LOG:
  2647. if ( pCBs->pfnGetEventLog )
  2648. {
  2649. zclGetEventLog_t eventLog;
  2650. eventLog.logID = *pData++;
  2651. eventLog.startTime = osal_build_uint32( pData, 4 );
  2652. pData += 4;
  2653. eventLog.endTime = osal_build_uint32( pData, 4 );
  2654. pData += 4;
  2655. eventLog.numEvents = *pData;
  2656. pCBs->pfnGetEventLog( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
  2657. &eventLog, pInMsg->hdr.transSeqNum );
  2658. }
  2659. break;
  2660. #endif // SE_UK_EXT
  2661. default:
  2662. stat = ZFailure;
  2663. break;
  2664. }
  2665. return ( stat );
  2666. }
  2667. #endif // ZCL_ALARMS
  2668. #ifdef ZCL_LOCATION
  2669. /*********************************************************************
  2670. * @fn zclGeneral_ProcessInLocationServer
  2671. *
  2672. * @brief Process in the received Location Command.
  2673. *
  2674. * @param pInMsg - pointer to the incoming message
  2675. *
  2676. * @return ZStatus_t
  2677. */
  2678. static ZStatus_t zclGeneral_ProcessInLocationServer( zclIncoming_t *pInMsg,
  2679. zclGeneral_AppCallbacks_t *pCBs )
  2680. {
  2681. uint8 *pData = pInMsg->pData;
  2682. zclLocation_t cmd;
  2683. ZStatus_t stat = ZSuccess;
  2684. osal_memset( (uint8*)&cmd, 0, sizeof( zclLocation_t ) );
  2685. switch ( pInMsg->hdr.commandID )
  2686. {
  2687. case COMMAND_LOCATION_SET_ABSOLUTE:
  2688. cmd.un.absLoc.coordinate1 = BUILD_UINT16( pData[0], pData[1] );
  2689. pData += 2;
  2690. cmd.un.absLoc.coordinate2 = BUILD_UINT16( pData[0], pData[1] );
  2691. pData += 2;
  2692. cmd.un.absLoc.coordinate3 = BUILD_UINT16( pData[0], pData[1] );
  2693. pData += 2;
  2694. cmd.un.absLoc.power = BUILD_UINT16( pData[0], pData[1] );
  2695. pData += 2;
  2696. cmd.un.absLoc.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
  2697. if ( pCBs->pfnLocation )
  2698. {
  2699. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  2700. cmd.cmdID = pInMsg->hdr.commandID;
  2701. // Update the absolute location info
  2702. pCBs->pfnLocation( &cmd );
  2703. }
  2704. break;
  2705. case COMMAND_LOCATION_SET_DEV_CFG:
  2706. cmd.un.devCfg.power = BUILD_UINT16( pData[0], pData[1] );
  2707. pData += 2;
  2708. cmd.un.devCfg.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
  2709. pData += 2;
  2710. cmd.un.devCfg.calcPeriod = BUILD_UINT16( pData[0], pData[1] );
  2711. pData += 2;
  2712. cmd.un.devCfg.numMeasurements = *pData++;
  2713. cmd.un.devCfg.reportPeriod = BUILD_UINT16( pData[0], pData[1] );
  2714. if ( pCBs->pfnLocation )
  2715. {
  2716. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  2717. cmd.cmdID = pInMsg->hdr.commandID;
  2718. // Update the device configuration info
  2719. pCBs->pfnLocation( &cmd );
  2720. }
  2721. break;
  2722. case COMMAND_LOCATION_GET_DEV_CFG:
  2723. cmd.un.ieeeAddr = pData;
  2724. if ( pCBs->pfnLocation )
  2725. {
  2726. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  2727. cmd.cmdID = pInMsg->hdr.commandID;
  2728. cmd.seqNum = pInMsg->hdr.transSeqNum;
  2729. // Retreive the Device Configuration
  2730. pCBs->pfnLocation( &cmd );
  2731. }
  2732. stat = ZCL_STATUS_CMD_HAS_RSP;
  2733. break;
  2734. case COMMAND_LOCATION_GET_DATA:
  2735. cmd.un.loc.bitmap.locByte = *pData++;
  2736. cmd.un.loc.numResponses = *pData++;
  2737. if ( cmd.un.loc.brdcastResponse == 0 ) // command is sent as a unicast
  2738. osal_cpyExtAddr( cmd.un.loc.targetAddr, pData );
  2739. if ( pCBs->pfnLocation )
  2740. {
  2741. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  2742. cmd.cmdID = pInMsg->hdr.commandID;
  2743. cmd.seqNum = pInMsg->hdr.transSeqNum;
  2744. // Retreive the Location Data
  2745. pCBs->pfnLocation( &cmd );
  2746. }
  2747. stat = ZCL_STATUS_CMD_HAS_RSP;
  2748. break;
  2749. default:
  2750. stat = ZFailure;
  2751. break;
  2752. }
  2753. return ( stat );
  2754. }
  2755. /*********************************************************************
  2756. * @fn zclGeneral_ProcessInLocationDataRsp
  2757. *
  2758. * @brief Process in the received Location Command.
  2759. *
  2760. * @param pInMsg - pointer to the incoming message
  2761. *
  2762. * @return ZStatus_t
  2763. */
  2764. static void zclGeneral_ProcessInLocationDataRsp( zclIncoming_t *pInMsg,
  2765. zclGeneral_AppCallbacks_t *pCBs )
  2766. {
  2767. uint8 *pData = pInMsg->pData;
  2768. zclLocationRsp_t rsp;
  2769. osal_memset( (uint8*)&rsp, 0, sizeof( zclLocationRsp_t ) );
  2770. if ( pCBs->pfnLocationRsp )
  2771. {
  2772. if ( pInMsg->hdr.commandID == COMMAND_LOCATION_DATA_RSP )
  2773. rsp.un.loc.status = *pData++;
  2774. if ( pInMsg->hdr.commandID != COMMAND_LOCATION_DATA_RSP ||
  2775. rsp.un.loc.status == ZCL_STATUS_SUCCESS )
  2776. {
  2777. rsp.un.loc.data.type = *pData++;
  2778. rsp.un.loc.data.absLoc.coordinate1 = BUILD_UINT16( pData[0], pData[1] );
  2779. pData += 2;
  2780. rsp.un.loc.data.absLoc.coordinate2 = BUILD_UINT16( pData[0], pData[1] );
  2781. pData += 2;
  2782. if ( locationType2D( rsp.un.loc.data.type ) == 0 )
  2783. {
  2784. rsp.un.loc.data.absLoc.coordinate3 = BUILD_UINT16( pData[0], pData[1] );
  2785. pData += 2;
  2786. }
  2787. if ( pInMsg->hdr.commandID != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
  2788. {
  2789. rsp.un.loc.data.absLoc.power = BUILD_UINT16( pData[0], pData[1] );
  2790. pData += 2;
  2791. rsp.un.loc.data.absLoc.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
  2792. pData += 2;
  2793. }
  2794. if ( locationTypeAbsolute( rsp.un.loc.data.type ) == 0 )
  2795. {
  2796. if ( pInMsg->hdr.commandID != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
  2797. rsp.un.loc.data.calcLoc.locationMethod = *pData++;
  2798. rsp.un.loc.data.calcLoc.qualityMeasure = *pData++;
  2799. rsp.un.loc.data.calcLoc.locationAge = BUILD_UINT16( pData[0], pData[1] );
  2800. }
  2801. }
  2802. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2803. rsp.cmdID = pInMsg->hdr.commandID;
  2804. // Notify the Application
  2805. pCBs->pfnLocationRsp( &rsp );
  2806. }
  2807. }
  2808. /*********************************************************************
  2809. * @fn zclGeneral_ProcessInLocationClient
  2810. *
  2811. * @brief Process in the received Location Command.
  2812. *
  2813. * @param pInMsg - pointer to the incoming message
  2814. *
  2815. * @return ZStatus_t
  2816. */
  2817. static ZStatus_t zclGeneral_ProcessInLocationClient( zclIncoming_t *pInMsg,
  2818. zclGeneral_AppCallbacks_t *pCBs )
  2819. {
  2820. uint8 *pData = pInMsg->pData;
  2821. zclLocationRsp_t rsp;
  2822. ZStatus_t stat = ZSuccess;
  2823. osal_memset( (uint8*)&rsp, 0, sizeof( zclLocationRsp_t ) );
  2824. switch ( pInMsg->hdr.commandID )
  2825. {
  2826. case COMMAND_LOCATION_DEV_CFG_RSP:
  2827. if ( pCBs->pfnLocationRsp )
  2828. {
  2829. rsp.un.devCfg.status = *pData++;
  2830. if ( rsp.un.devCfg.status == ZCL_STATUS_SUCCESS )
  2831. {
  2832. rsp.un.devCfg.data.power = BUILD_UINT16( pData[0], pData[1] );
  2833. pData += 2;
  2834. rsp.un.devCfg.data.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
  2835. pData += 2;
  2836. rsp.un.devCfg.data.calcPeriod = BUILD_UINT16( pData[0], pData[1] );
  2837. pData += 2;
  2838. rsp.un.devCfg.data.numMeasurements = *pData++;
  2839. rsp.un.devCfg.data.reportPeriod = BUILD_UINT16( pData[0], pData[1] );
  2840. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2841. rsp.cmdID = pInMsg->hdr.commandID;
  2842. // Notify the Application
  2843. pCBs->pfnLocationRsp( &rsp );
  2844. }
  2845. }
  2846. break;
  2847. case COMMAND_LOCATION_DATA_RSP:
  2848. case COMMAND_LOCATION_DATA_NOTIF:
  2849. case COMMAND_LOCATION_COMPACT_DATA_NOTIF:
  2850. zclGeneral_ProcessInLocationDataRsp( pInMsg, pCBs );
  2851. break;
  2852. case COMMAND_LOCATION_RSSI_PING:
  2853. if ( pCBs->pfnLocationRsp )
  2854. {
  2855. rsp.un.locationType = *pData;
  2856. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2857. rsp.cmdID = pInMsg->hdr.commandID;
  2858. // Notify the Application
  2859. pCBs->pfnLocationRsp( &rsp );
  2860. }
  2861. break;
  2862. default:
  2863. stat = ZFailure;
  2864. break;
  2865. }
  2866. return ( stat );
  2867. }
  2868. #endif // ZCL_LOCATION
  2869. #ifdef ZCL_SCENES
  2870. /*********************************************************************
  2871. * @fn zclGeneral_ScenesInitNV
  2872. *
  2873. * @brief Initialize the NV Scene Table Items
  2874. *
  2875. * @param none
  2876. *
  2877. * @return number of scenes
  2878. */
  2879. static uint8 zclGeneral_ScenesInitNV( void )
  2880. {
  2881. uint8 status;
  2882. uint16 size;
  2883. size = (uint16)((sizeof ( nvGenScenesHdr_t ))
  2884. + ( sizeof( zclGenSceneNVItem_t ) * ZCL_GEN_MAX_SCENES ));
  2885. status = osal_nv_item_init( ZCD_NV_SCENE_TABLE, size, NULL );
  2886. if ( status != ZSUCCESS )
  2887. {
  2888. zclGeneral_ScenesSetDefaultNV();
  2889. }
  2890. return status;
  2891. }
  2892. /*********************************************************************
  2893. * @fn zclGeneral_ScenesSetDefaultNV
  2894. *
  2895. * @brief Write the defaults to NV
  2896. *
  2897. * @param none
  2898. *
  2899. * @return none
  2900. */
  2901. static void zclGeneral_ScenesSetDefaultNV( void )
  2902. {
  2903. nvGenScenesHdr_t hdr;
  2904. // Initialize the header
  2905. hdr.numRecs = 0;
  2906. // Save off the header
  2907. osal_nv_write( ZCD_NV_SCENE_TABLE, 0, sizeof( nvGenScenesHdr_t ), &hdr );
  2908. }
  2909. /*********************************************************************
  2910. * @fn zclGeneral_ScenesWriteNV
  2911. *
  2912. * @brief Save the Scene Table in NV
  2913. *
  2914. * @param none
  2915. *
  2916. * @return none
  2917. */
  2918. static void zclGeneral_ScenesWriteNV( void )
  2919. {
  2920. nvGenScenesHdr_t hdr;
  2921. zclGenSceneItem_t *pLoop;
  2922. zclGenSceneNVItem_t item;
  2923. hdr.numRecs = 0;
  2924. // Look for end of list
  2925. pLoop = zclGenSceneTable;
  2926. while ( pLoop )
  2927. {
  2928. // Build the record
  2929. item.endpoint = pLoop->endpoint;
  2930. osal_memcpy( &(item.scene), &(pLoop->scene), sizeof ( zclGeneral_Scene_t ) );
  2931. // Save the record to NV
  2932. osal_nv_write( ZCD_NV_SCENE_TABLE,
  2933. (uint16)((sizeof( nvGenScenesHdr_t )) + (hdr.numRecs * sizeof ( zclGenSceneNVItem_t ))),
  2934. sizeof ( zclGenSceneNVItem_t ), &item );
  2935. hdr.numRecs++;
  2936. pLoop = pLoop->next;
  2937. }
  2938. // Save off the header
  2939. osal_nv_write( ZCD_NV_SCENE_TABLE, 0, sizeof( nvGenScenesHdr_t ), &hdr );
  2940. }
  2941. /*********************************************************************
  2942. * @fn zclGeneral_ScenesRestoreFromNV
  2943. *
  2944. * @brief Restore the Scene table from NV
  2945. *
  2946. * @param none
  2947. *
  2948. * @return Number of entries restored
  2949. */
  2950. static uint16 zclGeneral_ScenesRestoreFromNV( void )
  2951. {
  2952. uint16 x;
  2953. nvGenScenesHdr_t hdr;
  2954. zclGenSceneNVItem_t item;
  2955. uint16 numAdded = 0;
  2956. if ( osal_nv_read( ZCD_NV_SCENE_TABLE, 0, sizeof(nvGenScenesHdr_t), &hdr ) == ZSuccess )
  2957. {
  2958. // Read in the device list
  2959. for ( x = 0; x < hdr.numRecs; x++ )
  2960. {
  2961. if ( osal_nv_read( ZCD_NV_SCENE_TABLE,
  2962. (uint16)(sizeof(nvGenScenesHdr_t) + (x * sizeof ( zclGenSceneNVItem_t ))),
  2963. sizeof ( zclGenSceneNVItem_t ), &item ) == ZSUCCESS )
  2964. {
  2965. // Add the scene
  2966. if ( zclGeneral_AddScene( item.endpoint, &(item.scene) ) == ZSuccess )
  2967. {
  2968. numAdded++;
  2969. }
  2970. }
  2971. }
  2972. }
  2973. return ( numAdded );
  2974. }
  2975. #endif // ZCL_SCENES
  2976. /***************************************************************************
  2977. ****************************************************************************/