zcl_general.c 97 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153
  1. /**************************************************************************************************
  2. Filename: zcl_general.c
  3. Revised: $Date: 2009-01-06 13:51:37 -0800 (Tue, 06 Jan 2009) $
  4. Revision: $Revision: 18695 $
  5. Description: Zigbee Cluster Library - General. This application receives all
  6. ZCL messages and initially parses them before passing to application.
  7. Copyright 2006-2008 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_LOCATION,
  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. #endif // ZCL_ALARMS
  816. #ifdef ZCL_LOCATION
  817. /*********************************************************************
  818. * @fn zclGeneral_SendLocationSetAbsolute
  819. *
  820. * @brief Call to send out a Set Absolute Location Command
  821. *
  822. * @param srcEP - Sending application's endpoint
  823. * @param dstAddr - where you want the message to go
  824. * @param absLoc - absolute location info
  825. *
  826. * @return ZStatus_t
  827. */
  828. ZStatus_t zclGeneral_SendLocationSetAbsolute( uint8 srcEP, afAddrType_t *dstAddr,
  829. zclLocationAbsolute_t *absLoc,
  830. uint8 disableDefaultRsp, uint8 seqNum )
  831. {
  832. uint8 buf[10]; // 5 fields (2 octects each)
  833. buf[0] = LO_UINT16( absLoc->coordinate1 );
  834. buf[1] = HI_UINT16( absLoc->coordinate1 );
  835. buf[2] = LO_UINT16( absLoc->coordinate2 );
  836. buf[3] = HI_UINT16( absLoc->coordinate2 );
  837. buf[4] = LO_UINT16( absLoc->coordinate3 );
  838. buf[5] = HI_UINT16( absLoc->coordinate3 );
  839. buf[6] = LO_UINT16( absLoc->power );
  840. buf[7] = HI_UINT16( absLoc->power );
  841. buf[8] = LO_UINT16( absLoc->pathLossExponent );
  842. buf[9] = HI_UINT16( absLoc->pathLossExponent );
  843. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  844. COMMAND_LOCATION_SET_ABSOLUTE, TRUE,
  845. ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 10, buf );
  846. }
  847. /*********************************************************************
  848. * @fn zclGeneral_SendLocationSetDevCfg
  849. *
  850. * @brief Call to send out a Set Device Configuration Command
  851. *
  852. * @param srcEP - Sending application's endpoint
  853. * @param dstAddr - where you want the message to go
  854. * @param devCfg - device configuration info
  855. *
  856. * @return ZStatus_t
  857. */
  858. ZStatus_t zclGeneral_SendLocationSetDevCfg( uint8 srcEP, afAddrType_t *dstAddr,
  859. zclLocationDevCfg_t *devCfg,
  860. uint8 disableDefaultRsp, uint8 seqNum )
  861. {
  862. uint8 buf[9]; // 4 fields (2 octects each) + 1 field with 1 octect
  863. buf[0] = LO_UINT16( devCfg->power );
  864. buf[1] = HI_UINT16( devCfg->power );
  865. buf[2] = LO_UINT16( devCfg->pathLossExponent );
  866. buf[3] = HI_UINT16( devCfg->pathLossExponent );
  867. buf[4] = LO_UINT16( devCfg->calcPeriod );
  868. buf[5] = HI_UINT16( devCfg->calcPeriod );
  869. buf[6] = devCfg->numMeasurements;
  870. buf[7] = LO_UINT16( devCfg->reportPeriod );
  871. buf[8] = HI_UINT16( devCfg->reportPeriod );
  872. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  873. COMMAND_LOCATION_SET_DEV_CFG, TRUE,
  874. ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 9, buf );
  875. }
  876. /*********************************************************************
  877. * @fn zclGeneral_SendLocationGetDevCfg
  878. *
  879. * @brief Call to send out a Get Device Configuration Command
  880. *
  881. * @param srcEP - Sending application's endpoint
  882. * @param dstAddr - where you want the message to go
  883. * @param targetAddr - device for which location parameters are being requested
  884. *
  885. * @return ZStatus_t
  886. */
  887. ZStatus_t zclGeneral_SendLocationGetDevCfg( uint8 srcEP, afAddrType_t *dstAddr,
  888. uint8 *targetAddr, uint8 disableDefaultRsp, uint8 seqNum )
  889. {
  890. uint8 buf[8];
  891. osal_cpyExtAddr( buf, targetAddr );
  892. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  893. COMMAND_LOCATION_GET_DEV_CFG, TRUE,
  894. ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 8, buf );
  895. }
  896. /*********************************************************************
  897. * @fn zclGeneral_SendLocationGetData
  898. *
  899. * @brief Call to send out a Get Location Data Command
  900. *
  901. * @param srcEP - Sending application's endpoint
  902. * @param dstAddr - where you want the message to go
  903. * @param locaData - location information and channel parameters that are requested.
  904. *
  905. * @return ZStatus_t
  906. */
  907. ZStatus_t zclGeneral_SendLocationGetData( uint8 srcEP, afAddrType_t *dstAddr,
  908. zclLocationGetData_t *locData,
  909. uint8 disableDefaultRsp, uint8 seqNum )
  910. {
  911. uint8 buf[10]; // bitmap (1) + number responses (1) + IEEE Address (8)
  912. uint8 *pBuf = buf;
  913. uint8 len = 2; // bitmap + number responses
  914. *pBuf = locData->absoluteOnly;
  915. *pBuf |= locData->recalculate << 1;
  916. *pBuf |= locData->brdcastIndicator << 2;
  917. *pBuf |= locData->brdcastResponse << 3;
  918. *pBuf |= locData->compactResponse << 4;
  919. pBuf++; // move past the bitmap field
  920. *pBuf++ = locData->numResponses;
  921. if ( locData->brdcastIndicator == 0 )
  922. {
  923. osal_cpyExtAddr( pBuf, locData->targetAddr );
  924. len += 8; // ieee addr
  925. }
  926. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  927. COMMAND_LOCATION_GET_DATA, TRUE,
  928. ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, len, buf );
  929. }
  930. /*********************************************************************
  931. * @fn zclGeneral_SendLocationDevCfgResponse
  932. *
  933. * @brief Call to send out a Device Configuration Response Command
  934. *
  935. * @param srcEP - Sending application's endpoint
  936. * @param dstAddr - where you want the message to go
  937. * @param devCfg - device's location parameters that are requested
  938. *
  939. * @return ZStatus_t
  940. */
  941. ZStatus_t zclGeneral_SendLocationDevCfgResponse( uint8 srcEP, afAddrType_t *dstAddr,
  942. zclLocationDevCfgRsp_t *devCfg,
  943. uint8 disableDefaultRsp, uint8 seqNum )
  944. {
  945. uint8 buf[10]; // 4 fields (2 octects each) + 2 fields (1 octect each)
  946. uint8 len = 1; // Status
  947. buf[0] = devCfg->status;
  948. if ( devCfg->status == ZCL_STATUS_SUCCESS )
  949. {
  950. buf[1] = LO_UINT16( devCfg->data.power );
  951. buf[2] = HI_UINT16( devCfg->data.power );
  952. buf[3] = LO_UINT16( devCfg->data.pathLossExponent );
  953. buf[4] = HI_UINT16( devCfg->data.pathLossExponent );
  954. buf[5] = LO_UINT16( devCfg->data.calcPeriod );
  955. buf[6] = HI_UINT16( devCfg->data.calcPeriod );
  956. buf[7] = devCfg->data.numMeasurements;
  957. buf[8] = LO_UINT16( devCfg->data.reportPeriod );
  958. buf[9] = HI_UINT16( devCfg->data.reportPeriod );
  959. len += 9;
  960. }
  961. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  962. COMMAND_LOCATION_DEV_CFG_RSP, TRUE,
  963. ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
  964. }
  965. /*********************************************************************
  966. * @fn zclGeneral_SendLocationData
  967. *
  968. * @brief Call to send out location data
  969. *
  970. * @param srcEP - Sending application's endpoint
  971. * @param dstAddr - where you want the message to go
  972. * @param status - indicates whether response to request was successful or not
  973. * @param locData - location information and channel parameters being sent
  974. *
  975. * @return ZStatus_t
  976. */
  977. ZStatus_t zclGeneral_SendLocationData( uint8 srcEP, afAddrType_t *dstAddr, uint8 cmd,
  978. uint8 status, zclLocationData_t *locData,
  979. uint8 disableDefaultRsp, uint8 seqNum )
  980. {
  981. uint8 buf[16];
  982. uint8 *pBuf = buf;
  983. uint8 len = 0;
  984. if ( cmd == COMMAND_LOCATION_DATA_RSP )
  985. {
  986. // Only response command includes a status field
  987. *pBuf++ = status;
  988. len++;
  989. }
  990. if ( cmd != COMMAND_LOCATION_DATA_RSP || status == ZCL_STATUS_SUCCESS )
  991. {
  992. // Notification or Response with successful status
  993. *pBuf++ = locData->type;
  994. *pBuf++ = LO_UINT16( locData->absLoc.coordinate1 );
  995. *pBuf++ = HI_UINT16( locData->absLoc.coordinate1 );
  996. *pBuf++ = LO_UINT16( locData->absLoc.coordinate2 );
  997. *pBuf++ = HI_UINT16( locData->absLoc.coordinate2 );
  998. len += 5;
  999. if ( locationType2D(locData->type) == 0 )
  1000. {
  1001. // 2D location doesn't have coordinate 3
  1002. *pBuf++ = LO_UINT16( locData->absLoc.coordinate3 );
  1003. *pBuf++ = HI_UINT16( locData->absLoc.coordinate3 );
  1004. len += 2;
  1005. }
  1006. if ( cmd != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
  1007. {
  1008. // Compact notification doesn't include these fields
  1009. *pBuf++ = LO_UINT16( locData->absLoc.power );
  1010. *pBuf++ = HI_UINT16( locData->absLoc.power );
  1011. *pBuf++ = LO_UINT16( locData->absLoc.pathLossExponent );
  1012. *pBuf++ = HI_UINT16( locData->absLoc.pathLossExponent );
  1013. len += 4;
  1014. }
  1015. if ( locationTypeAbsolute(locData->type) == 0 )
  1016. {
  1017. // Absolute location doesn't include these fields
  1018. if ( cmd != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
  1019. {
  1020. // Compact notification doesn't include this field
  1021. *pBuf++ = locData->calcLoc.locationMethod;
  1022. len++;
  1023. }
  1024. *pBuf++ = locData->calcLoc.qualityMeasure;
  1025. *pBuf++ = LO_UINT16( locData->calcLoc.locationAge );
  1026. *pBuf++ = HI_UINT16( locData->calcLoc.locationAge );
  1027. len += 3;
  1028. }
  1029. }
  1030. return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
  1031. cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
  1032. disableDefaultRsp, 0, seqNum, len, buf );
  1033. }
  1034. #endif // ZCL_LOCATION
  1035. /*********************************************************************
  1036. * @fn zclGeneral_FindCallbacks
  1037. *
  1038. * @brief Find the callbacks for an endpoint
  1039. *
  1040. * @param endpoint - endpoint to find the application callbacks for
  1041. *
  1042. * @return pointer to the callbacks
  1043. */
  1044. static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint )
  1045. {
  1046. zclGenCBRec_t *pCBs;
  1047. pCBs = zclGenCBs;
  1048. while ( pCBs )
  1049. {
  1050. if ( pCBs->endpoint == endpoint )
  1051. return ( pCBs->CBs );
  1052. pCBs = pCBs->next;
  1053. }
  1054. return ( (zclGeneral_AppCallbacks_t *)NULL );
  1055. }
  1056. /*********************************************************************
  1057. * @fn zclGeneral_HdlIncoming
  1058. *
  1059. * @brief Callback from ZCL to process incoming Commands specific
  1060. * to this cluster library or Profile commands for attributes
  1061. * that aren't in the attribute list
  1062. *
  1063. *
  1064. * @param pInMsg - pointer to the incoming message
  1065. *
  1066. * @return ZStatus_t
  1067. */
  1068. static ZStatus_t zclGeneral_HdlIncoming( zclIncoming_t *pInMsg )
  1069. {
  1070. ZStatus_t stat = ZSuccess;
  1071. #if defined ( INTER_PAN )
  1072. if ( StubAPS_InterPan( pInMsg->msg->srcAddr.panId, pInMsg->msg->srcAddr.endPoint ) )
  1073. return ( stat ); // Cluster not supported thru Inter-PAN
  1074. #endif
  1075. if ( zcl_ClusterCmd( pInMsg->hdr.fc.type ) )
  1076. {
  1077. // Is this a manufacturer specific command?
  1078. if ( pInMsg->hdr.fc.manuSpecific == 0 )
  1079. {
  1080. stat = zclGeneral_HdlInSpecificCommands( pInMsg );
  1081. }
  1082. else
  1083. {
  1084. // We don't support any manufacturer specific command.
  1085. stat = ZFailure;
  1086. }
  1087. }
  1088. else
  1089. {
  1090. // Handle all the normal (Read, Write...) commands -- should never get here
  1091. stat = ZFailure;
  1092. }
  1093. return ( stat );
  1094. }
  1095. /*********************************************************************
  1096. * @fn zclGeneral_HdlInSpecificCommands
  1097. *
  1098. * @brief Callback from ZCL to process incoming Commands specific
  1099. * to this cluster library
  1100. * @param pInMsg - pointer to the incoming message
  1101. *
  1102. * @return ZStatus_t
  1103. */
  1104. static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg )
  1105. {
  1106. ZStatus_t stat;
  1107. zclGeneral_AppCallbacks_t *pCBs;
  1108. // make sure endpoint exists
  1109. pCBs = zclGeneral_FindCallbacks( pInMsg->msg->endPoint );
  1110. if ( pCBs == NULL )
  1111. return ( ZFailure );
  1112. switch ( pInMsg->msg->clusterId )
  1113. {
  1114. #ifdef ZCL_BASIC
  1115. case ZCL_CLUSTER_ID_GEN_BASIC:
  1116. stat = zclGeneral_ProcessInBasic( pInMsg, pCBs );
  1117. break;
  1118. #endif // ZCL_BASIC
  1119. #ifdef ZCL_IDENTIFY
  1120. case ZCL_CLUSTER_ID_GEN_IDENTIFY:
  1121. stat = zclGeneral_ProcessInIdentity( pInMsg, pCBs );
  1122. break;
  1123. #endif // ZCL_IDENTIFY
  1124. #ifdef ZCL_GROUPS
  1125. case ZCL_CLUSTER_ID_GEN_GROUPS:
  1126. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1127. stat = zclGeneral_ProcessInGroupsServer( pInMsg );
  1128. else
  1129. stat = zclGeneral_ProcessInGroupsClient( pInMsg, pCBs );
  1130. break;
  1131. #endif // ZCL_GROUPS
  1132. #ifdef ZCL_SCENES
  1133. case ZCL_CLUSTER_ID_GEN_SCENES:
  1134. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1135. stat = zclGeneral_ProcessInScenesServer( pInMsg, pCBs );
  1136. else
  1137. stat = zclGeneral_ProcessInScenesClient( pInMsg, pCBs );
  1138. break;
  1139. #endif // ZCL_SCENES
  1140. #ifdef ZCL_ON_OFF
  1141. case ZCL_CLUSTER_ID_GEN_ON_OFF:
  1142. stat = zclGeneral_ProcessInOnOff( pInMsg, pCBs );
  1143. break;
  1144. #endif // ZCL_ON_OFF
  1145. #ifdef ZCL_LEVEL_CTRL
  1146. case ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL:
  1147. stat = zclGeneral_ProcessInLevelControl( pInMsg, pCBs );
  1148. break;
  1149. #endif // ZCL_LEVEL_CTRL
  1150. #ifdef ZCL_ALARMS
  1151. case ZCL_CLUSTER_ID_GEN_ALARMS:
  1152. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1153. stat = zclGeneral_ProcessInAlarmsServer( pInMsg, pCBs );
  1154. else
  1155. stat = zclGeneral_ProcessInAlarmsClient( pInMsg, pCBs );
  1156. break;
  1157. #endif // ZCL_ALARMS
  1158. #ifdef ZCL_LOCATION
  1159. case ZCL_CLUSTER_ID_GEN_LOCATION:
  1160. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1161. stat = zclGeneral_ProcessInLocationServer( pInMsg, pCBs );
  1162. else
  1163. stat = zclGeneral_ProcessInLocationClient( pInMsg, pCBs );
  1164. break;
  1165. #endif // ZCL_LOCATION
  1166. case ZCL_CLUSTER_ID_GEN_POWER_CFG:
  1167. case ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG:
  1168. case ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG:
  1169. case ZCL_CLUSTER_ID_GEN_TIME:
  1170. default:
  1171. stat = ZFailure;
  1172. break;
  1173. }
  1174. return ( stat );
  1175. }
  1176. #ifdef ZCL_BASIC
  1177. /*********************************************************************
  1178. * @fn zclGeneral_ProcessInBasic
  1179. *
  1180. * @brief Process in the received Basic Command.
  1181. *
  1182. * @param pInMsg - pointer to the incoming message
  1183. *
  1184. * @return ZStatus_t
  1185. */
  1186. static ZStatus_t zclGeneral_ProcessInBasic( zclIncoming_t *pInMsg,
  1187. zclGeneral_AppCallbacks_t *pCBs )
  1188. {
  1189. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1190. {
  1191. if ( pInMsg->hdr.commandID > COMMAND_BASIC_RESET_FACT_DEFAULT )
  1192. return ( ZFailure ); // Error ignore the command
  1193. if ( pCBs->pfnBasicReset )
  1194. pCBs->pfnBasicReset();
  1195. }
  1196. // no Client command
  1197. return ( ZSuccess );
  1198. }
  1199. #endif // ZCL_BASIC
  1200. #ifdef ZCL_IDENTIFY
  1201. /*********************************************************************
  1202. * @fn zclGeneral_ProcessInIdentity
  1203. *
  1204. * @brief Process in the received Identity Command.
  1205. *
  1206. * @param pInMsg - pointer to the incoming message
  1207. *
  1208. * @return ZStatus_t
  1209. */
  1210. static ZStatus_t zclGeneral_ProcessInIdentity( zclIncoming_t *pInMsg,
  1211. zclGeneral_AppCallbacks_t *pCBs )
  1212. {
  1213. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  1214. {
  1215. if ( pInMsg->hdr.commandID > COMMAND_IDENTIFY_QUERY )
  1216. return ( ZFailure ); // Error ignore the command
  1217. if ( pInMsg->hdr.commandID == COMMAND_IDENTIFY )
  1218. {
  1219. if ( pCBs->pfnIdentify )
  1220. {
  1221. zclIdentify_t cmd;
  1222. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  1223. cmd.identifyTime = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
  1224. pCBs->pfnIdentify( &cmd );
  1225. }
  1226. }
  1227. else
  1228. {
  1229. zclAttrRec_t attrRec;
  1230. uint16 identifyTime = 0;
  1231. // Retrieve Identify Time
  1232. if ( zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, ATTRID_IDENTIFY_TIME, &attrRec ) )
  1233. zclReadAttrData( (uint8 *)&identifyTime, &attrRec );
  1234. // Is device identifying itself?
  1235. if ( identifyTime > 0 )
  1236. {
  1237. zclGeneral_SendIdentifyQueryResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1238. identifyTime, true, pInMsg->hdr.transSeqNum );
  1239. }
  1240. return ( ZCL_STATUS_CMD_HAS_RSP );
  1241. }
  1242. }
  1243. else // Client Command
  1244. {
  1245. if ( pInMsg->hdr.commandID > COMMAND_IDENTIFY_QUERY_RSP )
  1246. return ( ZFailure ); // Error ignore the command
  1247. if ( pCBs->pfnIdentifyQueryRsp )
  1248. {
  1249. zclIdentifyQueryRsp_t rsp;
  1250. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  1251. rsp.timeout = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
  1252. pCBs->pfnIdentifyQueryRsp( &rsp );
  1253. }
  1254. }
  1255. return ( ZSuccess );
  1256. }
  1257. #endif // ZCL_IDENTIFY
  1258. #ifdef ZCL_GROUPS
  1259. /*********************************************************************
  1260. * @fn zclGeneral_AddGroup
  1261. *
  1262. * @brief Add a Group.
  1263. *
  1264. * @param endPoint - application endpoint
  1265. * @param group - group to be added
  1266. * @param pData - pointer to the group info
  1267. *
  1268. * @return ZStatus_t
  1269. */
  1270. static ZStatus_t zclGeneral_AddGroup( uint8 endPoint, aps_Group_t *group, uint8 *pData )
  1271. {
  1272. zclAttrRec_t attrRec;
  1273. uint8 nameLen;
  1274. uint8 nameSupport = FALSE;
  1275. pData += 2; // Move past group ID
  1276. nameLen = *pData++;
  1277. // Retrieve Name Support attribute
  1278. if ( zclFindAttrRec( endPoint, ZCL_CLUSTER_ID_GEN_GROUPS, ATTRID_GROUP_NAME_SUPPORT, &attrRec ) )
  1279. zclReadAttrData( &nameSupport, &attrRec );
  1280. if ( nameSupport )
  1281. {
  1282. if ( nameLen > (APS_GROUP_NAME_LEN-1) )
  1283. nameLen = (APS_GROUP_NAME_LEN-1);
  1284. group->name[0] = nameLen;
  1285. osal_memcpy( &(group->name[1]), pData, nameLen );
  1286. }
  1287. return ( aps_AddGroup( endPoint, group ) );
  1288. }
  1289. /*********************************************************************
  1290. * @fn zclGeneral_ProcessInGroupsServer
  1291. *
  1292. * @brief Process in the received Groups Command.
  1293. *
  1294. * @param pInMsg - pointer to the incoming message
  1295. *
  1296. * @return ZStatus_t
  1297. */
  1298. static ZStatus_t zclGeneral_ProcessInGroupsServer( zclIncoming_t *pInMsg )
  1299. {
  1300. zclAttrRec_t attrRec;
  1301. aps_Group_t group;
  1302. aps_Group_t *pGroup;
  1303. uint8 *pData;
  1304. uint8 status;
  1305. uint8 grpCnt;
  1306. uint8 grpRspCnt = 0;
  1307. uint16 *grpList;
  1308. uint16 identifyTime = 0;
  1309. uint8 i;
  1310. ZStatus_t stat = ZSuccess;
  1311. osal_memset( (uint8*)&group, 0, sizeof( aps_Group_t ) );
  1312. pData = pInMsg->pData;
  1313. group.ID = BUILD_UINT16( pData[0], pData[1] );
  1314. switch ( pInMsg->hdr.commandID )
  1315. {
  1316. case COMMAND_GROUP_ADD:
  1317. status = zclGeneral_AddGroup( pInMsg->msg->endPoint, &group, pData );
  1318. if ( status != ZSuccess )
  1319. {
  1320. if ( status == ZApsDuplicateEntry )
  1321. status = ZCL_STATUS_DUPLICATE_EXISTS;
  1322. else
  1323. status = ZCL_STATUS_INSUFFICIENT_SPACE;
  1324. }
  1325. zclGeneral_SendGroupAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1326. status, group.ID, true, pInMsg->hdr.transSeqNum );
  1327. stat = ZCL_STATUS_CMD_HAS_RSP;
  1328. break;
  1329. case COMMAND_GROUP_VIEW:
  1330. pGroup = aps_FindGroup( pInMsg->msg->endPoint, group.ID );
  1331. if ( pGroup )
  1332. {
  1333. status = ZCL_STATUS_SUCCESS;
  1334. }
  1335. else
  1336. {
  1337. // Group not found
  1338. status = ZCL_STATUS_NOT_FOUND;
  1339. pGroup = &group;
  1340. }
  1341. zclGeneral_SendGroupViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1342. status, pGroup, true, pInMsg->hdr.transSeqNum );
  1343. stat = ZCL_STATUS_CMD_HAS_RSP;
  1344. break;
  1345. case COMMAND_GROUP_GET_MEMBERSHIP:
  1346. grpCnt = *pData++;
  1347. // Allocate space for the group list
  1348. grpList = osal_mem_alloc( sizeof( uint16 ) * APS_MAX_GROUPS );
  1349. if ( grpList != NULL )
  1350. {
  1351. if ( grpCnt == 0 )
  1352. {
  1353. // Find out all the groups of which the endpoint is a member.
  1354. grpRspCnt = aps_FindAllGroupsForEndpoint( pInMsg->msg->endPoint, grpList );
  1355. }
  1356. else
  1357. {
  1358. // Find out the groups (in the list) of which the endpoint is a member.
  1359. for ( i = 0; i < grpCnt; i++ )
  1360. {
  1361. group.ID = BUILD_UINT16( pData[0], pData[1] );
  1362. pData += 2;
  1363. if ( aps_FindGroup( pInMsg->msg->endPoint, group.ID ) )
  1364. grpList[grpRspCnt++] = group.ID;
  1365. }
  1366. }
  1367. if ( grpCnt == 0 || grpRspCnt != 0 )
  1368. {
  1369. zclGeneral_SendGroupGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1370. aps_GroupsRemaingCapacity(), grpRspCnt,
  1371. grpList, true, pInMsg->hdr.transSeqNum );
  1372. }
  1373. osal_mem_free( grpList );
  1374. }
  1375. else
  1376. {
  1377. // Couldn't allocate space for the group list -- send a Default Response command back.
  1378. zclDefaultRspCmd_t defaultRspCmd;
  1379. defaultRspCmd.commandID = pInMsg->hdr.commandID;
  1380. defaultRspCmd.statusCode = ZCL_STATUS_INSUFFICIENT_SPACE;
  1381. zcl_SendDefaultRspCmd( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
  1382. pInMsg->msg->clusterId, &defaultRspCmd,
  1383. ZCL_FRAME_SERVER_CLIENT_DIR, true, pInMsg->hdr.transSeqNum );
  1384. }
  1385. stat = ZCL_STATUS_CMD_HAS_RSP;
  1386. break;
  1387. case COMMAND_GROUP_REMOVE:
  1388. if ( aps_RemoveGroup( pInMsg->msg->endPoint, group.ID ) )
  1389. status = ZCL_STATUS_SUCCESS;
  1390. else
  1391. status = ZCL_STATUS_NOT_FOUND;
  1392. zclGeneral_SendGroupRemoveResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1393. status, group.ID, true, pInMsg->hdr.transSeqNum );
  1394. stat = ZCL_STATUS_CMD_HAS_RSP;
  1395. break;
  1396. case COMMAND_GROUP_REMOVE_ALL:
  1397. aps_RemoveAllGroup( pInMsg->msg->endPoint );
  1398. break;
  1399. case COMMAND_GROUP_ADD_IF_IDENTIFYING:
  1400. // Retrieve Identify Time
  1401. if ( zclFindAttrRec( pInMsg->msg->endPoint, ZCL_CLUSTER_ID_GEN_IDENTIFY, ATTRID_IDENTIFY_TIME, &attrRec ) )
  1402. zclReadAttrData( (uint8 *)&identifyTime, &attrRec );
  1403. // Is device identifying itself?
  1404. if ( identifyTime > 0 )
  1405. zclGeneral_AddGroup( pInMsg->msg->endPoint, &group, pData );
  1406. break;
  1407. default:
  1408. stat = ZFailure;
  1409. break;
  1410. }
  1411. return ( stat );
  1412. }
  1413. /*********************************************************************
  1414. * @fn zclGeneral_ProcessInGroupsClient
  1415. *
  1416. * @brief Process in the received Groups Command.
  1417. *
  1418. * @param pInMsg - pointer to the incoming message
  1419. *
  1420. * @return ZStatus_t
  1421. */
  1422. static ZStatus_t zclGeneral_ProcessInGroupsClient( zclIncoming_t *pInMsg,
  1423. zclGeneral_AppCallbacks_t *pCBs )
  1424. {
  1425. aps_Group_t group;
  1426. uint8 *pData = pInMsg->pData;
  1427. uint16 *grpList;
  1428. uint8 grpCnt;
  1429. uint8 nameLen;
  1430. zclGroupRsp_t rsp;
  1431. uint8 i;
  1432. ZStatus_t stat = ZSuccess;
  1433. osal_memset( (uint8*)&group, 0, sizeof( aps_Group_t ) );
  1434. osal_memset( (uint8*)&rsp, 0, sizeof( zclGroupRsp_t ) );
  1435. switch ( pInMsg->hdr.commandID )
  1436. {
  1437. case COMMAND_GROUP_ADD_RSP:
  1438. case COMMAND_GROUP_VIEW_RSP:
  1439. case COMMAND_GROUP_REMOVE_RSP:
  1440. rsp.status = *pData++;
  1441. group.ID = BUILD_UINT16( pData[0], pData[1] );
  1442. if ( rsp.status == ZCL_STATUS_SUCCESS && pInMsg->hdr.commandID == COMMAND_GROUP_VIEW_RSP )
  1443. {
  1444. pData += 2; // Move past ID
  1445. nameLen = *pData++;
  1446. if ( nameLen > (APS_GROUP_NAME_LEN-1) )
  1447. nameLen = (APS_GROUP_NAME_LEN-1);
  1448. group.name[0] = nameLen;
  1449. osal_memcpy( &(group.name[1]), pData, nameLen );
  1450. rsp.grpName = group.name;
  1451. }
  1452. if ( pCBs->pfnGroupRsp )
  1453. {
  1454. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  1455. rsp.cmdID = pInMsg->hdr.commandID;
  1456. rsp.grpCnt = 1;
  1457. rsp.grpList = &group.ID;
  1458. rsp.capacity = 0;
  1459. pCBs->pfnGroupRsp( &rsp );
  1460. }
  1461. break;
  1462. case COMMAND_GROUP_GET_MEMBERSHIP_RSP:
  1463. rsp.capacity = *pData++;
  1464. grpCnt = *pData++;
  1465. if ( grpCnt > 0 )
  1466. {
  1467. // Allocate space for the group list
  1468. grpList = osal_mem_alloc( sizeof( uint16 ) * grpCnt );
  1469. if ( grpList != NULL )
  1470. {
  1471. rsp.grpCnt = grpCnt;
  1472. for ( i = 0; i < grpCnt; i++ )
  1473. {
  1474. grpList[i] = BUILD_UINT16( pData[0], pData[1] );
  1475. pData += 2;
  1476. }
  1477. }
  1478. }
  1479. if ( pCBs->pfnGroupRsp )
  1480. {
  1481. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  1482. rsp.cmdID = pInMsg->hdr.commandID;
  1483. rsp.grpList = grpList;
  1484. pCBs->pfnGroupRsp( &rsp );
  1485. }
  1486. if ( grpList != NULL )
  1487. osal_mem_free( grpList );
  1488. break;
  1489. default:
  1490. stat = ZFailure;
  1491. break;
  1492. }
  1493. return ( stat );
  1494. }
  1495. #endif // ZCL_GROUPS
  1496. #ifdef ZCL_SCENES
  1497. /*********************************************************************
  1498. * @fn zclGeneral_AddScene
  1499. *
  1500. * @brief Add a scene for an endpoint
  1501. *
  1502. * @param endpoint -
  1503. * @param scene - new scene item
  1504. *
  1505. * @return ZStatus_t
  1506. */
  1507. ZStatus_t zclGeneral_AddScene( uint8 endpoint, zclGeneral_Scene_t *scene )
  1508. {
  1509. zclGenSceneItem_t *pNewItem;
  1510. zclGenSceneItem_t *pLoop;
  1511. // Fill in the new profile list
  1512. pNewItem = osal_mem_alloc( sizeof( zclGenSceneItem_t ) );
  1513. if ( pNewItem == NULL )
  1514. return ( ZMemError );
  1515. // Fill in the plugin record.
  1516. pNewItem->next = (zclGenSceneItem_t *)NULL;
  1517. pNewItem->endpoint = endpoint;
  1518. osal_memcpy( (uint8*)&(pNewItem->scene), (uint8*)scene, sizeof ( zclGeneral_Scene_t ));
  1519. // Find spot in list
  1520. if ( zclGenSceneTable == NULL )
  1521. {
  1522. zclGenSceneTable = pNewItem;
  1523. }
  1524. else
  1525. {
  1526. // Look for end of list
  1527. pLoop = zclGenSceneTable;
  1528. while ( pLoop->next != NULL )
  1529. pLoop = pLoop->next;
  1530. // Put new item at end of list
  1531. pLoop->next = pNewItem;
  1532. }
  1533. // Update NV
  1534. zclGeneral_ScenesWriteNV();
  1535. return ( ZSuccess );
  1536. }
  1537. /*********************************************************************
  1538. * @fn zclGeneral_FindScene
  1539. *
  1540. * @brief Find a scene with endpoint and sceneID
  1541. *
  1542. * @param endpoint -
  1543. * @param groupID - what group the scene belongs to
  1544. * @param sceneID - ID to look for scene
  1545. *
  1546. * @return a pointer to the scene information, NULL if not found
  1547. */
  1548. zclGeneral_Scene_t *zclGeneral_FindScene( uint8 endpoint, uint16 groupID, uint8 sceneID )
  1549. {
  1550. zclGenSceneItem_t *pLoop;
  1551. // Look for end of list
  1552. pLoop = zclGenSceneTable;
  1553. while ( pLoop )
  1554. {
  1555. if ( (pLoop->endpoint == endpoint || endpoint == 0xFF)
  1556. && pLoop->scene.groupID == groupID && pLoop->scene.ID == sceneID )
  1557. {
  1558. return ( &(pLoop->scene) );
  1559. }
  1560. pLoop = pLoop->next;
  1561. }
  1562. return ( (zclGeneral_Scene_t *)NULL );
  1563. }
  1564. /*********************************************************************
  1565. * @fn aps_FindAllScensForGroup
  1566. *
  1567. * @brief Find all the scenes with groupID
  1568. *
  1569. * @param endpoint - endpoint to look for
  1570. * @param sceneList - List to hold scene IDs (should hold APS_MAX_SCENES entries)
  1571. *
  1572. * @return number of scenes copied to sceneList
  1573. */
  1574. uint8 zclGeneral_FindAllScenesForGroup( uint8 endpoint, uint16 groupID, uint8 *sceneList )
  1575. {
  1576. zclGenSceneItem_t *pLoop;
  1577. uint8 cnt = 0;
  1578. // Look for end of list
  1579. pLoop = zclGenSceneTable;
  1580. while ( pLoop )
  1581. {
  1582. if ( pLoop->endpoint == endpoint && pLoop->scene.groupID == groupID )
  1583. sceneList[cnt++] = pLoop->scene.ID;
  1584. pLoop = pLoop->next;
  1585. }
  1586. return ( cnt );
  1587. }
  1588. /*********************************************************************
  1589. * @fn zclGeneral_RemoveScene
  1590. *
  1591. * @brief Remove a scene with endpoint and sceneID
  1592. *
  1593. * @param endpoint -
  1594. * @param groupID - what group the scene belongs to
  1595. * @param sceneID - ID to look for scene
  1596. *
  1597. * @return TRUE if removed, FALSE if not found
  1598. */
  1599. uint8 zclGeneral_RemoveScene( uint8 endpoint, uint16 groupID, uint8 sceneID )
  1600. {
  1601. zclGenSceneItem_t *pLoop;
  1602. zclGenSceneItem_t *pPrev;
  1603. // Look for end of list
  1604. pLoop = zclGenSceneTable;
  1605. pPrev = NULL;
  1606. while ( pLoop )
  1607. {
  1608. if ( pLoop->endpoint == endpoint
  1609. && pLoop->scene.groupID == groupID && pLoop->scene.ID == sceneID )
  1610. {
  1611. if ( pPrev == NULL )
  1612. zclGenSceneTable = pLoop->next;
  1613. else
  1614. pPrev->next = pLoop->next;
  1615. // Free the memory
  1616. osal_mem_free( pLoop );
  1617. // Update NV
  1618. zclGeneral_ScenesWriteNV();
  1619. return ( TRUE );
  1620. }
  1621. pPrev = pLoop;
  1622. pLoop = pLoop->next;
  1623. }
  1624. return ( FALSE );
  1625. }
  1626. /*********************************************************************
  1627. * @fn zclGeneral_RemoveAllScenes
  1628. *
  1629. * @brief Remove all scenes with endpoint and group Id
  1630. *
  1631. * @param endpoint -
  1632. * @param groupID - ID to look for group
  1633. *
  1634. * @return none
  1635. */
  1636. void zclGeneral_RemoveAllScenes( uint8 endpoint, uint16 groupID )
  1637. {
  1638. zclGenSceneItem_t *pLoop;
  1639. zclGenSceneItem_t *pPrev;
  1640. zclGenSceneItem_t *pNext;
  1641. // Look for end of list
  1642. pLoop = zclGenSceneTable;
  1643. pPrev = NULL;
  1644. while ( pLoop )
  1645. {
  1646. if ( pLoop->endpoint == endpoint && pLoop->scene.groupID == groupID )
  1647. {
  1648. if ( pPrev == NULL )
  1649. zclGenSceneTable = pLoop->next;
  1650. else
  1651. pPrev->next = pLoop->next;
  1652. pNext = pLoop->next;
  1653. // Free the memory
  1654. osal_mem_free( pLoop );
  1655. pLoop = pNext;
  1656. }
  1657. else
  1658. {
  1659. pPrev = pLoop;
  1660. pLoop = pLoop->next;
  1661. }
  1662. }
  1663. // Update NV
  1664. zclGeneral_ScenesWriteNV();
  1665. }
  1666. /*********************************************************************
  1667. * @fn zclGeneral_CountScenes
  1668. *
  1669. * @brief Count the number of scenes for an endpoint
  1670. *
  1671. * @param endpoint -
  1672. *
  1673. * @return number of scenes assigned to an endpoint
  1674. */
  1675. uint8 zclGeneral_CountScenes( uint8 endpoint )
  1676. {
  1677. zclGenSceneItem_t *pLoop;
  1678. uint8 cnt = 0;
  1679. // Look for end of list
  1680. pLoop = zclGenSceneTable;
  1681. while ( pLoop )
  1682. {
  1683. if ( pLoop->endpoint == endpoint )
  1684. cnt++;
  1685. pLoop = pLoop->next;
  1686. }
  1687. return ( cnt );
  1688. }
  1689. /*********************************************************************
  1690. * @fn zclGeneral_CountAllScenes
  1691. *
  1692. * @brief Count the total number of scenes
  1693. *
  1694. * @param none
  1695. *
  1696. * @return number of scenes
  1697. */
  1698. uint8 zclGeneral_CountAllScenes( void )
  1699. {
  1700. zclGenSceneItem_t *pLoop;
  1701. uint8 cnt = 0;
  1702. // Look for end of list
  1703. pLoop = zclGenSceneTable;
  1704. while ( pLoop )
  1705. {
  1706. cnt++;
  1707. pLoop = pLoop->next;
  1708. }
  1709. return ( cnt );
  1710. }
  1711. /*********************************************************************
  1712. * @fn zclGeneral_ProcessInScenesServer
  1713. *
  1714. * @brief Process in the received Scenes Command.
  1715. *
  1716. * @param pInMsg - pointer to the incoming message
  1717. *
  1718. * @return ZStatus_t
  1719. */
  1720. static ZStatus_t zclGeneral_ProcessInScenesServer( zclIncoming_t *pInMsg,
  1721. zclGeneral_AppCallbacks_t *pCBs )
  1722. {
  1723. zclAttrRec_t attrRec;
  1724. zclGeneral_Scene_t scene;
  1725. zclGeneral_Scene_t *pScene;
  1726. uint8 *pData = pInMsg->pData;
  1727. uint8 nameLen;
  1728. uint8 status;
  1729. uint8 sceneCnt = 0;
  1730. uint8 *sceneList = NULL;
  1731. uint8 sendRsp = FALSE;
  1732. uint8 nameSupport = FALSE;
  1733. ZStatus_t stat = ZSuccess;
  1734. osal_memset( (uint8*)&scene, 0, sizeof( zclGeneral_Scene_t ) );
  1735. scene.groupID = BUILD_UINT16( pData[0], pData[1] );
  1736. pData += 2; // Move past group ID
  1737. scene.ID = *pData++;
  1738. switch ( pInMsg->hdr.commandID )
  1739. {
  1740. case COMMAND_SCENE_ADD:
  1741. // Parse the rest of the incoming message
  1742. scene.transTime = BUILD_UINT16( pData[0], pData[1] );
  1743. pData += 2;
  1744. nameLen= *pData++; // Name length
  1745. // Retrieve Name Support attribute
  1746. if ( zclFindAttrRec( pInMsg->msg->endPoint, ZCL_CLUSTER_ID_GEN_SCENES, ATTRID_SCENES_NAME_SUPPORT, &attrRec ) )
  1747. zclReadAttrData( &nameSupport, &attrRec );
  1748. if ( nameSupport )
  1749. {
  1750. if ( nameLen > (ZCL_GEN_SCENE_NAME_LEN-1) )
  1751. nameLen = (ZCL_GEN_SCENE_NAME_LEN-1);
  1752. scene.name[0] = nameLen;
  1753. osal_memcpy( &(scene.name[1]), pData, nameLen );
  1754. }
  1755. pData += nameLen; // move pass name
  1756. scene.extLen = pInMsg->pDataLen - ( (uint8)( pData - pInMsg->pData ) );
  1757. if ( scene.extLen > 0 )
  1758. {
  1759. // Copy the extention field(s)
  1760. if ( scene.extLen > ZCL_GEN_SCENE_EXT_LEN )
  1761. scene.extLen = ZCL_GEN_SCENE_EXT_LEN;
  1762. osal_memcpy( scene.extField, pData, scene.extLen );
  1763. }
  1764. if ( scene.groupID == 0x0000 ||
  1765. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
  1766. {
  1767. // Either the Scene doesn't belong to a Group (Group ID = 0x0000) or it
  1768. // does and the corresponding Group exits
  1769. pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
  1770. if ( pScene || ( zclGeneral_CountAllScenes() < ZCL_GEN_MAX_SCENES ) )
  1771. {
  1772. status = ZCL_STATUS_SUCCESS;
  1773. if ( pScene != NULL )
  1774. {
  1775. // The Scene already exists so update it
  1776. pScene->transTime = scene.transTime;
  1777. osal_memcpy( pScene->name, scene.name, ZCL_GEN_SCENE_NAME_LEN );
  1778. // Use the new extention field(s)
  1779. osal_memcpy( pScene->extField, scene.extField, scene.extLen );
  1780. pScene->extLen = scene.extLen;
  1781. // Update NV
  1782. zclGeneral_ScenesWriteNV();
  1783. }
  1784. else
  1785. {
  1786. // The Scene doesn't exist so add it
  1787. zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
  1788. }
  1789. }
  1790. else
  1791. status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
  1792. }
  1793. else
  1794. status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
  1795. zclGeneral_SendSceneAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1796. status, scene.groupID, scene.ID,
  1797. true, pInMsg->hdr.transSeqNum );
  1798. stat = ZCL_STATUS_CMD_HAS_RSP;
  1799. break;
  1800. case COMMAND_SCENE_VIEW:
  1801. pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
  1802. if ( pScene != NULL )
  1803. {
  1804. status = ZCL_STATUS_SUCCESS;
  1805. }
  1806. else
  1807. {
  1808. // Scene not found
  1809. if ( scene.groupID != 0x0000 &&
  1810. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) == NULL )
  1811. {
  1812. status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
  1813. }
  1814. else
  1815. status = ZCL_STATUS_NOT_FOUND;
  1816. pScene = &scene;
  1817. }
  1818. zclGeneral_SendSceneViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1819. status, pScene, true, pInMsg->hdr.transSeqNum );
  1820. stat = ZCL_STATUS_CMD_HAS_RSP;
  1821. break;
  1822. case COMMAND_SCENE_REMOVE:
  1823. if ( zclGeneral_RemoveScene( pInMsg->msg->endPoint, scene.groupID, scene.ID ) )
  1824. {
  1825. status = ZCL_STATUS_SUCCESS;
  1826. }
  1827. else
  1828. {
  1829. // Scene not found
  1830. if ( aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) == NULL )
  1831. {
  1832. // The Group is not in the Group Table
  1833. status = ZCL_STATUS_INVALID_FIELD;
  1834. }
  1835. else
  1836. status = ZCL_STATUS_NOT_FOUND;
  1837. }
  1838. if ( UNICAST_MSG( pInMsg->msg ) )
  1839. {
  1840. // Addressed to this device (not to a group) - send a response back
  1841. zclGeneral_SendSceneRemoveResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1842. status, scene.groupID,
  1843. scene.ID, true, pInMsg->hdr.transSeqNum );
  1844. }
  1845. stat = ZCL_STATUS_CMD_HAS_RSP;
  1846. break;
  1847. case COMMAND_SCENE_REMOVE_ALL:
  1848. if ( scene.groupID == 0x0000 ||
  1849. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
  1850. {
  1851. zclGeneral_RemoveAllScenes( pInMsg->msg->endPoint, scene.groupID );
  1852. status = ZCL_STATUS_SUCCESS;
  1853. }
  1854. else
  1855. status = ZCL_STATUS_INVALID_FIELD;
  1856. if ( UNICAST_MSG( pInMsg->msg ) )
  1857. {
  1858. // Addressed to this device (not to a group) - send a response back
  1859. zclGeneral_SendSceneRemoveAllResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1860. status, scene.groupID, true, pInMsg->hdr.transSeqNum );
  1861. }
  1862. stat = ZCL_STATUS_CMD_HAS_RSP;
  1863. break;
  1864. case COMMAND_SCENE_STORE:
  1865. if ( scene.groupID == 0x0000 ||
  1866. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
  1867. {
  1868. // Either the Scene doesn't belong to a Group (Group ID = 0x0000) or it
  1869. // does and the corresponding Group exits
  1870. pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
  1871. if ( pScene || ( zclGeneral_CountAllScenes() < ZCL_GEN_MAX_SCENES ) )
  1872. {
  1873. uint8 sceneChanged = FALSE;
  1874. status = ZCL_STATUS_SUCCESS;
  1875. if ( pScene == NULL )
  1876. {
  1877. // Haven't been added yet
  1878. pScene = &scene;
  1879. }
  1880. if ( pCBs->pfnSceneStoreReq )
  1881. {
  1882. zclSceneReq_t req;
  1883. req.srcAddr = &(pInMsg->msg->srcAddr);
  1884. req.scene = pScene;
  1885. // Get the latest Scene info
  1886. if ( pCBs->pfnSceneStoreReq( &req ) )
  1887. sceneChanged = TRUE;
  1888. }
  1889. if ( pScene == &scene )
  1890. {
  1891. // The Scene doesn't exist so add it
  1892. zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
  1893. }
  1894. else if ( sceneChanged )
  1895. {
  1896. // The Scene already exists so update only NV
  1897. zclGeneral_ScenesWriteNV();
  1898. }
  1899. }
  1900. else
  1901. status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
  1902. }
  1903. else
  1904. status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
  1905. if ( UNICAST_MSG( pInMsg->msg ) )
  1906. {
  1907. // Addressed to this device (not to a group) - send a response back
  1908. zclGeneral_SendSceneStoreResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1909. status, scene.groupID, scene.ID,
  1910. true, pInMsg->hdr.transSeqNum );
  1911. }
  1912. stat = ZCL_STATUS_CMD_HAS_RSP;
  1913. break;
  1914. case COMMAND_SCENE_RECALL:
  1915. pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
  1916. if ( pScene && pCBs->pfnSceneRecallReq )
  1917. {
  1918. zclSceneReq_t req;
  1919. req.srcAddr = &(pInMsg->msg->srcAddr);
  1920. req.scene = pScene;
  1921. pCBs->pfnSceneRecallReq( &req );
  1922. }
  1923. // No response
  1924. break;
  1925. case COMMAND_SCENE_GET_MEMBERSHIP:
  1926. // Find all the Scenes corresponding to the Group ID
  1927. if ( scene.groupID == 0x0000 ||
  1928. aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
  1929. {
  1930. // Allocate space for the scene list
  1931. sceneList = osal_mem_alloc( ZCL_GEN_MAX_SCENES );
  1932. if ( sceneList != NULL )
  1933. {
  1934. sceneCnt = zclGeneral_FindAllScenesForGroup( pInMsg->msg->endPoint,
  1935. scene.groupID, sceneList );
  1936. status = ZCL_STATUS_SUCCESS;
  1937. if ( UNICAST_MSG( pInMsg->msg ) )
  1938. {
  1939. // Addressed only to this device - send a response back
  1940. sendRsp = TRUE;
  1941. }
  1942. else
  1943. {
  1944. // Addressed to the Group - ONLY send a response if an entry within the
  1945. // Scene Table corresponds to the Group ID
  1946. if ( sceneCnt != 0 )
  1947. sendRsp = TRUE;
  1948. }
  1949. }
  1950. else
  1951. {
  1952. // Couldn't allocate space for the scene list!
  1953. status = ZCL_STATUS_INSUFFICIENT_SPACE;
  1954. sendRsp = TRUE;
  1955. }
  1956. }
  1957. else
  1958. {
  1959. // The Group is not in the Group Table - send a response back
  1960. status = ZCL_STATUS_INVALID_FIELD;
  1961. sendRsp = TRUE;
  1962. }
  1963. if ( sendRsp )
  1964. {
  1965. zclGeneral_SendSceneGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  1966. status, zclGeneral_ScenesRemaingCapacity(), sceneCnt, sceneList,
  1967. scene.groupID, true, pInMsg->hdr.transSeqNum );
  1968. }
  1969. if ( sceneList != NULL )
  1970. osal_mem_free( sceneList );
  1971. stat = ZCL_STATUS_CMD_HAS_RSP;
  1972. break;
  1973. default:
  1974. stat = ZFailure;
  1975. break;
  1976. }
  1977. return ( stat );
  1978. }
  1979. /*********************************************************************
  1980. * @fn zclGeneral_ProcessInScenesClient
  1981. *
  1982. * @brief Process in the received Scenes Command.
  1983. *
  1984. * @param pInMsg - pointer to the incoming message
  1985. *
  1986. * @return ZStatus_t
  1987. */
  1988. static ZStatus_t zclGeneral_ProcessInScenesClient( zclIncoming_t *pInMsg,
  1989. zclGeneral_AppCallbacks_t *pCBs )
  1990. {
  1991. zclGeneral_Scene_t scene;
  1992. uint8 *pData = pInMsg->pData;
  1993. uint8 nameLen;
  1994. uint8 *sceneList = NULL;
  1995. zclSceneRsp_t rsp;
  1996. uint8 i;
  1997. ZStatus_t stat = ZSuccess;
  1998. osal_memset( (uint8*)&scene, 0, sizeof( zclGeneral_Scene_t ) );
  1999. osal_memset( (uint8*)&rsp, 0, sizeof( zclSceneRsp_t ) );
  2000. // Get the status field first
  2001. rsp.status = *pData++;
  2002. if ( pInMsg->hdr.commandID == COMMAND_SCENE_GET_MEMBERSHIP_RSP )
  2003. rsp.capacity = *pData++;
  2004. scene.groupID = BUILD_UINT16( pData[0], pData[1] );
  2005. pData += 2; // Move past group ID
  2006. switch ( pInMsg->hdr.commandID )
  2007. {
  2008. case COMMAND_SCENE_VIEW_RSP:
  2009. // Parse the rest of the incoming message
  2010. scene.ID = *pData++; // Not applicable to Remove All Response command
  2011. scene.transTime = BUILD_UINT16( pData[0], pData[1] );
  2012. pData += 2;
  2013. nameLen = *pData++; // Name length
  2014. if ( nameLen > (ZCL_GEN_SCENE_NAME_LEN-1) )
  2015. nameLen = (ZCL_GEN_SCENE_NAME_LEN-1);
  2016. scene.name[0] = nameLen;
  2017. osal_memcpy( &(scene.name[1]), pData, nameLen );
  2018. pData += nameLen; // move pass name
  2019. //*** Do something with the extension field(s)
  2020. // Fall through to callback - break is left off intentionally
  2021. case COMMAND_SCENE_ADD_RSP:
  2022. case COMMAND_SCENE_REMOVE_RSP:
  2023. case COMMAND_SCENE_REMOVE_ALL_RSP:
  2024. case COMMAND_SCENE_STORE_RSP:
  2025. if ( pCBs->pfnSceneRsp )
  2026. {
  2027. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2028. rsp.cmdID = pInMsg->hdr.commandID;
  2029. rsp.scene = &scene;
  2030. pCBs->pfnSceneRsp( &rsp );
  2031. }
  2032. break;
  2033. case COMMAND_SCENE_GET_MEMBERSHIP_RSP:
  2034. if ( rsp.status == ZCL_STATUS_SUCCESS )
  2035. {
  2036. uint8 sceneCnt = *pData++;
  2037. if ( sceneCnt > 0 )
  2038. {
  2039. // Allocate space for the scene list
  2040. sceneList = osal_mem_alloc( sceneCnt );
  2041. if ( sceneList != NULL )
  2042. {
  2043. rsp.sceneCnt = sceneCnt;
  2044. for ( i = 0; i < sceneCnt; i++ )
  2045. sceneList[i] = *pData++;
  2046. }
  2047. }
  2048. }
  2049. if ( pCBs->pfnSceneRsp )
  2050. {
  2051. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2052. rsp.cmdID = pInMsg->hdr.commandID;
  2053. rsp.sceneList = sceneList;
  2054. rsp.scene = &scene;
  2055. pCBs->pfnSceneRsp( &rsp);
  2056. }
  2057. if ( sceneList != NULL )
  2058. osal_mem_free( sceneList );
  2059. break;
  2060. default:
  2061. stat = ZFailure;
  2062. break;
  2063. }
  2064. return ( stat );
  2065. }
  2066. #endif // ZCL_SCENES
  2067. #ifdef ZCL_ON_OFF
  2068. /*********************************************************************
  2069. * @fn zclGeneral_ProcessInCmdOnOff
  2070. *
  2071. * @brief Process in the received On/Off Command.
  2072. *
  2073. * @param pInMsg - pointer to the incoming message
  2074. *
  2075. * @return ZStatus_t
  2076. */
  2077. static ZStatus_t zclGeneral_ProcessInOnOff( zclIncoming_t *pInMsg,
  2078. zclGeneral_AppCallbacks_t *pCBs )
  2079. {
  2080. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  2081. {
  2082. if ( pInMsg->hdr.commandID > COMMAND_TOGGLE )
  2083. return ( ZFailure ); // Error ignore the command
  2084. if ( pCBs->pfnOnOff )
  2085. pCBs->pfnOnOff( pInMsg->hdr.commandID );
  2086. }
  2087. // no Client command
  2088. return ( ZSuccess );
  2089. }
  2090. #endif // ZCL_ON_OFF
  2091. #ifdef ZCL_LEVEL_CTRL
  2092. /*********************************************************************
  2093. * @fn zclGeneral_ProcessInLevelControl
  2094. *
  2095. * @brief Process in the received Level Control Command.
  2096. *
  2097. * @param pInMsg - pointer to the incoming message
  2098. *
  2099. * @return ZStatus_t
  2100. */
  2101. static ZStatus_t zclGeneral_ProcessInLevelControl( zclIncoming_t *pInMsg,
  2102. zclGeneral_AppCallbacks_t *pCBs )
  2103. {
  2104. uint8 withOnOff = FALSE;
  2105. ZStatus_t stat = ZSuccess;
  2106. if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
  2107. {
  2108. switch ( pInMsg->hdr.commandID )
  2109. {
  2110. case COMMAND_LEVEL_MOVE_TO_LEVEL_WITH_ON_OFF:
  2111. withOnOff = TRUE;
  2112. // fall through
  2113. case COMMAND_LEVEL_MOVE_TO_LEVEL:
  2114. if ( pCBs->pfnLevelControlMoveToLevel )
  2115. {
  2116. zclLCMoveToLevel_t cmd;
  2117. cmd.level = pInMsg->pData[0];
  2118. cmd.transitionTime = BUILD_UINT16( pInMsg->pData[1], pInMsg->pData[2] );
  2119. cmd.withOnOff = withOnOff;
  2120. pCBs->pfnLevelControlMoveToLevel( &cmd );
  2121. }
  2122. break;
  2123. case COMMAND_LEVEL_MOVE_WITH_ON_OFF:
  2124. withOnOff = TRUE;
  2125. // fall through
  2126. case COMMAND_LEVEL_MOVE:
  2127. if ( pCBs->pfnLevelControlMove )
  2128. {
  2129. zclLCMove_t cmd;
  2130. cmd.moveMode = pInMsg->pData[0];
  2131. cmd.rate = pInMsg->pData[1];
  2132. cmd.withOnOff = withOnOff;
  2133. pCBs->pfnLevelControlMove( &cmd );
  2134. }
  2135. break;
  2136. case COMMAND_LEVEL_STEP_WITH_ON_OFF:
  2137. withOnOff = TRUE;
  2138. // fall through
  2139. case COMMAND_LEVEL_STEP:
  2140. if ( pCBs->pfnLevelControlStep )
  2141. {
  2142. zclLCStep_t cmd;
  2143. cmd.stepMode = pInMsg->pData[0];
  2144. cmd.amount = pInMsg->pData[1];
  2145. cmd.transitionTime = BUILD_UINT16( pInMsg->pData[2], pInMsg->pData[3] );
  2146. cmd.withOnOff = withOnOff;
  2147. pCBs->pfnLevelControlStep( &cmd );
  2148. }
  2149. break;
  2150. case COMMAND_LEVEL_STOP:
  2151. case COMMAND_LEVEL_STOP_WITH_ON_OFF:
  2152. // Both Stop commands are identical
  2153. if ( pCBs->pfnLevelControlStop )
  2154. {
  2155. pCBs->pfnLevelControlStop();
  2156. }
  2157. break;
  2158. default:
  2159. stat = ZFailure;
  2160. break;
  2161. }
  2162. }
  2163. // no Client command
  2164. return ( stat );
  2165. }
  2166. #endif // ZCL_LEVEL_CTRL
  2167. #ifdef ZCL_ALARMS
  2168. /*********************************************************************
  2169. * @fn zclGeneral_AddAlarm
  2170. *
  2171. * @brief Add an alarm for a cluster
  2172. *
  2173. * @param endpoint -
  2174. * @param alarm - new alarm item
  2175. *
  2176. * @return ZStatus_t
  2177. */
  2178. ZStatus_t zclGeneral_AddAlarm( uint8 endpoint, zclGeneral_Alarm_t *alarm )
  2179. {
  2180. zclGenAlarmItem_t *pNewItem;
  2181. zclGenAlarmItem_t *pLoop;
  2182. // Fill in the new profile list
  2183. pNewItem = osal_mem_alloc( sizeof( zclGenAlarmItem_t ) );
  2184. if ( pNewItem == NULL )
  2185. return ( ZMemError );
  2186. // Fill in the plugin record.
  2187. pNewItem->next = (zclGenAlarmItem_t *)NULL;
  2188. pNewItem->endpoint = endpoint;
  2189. osal_memcpy( (uint8*)(&pNewItem->alarm), (uint8*)alarm, sizeof ( zclGeneral_Alarm_t ) );
  2190. // Find spot in list
  2191. if ( zclGenAlarmTable == NULL )
  2192. {
  2193. zclGenAlarmTable = pNewItem;
  2194. }
  2195. else
  2196. {
  2197. // Look for end of list
  2198. pLoop = zclGenAlarmTable;
  2199. while ( pLoop->next != NULL )
  2200. pLoop = pLoop->next;
  2201. // Put new item at end of list
  2202. pLoop->next = pNewItem;
  2203. }
  2204. return ( ZSuccess );
  2205. }
  2206. /*********************************************************************
  2207. * @fn zclGeneral_FindAlarm
  2208. *
  2209. * @brief Find an alarm with alarmCode and clusterID
  2210. *
  2211. * @param endpoint -
  2212. * @param groupID - what group the scene belongs to
  2213. * @param sceneID - ID to look for scene
  2214. *
  2215. * @return a pointer to the alarm information, NULL if not found
  2216. */
  2217. zclGeneral_Alarm_t *zclGeneral_FindAlarm( uint8 endpoint, uint8 alarmCode, uint16 clusterID )
  2218. {
  2219. zclGenAlarmItem_t *pLoop;
  2220. // Look for the alarm
  2221. pLoop = zclGenAlarmTable;
  2222. while ( pLoop )
  2223. {
  2224. if ( pLoop->endpoint == endpoint &&
  2225. pLoop->alarm.code == alarmCode && pLoop->alarm.clusterID == clusterID )
  2226. {
  2227. return ( &(pLoop->alarm) );
  2228. }
  2229. pLoop = pLoop->next;
  2230. }
  2231. return ( (zclGeneral_Alarm_t *)NULL );
  2232. }
  2233. /*********************************************************************
  2234. * @fn zclGeneral_FindEarliestAlarm
  2235. *
  2236. * @brief Find an alarm with the earliest timestamp
  2237. *
  2238. * @param endpoint -
  2239. *
  2240. * @return a pointer to the alarm information, NULL if not found
  2241. */
  2242. zclGeneral_Alarm_t *zclGeneral_FindEarliestAlarm( uint8 endpoint )
  2243. {
  2244. zclGenAlarmItem_t *pLoop;
  2245. zclGenAlarmItem_t earliestAlarm;
  2246. zclGenAlarmItem_t *pEarliestAlarm = &earliestAlarm;
  2247. pEarliestAlarm->alarm.timeStamp = 0xFFFFFFFF;
  2248. // Look for alarm with earliest time
  2249. pLoop = zclGenAlarmTable;
  2250. while ( pLoop )
  2251. {
  2252. if ( pLoop->endpoint == endpoint &&
  2253. pLoop->alarm.timeStamp < pEarliestAlarm->alarm.timeStamp )
  2254. {
  2255. pEarliestAlarm = pLoop;
  2256. }
  2257. pLoop = pLoop->next;
  2258. }
  2259. if ( pEarliestAlarm->alarm.timeStamp != 0xFFFFFFFF )
  2260. return ( &(pEarliestAlarm->alarm) );
  2261. // No alarm
  2262. return ( (zclGeneral_Alarm_t *)NULL );
  2263. }
  2264. /*********************************************************************
  2265. * @fn zclGeneral_ResetAlarm
  2266. *
  2267. * @brief Remove a scene with endpoint and sceneID
  2268. *
  2269. * @param endpoint -
  2270. * @param alarmCode -
  2271. * @param clusterID -
  2272. *
  2273. * @return TRUE if removed, FALSE if not found
  2274. */
  2275. void zclGeneral_ResetAlarm( uint8 endpoint, uint8 alarmCode, uint16 clusterID )
  2276. {
  2277. zclGenAlarmItem_t *pLoop;
  2278. zclGenAlarmItem_t *pPrev;
  2279. // Look for end of list
  2280. pLoop = zclGenAlarmTable;
  2281. pPrev = NULL;
  2282. while ( pLoop )
  2283. {
  2284. if ( pLoop->endpoint == endpoint &&
  2285. pLoop->alarm.code == alarmCode && pLoop->alarm.clusterID == clusterID )
  2286. {
  2287. if ( pPrev == NULL )
  2288. zclGenAlarmTable = pLoop->next;
  2289. else
  2290. pPrev->next = pLoop->next;
  2291. // Free the memory
  2292. osal_mem_free( pLoop );
  2293. // Notify the Application so that if the alarm condition still active then
  2294. // a new notification will be generated, and a new alarm record will be
  2295. // added to the alarm log
  2296. // zclGeneral_NotifyReset( alarmCode, clusterID ); // callback function?
  2297. return;
  2298. }
  2299. pPrev = pLoop;
  2300. pLoop = pLoop->next;
  2301. }
  2302. }
  2303. /*********************************************************************
  2304. * @fn zclGeneral_ResetAllAlarms
  2305. *
  2306. * @brief Remove all alarms with endpoint
  2307. *
  2308. * @param endpoint -
  2309. * @param notifyApp -
  2310. *
  2311. * @return none
  2312. */
  2313. void zclGeneral_ResetAllAlarms( uint8 endpoint, uint8 notifyApp )
  2314. {
  2315. zclGenAlarmItem_t *pLoop;
  2316. zclGenAlarmItem_t *pPrev;
  2317. zclGenAlarmItem_t *pNext;
  2318. // Look for end of list
  2319. pLoop = zclGenAlarmTable;
  2320. pPrev = NULL;
  2321. while ( pLoop )
  2322. {
  2323. if ( pLoop->endpoint == endpoint )
  2324. {
  2325. if ( pPrev == NULL )
  2326. zclGenAlarmTable = pLoop->next;
  2327. else
  2328. pPrev->next = pLoop->next;
  2329. pNext = pLoop->next;
  2330. // Free the memory
  2331. osal_mem_free( pLoop );
  2332. pLoop = pNext;
  2333. }
  2334. else
  2335. {
  2336. pPrev = pLoop;
  2337. pLoop = pLoop->next;
  2338. }
  2339. }
  2340. if ( notifyApp )
  2341. {
  2342. // Notify the Application so that if any alarm conditions still active then
  2343. // a new notification will be generated, and a new alarm record will be
  2344. // added to the alarm log
  2345. // zclGeneral_NotifyResetAll(); // callback function?
  2346. }
  2347. }
  2348. /*********************************************************************
  2349. * @fn zclGeneral_ProcessInAlarmsServer
  2350. *
  2351. * @brief Process in the received Alarms Command.
  2352. *
  2353. * @param pInMsg - pointer to the incoming message
  2354. *
  2355. * @return ZStatus_t
  2356. */
  2357. static ZStatus_t zclGeneral_ProcessInAlarmsServer( zclIncoming_t *pInMsg,
  2358. zclGeneral_AppCallbacks_t *pCBs )
  2359. {
  2360. zclGeneral_Alarm_t *pAlarm;
  2361. uint8 *pData = pInMsg->pData;
  2362. ZStatus_t stat = ZSuccess;
  2363. switch ( pInMsg->hdr.commandID )
  2364. {
  2365. case COMMAND_ALARMS_RESET:
  2366. zclGeneral_ResetAlarm( pInMsg->msg->endPoint, pData[0],
  2367. BUILD_UINT16( pData[1], pData[2] ) );
  2368. break;
  2369. case COMMAND_ALARMS_RESET_ALL:
  2370. zclGeneral_ResetAllAlarms( pInMsg->msg->endPoint, TRUE );
  2371. break;
  2372. case COMMAND_ALARMS_GET:
  2373. pAlarm = zclGeneral_FindEarliestAlarm( pInMsg->msg->endPoint );
  2374. if ( pAlarm )
  2375. {
  2376. // Send a response back
  2377. zclGeneral_SendAlarmGetRespnose( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  2378. ZCL_STATUS_SUCCESS, pAlarm->code,
  2379. pAlarm->clusterID, pAlarm->timeStamp,
  2380. true, pInMsg->hdr.transSeqNum );
  2381. // Remove the entry from the Alarm table
  2382. zclGeneral_ResetAlarm( pInMsg->msg->endPoint, pAlarm->code, pAlarm->clusterID );
  2383. }
  2384. else
  2385. {
  2386. // Send a response back
  2387. zclGeneral_SendAlarmGetRespnose( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  2388. ZCL_STATUS_NOT_FOUND, 0, 0, 0,
  2389. true, pInMsg->hdr.transSeqNum );
  2390. }
  2391. stat = ZCL_STATUS_CMD_HAS_RSP;
  2392. break;
  2393. case COMMAND_ALARMS_RESET_LOG:
  2394. zclGeneral_ResetAllAlarms( pInMsg->msg->endPoint, FALSE );
  2395. break;
  2396. default:
  2397. stat = ZFailure;
  2398. break;
  2399. }
  2400. return ( stat );
  2401. }
  2402. /*********************************************************************
  2403. * @fn zclGeneral_ProcessInAlarmsClient
  2404. *
  2405. * @brief Process in the received Alarms Command.
  2406. *
  2407. * @param pInMsg - pointer to the incoming message
  2408. *
  2409. * @return ZStatus_t
  2410. */
  2411. static ZStatus_t zclGeneral_ProcessInAlarmsClient( zclIncoming_t *pInMsg,
  2412. zclGeneral_AppCallbacks_t *pCBs )
  2413. {
  2414. uint8 *pData = pInMsg->pData;
  2415. zclAlarm_t alarm;
  2416. ZStatus_t stat = ZSuccess;
  2417. osal_memset( (uint8*)&alarm, 0, sizeof( zclAlarm_t ) );
  2418. switch ( pInMsg->hdr.commandID )
  2419. {
  2420. case COMMAND_ALARMS_ALARM:
  2421. if ( pCBs->pfnAlarm )
  2422. {
  2423. alarm.srcAddr = &(pInMsg->msg->srcAddr);
  2424. alarm.cmdID = pInMsg->hdr.commandID;
  2425. alarm.status = *pData++;
  2426. alarm.alarmCode = *pData++;
  2427. alarm.clusterID = BUILD_UINT16( pData[0], pData[1] );
  2428. pData += 2;
  2429. alarm.timeStamp = osal_build_uint32( pData, 4 );
  2430. pCBs->pfnAlarm( &alarm );
  2431. }
  2432. break;
  2433. case COMMAND_ALARMS_GET_RSP:
  2434. if ( pCBs->pfnAlarm )
  2435. {
  2436. alarm.srcAddr = &(pInMsg->msg->srcAddr);
  2437. alarm.cmdID = pInMsg->hdr.commandID;
  2438. alarm.alarmCode = *pData++;
  2439. alarm.clusterID = BUILD_UINT16( pData[0], pData[1] );
  2440. pCBs->pfnAlarm( &alarm );
  2441. }
  2442. break;
  2443. default:
  2444. stat = ZFailure;
  2445. break;
  2446. }
  2447. return ( stat );
  2448. }
  2449. #endif // ZCL_ALARMS
  2450. #ifdef ZCL_LOCATION
  2451. /*********************************************************************
  2452. * @fn zclGeneral_ProcessInLocationServer
  2453. *
  2454. * @brief Process in the received Location Command.
  2455. *
  2456. * @param pInMsg - pointer to the incoming message
  2457. *
  2458. * @return ZStatus_t
  2459. */
  2460. static ZStatus_t zclGeneral_ProcessInLocationServer( zclIncoming_t *pInMsg,
  2461. zclGeneral_AppCallbacks_t *pCBs )
  2462. {
  2463. uint8 *pData = pInMsg->pData;
  2464. zclLocation_t cmd;
  2465. ZStatus_t stat = ZSuccess;
  2466. osal_memset( (uint8*)&cmd, 0, sizeof( zclLocation_t ) );
  2467. switch ( pInMsg->hdr.commandID )
  2468. {
  2469. case COMMAND_LOCATION_SET_ABSOLUTE:
  2470. cmd.un.absLoc.coordinate1 = BUILD_UINT16( pData[0], pData[1] );
  2471. pData += 2;
  2472. cmd.un.absLoc.coordinate2 = BUILD_UINT16( pData[0], pData[1] );
  2473. pData += 2;
  2474. cmd.un.absLoc.coordinate3 = BUILD_UINT16( pData[0], pData[1] );
  2475. pData += 2;
  2476. cmd.un.absLoc.power = BUILD_UINT16( pData[0], pData[1] );
  2477. pData += 2;
  2478. cmd.un.absLoc.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
  2479. if ( pCBs->pfnLocation )
  2480. {
  2481. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  2482. cmd.cmdID = pInMsg->hdr.commandID;
  2483. // Update the absolute location info
  2484. pCBs->pfnLocation( &cmd );
  2485. }
  2486. break;
  2487. case COMMAND_LOCATION_SET_DEV_CFG:
  2488. cmd.un.devCfg.power = BUILD_UINT16( pData[0], pData[1] );
  2489. pData += 2;
  2490. cmd.un.devCfg.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
  2491. pData += 2;
  2492. cmd.un.devCfg.calcPeriod = BUILD_UINT16( pData[0], pData[1] );
  2493. pData += 2;
  2494. cmd.un.devCfg.numMeasurements = *pData++;
  2495. cmd.un.devCfg.reportPeriod = BUILD_UINT16( pData[0], pData[1] );
  2496. if ( pCBs->pfnLocation )
  2497. {
  2498. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  2499. cmd.cmdID = pInMsg->hdr.commandID;
  2500. // Update the device configuration info
  2501. pCBs->pfnLocation( &cmd );
  2502. }
  2503. break;
  2504. case COMMAND_LOCATION_GET_DEV_CFG:
  2505. cmd.un.ieeeAddr = pData;
  2506. if ( pCBs->pfnLocation )
  2507. {
  2508. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  2509. cmd.cmdID = pInMsg->hdr.commandID;
  2510. cmd.seqNum = pInMsg->hdr.transSeqNum;
  2511. // Retreive the Device Configuration
  2512. pCBs->pfnLocation( &cmd );
  2513. }
  2514. stat = ZCL_STATUS_CMD_HAS_RSP;
  2515. break;
  2516. case COMMAND_LOCATION_GET_DATA:
  2517. cmd.un.loc.bitmap.locByte = *pData++;
  2518. cmd.un.loc.numResponses = *pData++;
  2519. if ( cmd.un.loc.brdcastResponse == 0 ) // command is sent as a unicast
  2520. osal_cpyExtAddr( cmd.un.loc.targetAddr, pData );
  2521. if ( pCBs->pfnLocation )
  2522. {
  2523. cmd.srcAddr = &(pInMsg->msg->srcAddr);
  2524. cmd.cmdID = pInMsg->hdr.commandID;
  2525. cmd.seqNum = pInMsg->hdr.transSeqNum;
  2526. // Retreive the Location Data
  2527. pCBs->pfnLocation( &cmd );
  2528. }
  2529. stat = ZCL_STATUS_CMD_HAS_RSP;
  2530. break;
  2531. default:
  2532. stat = ZFailure;
  2533. break;
  2534. }
  2535. return ( stat );
  2536. }
  2537. /*********************************************************************
  2538. * @fn zclGeneral_ProcessInLocationDataRsp
  2539. *
  2540. * @brief Process in the received Location Command.
  2541. *
  2542. * @param pInMsg - pointer to the incoming message
  2543. *
  2544. * @return ZStatus_t
  2545. */
  2546. static void zclGeneral_ProcessInLocationDataRsp( zclIncoming_t *pInMsg,
  2547. zclGeneral_AppCallbacks_t *pCBs )
  2548. {
  2549. uint8 *pData = pInMsg->pData;
  2550. zclLocationRsp_t rsp;
  2551. osal_memset( (uint8*)&rsp, 0, sizeof( zclLocationRsp_t ) );
  2552. if ( pCBs->pfnLocationRsp )
  2553. {
  2554. if ( pInMsg->hdr.commandID == COMMAND_LOCATION_DATA_RSP )
  2555. rsp.un.loc.status = *pData++;
  2556. if ( pInMsg->hdr.commandID != COMMAND_LOCATION_DATA_RSP ||
  2557. rsp.un.loc.status == ZCL_STATUS_SUCCESS )
  2558. {
  2559. rsp.un.loc.data.type = *pData++;
  2560. rsp.un.loc.data.absLoc.coordinate1 = BUILD_UINT16( pData[0], pData[1] );
  2561. pData += 2;
  2562. rsp.un.loc.data.absLoc.coordinate2 = BUILD_UINT16( pData[0], pData[1] );
  2563. pData += 2;
  2564. if ( locationType2D( rsp.un.loc.data.type ) == 0 )
  2565. {
  2566. rsp.un.loc.data.absLoc.coordinate3 = BUILD_UINT16( pData[0], pData[1] );
  2567. pData += 2;
  2568. }
  2569. if ( pInMsg->hdr.commandID != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
  2570. {
  2571. rsp.un.loc.data.absLoc.power = BUILD_UINT16( pData[0], pData[1] );
  2572. pData += 2;
  2573. rsp.un.loc.data.absLoc.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
  2574. pData += 2;
  2575. }
  2576. if ( locationTypeAbsolute( rsp.un.loc.data.type ) == 0 )
  2577. {
  2578. if ( pInMsg->hdr.commandID != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
  2579. rsp.un.loc.data.calcLoc.locationMethod = *pData++;
  2580. rsp.un.loc.data.calcLoc.qualityMeasure = *pData++;
  2581. rsp.un.loc.data.calcLoc.locationAge = BUILD_UINT16( pData[0], pData[1] );
  2582. }
  2583. }
  2584. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2585. rsp.cmdID = pInMsg->hdr.commandID;
  2586. // Notify the Application
  2587. pCBs->pfnLocationRsp( &rsp );
  2588. }
  2589. }
  2590. /*********************************************************************
  2591. * @fn zclGeneral_ProcessInLocationClient
  2592. *
  2593. * @brief Process in the received Location Command.
  2594. *
  2595. * @param pInMsg - pointer to the incoming message
  2596. *
  2597. * @return ZStatus_t
  2598. */
  2599. static ZStatus_t zclGeneral_ProcessInLocationClient( zclIncoming_t *pInMsg,
  2600. zclGeneral_AppCallbacks_t *pCBs )
  2601. {
  2602. uint8 *pData = pInMsg->pData;
  2603. zclLocationRsp_t rsp;
  2604. ZStatus_t stat = ZSuccess;
  2605. osal_memset( (uint8*)&rsp, 0, sizeof( zclLocationRsp_t ) );
  2606. switch ( pInMsg->hdr.commandID )
  2607. {
  2608. case COMMAND_LOCATION_DEV_CFG_RSP:
  2609. if ( pCBs->pfnLocationRsp )
  2610. {
  2611. rsp.un.devCfg.status = *pData++;
  2612. if ( rsp.un.devCfg.status == ZCL_STATUS_SUCCESS )
  2613. {
  2614. rsp.un.devCfg.data.power = BUILD_UINT16( pData[0], pData[1] );
  2615. pData += 2;
  2616. rsp.un.devCfg.data.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
  2617. pData += 2;
  2618. rsp.un.devCfg.data.calcPeriod = BUILD_UINT16( pData[0], pData[1] );
  2619. pData += 2;
  2620. rsp.un.devCfg.data.numMeasurements = *pData++;
  2621. rsp.un.devCfg.data.reportPeriod = BUILD_UINT16( pData[0], pData[1] );
  2622. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2623. rsp.cmdID = pInMsg->hdr.commandID;
  2624. // Notify the Application
  2625. pCBs->pfnLocationRsp( &rsp );
  2626. }
  2627. }
  2628. break;
  2629. case COMMAND_LOCATION_DATA_RSP:
  2630. case COMMAND_LOCATION_DATA_NOTIF:
  2631. case COMMAND_LOCATION_COMPACT_DATA_NOTIF:
  2632. zclGeneral_ProcessInLocationDataRsp( pInMsg, pCBs );
  2633. break;
  2634. case COMMAND_LOCATION_RSSI_PING:
  2635. if ( pCBs->pfnLocationRsp )
  2636. {
  2637. rsp.un.locationType = *pData;
  2638. rsp.srcAddr = &(pInMsg->msg->srcAddr);
  2639. rsp.cmdID = pInMsg->hdr.commandID;
  2640. // Notify the Application
  2641. pCBs->pfnLocationRsp( &rsp );
  2642. }
  2643. break;
  2644. default:
  2645. stat = ZFailure;
  2646. break;
  2647. }
  2648. return ( stat );
  2649. }
  2650. #endif // ZCL_LOCATION
  2651. #ifdef ZCL_SCENES
  2652. /*********************************************************************
  2653. * @fn zclGeneral_ScenesInitNV
  2654. *
  2655. * @brief Initialize the NV Scene Table Items
  2656. *
  2657. * @param none
  2658. *
  2659. * @return number of scenes
  2660. */
  2661. static uint8 zclGeneral_ScenesInitNV( void )
  2662. {
  2663. uint8 status;
  2664. uint16 size;
  2665. size = (uint16)((sizeof ( nvGenScenesHdr_t ))
  2666. + ( sizeof( zclGenSceneNVItem_t ) * ZCL_GEN_MAX_SCENES ));
  2667. status = osal_nv_item_init( ZCD_NV_SCENE_TABLE, size, NULL );
  2668. if ( status != ZSUCCESS )
  2669. {
  2670. zclGeneral_ScenesSetDefaultNV();
  2671. }
  2672. return status;
  2673. }
  2674. /*********************************************************************
  2675. * @fn zclGeneral_ScenesSetDefaultNV
  2676. *
  2677. * @brief Write the defaults to NV
  2678. *
  2679. * @param none
  2680. *
  2681. * @return none
  2682. */
  2683. static void zclGeneral_ScenesSetDefaultNV( void )
  2684. {
  2685. nvGenScenesHdr_t hdr;
  2686. // Initialize the header
  2687. hdr.numRecs = 0;
  2688. // Save off the header
  2689. osal_nv_write( ZCD_NV_SCENE_TABLE, 0, sizeof( nvGenScenesHdr_t ), &hdr );
  2690. }
  2691. /*********************************************************************
  2692. * @fn zclGeneral_ScenesWriteNV
  2693. *
  2694. * @brief Save the Scene Table in NV
  2695. *
  2696. * @param none
  2697. *
  2698. * @return none
  2699. */
  2700. static void zclGeneral_ScenesWriteNV( void )
  2701. {
  2702. nvGenScenesHdr_t hdr;
  2703. zclGenSceneItem_t *pLoop;
  2704. zclGenSceneNVItem_t item;
  2705. hdr.numRecs = 0;
  2706. // Look for end of list
  2707. pLoop = zclGenSceneTable;
  2708. while ( pLoop )
  2709. {
  2710. // Build the record
  2711. item.endpoint = pLoop->endpoint;
  2712. osal_memcpy( &(item.scene), &(pLoop->scene), sizeof ( zclGeneral_Scene_t ) );
  2713. // Save the record to NV
  2714. osal_nv_write( ZCD_NV_SCENE_TABLE,
  2715. (uint16)((sizeof( nvGenScenesHdr_t )) + (hdr.numRecs * sizeof ( zclGenSceneNVItem_t ))),
  2716. sizeof ( zclGenSceneNVItem_t ), &item );
  2717. hdr.numRecs++;
  2718. pLoop = pLoop->next;
  2719. }
  2720. // Save off the header
  2721. osal_nv_write( ZCD_NV_SCENE_TABLE, 0, sizeof( nvGenScenesHdr_t ), &hdr );
  2722. }
  2723. /*********************************************************************
  2724. * @fn zclGeneral_ScenesRestoreFromNV
  2725. *
  2726. * @brief Restore the Scene table from NV
  2727. *
  2728. * @param none
  2729. *
  2730. * @return Number of entries restored
  2731. */
  2732. static uint16 zclGeneral_ScenesRestoreFromNV( void )
  2733. {
  2734. uint16 x;
  2735. nvGenScenesHdr_t hdr;
  2736. zclGenSceneNVItem_t item;
  2737. uint16 numAdded = 0;
  2738. if ( osal_nv_read( ZCD_NV_SCENE_TABLE, 0, sizeof(nvGenScenesHdr_t), &hdr ) == ZSuccess )
  2739. {
  2740. // Read in the device list
  2741. for ( x = 0; x < hdr.numRecs; x++ )
  2742. {
  2743. if ( osal_nv_read( ZCD_NV_SCENE_TABLE,
  2744. (uint16)(sizeof(nvGenScenesHdr_t) + (x * sizeof ( zclGenSceneNVItem_t ))),
  2745. sizeof ( zclGenSceneNVItem_t ), &item ) == ZSUCCESS )
  2746. {
  2747. // Add the scene
  2748. if ( zclGeneral_AddScene( item.endpoint, &(item.scene) ) == ZSuccess )
  2749. {
  2750. numAdded++;
  2751. }
  2752. }
  2753. }
  2754. }
  2755. return ( numAdded );
  2756. }
  2757. #endif // ZCL_SCENES
  2758. /***************************************************************************
  2759. ****************************************************************************/