zcl.c 103 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349
  1. /**************************************************************************************************
  2. Filename: zcl.c
  3. Revised: $Date: 2009-04-06 09:08:36 -0700 (Mon, 06 Apr 2009) $
  4. Revision: $Revision: 19702 $
  5. Description: This file contains the Zigbee Cluster Library Foundation functions.
  6. Copyright 2006-2009 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. /*********************************************************************
  34. * INCLUDES
  35. */
  36. #include "ZComDef.h"
  37. #include "OSAL.h"
  38. #include "OSAL_Tasks.h"
  39. #include "AF.h"
  40. #include "ZDConfig.h"
  41. #include "zcl.h"
  42. #include "zcl_general.h"
  43. #if defined ( INTER_PAN )
  44. #include "stub_aps.h"
  45. #endif
  46. /*********************************************************************
  47. * MACROS
  48. */
  49. /*** Frame Control ***/
  50. #define zcl_FCType( a ) ( (a) & ZCL_FRAME_CONTROL_TYPE )
  51. #define zcl_FCManuSpecific( a ) ( (a) & ZCL_FRAME_CONTROL_MANU_SPECIFIC )
  52. #define zcl_FCDirection( a ) ( (a) & ZCL_FRAME_CONTROL_DIRECTION )
  53. #define zcl_FCDisableDefaultRsp( a ) ( (a) & ZCL_FRAME_CONTROL_DISABLE_DEFAULT_RSP )
  54. /*** Attribute Access Control ***/
  55. #define zcl_AccessCtrlRead( a ) ( (a) & ACCESS_CONTROL_READ )
  56. #define zcl_AccessCtrlWrite( a ) ( (a) & ACCESS_CONTROL_WRITE )
  57. #define zcl_AccessCtrlCmd( a ) ( (a) & ACCESS_CONTROL_CMD )
  58. #define zclParseCmd( a, b ) zclCmdTable[(a)].pfnParseInProfile( (b) )
  59. #define zclProcessCmd( a, b ) zclCmdTable[(a)].pfnProcessInProfile( (b) )
  60. #define zcl_DefaultRspCmd( zclHdr ) ( zcl_ProfileCmd( (zclHdr).fc.type ) && \
  61. (zclHdr).fc.manuSpecific == 0 && \
  62. (zclHdr).commandID == ZCL_CMD_DEFAULT_RSP )
  63. // Commands that have corresponding responses
  64. #define CMD_HAS_RSP( cmd ) ( (cmd) == ZCL_CMD_READ || \
  65. (cmd) == ZCL_CMD_WRITE || \
  66. (cmd) == ZCL_CMD_WRITE_UNDIVIDED || \
  67. (cmd) == ZCL_CMD_CONFIG_REPORT || \
  68. (cmd) == ZCL_CMD_READ_REPORT_CFG || \
  69. (cmd) == ZCL_CMD_DISCOVER || \
  70. (cmd) == ZCL_CMD_DEFAULT_RSP ) // exception
  71. /*********************************************************************
  72. * CONSTANTS
  73. */
  74. /*********************************************************************
  75. * TYPEDEFS
  76. */
  77. typedef struct zclLibPlugin
  78. {
  79. struct zclLibPlugin *next;
  80. uint16 startClusterID; // starting cluster ID
  81. uint16 endClusterID; // ending cluster ID
  82. zclInHdlr_t pfnIncomingHdlr; // function to handle incoming message
  83. } zclLibPlugin_t;
  84. // Attribute record list item
  85. typedef struct zclAttrRecsList
  86. {
  87. struct zclAttrRecsList *next;
  88. uint8 endpoint; // Used to link it into the endpoint descriptor
  89. uint8 numAttributes; // Number of the following records
  90. CONST zclAttrRec_t *attrs; // attribute records
  91. } zclAttrRecsList;
  92. // Cluster option list item
  93. typedef struct zclClusterOptionList
  94. {
  95. struct zclClusterOptionList *next;
  96. uint8 endpoint; // Used to link it into the endpoint descriptor
  97. uint8 numOptions; // Number of the following records
  98. zclOptionRec_t *options; // option records
  99. } zclClusterOptionList;
  100. typedef void *(*zclParseInProfileCmd_t)( zclParseCmd_t *pCmd );
  101. typedef uint8 (*zclProcessInProfileCmd_t)( zclIncoming_t *pInMsg );
  102. typedef struct
  103. {
  104. zclParseInProfileCmd_t pfnParseInProfile;
  105. zclProcessInProfileCmd_t pfnProcessInProfile;
  106. } zclCmdItems_t;
  107. /*********************************************************************
  108. * GLOBAL VARIABLES
  109. */
  110. uint8 zcl_TaskID;
  111. // The task Id of the Application where the unprocessed Foundation
  112. // Command/Response messages will be sent to.
  113. uint8 zcl_RegisteredMsgTaskID = TASK_NO_TASK;
  114. // The Application should register its attribute data validation function
  115. zclValidateAttrData_t zcl_ValidateAttrDataCB = NULL;
  116. // ZCL Sequence number
  117. uint8 zcl_SeqNum = 0x00;
  118. /*********************************************************************
  119. * EXTERNAL VARIABLES
  120. */
  121. /*********************************************************************
  122. * EXTERNAL FUNCTIONS
  123. */
  124. /*********************************************************************
  125. * LOCAL VARIABLES
  126. */
  127. static zclLibPlugin_t *plugins;
  128. static zclAttrRecsList *attrList;
  129. static zclClusterOptionList *clusterOptionList;
  130. static uint8 zcl_TransID = 0; // This is the unique message ID (counter)
  131. /*********************************************************************
  132. * LOCAL FUNCTIONS
  133. */
  134. static void zclProcessMessageMSG( afIncomingMSGPacket_t *pkt );
  135. static uint8 *zclBuildHdr( zclFrameHdr_t *hdr, uint8 *pData );
  136. static uint8 zclCalcHdrSize( zclFrameHdr_t *hdr );
  137. static zclLibPlugin_t *zclFindPlugin( uint16 clusterID, uint16 profileID );
  138. static zclOptionRec_t *zclFindClusterOption( uint8 endpoint, uint16 clusterID );
  139. static uint8 zclGetClusterOption( uint8 endpoint, uint16 clusterID );
  140. static void zclSetSecurityOption( uint8 endpoint, uint16 clusterID, uint8 enable );
  141. static uint8 zcl_DeviceOperational( uint8 srcEP, uint16 clusterID, uint8 frameType, uint8 cmd, uint16 profileID );
  142. #if defined(ZCL_READ) || defined(ZCL_WRITE) || defined(ZCL_REPORT)
  143. static void zclSerializeData( uint8 dataType, void *attrData, uint8 *buf );
  144. #endif // ZCL_READ || ZCL_WRITE || ZCL_REPORT
  145. #ifdef ZCL_READ
  146. static void *zclParseInReadRspCmd( zclParseCmd_t *pCmd );
  147. static uint8 zclProcessInReadCmd( zclIncoming_t *pInMsg );
  148. #endif // ZCL_READ
  149. #ifdef ZCL_WRITE
  150. static uint8 zclWriteAttrData( zclAttrRec_t *pAttr, zclWriteRec_t *pWriteRec );
  151. static void *zclParseInWriteRspCmd( zclParseCmd_t *pCmd );
  152. static uint8 zclProcessInWriteCmd( zclIncoming_t *pInMsg );
  153. static uint8 zclProcessInWriteUndividedCmd( zclIncoming_t *pInMsg );
  154. #endif // ZCL_WRITE
  155. #ifdef ZCL_REPORT
  156. static void *zclParseInConfigReportRspCmd( zclParseCmd_t *pCmd );
  157. static void *zclParseInReadReportCfgRspCmd( zclParseCmd_t *pCmd );
  158. #endif // ZCL_REPORT
  159. static void *zclParseInDefaultRspCmd( zclParseCmd_t *pCmd );
  160. #ifdef ZCL_DISCOVER
  161. static uint8 zclFindNextAttrRec( uint8 endpoint, uint16 clusterID, uint16 *attrId, zclAttrRec_t *pAttr );
  162. static void *zclParseInDiscRspCmd( zclParseCmd_t *pCmd );
  163. static uint8 zclProcessInDiscCmd( zclIncoming_t *pInMsg );
  164. #endif // ZCL_DISCOVER
  165. static uint8 zclSendMsg( zclIncoming_t *pInMsg );
  166. /*********************************************************************
  167. * Parse Profile Command Function Table
  168. */
  169. static CONST zclCmdItems_t zclCmdTable[] =
  170. {
  171. #ifdef ZCL_READ
  172. /* ZCL_CMD_READ */ { zclParseInReadCmd, zclProcessInReadCmd },
  173. /* ZCL_CMD_READ_RSP */ { zclParseInReadRspCmd, zclSendMsg },
  174. #else
  175. /* ZCL_CMD_READ */ { NULL, NULL },
  176. /* ZCL_CMD_READ_RSP */ { NULL, NULL },
  177. #endif // ZCL_READ
  178. #ifdef ZCL_WRITE
  179. /* ZCL_CMD_WRITE */ { zclParseInWriteCmd, zclProcessInWriteCmd },
  180. /* ZCL_CMD_WRITE_UNDIVIDED */ { zclParseInWriteCmd, zclProcessInWriteUndividedCmd },
  181. /* ZCL_CMD_WRITE_RSP */ { zclParseInWriteRspCmd, zclSendMsg },
  182. /* ZCL_CMD_WRITE_NO_RSP */ { zclParseInWriteCmd, zclProcessInWriteCmd },
  183. #else
  184. /* ZCL_CMD_WRITE */ { NULL, NULL },
  185. /* ZCL_CMD_WRITE_UNDIVIDED */ { NULL, NULL },
  186. /* ZCL_CMD_WRITE_RSP */ { NULL, NULL },
  187. /* ZCL_CMD_WRITE_NO_RSP */ { NULL, NULL },
  188. #endif // ZCL_WRITE
  189. #ifdef ZCL_REPORT
  190. /* ZCL_CMD_CONFIG_REPORT */ { zclParseInConfigReportCmd, zclSendMsg },
  191. /* ZCL_CMD_CONFIG_REPORT_RSP */ { zclParseInConfigReportRspCmd, zclSendMsg },
  192. /* ZCL_CMD_READ_REPORT_CFG */ { zclParseInReadReportCfgCmd, zclSendMsg },
  193. /* ZCL_CMD_READ_REPORT_CFG_RSP */ { zclParseInReadReportCfgRspCmd, zclSendMsg },
  194. /* ZCL_CMD_REPORT */ { zclParseInReportCmd, zclSendMsg },
  195. #else
  196. /* ZCL_CMD_CONFIG_REPORT */ { NULL, NULL },
  197. /* ZCL_CMD_CONFIG_REPORT_RSP */ { NULL, NULL },
  198. /* ZCL_CMD_READ_REPORT_CFG */ { NULL, NULL },
  199. /* ZCL_CMD_READ_REPORT_CFG_RSP */ { NULL, NULL },
  200. /* ZCL_CMD_REPORT */ { NULL, NULL },
  201. #endif // ZCL_REPORT
  202. /* ZCL_CMD_DEFAULT_RSP */ { zclParseInDefaultRspCmd, zclSendMsg },
  203. #ifdef ZCL_DISCOVER
  204. /* ZCL_CMD_DISCOVER */ { zclParseInDiscCmd, zclProcessInDiscCmd },
  205. /* ZCL_CMD_DISCOVER_RSP */ { zclParseInDiscRspCmd, zclSendMsg }
  206. #else
  207. /* ZCL_CMD_DISCOVER */ { NULL, NULL },
  208. /* ZCL_CMD_DISCOVER_RSP */ { NULL, NULL }
  209. #endif // ZCL_DISCOVER
  210. };
  211. /*********************************************************************
  212. * PUBLIC FUNCTIONS
  213. *********************************************************************/
  214. /*********************************************************************
  215. * @fn zcl_Init
  216. *
  217. * @brief Initialization function for the zcl layer.
  218. *
  219. * @param task_id - ZCL task id
  220. *
  221. * @return none
  222. */
  223. void zcl_Init( uint8 task_id )
  224. {
  225. zcl_TaskID = task_id;
  226. plugins = (zclLibPlugin_t *)NULL;
  227. attrList = (zclAttrRecsList *)NULL;
  228. clusterOptionList = (zclClusterOptionList *)NULL;
  229. }
  230. /*********************************************************************
  231. * @fn zcl_event_loop
  232. *
  233. * @brief Event Loop Processor for zcl.
  234. *
  235. * @param task_id - task id
  236. * @param events - event bitmap
  237. *
  238. * @return unprocessed events
  239. */
  240. uint16 zcl_event_loop( uint8 task_id, uint16 events )
  241. {
  242. uint8 *msgPtr;
  243. (void)task_id; // Intentionally unreferenced parameter
  244. if ( events & SYS_EVENT_MSG )
  245. {
  246. msgPtr = osal_msg_receive( zcl_TaskID );
  247. while ( msgPtr != NULL )
  248. {
  249. uint8 dealloc = TRUE;
  250. if ( *msgPtr == AF_INCOMING_MSG_CMD )
  251. {
  252. zclProcessMessageMSG( (afIncomingMSGPacket_t *)msgPtr );
  253. }
  254. else if ( zcl_RegisteredMsgTaskID != TASK_NO_TASK )
  255. {
  256. // send it to another task to process.
  257. osal_msg_send( zcl_RegisteredMsgTaskID, msgPtr );
  258. dealloc = FALSE;
  259. }
  260. // Release the memory
  261. if ( dealloc )
  262. {
  263. osal_msg_deallocate( msgPtr );
  264. }
  265. // Next
  266. msgPtr = osal_msg_receive( zcl_TaskID );
  267. }
  268. // return unprocessed events
  269. return (events ^ SYS_EVENT_MSG);
  270. }
  271. // Discard unknown events
  272. return 0;
  273. }
  274. /*********************************************************************
  275. * @fn zcl_registerPlugin
  276. *
  277. * @brief Add a Cluster Library handler
  278. *
  279. * @param startClusterID - starting cluster ID
  280. * @param endClusterID - ending cluster ID
  281. * @param pfnHdlr - function pointer to incoming message handler
  282. *
  283. * @return ZSuccess if OK
  284. */
  285. ZStatus_t zcl_registerPlugin( uint16 startClusterID,
  286. uint16 endClusterID, zclInHdlr_t pfnIncomingHdlr )
  287. {
  288. zclLibPlugin_t *pNewItem;
  289. zclLibPlugin_t *pLoop;
  290. // Fill in the new profile list
  291. pNewItem = osal_mem_alloc( sizeof( zclLibPlugin_t ) );
  292. if ( pNewItem == NULL )
  293. return (ZMemError);
  294. // Fill in the plugin record.
  295. pNewItem->next = (zclLibPlugin_t *)NULL;
  296. pNewItem->startClusterID = startClusterID;
  297. pNewItem->endClusterID = endClusterID;
  298. pNewItem->pfnIncomingHdlr = pfnIncomingHdlr;
  299. // Find spot in list
  300. if ( plugins == NULL )
  301. {
  302. plugins = pNewItem;
  303. }
  304. else
  305. {
  306. // Look for end of list
  307. pLoop = plugins;
  308. while ( pLoop->next != NULL )
  309. pLoop = pLoop->next;
  310. // Put new item at end of list
  311. pLoop->next = pNewItem;
  312. }
  313. return ( ZSuccess );
  314. }
  315. /*********************************************************************
  316. * @fn zcl_registerAttrList
  317. *
  318. * @brief Register an Attribute List with ZCL Foundation
  319. *
  320. * @param endpoint - endpoint the attribute list belongs to
  321. * @param numAttr - number of attributes in list
  322. * @param newAttrList - array of Attribute records.
  323. * NOTE: THE ATTRIBUTE IDs (FOR A CLUSTER) MUST BE IN
  324. * ASCENDING ORDER. OTHERWISE, THE DISCOVERY RESPONSE
  325. * COMMAND WILL NOT HAVE THE RIGHT ATTRIBUTE INFO
  326. *
  327. * @return ZSuccess if OK
  328. */
  329. ZStatus_t zcl_registerAttrList( uint8 endpoint, uint8 numAttr, CONST zclAttrRec_t newAttrList[] )
  330. {
  331. zclAttrRecsList *pNewItem;
  332. zclAttrRecsList *pLoop;
  333. // Fill in the new profile list
  334. pNewItem = osal_mem_alloc( sizeof( zclAttrRecsList ) );
  335. if ( pNewItem == NULL )
  336. return (ZMemError);
  337. pNewItem->next = (zclAttrRecsList *)NULL;
  338. pNewItem->endpoint = endpoint;
  339. pNewItem->numAttributes = numAttr;
  340. pNewItem->attrs = newAttrList;
  341. // Find spot in list
  342. if ( attrList == NULL )
  343. {
  344. attrList = pNewItem;
  345. }
  346. else
  347. {
  348. // Look for end of list
  349. pLoop = attrList;
  350. while ( pLoop->next != NULL )
  351. pLoop = pLoop->next;
  352. // Put new item at end of list
  353. pLoop->next = pNewItem;
  354. }
  355. return ( ZSuccess );
  356. }
  357. /*********************************************************************
  358. * @fn zcl_registerClusterOptionList
  359. *
  360. * @brief Register a Cluster Option List with ZCL Foundation
  361. *
  362. * @param endpoint - endpoint the option list belongs to
  363. * @param numOption - number of options in list
  364. * @param optionList - array of cluster option records.
  365. *
  366. * NOTE: This API should be called to enable 'Application
  367. * Link Key' security and/or 'APS ACK' for a specific
  368. * Cluster. The 'Application Link Key' is discarded
  369. * if security isn't enabled on the device.
  370. * The default behavior is 'Network Key' when security
  371. * is enabled and no 'APS ACK' for the ZCL messages.
  372. *
  373. * @return ZSuccess if OK
  374. */
  375. ZStatus_t zcl_registerClusterOptionList( uint8 endpoint, uint8 numOption, zclOptionRec_t optionList[] )
  376. {
  377. zclClusterOptionList *pNewItem;
  378. zclClusterOptionList *pLoop;
  379. // Fill in the new profile list
  380. pNewItem = osal_mem_alloc( sizeof( zclClusterOptionList ) );
  381. if ( pNewItem == NULL )
  382. return (ZMemError);
  383. pNewItem->next = (zclClusterOptionList *)NULL;
  384. pNewItem->endpoint = endpoint;
  385. pNewItem->numOptions = numOption;
  386. pNewItem->options = optionList;
  387. // Find spot in list
  388. if ( clusterOptionList == NULL )
  389. {
  390. clusterOptionList = pNewItem;
  391. }
  392. else
  393. {
  394. // Look for end of list
  395. pLoop = clusterOptionList;
  396. while ( pLoop->next != NULL )
  397. pLoop = pLoop->next;
  398. // Put new item at end of list
  399. pLoop->next = pNewItem;
  400. }
  401. return ( ZSuccess );
  402. }
  403. /*********************************************************************
  404. * @fn zcl_registerValidateAttrData
  405. *
  406. * @brief Add a validation function for attribute data
  407. *
  408. * @param pfnValidateAttrData - function pointer to validate routine
  409. *
  410. * @return ZSuccess if OK
  411. */
  412. ZStatus_t zcl_registerValidateAttrData( zclValidateAttrData_t pfnValidateAttrData )
  413. {
  414. zcl_ValidateAttrDataCB = pfnValidateAttrData;
  415. return ( ZSuccess );
  416. }
  417. /*********************************************************************
  418. * @fn zcl_registerForMsg
  419. *
  420. * @brief The ZCL is setup to send all incoming Foundation Command/Response
  421. * messages that aren't processed to one task (if a task is
  422. * registered).
  423. *
  424. * @param taskId - task Id of the Application where commands will be sent to
  425. *
  426. * @return TRUE if task registeration successful, FALSE otherwise
  427. *********************************************************************/
  428. uint8 zcl_registerForMsg( uint8 taskId )
  429. {
  430. // Allow only the first task
  431. if ( zcl_RegisteredMsgTaskID == TASK_NO_TASK )
  432. {
  433. zcl_RegisteredMsgTaskID = taskId;
  434. return ( true );
  435. }
  436. return ( false );
  437. }
  438. /*********************************************************************
  439. * @fn zcl_DeviceOperational
  440. *
  441. * @brief Used to see whether or not the device can send or respond
  442. * to application level commands.
  443. *
  444. * @param srcEP - source endpoint
  445. * @param clusterID - cluster ID
  446. * @param frameType - command type
  447. * @param cmd - command ID
  448. *
  449. * @return TRUE if device is operational, FALSE otherwise
  450. */
  451. static uint8 zcl_DeviceOperational( uint8 srcEP, uint16 clusterID,
  452. uint8 frameType, uint8 cmd, uint16 profileID )
  453. {
  454. zclAttrRec_t attrRec;
  455. uint8 deviceEnabled = DEVICE_ENABLED; // default value
  456. (void)profileID; // Intentionally unreferenced parameter
  457. // If the device is Disabled (DeviceEnabled attribute is set to Disabled), it
  458. // cannot send or respond to application level commands, other than commands
  459. // to read or write attributes. Note that the Identify cluster cannot be
  460. // disabled, and remains functional regardless of this setting.
  461. if ( zcl_ProfileCmd( frameType ) && cmd <= ZCL_CMD_WRITE_NO_RSP )
  462. return ( TRUE );
  463. if ( clusterID == ZCL_CLUSTER_ID_GEN_IDENTIFY )
  464. return ( TRUE );
  465. // Is device enabled?
  466. if ( zclFindAttrRec( srcEP, ZCL_CLUSTER_ID_GEN_BASIC, ATTRID_BASIC_DEVICE_ENABLED, &attrRec ) )
  467. zclReadAttrData( &deviceEnabled, &attrRec );
  468. return ( deviceEnabled == DEVICE_ENABLED ? TRUE : FALSE );
  469. }
  470. /*********************************************************************
  471. * @fn zcl_SendCommand
  472. *
  473. * @brief Used to send Profile and Cluster Specific Command messages.
  474. *
  475. * NOTE: The calling application is responsible for incrementing
  476. * the Sequence Number.
  477. *
  478. * @param srcEp - source endpoint
  479. * @param destAddr - destination address
  480. * @param clusterID - cluster ID
  481. * @param cmd - command ID
  482. * @param specific - whether the command is Cluster Specific
  483. * @param direction - client/server direction of the command
  484. * @param disableDefaultRsp - disable Default Response command
  485. * @param manuCode - manufacturer code for proprietary extensions to a profile
  486. * @param seqNumber - identification number for the transaction
  487. * @param cmdFormatLen - length of the command to be sent
  488. * @param cmdFormat - command to be sent
  489. *
  490. * @return ZSuccess if OK
  491. */
  492. ZStatus_t zcl_SendCommand( uint8 srcEP, afAddrType_t *destAddr,
  493. uint16 clusterID, uint8 cmd, uint8 specific, uint8 direction,
  494. uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum,
  495. uint8 cmdFormatLen, uint8 *cmdFormat )
  496. {
  497. endPointDesc_t *epDesc;
  498. zclFrameHdr_t hdr;
  499. uint8 *msgBuf;
  500. uint8 msgLen;
  501. uint8 *pBuf;
  502. afAddrType_t dstAddr;
  503. uint8 options;
  504. ZStatus_t status;
  505. osal_memcpy( &dstAddr, destAddr, sizeof ( afAddrType_t ) );
  506. epDesc = afFindEndPointDesc( srcEP );
  507. if ( epDesc == NULL )
  508. return ( ZInvalidParameter ); // EMBEDDED RETURN
  509. if ( clusterID == ZCL_INVALID_CLUSTER_ID )
  510. return ( ZInvalidParameter ); // EMBEDDED RETURN
  511. #if defined ( INTER_PAN )
  512. if ( StubAPS_InterPan( destAddr->panId, destAddr->endPoint ) )
  513. options = AF_TX_OPTIONS_NONE;
  514. else
  515. #endif
  516. options = zclGetClusterOption( srcEP, clusterID );
  517. osal_memset( &hdr, 0, sizeof( zclFrameHdr_t ) );
  518. // Not Profile wide command (like READ, WRITE)
  519. if ( specific )
  520. hdr.fc.type = ZCL_FRAME_TYPE_SPECIFIC_CMD;
  521. else
  522. hdr.fc.type = ZCL_FRAME_TYPE_PROFILE_CMD;
  523. if ( zcl_DeviceOperational( srcEP, clusterID, hdr.fc.type, cmd, epDesc->simpleDesc->AppProfId ) == FALSE )
  524. return ( ZFailure ); // EMBEDDED RETURN
  525. // Fill in the Maufacturer Code
  526. if ( manuCode != 0 )
  527. {
  528. hdr.fc.manuSpecific = 1;
  529. hdr.manuCode = manuCode;
  530. }
  531. // Set the Command Direction
  532. if ( direction )
  533. hdr.fc.direction = ZCL_FRAME_SERVER_CLIENT_DIR;
  534. else
  535. hdr.fc.direction = ZCL_FRAME_CLIENT_SERVER_DIR;
  536. // Set the Disable Default Response field
  537. if ( disableDefaultRsp )
  538. hdr.fc.disableDefaultRsp = 1;
  539. else
  540. hdr.fc.disableDefaultRsp = 0;
  541. // Fill in the Transaction Sequence Number
  542. hdr.transSeqNum = seqNum;
  543. // Fill in the command
  544. hdr.commandID = cmd;
  545. // calculate the needed buffer size
  546. msgLen = zclCalcHdrSize( &hdr );
  547. msgLen += cmdFormatLen;
  548. // Allocate the buffer needed
  549. msgBuf = osal_mem_alloc( msgLen );
  550. if ( msgBuf != NULL )
  551. {
  552. // Fill in the ZCL Header
  553. pBuf = zclBuildHdr( &hdr, msgBuf );
  554. // Fill in the command frame
  555. osal_memcpy( pBuf, cmdFormat, cmdFormatLen );
  556. status = AF_DataRequest( &dstAddr, epDesc, clusterID, msgLen, msgBuf,
  557. &zcl_TransID, options, AF_DEFAULT_RADIUS );
  558. osal_mem_free ( msgBuf );
  559. }
  560. else
  561. status = ZMemError;
  562. return ( status );
  563. }
  564. #ifdef ZCL_READ
  565. /*********************************************************************
  566. * @fn zcl_SendRead
  567. *
  568. * @brief Send a Read command
  569. *
  570. * @param srcEP - Application's endpoint
  571. * @param dstAddr - destination address
  572. * @param clusterID - cluster ID
  573. * @param readCmd - read command to be sent
  574. * @param direction - direction of the command
  575. * @param seqNum - transaction sequence number
  576. *
  577. * @return ZSuccess if OK
  578. */
  579. ZStatus_t zcl_SendRead( uint8 srcEP, afAddrType_t *dstAddr,
  580. uint16 clusterID, zclReadCmd_t *readCmd,
  581. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum)
  582. {
  583. uint8 dataLen;
  584. uint8 *buf;
  585. uint8 *pBuf;
  586. ZStatus_t status;
  587. dataLen = readCmd->numAttr * 2; // Attribute ID
  588. buf = osal_mem_alloc( dataLen );
  589. if ( buf != NULL )
  590. {
  591. uint8 i;
  592. // Load the buffer - serially
  593. pBuf = buf;
  594. for (i = 0; i < readCmd->numAttr; i++)
  595. {
  596. *pBuf++ = LO_UINT16( readCmd->attrID[i] );
  597. *pBuf++ = HI_UINT16( readCmd->attrID[i] );
  598. }
  599. status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_READ, FALSE,
  600. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  601. osal_mem_free( buf );
  602. }
  603. else
  604. status = ZMemError;
  605. return ( status );
  606. }
  607. /*********************************************************************
  608. * @fn zcl_SendReadRsp
  609. *
  610. * @brief Send a Read Response command.
  611. *
  612. * @param srcEP - Application's endpoint
  613. * @param dstAddr - destination address
  614. * @param clusterID - cluster ID
  615. * @param readRspCmd - read response command to be sent
  616. * @param direction - direction of the command
  617. * @param seqNum - transaction sequence number
  618. *
  619. * @return ZSuccess if OK
  620. */
  621. ZStatus_t zcl_SendReadRsp( uint8 srcEP, afAddrType_t *dstAddr,
  622. uint16 clusterID, zclReadRspCmd_t *readRspCmd,
  623. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  624. {
  625. uint8 *buf;
  626. uint8 *pBuf;
  627. zclReadRspStatus_t *statusRec;
  628. uint8 len = 0;
  629. uint8 i;
  630. ZStatus_t status;
  631. // calculate the size of the command
  632. for ( i = 0; i < readRspCmd->numAttr; i++ )
  633. {
  634. statusRec = &(readRspCmd->attrList[i]);
  635. len += 2 + 1; // Attribute ID + Status
  636. if ( statusRec->status == ZCL_STATUS_SUCCESS )
  637. {
  638. len++; // Attribute Data Type
  639. len += zclGetAttrDataLength( statusRec->dataType, statusRec->data); // Attribute Data
  640. }
  641. }
  642. buf = osal_mem_alloc( len );
  643. if ( buf != NULL )
  644. {
  645. // Load the buffer - serially
  646. pBuf = buf;
  647. for ( i = 0; i < readRspCmd->numAttr; i++ )
  648. {
  649. statusRec = &(readRspCmd->attrList[i]);
  650. *pBuf++ = LO_UINT16( statusRec->attrID );
  651. *pBuf++ = HI_UINT16( statusRec->attrID );
  652. *pBuf++ = statusRec->status;
  653. if ( statusRec->status == ZCL_STATUS_SUCCESS )
  654. {
  655. *pBuf++ = statusRec->dataType;
  656. zclSerializeData( statusRec->dataType, statusRec->data, pBuf );
  657. // move pass attribute data
  658. pBuf += zclGetAttrDataLength( statusRec->dataType, statusRec->data );
  659. }
  660. } // for loop
  661. status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_READ_RSP, FALSE,
  662. direction, disableDefaultRsp, 0, seqNum, len, buf );
  663. osal_mem_free( buf );
  664. }
  665. else
  666. status = ZMemError;
  667. return ( status );
  668. }
  669. #endif // ZCL_READ
  670. #ifdef ZCL_WRITE
  671. /*********************************************************************
  672. * @fn sendWriteRequest
  673. *
  674. * @brief Send a Write command
  675. *
  676. * @param dstAddr - destination address
  677. * @param clusterID - cluster ID
  678. * @param writeCmd - write command to be sent
  679. * @param cmd - ZCL_CMD_WRITE, ZCL_CMD_WRITE_UNDIVIDED or ZCL_CMD_WRITE_NO_RSP
  680. * @param direction - direction of the command
  681. * @param seqNum - transaction sequence number
  682. *
  683. * @return ZSuccess if OK
  684. */
  685. ZStatus_t zcl_SendWriteRequest( uint8 srcEP, afAddrType_t *dstAddr, uint16 clusterID,
  686. zclWriteCmd_t *writeCmd, uint8 cmd, uint8 direction,
  687. uint8 disableDefaultRsp, uint8 seqNum )
  688. {
  689. uint8 *buf;
  690. uint8 *pBuf;
  691. zclWriteRec_t *statusRec;
  692. uint8 attrDataLen;
  693. uint8 dataLen = 0;
  694. uint8 i;
  695. ZStatus_t status;
  696. for ( i = 0; i < writeCmd->numAttr; i++ )
  697. {
  698. statusRec = &(writeCmd->attrList[i]);
  699. attrDataLen = zclGetAttrDataLength( statusRec->dataType, statusRec->attrData );
  700. dataLen += 2 + 1 + attrDataLen; // Attribute ID + Attribute Type + Attribute Data
  701. }
  702. buf = osal_mem_alloc( dataLen );
  703. if ( buf != NULL )
  704. {
  705. // Load the buffer - serially
  706. pBuf = buf;
  707. for ( i = 0; i < writeCmd->numAttr; i++ )
  708. {
  709. statusRec = &(writeCmd->attrList[i]);
  710. *pBuf++ = LO_UINT16( statusRec->attrID );
  711. *pBuf++ = HI_UINT16( statusRec->attrID );
  712. *pBuf++ = statusRec->dataType;
  713. zclSerializeData( statusRec->dataType, statusRec->attrData, pBuf );
  714. attrDataLen = zclGetAttrDataLength( statusRec->dataType, statusRec->attrData );
  715. pBuf += attrDataLen; // move pass attribute data
  716. }
  717. status = zcl_SendCommand( srcEP, dstAddr, clusterID, cmd, FALSE,
  718. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  719. osal_mem_free( buf );
  720. }
  721. else
  722. status = ZMemError;
  723. return ( status);
  724. }
  725. /*********************************************************************
  726. * @fn zcl_SendWriteRsp
  727. *
  728. * @brief Send a Write Response command
  729. *
  730. * @param dstAddr - destination address
  731. * @param clusterID - cluster ID
  732. * @param wrtieRspCmd - write response command to be sent
  733. * @param direction - direction of the command
  734. * @param seqNum - transaction sequence number
  735. *
  736. * @return ZSuccess if OK
  737. */
  738. ZStatus_t zcl_SendWriteRsp( uint8 srcEP, afAddrType_t *dstAddr,
  739. uint16 clusterID, zclWriteRspCmd_t *writeRspCmd,
  740. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  741. {
  742. uint8 dataLen;
  743. uint8 *buf;
  744. uint8 *pBuf;
  745. uint8 i;
  746. ZStatus_t status;
  747. dataLen = writeRspCmd->numAttr * ( 1 + 2 ); // status + attribute id
  748. buf = osal_mem_alloc( dataLen );
  749. if ( buf != NULL )
  750. {
  751. // Load the buffer - serially
  752. pBuf = buf;
  753. for ( i = 0; i < writeRspCmd->numAttr; i++ )
  754. {
  755. *pBuf++ = writeRspCmd->attrList[i].status;
  756. *pBuf++ = LO_UINT16( writeRspCmd->attrList[i].attrID );
  757. *pBuf++ = HI_UINT16( writeRspCmd->attrList[i].attrID );
  758. }
  759. // If there's only a single status record and its status field is set to
  760. // SUCCESS then omit the attribute ID field.
  761. if ( writeRspCmd->numAttr == 1 && writeRspCmd->attrList[0].status == ZCL_STATUS_SUCCESS )
  762. dataLen = 1;
  763. status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_WRITE_RSP, FALSE,
  764. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  765. osal_mem_free( buf );
  766. }
  767. else
  768. status = ZMemError;
  769. return ( status );
  770. }
  771. #endif // ZCL_WRITE
  772. #ifdef ZCL_REPORT
  773. /*********************************************************************
  774. * @fn zcl_SendConfigReportCmd
  775. *
  776. * @brief Send a Configure Reporting command
  777. *
  778. * @param dstAddr - destination address
  779. * @param clusterID - cluster ID
  780. * @param cfgReportCmd - configure reporting command to be sent
  781. * @param direction - direction of the command
  782. * @param seqNum - transaction sequence number
  783. *
  784. * @return ZSuccess if OK
  785. */
  786. ZStatus_t zcl_SendConfigReportCmd( uint8 srcEP, afAddrType_t *dstAddr,
  787. uint16 clusterID, zclCfgReportCmd_t *cfgReportCmd,
  788. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  789. {
  790. uint8 *buf;
  791. uint8 *pBuf;
  792. uint8 dataLen = 0;
  793. zclCfgReportRec_t *reportRec;
  794. uint8 reportChangeLen; // length of Reportable Change field
  795. uint8 i;
  796. ZStatus_t status;
  797. // Find out the data length
  798. for ( i = 0; i < cfgReportCmd->numAttr; i++ )
  799. {
  800. reportRec = &(cfgReportCmd->attrList[i]);
  801. dataLen += 1 + 2; // Direction + Attribute ID
  802. reportChangeLen = 0;
  803. if ( reportRec->direction == ZCL_SEND_ATTR_REPORTS )
  804. {
  805. dataLen += 1 + 2 + 2; // Data Type + Min + Max Reporting Intervals
  806. // Find out the size of the Reportable Change field (for Analog data types)
  807. if ( zclAnalogDataType( reportRec->dataType ) )
  808. {
  809. reportChangeLen = zclGetDataTypeLength( reportRec->dataType );
  810. dataLen += reportChangeLen;
  811. }
  812. }
  813. else
  814. {
  815. dataLen += 2; // Timeout Period
  816. }
  817. }
  818. buf = osal_mem_alloc( dataLen );
  819. if ( buf != NULL )
  820. {
  821. // Load the buffer - serially
  822. pBuf = buf;
  823. for ( i = 0; i < cfgReportCmd->numAttr; i++ )
  824. {
  825. reportRec = &(cfgReportCmd->attrList[i]);
  826. *pBuf++ = reportRec->direction;
  827. *pBuf++ = LO_UINT16( reportRec->attrID );
  828. *pBuf++ = HI_UINT16( reportRec->attrID );
  829. if ( reportRec->direction == ZCL_SEND_ATTR_REPORTS )
  830. {
  831. *pBuf++ = reportRec->dataType;
  832. *pBuf++ = LO_UINT16( reportRec->minReportInt );
  833. *pBuf++ = HI_UINT16( reportRec->minReportInt );
  834. *pBuf++ = LO_UINT16( reportRec->maxReportInt );
  835. *pBuf++ = HI_UINT16( reportRec->maxReportInt );
  836. if ( zclAnalogDataType( reportRec->dataType ) )
  837. {
  838. zclSerializeData( reportRec->dataType, reportRec->reportableChange, pBuf );
  839. reportChangeLen = zclGetDataTypeLength( reportRec->dataType );
  840. pBuf += reportChangeLen;
  841. }
  842. }
  843. else
  844. {
  845. *pBuf++ = LO_UINT16( reportRec->timeoutPeriod );
  846. *pBuf++ = HI_UINT16( reportRec->timeoutPeriod );
  847. }
  848. } // for loop
  849. status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_CONFIG_REPORT, FALSE,
  850. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  851. osal_mem_free( buf );
  852. }
  853. else
  854. status = ZMemError;
  855. return ( status );
  856. }
  857. /*********************************************************************
  858. * @fn zcl_SendConfigReportRspCmd
  859. *
  860. * @brief Send a Configure Reporting Response command
  861. *
  862. * @param dstAddr - destination address
  863. * @param clusterID - cluster ID
  864. * @param cfgReportRspCmd - configure reporting response command to be sent
  865. * @param direction - direction of the command
  866. * @param seqNum - transaction sequence number
  867. *
  868. * @return ZSuccess if OK
  869. */
  870. ZStatus_t zcl_SendConfigReportRspCmd( uint8 srcEP, afAddrType_t *dstAddr,
  871. uint16 clusterID, zclCfgReportRspCmd_t *cfgReportRspCmd,
  872. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  873. {
  874. uint8 dataLen;
  875. uint8 *buf;
  876. uint8 *pBuf;
  877. uint8 i;
  878. ZStatus_t status;
  879. // Atrribute list (Status, Direction and Attribute ID)
  880. dataLen = cfgReportRspCmd->numAttr * ( 1 + 1 + 2 );
  881. buf = osal_mem_alloc( dataLen );
  882. if ( buf != NULL )
  883. {
  884. // Load the buffer - serially
  885. pBuf = buf;
  886. for ( i = 0; i < cfgReportRspCmd->numAttr; i++ )
  887. {
  888. *pBuf++ = cfgReportRspCmd->attrList[i].status;
  889. *pBuf++ = cfgReportRspCmd->attrList[i].direction;
  890. *pBuf++ = LO_UINT16( cfgReportRspCmd->attrList[i].attrID );
  891. *pBuf++ = HI_UINT16( cfgReportRspCmd->attrList[i].attrID );
  892. }
  893. // If there's only a single status record and its status field is set to
  894. // SUCCESS then omit the attribute ID field.
  895. if ( cfgReportRspCmd->numAttr == 1 && cfgReportRspCmd->attrList[0].status == ZCL_STATUS_SUCCESS )
  896. dataLen = 1;
  897. status = zcl_SendCommand( srcEP, dstAddr, clusterID,
  898. ZCL_CMD_CONFIG_REPORT_RSP, FALSE, direction,
  899. disableDefaultRsp, 0, seqNum, dataLen, buf );
  900. osal_mem_free( buf );
  901. }
  902. else
  903. status = ZMemError;
  904. return ( status );
  905. }
  906. /*********************************************************************
  907. * @fn zcl_SendReadReportCfgCmd
  908. *
  909. * @brief Send a Read Reporting Configuration command
  910. *
  911. * @param dstAddr - destination address
  912. * @param clusterID - cluster ID
  913. * @param readReportCfgCmd - read reporting configuration command to be sent
  914. * @param direction - direction of the command
  915. * @param seqNum - transaction sequence number
  916. *
  917. * @return ZSuccess if OK
  918. */
  919. ZStatus_t zcl_SendReadReportCfgCmd( uint8 srcEP, afAddrType_t *dstAddr,
  920. uint16 clusterID, zclReadReportCfgCmd_t *readReportCfgCmd,
  921. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  922. {
  923. uint8 dataLen;
  924. uint8 *buf;
  925. uint8 *pBuf;
  926. uint8 i;
  927. ZStatus_t status;
  928. dataLen = readReportCfgCmd->numAttr * ( 1 + 2 ); // Direction + Atrribute ID
  929. buf = osal_mem_alloc( dataLen );
  930. if ( buf != NULL )
  931. {
  932. // Load the buffer - serially
  933. pBuf = buf;
  934. for ( i = 0; i < readReportCfgCmd->numAttr; i++ )
  935. {
  936. *pBuf++ = readReportCfgCmd->attrList[i].direction;
  937. *pBuf++ = LO_UINT16( readReportCfgCmd->attrList[i].attrID );
  938. *pBuf++ = HI_UINT16( readReportCfgCmd->attrList[i].attrID );
  939. }
  940. status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_READ_REPORT_CFG, FALSE,
  941. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  942. osal_mem_free( buf );
  943. }
  944. else
  945. status = ZMemError;
  946. return ( status );
  947. }
  948. /*********************************************************************
  949. * @fn zcl_SendReadReportCfgRspCmd
  950. *
  951. * @brief Send a Read Reporting Configuration Response command
  952. *
  953. * @param dstAddr - destination address
  954. * @param clusterID - cluster ID
  955. * @param readReportCfgRspCmd - read reporting configuration response command to be sent
  956. * @param direction - direction of the command
  957. * @param seqNum - transaction sequence number
  958. *
  959. * @return ZSuccess if OK
  960. */
  961. ZStatus_t zcl_SendReadReportCfgRspCmd( uint8 srcEP, afAddrType_t *dstAddr,
  962. uint16 clusterID, zclReadReportCfgRspCmd_t *readReportCfgRspCmd,
  963. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  964. {
  965. uint8 *buf;
  966. uint8 *pBuf;
  967. uint8 dataLen = 0;
  968. zclReportCfgRspRec_t *reportRspRec;
  969. uint8 reportChangeLen;
  970. uint8 i;
  971. ZStatus_t status;
  972. // Find out the data length
  973. for ( i = 0; i < readReportCfgRspCmd->numAttr; i++ )
  974. {
  975. reportRspRec = &(readReportCfgRspCmd->attrList[i]);
  976. dataLen += 1 + 1 + 2 ; // Status, Direction and Atrribute ID
  977. if ( reportRspRec->status == ZCL_STATUS_SUCCESS )
  978. {
  979. if ( reportRspRec->direction == ZCL_SEND_ATTR_REPORTS )
  980. {
  981. dataLen += 1 + 2 + 2; // Data Type + Min + Max Reporting Intervals
  982. if ( zclAnalogDataType( reportRspRec->dataType ) )
  983. {
  984. reportChangeLen = zclGetDataTypeLength( reportRspRec->dataType );
  985. dataLen += reportChangeLen; // Reportable Change field
  986. }
  987. }
  988. else
  989. {
  990. dataLen += 2; // Timeout Period
  991. }
  992. }
  993. }
  994. buf = osal_mem_alloc( dataLen );
  995. if ( buf != NULL )
  996. {
  997. // Load the buffer - serially
  998. pBuf = buf;
  999. for ( i = 0; i < readReportCfgRspCmd->numAttr; i++ )
  1000. {
  1001. reportRspRec = &(readReportCfgRspCmd->attrList[i]);
  1002. *pBuf++ = reportRspRec->status;
  1003. *pBuf++ = reportRspRec->direction;
  1004. *pBuf++ = LO_UINT16( reportRspRec->attrID );
  1005. *pBuf++ = HI_UINT16( reportRspRec->attrID );
  1006. if ( reportRspRec->status == ZCL_STATUS_SUCCESS )
  1007. {
  1008. if ( reportRspRec->direction == ZCL_SEND_ATTR_REPORTS )
  1009. {
  1010. *pBuf++ = reportRspRec->dataType;
  1011. *pBuf++ = LO_UINT16( reportRspRec->minReportInt );
  1012. *pBuf++ = HI_UINT16( reportRspRec->minReportInt );
  1013. *pBuf++ = LO_UINT16( reportRspRec->maxReportInt );
  1014. *pBuf++ = HI_UINT16( reportRspRec->maxReportInt );
  1015. if ( zclAnalogDataType( reportRspRec->dataType ) )
  1016. {
  1017. zclSerializeData( reportRspRec->dataType,
  1018. reportRspRec->reportableChange, pBuf );
  1019. reportChangeLen = zclGetDataTypeLength( reportRspRec->dataType );
  1020. pBuf += reportChangeLen;
  1021. }
  1022. }
  1023. else
  1024. {
  1025. *pBuf++ = LO_UINT16( reportRspRec->timeoutPeriod );
  1026. *pBuf++ = HI_UINT16( reportRspRec->timeoutPeriod );
  1027. }
  1028. }
  1029. }
  1030. status = zcl_SendCommand( srcEP, dstAddr, clusterID,
  1031. ZCL_CMD_READ_REPORT_CFG_RSP, FALSE,
  1032. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  1033. osal_mem_free( buf );
  1034. }
  1035. else
  1036. status = ZMemError;
  1037. return ( status );
  1038. }
  1039. /*********************************************************************
  1040. * @fn zcl_SendReportCmd
  1041. *
  1042. * @brief Send a Report command
  1043. *
  1044. * @param dstAddr - destination address
  1045. * @param clusterID - cluster ID
  1046. * @param reportCmd - report command to be sent
  1047. * @param direction - direction of the command
  1048. * @param seqNum - transaction sequence number
  1049. *
  1050. * @return ZSuccess if OK
  1051. */
  1052. ZStatus_t zcl_SendReportCmd( uint8 srcEP, afAddrType_t *dstAddr,
  1053. uint16 clusterID, zclReportCmd_t *reportCmd,
  1054. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  1055. {
  1056. zclReport_t *reportRec;
  1057. uint8 attrDataLen;
  1058. uint8 dataLen = 0;
  1059. uint8 *buf;
  1060. uint8 *pBuf;
  1061. uint8 i;
  1062. ZStatus_t status;
  1063. // calculate the size of the command
  1064. for ( i = 0; i < reportCmd->numAttr; i++ )
  1065. {
  1066. reportRec = &(reportCmd->attrList[i]);
  1067. dataLen += 2 + 1; // Attribute ID + data type
  1068. attrDataLen = zclGetAttrDataLength( reportRec->dataType, reportRec->attrData );
  1069. dataLen += attrDataLen; // Attribute Data
  1070. }
  1071. buf = osal_mem_alloc( dataLen );
  1072. if ( buf != NULL )
  1073. {
  1074. // Load the buffer - serially
  1075. pBuf = buf;
  1076. for ( i = 0; i < reportCmd->numAttr; i++ )
  1077. {
  1078. reportRec = &(reportCmd->attrList[i]);
  1079. *pBuf++ = LO_UINT16( reportRec->attrID );
  1080. *pBuf++ = HI_UINT16( reportRec->attrID );
  1081. *pBuf++ = reportRec->dataType;
  1082. zclSerializeData( reportRec->dataType, reportRec->attrData, pBuf );
  1083. attrDataLen = zclGetAttrDataLength( reportRec->dataType, reportRec->attrData );
  1084. pBuf += attrDataLen; // move pass attribute data
  1085. }
  1086. status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_REPORT, FALSE,
  1087. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  1088. osal_mem_free( buf );
  1089. }
  1090. else
  1091. status = ZMemError;
  1092. return ( status );
  1093. }
  1094. #endif // ZCL_REPORT
  1095. /*********************************************************************
  1096. * @fn zcl_SendDefaultRspCmd
  1097. *
  1098. * @brief Send a Default Response command
  1099. *
  1100. * @param dstAddr - destination address
  1101. * @param clusterID - cluster ID
  1102. * @param defaultRspCmd - default response command to be sent
  1103. * @param direction - direction of the command
  1104. * @param seqNum - transaction sequence number
  1105. *
  1106. * @return ZSuccess if OK
  1107. */
  1108. ZStatus_t zcl_SendDefaultRspCmd( uint8 srcEP, afAddrType_t *dstAddr,
  1109. uint16 clusterID, zclDefaultRspCmd_t *defaultRspCmd,
  1110. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  1111. {
  1112. uint8 buf[2]; // Command ID and Status;
  1113. // Load the buffer - serially
  1114. buf[0] = defaultRspCmd->commandID;
  1115. buf[1] = defaultRspCmd->statusCode;
  1116. return ( zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_DEFAULT_RSP, FALSE,
  1117. direction, disableDefaultRsp, 0, seqNum, 2, buf ) );
  1118. }
  1119. #ifdef ZCL_DISCOVER
  1120. /*********************************************************************
  1121. * @fn zcl_SendDiscoverCmd
  1122. *
  1123. * @brief Send a Discover command
  1124. *
  1125. * @param dstAddr - destination address
  1126. * @param clusterID - cluster ID
  1127. * @param discoverCmd - discover command to be sent
  1128. * @param direction - direction of the command
  1129. * @param seqNum - transaction sequence number
  1130. *
  1131. * @return ZSuccess if OK
  1132. */
  1133. ZStatus_t zcl_SendDiscoverCmd( uint8 srcEP, afAddrType_t *dstAddr,
  1134. uint16 clusterID, zclDiscoverCmd_t *discoverCmd,
  1135. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  1136. {
  1137. uint8 dataLen = 2 + 1; // Start Attribute ID and Max Attribute IDs
  1138. uint8 *buf;
  1139. uint8 *pBuf;
  1140. ZStatus_t status;
  1141. buf = osal_mem_alloc( dataLen );
  1142. if ( buf != NULL )
  1143. {
  1144. // Load the buffer - serially
  1145. pBuf = buf;
  1146. *pBuf++ = LO_UINT16(discoverCmd->startAttr);
  1147. *pBuf++ = HI_UINT16(discoverCmd->startAttr);
  1148. *pBuf++ = discoverCmd->maxAttrIDs;
  1149. status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_DISCOVER, FALSE,
  1150. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  1151. osal_mem_free( buf );
  1152. }
  1153. else
  1154. status = ZMemError;
  1155. return ( status );
  1156. }
  1157. /*********************************************************************
  1158. * @fn zcl_SendDiscoverRspCmd
  1159. *
  1160. * @brief Send a Discover Response command
  1161. *
  1162. * @param dstAddr - destination address
  1163. * @param clusterID - cluster ID
  1164. * @param reportRspCmd - report response command to be sent
  1165. * @param direction - direction of the command
  1166. * @param seqNum - transaction sequence number
  1167. *
  1168. * @return ZSuccess if OK
  1169. */
  1170. ZStatus_t zcl_SendDiscoverRspCmd( uint8 srcEP, afAddrType_t *dstAddr,
  1171. uint16 clusterID, zclDiscoverRspCmd_t *discoverRspCmd,
  1172. uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
  1173. {
  1174. uint8 dataLen = 1; // Discovery complete
  1175. uint8 *buf;
  1176. uint8 *pBuf;
  1177. uint8 i;
  1178. ZStatus_t status;
  1179. // calculate the size of the command
  1180. dataLen += discoverRspCmd->numAttr * (2 + 1); // Attribute ID and Data Type
  1181. buf = osal_mem_alloc( dataLen );
  1182. if ( buf != NULL )
  1183. {
  1184. // Load the buffer - serially
  1185. pBuf = buf;
  1186. *pBuf++ = discoverRspCmd->discComplete;
  1187. for ( i = 0; i < discoverRspCmd->numAttr; i++ )
  1188. {
  1189. *pBuf++ = LO_UINT16(discoverRspCmd->attrList[i].attrID);
  1190. *pBuf++ = HI_UINT16(discoverRspCmd->attrList[i].attrID);
  1191. *pBuf++ = discoverRspCmd->attrList[i].dataType;
  1192. }
  1193. status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_DISCOVER_RSP, FALSE,
  1194. direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
  1195. osal_mem_free( buf );
  1196. }
  1197. else
  1198. status = ZMemError;
  1199. return ( status );
  1200. }
  1201. #endif // ZCL_DISCOVER
  1202. /*********************************************************************
  1203. * PRIVATE FUNCTIONS
  1204. *********************************************************************/
  1205. /*********************************************************************
  1206. * @fn zclProcessMessageMSG
  1207. *
  1208. * @brief Data message processor callback. This function processes
  1209. * any incoming data - probably from other devices. So, based
  1210. * on cluster ID, perform the intended action.
  1211. *
  1212. * @param pkt - incoming message
  1213. *
  1214. * @return none
  1215. */
  1216. static void zclProcessMessageMSG( afIncomingMSGPacket_t *pkt )
  1217. {
  1218. endPointDesc_t *epDesc;
  1219. zclIncoming_t inMsg;
  1220. zclLibPlugin_t *pInPlugin;
  1221. zclDefaultRspCmd_t defautlRspCmd;
  1222. uint8 options;
  1223. uint8 securityEnable;
  1224. uint8 interPanMsg;
  1225. ZStatus_t status = ZFailure;
  1226. if ( pkt->cmd.DataLength == 0 )
  1227. return; // Error, ignore the message
  1228. // Initialize
  1229. inMsg.msg = pkt;
  1230. inMsg.attrCmd = NULL;
  1231. inMsg.pData = NULL;
  1232. inMsg.pDataLen = 0;
  1233. inMsg.pData = zclParseHdr( &(inMsg.hdr), pkt->cmd.Data );
  1234. inMsg.pDataLen = pkt->cmd.DataLength;
  1235. inMsg.pDataLen -= (uint8)(inMsg.pData - pkt->cmd.Data);
  1236. // Find the wanted endpoint
  1237. epDesc = afFindEndPointDesc( pkt->endPoint );
  1238. if ( epDesc == NULL )
  1239. return; // Error, ignore the message
  1240. if ( pkt->clusterId == ZCL_INVALID_CLUSTER_ID )
  1241. return; // Error, ignore the message
  1242. if ( zcl_DeviceOperational( pkt->endPoint, pkt->clusterId,
  1243. inMsg.hdr.fc.type, inMsg.hdr.commandID, epDesc->simpleDesc->AppProfId ) == FALSE )
  1244. {
  1245. return; // Error, ignore the message
  1246. }
  1247. #if defined ( INTER_PAN )
  1248. if ( StubAPS_InterPan( pkt->srcAddr.panId, pkt->srcAddr.endPoint ) )
  1249. {
  1250. // No foundation command is supported thru Inter-PAN communication
  1251. if ( zcl_ProfileCmd( inMsg.hdr.fc.type ) )
  1252. return;
  1253. interPanMsg = TRUE;
  1254. options = AF_TX_OPTIONS_NONE;
  1255. }
  1256. else
  1257. #endif
  1258. {
  1259. interPanMsg = FALSE;
  1260. options = zclGetClusterOption( pkt->endPoint, pkt->clusterId );
  1261. }
  1262. // Local and remote Security options must match except for Default Response command
  1263. if ( !zcl_DefaultRspCmd( inMsg.hdr ) )
  1264. {
  1265. securityEnable = ( options & AF_EN_SECURITY ) ? TRUE : FALSE;
  1266. if ( pkt->SecurityUse != securityEnable )
  1267. {
  1268. if ( UNICAST_MSG( inMsg.msg ) )
  1269. {
  1270. // Send a Default Response command back with no Application Link Key security
  1271. if ( securityEnable )
  1272. zclSetSecurityOption( pkt->endPoint, pkt->clusterId, FALSE );
  1273. defautlRspCmd.statusCode = status;
  1274. defautlRspCmd.commandID = inMsg.hdr.commandID;
  1275. zcl_SendDefaultRspCmd( inMsg.msg->endPoint, &(inMsg.msg->srcAddr),
  1276. inMsg.msg->clusterId, &defautlRspCmd,
  1277. ZCL_FRAME_SERVER_CLIENT_DIR, true, inMsg.hdr.transSeqNum );
  1278. if ( securityEnable )
  1279. zclSetSecurityOption( pkt->endPoint, pkt->clusterId, TRUE );
  1280. }
  1281. return; // Error, ignore the message
  1282. }
  1283. }
  1284. // Is this a foundation type message
  1285. if ( zcl_ProfileCmd( inMsg.hdr.fc.type ) )
  1286. {
  1287. if ( inMsg.hdr.fc.manuSpecific )
  1288. {
  1289. // We don't support any manufacturer specific command
  1290. status = ZCL_STATUS_UNSUP_MANU_GENERAL_COMMAND;
  1291. }
  1292. else if ( ( inMsg.hdr.commandID <= ZCL_CMD_MAX ) &&
  1293. ( zclCmdTable[inMsg.hdr.commandID].pfnParseInProfile != NULL ) )
  1294. {
  1295. zclParseCmd_t parseCmd;
  1296. parseCmd.endpoint = pkt->endPoint;
  1297. parseCmd.dataLen = inMsg.pDataLen;
  1298. parseCmd.pData = inMsg.pData;
  1299. // Parse the command, remember that the return value is a pointer to allocated memory
  1300. inMsg.attrCmd = zclParseCmd( inMsg.hdr.commandID, &parseCmd );
  1301. if ( (inMsg.attrCmd != NULL) && (zclCmdTable[inMsg.hdr.commandID].pfnProcessInProfile != NULL) )
  1302. {
  1303. // Process the command
  1304. if ( zclProcessCmd( inMsg.hdr.commandID, &inMsg ) == FALSE )
  1305. {
  1306. // Couldn't find attribute in the table.
  1307. }
  1308. }
  1309. // Free the buffer
  1310. if ( inMsg.attrCmd )
  1311. osal_mem_free( inMsg.attrCmd );
  1312. if ( CMD_HAS_RSP( inMsg.hdr.commandID ) )
  1313. return; // We're done
  1314. status = ZSuccess;
  1315. }
  1316. else
  1317. {
  1318. // Unsupported message
  1319. status = ZCL_STATUS_UNSUP_GENERAL_COMMAND;
  1320. }
  1321. }
  1322. else
  1323. {
  1324. // Nope, must be specific to the cluster ID
  1325. // Find the appropriate plugin
  1326. pInPlugin = zclFindPlugin( pkt->clusterId, epDesc->simpleDesc->AppProfId );
  1327. if ( pInPlugin && pInPlugin->pfnIncomingHdlr )
  1328. {
  1329. // The return value of the plugin function will be
  1330. // ZSuccess - Supported and need default response
  1331. // ZFailure - Unsupported
  1332. // ZCL_STATUS_CMD_HAS_RSP - Supported and do not need default rsp
  1333. // ZCL_STATUS_INVALID_FIELD - Supported, but the incoming msg is wrong formatted
  1334. // ZCL_STATUS_INVALID_VALUE - Supported, but the request not achievable by the h/w
  1335. // ZCL_STATUS_SOFTWARE_FAILURE - Supported but ZStack memory allocation fails
  1336. status = pInPlugin->pfnIncomingHdlr( &inMsg );
  1337. if ( status == ZCL_STATUS_CMD_HAS_RSP || ( interPanMsg && status == ZSuccess ) )
  1338. return; // We're done
  1339. }
  1340. if ( status == ZFailure )
  1341. {
  1342. // Unsupported message
  1343. if ( inMsg.hdr.fc.manuSpecific )
  1344. status = ZCL_STATUS_UNSUP_MANU_CLUSTER_COMMAND;
  1345. else
  1346. status = ZCL_STATUS_UNSUP_CLUSTER_COMMAND;
  1347. }
  1348. }
  1349. if ( UNICAST_MSG( inMsg.msg ) && inMsg.hdr.fc.disableDefaultRsp == 0 )
  1350. {
  1351. // Send a Default Response command back
  1352. defautlRspCmd.statusCode = status;
  1353. defautlRspCmd.commandID = inMsg.hdr.commandID;
  1354. zcl_SendDefaultRspCmd( inMsg.msg->endPoint, &(inMsg.msg->srcAddr),
  1355. inMsg.msg->clusterId, &defautlRspCmd,
  1356. ZCL_FRAME_SERVER_CLIENT_DIR, true, inMsg.hdr.transSeqNum );
  1357. }
  1358. }
  1359. /*********************************************************************
  1360. * @fn zclParseHdr
  1361. *
  1362. * @brief Parse header of the ZCL format
  1363. *
  1364. * @param hdr - place to put the frame control information
  1365. * @param pData - incoming buffer to parse
  1366. *
  1367. * @return pointer past the header
  1368. */
  1369. uint8 *zclParseHdr( zclFrameHdr_t *hdr, uint8 *pData )
  1370. {
  1371. // Clear the header
  1372. osal_memset( (uint8 *)hdr, 0, sizeof ( zclFrameHdr_t ) );
  1373. // Parse the Frame Control
  1374. hdr->fc.type = zcl_FCType( *pData );
  1375. hdr->fc.manuSpecific = zcl_FCManuSpecific( *pData ) ? 1 : 0;
  1376. if ( zcl_FCDirection( *pData ) )
  1377. hdr->fc.direction = ZCL_FRAME_SERVER_CLIENT_DIR;
  1378. else
  1379. hdr->fc.direction = ZCL_FRAME_CLIENT_SERVER_DIR;
  1380. hdr->fc.disableDefaultRsp = zcl_FCDisableDefaultRsp( *pData ) ? 1 : 0;
  1381. pData++; // move past the frame control field
  1382. // parse the manfacturer code
  1383. if ( hdr->fc.manuSpecific )
  1384. {
  1385. hdr->manuCode = BUILD_UINT16( pData[0], pData[1] );
  1386. pData += 2;
  1387. }
  1388. // parse the Transaction Sequence Number
  1389. hdr->transSeqNum = *pData++;
  1390. // parse the Cluster's command ID
  1391. hdr->commandID = *pData++;
  1392. // Should point to the frame payload
  1393. return ( pData );
  1394. }
  1395. /*********************************************************************
  1396. * @fn zclBuildHdr
  1397. *
  1398. * @brief Build header of the ZCL format
  1399. *
  1400. * @param hdr - outgoing header information
  1401. * @param pData - outgoing header space
  1402. *
  1403. * @return pointer past the header
  1404. */
  1405. static uint8 *zclBuildHdr( zclFrameHdr_t *hdr, uint8 *pData )
  1406. {
  1407. // Build the Frame Control byte
  1408. *pData = hdr->fc.type;
  1409. *pData |= hdr->fc.manuSpecific << 2;
  1410. *pData |= hdr->fc.direction << 3;
  1411. *pData |= hdr->fc.disableDefaultRsp << 4;
  1412. pData++; // move past the frame control field
  1413. // Add the manfacturer code
  1414. if ( hdr->fc.manuSpecific )
  1415. {
  1416. *pData++ = LO_UINT16( hdr->manuCode );
  1417. *pData++ = HI_UINT16( hdr->manuCode );
  1418. }
  1419. // Add the Transaction Sequence Number
  1420. *pData++ = hdr->transSeqNum;
  1421. // Add the Cluster's command ID
  1422. *pData++ = hdr->commandID;
  1423. // Should point to the frame payload
  1424. return ( pData );
  1425. }
  1426. /*********************************************************************
  1427. * @fn zclCalcHdrSize
  1428. *
  1429. * @brief Calculate the number of bytes needed for an outgoing
  1430. * ZCL header.
  1431. *
  1432. * @param hdr - outgoing header information
  1433. *
  1434. * @return returns the number of bytes needed
  1435. */
  1436. static uint8 zclCalcHdrSize( zclFrameHdr_t *hdr )
  1437. {
  1438. uint8 needed = (1 + 1 + 1); // frame control + transaction seq num + cmd ID
  1439. // Add the manfacturer code
  1440. if ( hdr->fc.manuSpecific )
  1441. needed += 2;
  1442. return ( needed );
  1443. }
  1444. /*********************************************************************
  1445. * @fn zclFindPlugin
  1446. *
  1447. * @brief Find the right plugin for a cluster ID
  1448. *
  1449. * @param clusterID - cluster ID to look for
  1450. * @param profileID - profile ID
  1451. *
  1452. * @return pointer to plugin, NULL if not found
  1453. */
  1454. static zclLibPlugin_t *zclFindPlugin( uint16 clusterID, uint16 profileID )
  1455. {
  1456. zclLibPlugin_t *pLoop;
  1457. (void)profileID; // Intentionally unreferenced parameter
  1458. if ( clusterID != ZCL_INVALID_CLUSTER_ID )
  1459. {
  1460. pLoop = plugins;
  1461. while ( pLoop != NULL )
  1462. {
  1463. if ( clusterID >= pLoop->startClusterID && clusterID <= pLoop->endClusterID )
  1464. return ( pLoop );
  1465. pLoop = pLoop->next;
  1466. }
  1467. }
  1468. return ( (zclLibPlugin_t *)NULL );
  1469. }
  1470. /*********************************************************************
  1471. * @fn zclFindAttrRec
  1472. *
  1473. * @brief Find the attribute record that matchs the parameters
  1474. *
  1475. * @param endpoint - Application's endpoint
  1476. * @param clusterID - cluster ID
  1477. * @param attrId - attribute looking for
  1478. *
  1479. * @return TRUE if record found. FALSE, otherwise.
  1480. */
  1481. uint8 zclFindAttrRec( uint8 endpoint, uint16 clusterID, uint16 attrId, zclAttrRec_t *pAttr )
  1482. {
  1483. uint8 x;
  1484. zclAttrRecsList *pLoop;
  1485. pLoop = attrList;
  1486. while ( pLoop != NULL )
  1487. {
  1488. if ( pLoop->endpoint == endpoint )
  1489. {
  1490. for ( x = 0; x < pLoop->numAttributes; x++ )
  1491. {
  1492. if ( pLoop->attrs[x].clusterID == clusterID && pLoop->attrs[x].attr.attrId == attrId )
  1493. {
  1494. *pAttr = pLoop->attrs[x];
  1495. return ( TRUE ); // EMBEDDED RETURN
  1496. }
  1497. }
  1498. }
  1499. pLoop = pLoop->next;
  1500. }
  1501. return ( FALSE );
  1502. }
  1503. /*********************************************************************
  1504. * @fn zclFindClusterOption
  1505. *
  1506. * @brief Find the option record that matchs the cluster id
  1507. *
  1508. * @param endpoint - Application's endpoint
  1509. * @param clusterID - cluster ID looking for
  1510. *
  1511. * @return pointer to clutser option, NULL if not found
  1512. */
  1513. static zclOptionRec_t *zclFindClusterOption( uint8 endpoint, uint16 clusterID )
  1514. {
  1515. uint8 x;
  1516. zclClusterOptionList *pLoop;
  1517. pLoop = clusterOptionList;
  1518. while ( pLoop != NULL )
  1519. {
  1520. if ( pLoop->endpoint == endpoint )
  1521. {
  1522. for ( x = 0; x < pLoop->numOptions; x++ )
  1523. {
  1524. if ( pLoop->options[x].clusterID == clusterID )
  1525. return ( &(pLoop->options[x]) ); // EMBEDDED RETURN
  1526. }
  1527. }
  1528. pLoop = pLoop->next;
  1529. }
  1530. return ( NULL );
  1531. }
  1532. /*********************************************************************
  1533. * @fn zclGetClusterOption
  1534. *
  1535. * @brief Get the option record that matchs the cluster id
  1536. *
  1537. * @param endpoint - Application's endpoint
  1538. * @param clusterID - cluster ID looking for
  1539. *
  1540. * @return clutser option, AF_TX_OPTIONS_NONE if not found
  1541. */
  1542. static uint8 zclGetClusterOption( uint8 endpoint, uint16 clusterID )
  1543. {
  1544. uint8 option;
  1545. zclOptionRec_t *pOption;
  1546. pOption = zclFindClusterOption( endpoint, clusterID );
  1547. if ( pOption != NULL )
  1548. {
  1549. option = pOption->option;
  1550. if ( !ZG_SECURE_ENABLED )
  1551. option &= (AF_EN_SECURITY ^ 0xFF); // make sure Application Link Key security is off
  1552. return ( option ); // EMBEDDED RETURN
  1553. }
  1554. return ( AF_TX_OPTIONS_NONE );
  1555. }
  1556. /*********************************************************************
  1557. * @fn zclSetSecurityOption
  1558. *
  1559. * @brief Set the security option for the cluster id
  1560. *
  1561. * @param endpoint - Application's endpoint
  1562. * @param clusterID - cluster ID looking for
  1563. * @param enable - whether to enable (TRUE) or disable (FALSE) security option
  1564. *
  1565. * @return none
  1566. */
  1567. static void zclSetSecurityOption( uint8 endpoint, uint16 clusterID, uint8 enable )
  1568. {
  1569. zclOptionRec_t *pOption;
  1570. pOption = zclFindClusterOption( endpoint, clusterID );
  1571. if ( pOption != NULL )
  1572. {
  1573. if ( enable )
  1574. pOption->option |= AF_EN_SECURITY;
  1575. else
  1576. pOption->option &= (AF_EN_SECURITY ^ 0xFF);
  1577. }
  1578. }
  1579. #ifdef ZCL_DISCOVER
  1580. /*********************************************************************
  1581. * @fn zclFindNextAttrRec
  1582. *
  1583. * @brief Find the attribute (or next) record that matchs the parameters
  1584. *
  1585. * @param endpoint - Application's endpoint
  1586. * @param clusterID - cluster ID
  1587. * @param attr - attribute looking for
  1588. *
  1589. * @return pointer to attribute record, NULL if not found
  1590. */
  1591. static uint8 zclFindNextAttrRec( uint8 endpoint, uint16 clusterID,
  1592. uint16 *attrId, zclAttrRec_t *pAttr )
  1593. {
  1594. uint16 x;
  1595. zclAttrRecsList *pLoop;
  1596. pLoop = attrList;
  1597. while ( pLoop != NULL )
  1598. {
  1599. if ( pLoop->endpoint == endpoint )
  1600. {
  1601. for ( x = 0; x < pLoop->numAttributes; x++ )
  1602. {
  1603. if ( pLoop->attrs[x].clusterID == clusterID && pLoop->attrs[x].attr.attrId >= *attrId )
  1604. {
  1605. *pAttr = pLoop->attrs[x];
  1606. // Update attribute ID
  1607. *attrId = pAttr->attr.attrId;
  1608. return ( TRUE ); // EMBEDDED RETURN
  1609. }
  1610. }
  1611. }
  1612. pLoop = pLoop->next;
  1613. }
  1614. return ( FALSE );
  1615. }
  1616. #endif // ZCL_DISCOVER
  1617. #if defined(ZCL_READ) || defined(ZCL_WRITE) || defined(ZCL_REPORT)
  1618. /*********************************************************************
  1619. * @fn zclSerializeData
  1620. *
  1621. * @brief Builds a buffer from the attribute data to sent out over
  1622. * the air.
  1623. *
  1624. * @param dataType - data types defined in zcl.h
  1625. * @param attrData - pointer to the attribute data
  1626. * @param buf - where to put the serialized data
  1627. *
  1628. * @return none
  1629. */
  1630. static void zclSerializeData( uint8 dataType, void *attrData, uint8 *buf )
  1631. {
  1632. uint8 *pStr;
  1633. uint8 len;
  1634. switch ( dataType )
  1635. {
  1636. case ZCL_DATATYPE_DATA8:
  1637. case ZCL_DATATYPE_BOOLEAN:
  1638. case ZCL_DATATYPE_BITMAP8:
  1639. case ZCL_DATATYPE_INT8:
  1640. case ZCL_DATATYPE_UINT8:
  1641. case ZCL_DATATYPE_ENUM8:
  1642. *buf = *((uint8 *)attrData);
  1643. break;
  1644. case ZCL_DATATYPE_DATA16:
  1645. case ZCL_DATATYPE_BITMAP16:
  1646. case ZCL_DATATYPE_UINT16:
  1647. case ZCL_DATATYPE_INT16:
  1648. case ZCL_DATATYPE_ENUM16:
  1649. case ZCL_DATATYPE_SEMI_PREC:
  1650. case ZCL_DATATYPE_CLUSTER_ID:
  1651. case ZCL_DATATYPE_ATTR_ID:
  1652. *buf++ = LO_UINT16( *((uint16*)attrData) );
  1653. *buf++ = HI_UINT16( *((uint16*)attrData) );
  1654. break;
  1655. case ZCL_DATATYPE_DATA24:
  1656. case ZCL_DATATYPE_BITMAP24:
  1657. case ZCL_DATATYPE_UINT24:
  1658. case ZCL_DATATYPE_INT24:
  1659. *buf++ = BREAK_UINT32( *((uint32*)attrData), 0 );
  1660. *buf++ = BREAK_UINT32( *((uint32*)attrData), 1 );
  1661. *buf++ = BREAK_UINT32( *((uint32*)attrData), 2 );
  1662. break;
  1663. case ZCL_DATATYPE_DATA32:
  1664. case ZCL_DATATYPE_BITMAP32:
  1665. case ZCL_DATATYPE_UINT32:
  1666. case ZCL_DATATYPE_INT32:
  1667. case ZCL_DATATYPE_SINGLE_PREC:
  1668. case ZCL_DATATYPE_TOD:
  1669. case ZCL_DATATYPE_DATE:
  1670. case ZCL_DATATYPE_UTC:
  1671. case ZCL_DATATYPE_BAC_OID:
  1672. buf = osal_buffer_uint32( buf, *((uint32*)attrData) );
  1673. break;
  1674. case ZCL_DATATYPE_UINT40:
  1675. pStr = (uint8*)attrData;
  1676. osal_memcpy( buf, pStr, 5 );
  1677. break;
  1678. case ZCL_DATATYPE_UINT48:
  1679. pStr = (uint8*)attrData;
  1680. osal_memcpy( buf, pStr, 6 );
  1681. break;
  1682. case ZCL_DATATYPE_IEEE_ADDR:
  1683. pStr = (uint8*)attrData;
  1684. osal_memcpy( buf, pStr, 8 );
  1685. break;
  1686. case ZCL_DATATYPE_CHAR_STR:
  1687. case ZCL_DATATYPE_OCTET_STR:
  1688. pStr = (uint8*)attrData;
  1689. len = *pStr++;
  1690. *buf++ = len;
  1691. osal_memcpy( buf, pStr, len );
  1692. break;
  1693. case ZCL_DATATYPE_NO_DATA:
  1694. case ZCL_DATATYPE_UNKNOWN:
  1695. // Fall through
  1696. default:
  1697. break;
  1698. }
  1699. }
  1700. #endif // ZCL_READ || ZCL_WRITE || ZCL_REPORT
  1701. #ifdef ZCL_REPORT
  1702. /*********************************************************************
  1703. * @fn zclAnalogDataType
  1704. *
  1705. * @brief Checks to see if Data Type is Analog
  1706. *
  1707. * @param dataType - data type
  1708. *
  1709. * @return TRUE if data type is analog
  1710. */
  1711. uint8 zclAnalogDataType( uint8 dataType )
  1712. {
  1713. uint8 analog;
  1714. switch ( dataType )
  1715. {
  1716. case ZCL_DATATYPE_UINT8:
  1717. case ZCL_DATATYPE_UINT16:
  1718. case ZCL_DATATYPE_UINT24:
  1719. case ZCL_DATATYPE_UINT32:
  1720. case ZCL_DATATYPE_UINT40:
  1721. case ZCL_DATATYPE_UINT48:
  1722. case ZCL_DATATYPE_INT8:
  1723. case ZCL_DATATYPE_INT16:
  1724. case ZCL_DATATYPE_INT24:
  1725. case ZCL_DATATYPE_INT32:
  1726. case ZCL_DATATYPE_SEMI_PREC:
  1727. case ZCL_DATATYPE_SINGLE_PREC:
  1728. case ZCL_DATATYPE_DOUBLE_PREC:
  1729. case ZCL_DATATYPE_TOD:
  1730. case ZCL_DATATYPE_DATE:
  1731. case ZCL_DATATYPE_UTC:
  1732. analog = TRUE;
  1733. break;
  1734. default:
  1735. analog = FALSE;
  1736. break;
  1737. }
  1738. return ( analog );
  1739. }
  1740. /*********************************************************************
  1741. * @fn zcl_BuildAnalogData
  1742. *
  1743. * @brief Build an analog arribute out of sequential bytes.
  1744. *
  1745. * @param dataType - type of data
  1746. * @param pData - pointer to data
  1747. * @param pBuf - where to put the data
  1748. *
  1749. * @return none
  1750. */
  1751. static void zcl_BuildAnalogData( uint8 dataType, uint8 *pData, uint8 *pBuf)
  1752. {
  1753. switch ( dataType )
  1754. {
  1755. case ZCL_DATATYPE_UINT8:
  1756. case ZCL_DATATYPE_INT8:
  1757. *pData = *pBuf;
  1758. break;
  1759. case ZCL_DATATYPE_UINT16:
  1760. case ZCL_DATATYPE_INT16:
  1761. case ZCL_DATATYPE_SEMI_PREC:
  1762. *((uint16*)pData) = BUILD_UINT16( pBuf[0], pBuf[1] );
  1763. break;
  1764. case ZCL_DATATYPE_UINT24:
  1765. case ZCL_DATATYPE_INT24:
  1766. *((uint32*)pData) = osal_build_uint32( pBuf, 3 );
  1767. break;
  1768. case ZCL_DATATYPE_UINT32:
  1769. case ZCL_DATATYPE_INT32:
  1770. case ZCL_DATATYPE_SINGLE_PREC:
  1771. case ZCL_DATATYPE_TOD:
  1772. case ZCL_DATATYPE_DATE:
  1773. case ZCL_DATATYPE_UTC:
  1774. *((uint32*)pData) = osal_build_uint32( pBuf, 4 );
  1775. break;
  1776. case ZCL_DATATYPE_DOUBLE_PREC:
  1777. *pData = 0;
  1778. break;
  1779. default:
  1780. break;
  1781. }
  1782. }
  1783. #endif // ZCL_REPORT
  1784. /*********************************************************************
  1785. * @fn zclGetDataTypeLength
  1786. *
  1787. * @brief Return the length of the datatype in length.
  1788. * NOTE: Should not be called for ZCL_DATATYPE_OCTECT_STR or
  1789. * ZCL_DATATYPE_CHAR_STR data types.
  1790. *
  1791. * @param dataType - data type
  1792. *
  1793. * @return length of data
  1794. */
  1795. uint8 zclGetDataTypeLength( uint8 dataType )
  1796. {
  1797. uint8 len;
  1798. switch ( dataType )
  1799. {
  1800. case ZCL_DATATYPE_DATA8:
  1801. case ZCL_DATATYPE_BOOLEAN:
  1802. case ZCL_DATATYPE_BITMAP8:
  1803. case ZCL_DATATYPE_INT8:
  1804. case ZCL_DATATYPE_UINT8:
  1805. case ZCL_DATATYPE_ENUM8:
  1806. len = 1;
  1807. break;
  1808. case ZCL_DATATYPE_DATA16:
  1809. case ZCL_DATATYPE_BITMAP16:
  1810. case ZCL_DATATYPE_UINT16:
  1811. case ZCL_DATATYPE_INT16:
  1812. case ZCL_DATATYPE_ENUM16:
  1813. case ZCL_DATATYPE_SEMI_PREC:
  1814. case ZCL_DATATYPE_CLUSTER_ID:
  1815. case ZCL_DATATYPE_ATTR_ID:
  1816. len = 2;
  1817. break;
  1818. case ZCL_DATATYPE_DATA24:
  1819. case ZCL_DATATYPE_BITMAP24:
  1820. case ZCL_DATATYPE_UINT24:
  1821. case ZCL_DATATYPE_INT24:
  1822. len = 3;
  1823. break;
  1824. case ZCL_DATATYPE_DATA32:
  1825. case ZCL_DATATYPE_BITMAP32:
  1826. case ZCL_DATATYPE_UINT32:
  1827. case ZCL_DATATYPE_INT32:
  1828. case ZCL_DATATYPE_SINGLE_PREC:
  1829. case ZCL_DATATYPE_TOD:
  1830. case ZCL_DATATYPE_DATE:
  1831. case ZCL_DATATYPE_UTC:
  1832. case ZCL_DATATYPE_BAC_OID:
  1833. len = 4;
  1834. break;
  1835. case ZCL_DATATYPE_UINT40:
  1836. len = 5;
  1837. break;
  1838. case ZCL_DATATYPE_UINT48:
  1839. len = 6;
  1840. break;
  1841. case ZCL_DATATYPE_DOUBLE_PREC:
  1842. case ZCL_DATATYPE_IEEE_ADDR:
  1843. len = 8;
  1844. break;
  1845. case ZCL_DATATYPE_NO_DATA:
  1846. case ZCL_DATATYPE_UNKNOWN:
  1847. // Fall through
  1848. default:
  1849. len = 0;
  1850. break;
  1851. }
  1852. return ( len );
  1853. }
  1854. /*********************************************************************
  1855. * @fn zclGetAttrDataLength
  1856. *
  1857. * @brief Return the length of the attribute.
  1858. *
  1859. * @param dataType - data type
  1860. * @param pData - pointer to data
  1861. *
  1862. * @return returns atrribute lentgh
  1863. */
  1864. uint8 zclGetAttrDataLength( uint8 dataType, uint8 *pData)
  1865. {
  1866. uint8 dataLen = 0;
  1867. if ( dataType == ZCL_DATATYPE_CHAR_STR || dataType == ZCL_DATATYPE_OCTET_STR )
  1868. {
  1869. dataLen = *pData + 1; // string length + 1 for length field
  1870. }
  1871. else
  1872. {
  1873. dataLen = zclGetDataTypeLength( dataType );
  1874. }
  1875. return ( dataLen );
  1876. }
  1877. /*********************************************************************
  1878. * @fn zclReadAttrData
  1879. *
  1880. * @brief Read the attribute's current value into pAttrData.
  1881. *
  1882. * @param pAttrData - where to put attribute data
  1883. * @param pAttr - pointer to attribute
  1884. *
  1885. * @return Success
  1886. */
  1887. uint8 zclReadAttrData( uint8 *pAttrData, zclAttrRec_t *pAttr )
  1888. {
  1889. uint8 dataLen;
  1890. dataLen = zclGetAttrDataLength( pAttr->attr.dataType, (uint8*)(pAttr->attr.dataPtr) );
  1891. osal_memcpy( pAttrData, pAttr->attr.dataPtr, dataLen );
  1892. return ( ZCL_STATUS_SUCCESS );
  1893. }
  1894. #ifdef ZCL_WRITE
  1895. /*********************************************************************
  1896. * @fn zclWriteAttrData
  1897. *
  1898. * @brief Write the received data.
  1899. *
  1900. * @param pAttr - where to write data to
  1901. * @param pWriteRec - data to be written
  1902. *
  1903. * @return Successful if data was written
  1904. */
  1905. static uint8 zclWriteAttrData( zclAttrRec_t *pAttr, zclWriteRec_t *pWriteRec )
  1906. {
  1907. uint8 len;
  1908. if ( zcl_AccessCtrlWrite( pAttr->attr.accessControl ) )
  1909. {
  1910. if ( zcl_ValidateAttrDataCB && !zcl_ValidateAttrDataCB( pAttr, pWriteRec ) )
  1911. return ( ZCL_STATUS_INVALID_VALUE );
  1912. len = zclGetAttrDataLength( pAttr->attr.dataType, pWriteRec->attrData );
  1913. osal_memcpy( pAttr->attr.dataPtr, pWriteRec->attrData, len );
  1914. return ( ZCL_STATUS_SUCCESS );
  1915. }
  1916. return ( ZCL_STATUS_READ_ONLY );
  1917. }
  1918. #endif // ZCL_WRITE
  1919. #ifdef ZCL_READ
  1920. /*********************************************************************
  1921. * @fn zclParseInReadCmd
  1922. *
  1923. * @brief Parse the "Profile" Read Commands
  1924. *
  1925. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  1926. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  1927. *
  1928. * @param pCmd - pointer to incoming data to parse
  1929. *
  1930. * @return pointer to the parsed command structure
  1931. */
  1932. void *zclParseInReadCmd( zclParseCmd_t *pCmd )
  1933. {
  1934. zclReadCmd_t *readCmd;
  1935. uint8 *pBuf = pCmd->pData;
  1936. readCmd = (zclReadCmd_t *)osal_mem_alloc( sizeof ( zclReadCmd_t ) + pCmd->dataLen );
  1937. if ( readCmd != NULL )
  1938. {
  1939. uint8 i;
  1940. readCmd->numAttr = pCmd->dataLen / 2; // Atrribute ID
  1941. for ( i = 0; i < readCmd->numAttr; i++ )
  1942. {
  1943. readCmd->attrID[i] = BUILD_UINT16( pBuf[0], pBuf[1] );
  1944. pBuf += 2;
  1945. }
  1946. }
  1947. return ( (void *)readCmd );
  1948. }
  1949. /*********************************************************************
  1950. * @fn zclParseInReadRspCmd
  1951. *
  1952. * @brief Parse the "Profile" Read Response Commands
  1953. *
  1954. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  1955. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  1956. *
  1957. * @param pCmd - pointer to incoming data to parse
  1958. *
  1959. * @return pointer to the parsed command structure
  1960. */
  1961. static void *zclParseInReadRspCmd( zclParseCmd_t *pCmd )
  1962. {
  1963. zclReadRspCmd_t *readRspCmd;
  1964. zclReadRspStatus_t *statusRec;
  1965. uint8 *pBuf = pCmd->pData;
  1966. uint8 *dataPtr;
  1967. uint8 numAttr = 0;
  1968. uint8 hdrLen;
  1969. uint8 dataLen = 0;
  1970. uint8 attrDataLen;
  1971. uint8 dataType;
  1972. uint8 status;
  1973. uint8 i;
  1974. // find out the number of attributes and the length of attribute data
  1975. while ( pBuf < ( pCmd->pData + pCmd->dataLen ) )
  1976. {
  1977. numAttr++;
  1978. pBuf += 2; // move pass attribute id
  1979. status = *pBuf++;
  1980. if ( status == ZCL_STATUS_SUCCESS )
  1981. {
  1982. dataType = *pBuf++;
  1983. attrDataLen = zclGetAttrDataLength( dataType, pBuf );
  1984. pBuf += attrDataLen; // move pass attribute data
  1985. // add padding if needed
  1986. if ( PADDING_NEEDED( attrDataLen ) )
  1987. attrDataLen++;
  1988. dataLen += attrDataLen;
  1989. }
  1990. }
  1991. // calculate the length of the response header
  1992. hdrLen = sizeof( zclReadRspCmd_t ) + ( numAttr * sizeof( zclReadRspStatus_t ) );
  1993. readRspCmd = (zclReadRspCmd_t *)osal_mem_alloc( hdrLen + dataLen );
  1994. if ( readRspCmd != NULL )
  1995. {
  1996. pBuf = pCmd->pData;
  1997. dataPtr = (uint8 *)( (uint8 *)readRspCmd + hdrLen );
  1998. readRspCmd->numAttr = numAttr;
  1999. for ( i = 0; i < numAttr; i++ )
  2000. {
  2001. statusRec = &(readRspCmd->attrList[i]);
  2002. statusRec->attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2003. pBuf += 2;
  2004. statusRec->status = *pBuf++;
  2005. if ( statusRec->status == ZCL_STATUS_SUCCESS )
  2006. {
  2007. statusRec->dataType = *pBuf++;
  2008. attrDataLen = zclGetAttrDataLength( statusRec->dataType, pBuf );
  2009. osal_memcpy( dataPtr, pBuf, attrDataLen);
  2010. statusRec->data = dataPtr;
  2011. pBuf += attrDataLen; // move pass attribute data
  2012. // advance attribute data pointer
  2013. if ( PADDING_NEEDED( attrDataLen ) )
  2014. attrDataLen++;
  2015. dataPtr += attrDataLen;
  2016. }
  2017. }
  2018. }
  2019. return ( (void *)readRspCmd );
  2020. }
  2021. #endif // ZCL_READ
  2022. #ifdef ZCL_WRITE
  2023. /*********************************************************************
  2024. * @fn zclParseInWriteCmd
  2025. *
  2026. * @brief Parse the "Profile" Write, Write Undivided and Write No
  2027. * Response Commands
  2028. *
  2029. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2030. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2031. *
  2032. * @param pCmd - pointer to incoming data to parse
  2033. *
  2034. * @return pointer to the parsed command structure
  2035. */
  2036. void *zclParseInWriteCmd( zclParseCmd_t *pCmd )
  2037. {
  2038. zclWriteCmd_t *writeCmd;
  2039. zclWriteRec_t *statusRec;
  2040. uint8 *pBuf = pCmd->pData;
  2041. uint8 attrDataLen;
  2042. uint8 *dataPtr;
  2043. uint8 numAttr = 0;
  2044. uint8 hdrLen;
  2045. uint8 dataLen = 0;
  2046. uint8 dataType;
  2047. uint8 i;
  2048. // find out the number of attributes and the length of attribute data
  2049. while ( pBuf < ( pCmd->pData + pCmd->dataLen ) )
  2050. {
  2051. numAttr++;
  2052. pBuf += 2; // move pass attribute id
  2053. dataType = *pBuf++;
  2054. attrDataLen = zclGetAttrDataLength( dataType, pBuf );
  2055. pBuf += attrDataLen; // move pass attribute data
  2056. // add padding if needed
  2057. if ( PADDING_NEEDED( attrDataLen ) )
  2058. attrDataLen++;
  2059. dataLen += attrDataLen;
  2060. }
  2061. // calculate the length of the response header
  2062. hdrLen = sizeof( zclWriteCmd_t ) + ( numAttr * sizeof( zclWriteRec_t ) );
  2063. writeCmd = (zclWriteCmd_t *)osal_mem_alloc( hdrLen + dataLen );
  2064. if ( writeCmd != NULL )
  2065. {
  2066. pBuf = pCmd->pData;
  2067. dataPtr = (uint8 *)( (uint8 *)writeCmd + hdrLen );
  2068. writeCmd->numAttr = numAttr;
  2069. for ( i = 0; i < numAttr; i++ )
  2070. {
  2071. statusRec = &(writeCmd->attrList[i]);
  2072. statusRec->attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2073. pBuf += 2;
  2074. statusRec->dataType = *pBuf++;
  2075. attrDataLen = zclGetAttrDataLength( statusRec->dataType, pBuf );
  2076. osal_memcpy( dataPtr, pBuf, attrDataLen);
  2077. statusRec->attrData = dataPtr;
  2078. pBuf += attrDataLen; // move pass attribute data
  2079. // advance attribute data pointer
  2080. if ( PADDING_NEEDED( attrDataLen ) )
  2081. attrDataLen++;
  2082. dataPtr += attrDataLen;
  2083. }
  2084. }
  2085. return ( (void *)writeCmd );
  2086. }
  2087. /*********************************************************************
  2088. * @fn zclParseInWriteRspCmd
  2089. *
  2090. * @brief Parse the "Profile" Write Response Commands
  2091. *
  2092. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2093. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2094. *
  2095. * @param pCmd - pointer to incoming data to parse
  2096. *
  2097. * @return pointer to the parsed command structure
  2098. */
  2099. static void *zclParseInWriteRspCmd( zclParseCmd_t *pCmd )
  2100. {
  2101. zclWriteRspCmd_t *writeRspCmd;
  2102. uint8 *pBuf = pCmd->pData;
  2103. uint8 i = 0;
  2104. writeRspCmd = (zclWriteRspCmd_t *)osal_mem_alloc( sizeof ( zclWriteRspCmd_t ) + pCmd->dataLen );
  2105. if ( writeRspCmd != NULL )
  2106. {
  2107. if ( pCmd->dataLen == 1 )
  2108. {
  2109. // special case when all writes were successfull
  2110. writeRspCmd->attrList[i++].status = *pBuf;
  2111. }
  2112. else
  2113. {
  2114. while ( pBuf < ( pCmd->pData + pCmd->dataLen ) )
  2115. {
  2116. writeRspCmd->attrList[i].status = *pBuf++;
  2117. writeRspCmd->attrList[i++].attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2118. pBuf += 2;
  2119. }
  2120. }
  2121. writeRspCmd->numAttr = i;
  2122. }
  2123. return ( (void *)writeRspCmd );
  2124. }
  2125. #endif // ZCL_WRITE
  2126. #ifdef ZCL_REPORT
  2127. /*********************************************************************
  2128. * @fn zclParseInConfigReportCmd
  2129. *
  2130. * @brief Parse the "Profile" Configure Reporting Command
  2131. *
  2132. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2133. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2134. *
  2135. * @param pCmd - pointer to incoming data to parse
  2136. *
  2137. * @return pointer to the parsed command structure
  2138. */
  2139. void *zclParseInConfigReportCmd( zclParseCmd_t *pCmd )
  2140. {
  2141. zclCfgReportCmd_t *cfgReportCmd;
  2142. zclCfgReportRec_t *reportRec;
  2143. uint8 *pBuf = pCmd->pData;
  2144. uint8 *dataPtr;
  2145. uint8 numAttr = 0;
  2146. uint8 direction;
  2147. uint8 dataType;
  2148. uint8 hdrLen;
  2149. uint8 dataLen = 0;
  2150. uint8 reportChangeLen; // length of Reportable Change field
  2151. uint8 i;
  2152. // Calculate the length of the Request command
  2153. while ( pBuf < ( pCmd->pData + pCmd->dataLen ) )
  2154. {
  2155. numAttr++;
  2156. direction = *pBuf++;
  2157. pBuf += 2; // move pass the attribute ID
  2158. // Is there a Reportable Change field?
  2159. if ( direction == ZCL_SEND_ATTR_REPORTS )
  2160. {
  2161. dataType = *pBuf++;
  2162. pBuf += 4; // move pass the Min and Max Reporting Intervals
  2163. // For attributes of 'discrete' data types this field is omitted
  2164. if ( zclAnalogDataType( dataType ) )
  2165. {
  2166. reportChangeLen = zclGetDataTypeLength( dataType );
  2167. pBuf += reportChangeLen;
  2168. // add padding if needed
  2169. if ( PADDING_NEEDED( reportChangeLen ) )
  2170. reportChangeLen++;
  2171. dataLen += reportChangeLen;
  2172. }
  2173. }
  2174. else
  2175. {
  2176. pBuf += 2; // move pass the Timeout Period
  2177. }
  2178. } // while loop
  2179. hdrLen = sizeof( zclCfgReportCmd_t ) + ( numAttr * sizeof( zclCfgReportRec_t ) );
  2180. cfgReportCmd = (zclCfgReportCmd_t *)osal_mem_alloc( hdrLen + dataLen );
  2181. if ( cfgReportCmd != NULL )
  2182. {
  2183. pBuf = pCmd->pData;
  2184. dataPtr = (uint8 *)( (uint8 *)cfgReportCmd + hdrLen );
  2185. cfgReportCmd->numAttr = numAttr;
  2186. for ( i = 0; i < numAttr; i++ )
  2187. {
  2188. reportRec = &(cfgReportCmd->attrList[i]);
  2189. osal_memset( reportRec, 0, sizeof( zclCfgReportRec_t ) );
  2190. reportRec->direction = *pBuf++;
  2191. reportRec->attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2192. pBuf += 2;
  2193. if ( reportRec->direction == ZCL_SEND_ATTR_REPORTS )
  2194. {
  2195. // Attribute to be reported
  2196. reportRec->dataType = *pBuf++;
  2197. reportRec->minReportInt = BUILD_UINT16( pBuf[0], pBuf[1] );
  2198. pBuf += 2;
  2199. reportRec->maxReportInt = BUILD_UINT16( pBuf[0], pBuf[1] );
  2200. pBuf += 2;
  2201. // For attributes of 'discrete' data types this field is omitted
  2202. if ( zclAnalogDataType( reportRec->dataType ) )
  2203. {
  2204. zcl_BuildAnalogData( reportRec->dataType, dataPtr, pBuf);
  2205. reportRec->reportableChange = dataPtr;
  2206. reportChangeLen = zclGetDataTypeLength( reportRec->dataType );
  2207. pBuf += reportChangeLen;
  2208. // advance attribute data pointer
  2209. if ( PADDING_NEEDED( reportChangeLen ) )
  2210. reportChangeLen++;
  2211. dataPtr += reportChangeLen;
  2212. }
  2213. }
  2214. else
  2215. {
  2216. // Attribute reports to be received
  2217. reportRec->timeoutPeriod = BUILD_UINT16( pBuf[0], pBuf[1] );
  2218. pBuf += 2;
  2219. }
  2220. } // while loop
  2221. }
  2222. return ( (void *)cfgReportCmd );
  2223. }
  2224. /*********************************************************************
  2225. * @fn zclParseInConfigReportRspCmd
  2226. *
  2227. * @brief Parse the "Profile" Configure Reporting Response Command
  2228. *
  2229. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2230. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2231. *
  2232. * @param pCmd - pointer to incoming data to parse
  2233. *
  2234. * @return pointer to the parsed command structure
  2235. */
  2236. static void *zclParseInConfigReportRspCmd( zclParseCmd_t *pCmd )
  2237. {
  2238. zclCfgReportRspCmd_t *cfgReportRspCmd;
  2239. uint8 *pBuf = pCmd->pData;
  2240. uint8 numAttr;
  2241. uint8 i;
  2242. numAttr = pCmd->dataLen / ( 1 + 1 + 2 ); // Status + Direction + Attribute ID
  2243. cfgReportRspCmd = (zclCfgReportRspCmd_t *)osal_mem_alloc( sizeof( zclCfgReportRspCmd_t )
  2244. + ( numAttr * sizeof( zclCfgReportStatus_t ) ) );
  2245. if ( cfgReportRspCmd != NULL )
  2246. {
  2247. cfgReportRspCmd->numAttr = numAttr;
  2248. for ( i = 0; i < cfgReportRspCmd->numAttr; i++ )
  2249. {
  2250. cfgReportRspCmd->attrList[i].status = *pBuf++;
  2251. cfgReportRspCmd->attrList[i].direction = *pBuf++;
  2252. cfgReportRspCmd->attrList[i].attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2253. pBuf += 2;
  2254. }
  2255. }
  2256. return ( (void *)cfgReportRspCmd );
  2257. }
  2258. /*********************************************************************
  2259. * @fn zclParseInReadReportCfgCmd
  2260. *
  2261. * @brief Parse the "Profile" Read Reporting Configuration Command
  2262. *
  2263. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2264. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2265. *
  2266. * @param pCmd - pointer to incoming data to parse
  2267. *
  2268. * @return pointer to the parsed command structure
  2269. */
  2270. void *zclParseInReadReportCfgCmd( zclParseCmd_t *pCmd )
  2271. {
  2272. zclReadReportCfgCmd_t *readReportCfgCmd;
  2273. uint8 *pBuf = pCmd->pData;
  2274. uint8 numAttr;
  2275. uint8 i;
  2276. numAttr = pCmd->dataLen / ( 1 + 2 ); // Direction + Attribute ID
  2277. readReportCfgCmd = (zclReadReportCfgCmd_t *)osal_mem_alloc( sizeof( zclReadReportCfgCmd_t )
  2278. + ( numAttr * sizeof( zclReadReportCfgRec_t ) ) );
  2279. if ( readReportCfgCmd != NULL )
  2280. {
  2281. readReportCfgCmd->numAttr = numAttr;
  2282. for ( i = 0; i < readReportCfgCmd->numAttr; i++)
  2283. {
  2284. readReportCfgCmd->attrList[i].direction = *pBuf++;;
  2285. readReportCfgCmd->attrList[i].attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2286. pBuf += 2;
  2287. }
  2288. }
  2289. return ( (void *)readReportCfgCmd );
  2290. }
  2291. /*********************************************************************
  2292. * @fn zclParseInReadReportCfgRspCmd
  2293. *
  2294. * @brief Parse the "Profile" Read Reporting Configuration Response Command
  2295. *
  2296. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2297. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2298. *
  2299. * @param pCmd - pointer to incoming data to parse
  2300. *
  2301. * @return pointer to the parsed command structure
  2302. */
  2303. static void *zclParseInReadReportCfgRspCmd( zclParseCmd_t *pCmd )
  2304. {
  2305. zclReadReportCfgRspCmd_t *readReportCfgRspCmd;
  2306. zclReportCfgRspRec_t *reportRspRec;
  2307. uint8 reportChangeLen;
  2308. uint8 *pBuf = pCmd->pData;
  2309. uint8 *dataPtr;
  2310. uint8 numAttr = 0;
  2311. uint8 hdrLen;
  2312. uint8 dataLen = 0;
  2313. uint8 status;
  2314. uint8 direction;
  2315. uint8 dataType;
  2316. uint8 i;
  2317. // Calculate the length of the response command
  2318. while ( pBuf < ( pCmd->pData + pCmd->dataLen ) )
  2319. {
  2320. numAttr++;
  2321. status = *pBuf++;
  2322. direction = *pBuf++;
  2323. pBuf += 2; // move pass the attribute ID
  2324. if ( status == ZCL_STATUS_SUCCESS )
  2325. {
  2326. if ( direction == ZCL_SEND_ATTR_REPORTS )
  2327. {
  2328. dataType = *pBuf++;
  2329. pBuf += 4; // move pass the Min and Max Reporting Intervals
  2330. // For attributes of 'discrete' data types this field is omitted
  2331. if ( zclAnalogDataType( dataType ) )
  2332. {
  2333. reportChangeLen = zclGetDataTypeLength( dataType );
  2334. pBuf += reportChangeLen;
  2335. // add padding if needed
  2336. if ( PADDING_NEEDED( reportChangeLen ) )
  2337. reportChangeLen++;
  2338. dataLen += reportChangeLen;
  2339. }
  2340. }
  2341. else
  2342. {
  2343. pBuf += 2; // move pass the Timeout field
  2344. }
  2345. }
  2346. } // while loop
  2347. hdrLen = sizeof( zclReadReportCfgRspCmd_t ) + ( numAttr * sizeof( zclReportCfgRspRec_t ) );
  2348. readReportCfgRspCmd = (zclReadReportCfgRspCmd_t *)osal_mem_alloc( hdrLen + dataLen );
  2349. if ( readReportCfgRspCmd != NULL )
  2350. {
  2351. pBuf = pCmd->pData;
  2352. dataPtr = (uint8 *)( (uint8 *)readReportCfgRspCmd + hdrLen );
  2353. readReportCfgRspCmd->numAttr = numAttr;
  2354. for ( i = 0; i < numAttr; i++ )
  2355. {
  2356. reportRspRec = &(readReportCfgRspCmd->attrList[i]);
  2357. reportRspRec->status = *pBuf++;
  2358. reportRspRec->direction = *pBuf++;
  2359. reportRspRec->attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2360. pBuf += 2;
  2361. if ( reportRspRec->status == ZCL_STATUS_SUCCESS )
  2362. {
  2363. if ( reportRspRec->direction == ZCL_SEND_ATTR_REPORTS )
  2364. {
  2365. reportRspRec->dataType = *pBuf++;
  2366. reportRspRec->minReportInt = BUILD_UINT16( pBuf[0], pBuf[1] );
  2367. pBuf += 2;
  2368. reportRspRec->maxReportInt = BUILD_UINT16( pBuf[0], pBuf[1] );
  2369. pBuf += 2;
  2370. if ( zclAnalogDataType( reportRspRec->dataType ) )
  2371. {
  2372. zcl_BuildAnalogData( reportRspRec->dataType, dataPtr, pBuf);
  2373. reportRspRec->reportableChange = dataPtr;
  2374. reportChangeLen = zclGetDataTypeLength( reportRspRec->dataType );
  2375. pBuf += reportChangeLen;
  2376. // advance attribute data pointer
  2377. if ( PADDING_NEEDED( reportChangeLen ) )
  2378. reportChangeLen++;
  2379. dataPtr += reportChangeLen;
  2380. }
  2381. }
  2382. else
  2383. {
  2384. reportRspRec->timeoutPeriod = BUILD_UINT16( pBuf[0], pBuf[1] );
  2385. pBuf += 2;
  2386. }
  2387. }
  2388. }
  2389. }
  2390. return ( (void *)readReportCfgRspCmd );
  2391. }
  2392. /*********************************************************************
  2393. * @fn zclParseInReportCmd
  2394. *
  2395. * @brief Parse the "Profile" Report Command
  2396. *
  2397. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2398. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2399. *
  2400. * @param pCmd - pointer to incoming data to parse
  2401. *
  2402. * @return pointer to the parsed command structure
  2403. */
  2404. void *zclParseInReportCmd( zclParseCmd_t *pCmd )
  2405. {
  2406. zclReportCmd_t *reportCmd;
  2407. zclReport_t *reportRec;
  2408. uint8 *pBuf = pCmd->pData;
  2409. uint8 attrDataLen;
  2410. uint8 *dataPtr;
  2411. uint8 numAttr = 0;
  2412. uint8 hdrLen;
  2413. uint8 dataLen = 0;
  2414. uint8 dataType;
  2415. uint8 i;
  2416. // find out the number of attributes and the length of attribute data
  2417. while ( pBuf < ( pCmd->pData + pCmd->dataLen ) )
  2418. {
  2419. numAttr++;
  2420. pBuf += 2; // move pass attribute id
  2421. dataType = *pBuf++;
  2422. attrDataLen = zclGetAttrDataLength( dataType, pBuf );
  2423. pBuf += attrDataLen; // move pass attribute data
  2424. // add padding if needed
  2425. if ( PADDING_NEEDED( attrDataLen ) )
  2426. attrDataLen++;
  2427. dataLen += attrDataLen;
  2428. }
  2429. hdrLen = sizeof( zclReportCmd_t ) + ( numAttr * sizeof( zclReport_t ) );
  2430. reportCmd = (zclReportCmd_t *)osal_mem_alloc( hdrLen + dataLen );
  2431. if (reportCmd != NULL )
  2432. {
  2433. pBuf = pCmd->pData;
  2434. dataPtr = (uint8 *)( (uint8 *)reportCmd + hdrLen );
  2435. reportCmd->numAttr = numAttr;
  2436. for ( i = 0; i < numAttr; i++ )
  2437. {
  2438. reportRec = &(reportCmd->attrList[i]);
  2439. reportRec->attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2440. pBuf += 2;
  2441. reportRec->dataType = *pBuf++;
  2442. attrDataLen = zclGetAttrDataLength( reportRec->dataType, pBuf );
  2443. osal_memcpy( dataPtr, pBuf, attrDataLen );
  2444. reportRec->attrData = dataPtr;
  2445. pBuf += attrDataLen; // move pass attribute data
  2446. // advance attribute data pointer
  2447. if ( PADDING_NEEDED( attrDataLen ) )
  2448. attrDataLen++;
  2449. dataPtr += attrDataLen;
  2450. }
  2451. }
  2452. return ( (void *)reportCmd );
  2453. }
  2454. #endif // ZCL_REPORT
  2455. /*********************************************************************
  2456. * @fn zclParseInDefaultRspCmd
  2457. *
  2458. * @brief Parse the "Profile" Default Response Command
  2459. *
  2460. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2461. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2462. *
  2463. * @param pCmd - pointer to incoming data to parse
  2464. *
  2465. * @return pointer to the parsed command structure
  2466. */
  2467. static void *zclParseInDefaultRspCmd( zclParseCmd_t *pCmd )
  2468. {
  2469. zclDefaultRspCmd_t *defaultRspCmd;
  2470. uint8 *pBuf = pCmd->pData;
  2471. defaultRspCmd = (zclDefaultRspCmd_t *)osal_mem_alloc( sizeof ( zclDefaultRspCmd_t ) );
  2472. if ( defaultRspCmd != NULL )
  2473. {
  2474. defaultRspCmd->commandID = *pBuf++;
  2475. defaultRspCmd->statusCode = *pBuf;
  2476. }
  2477. return ( (void *)defaultRspCmd );
  2478. }
  2479. #ifdef ZCL_DISCOVER
  2480. /*********************************************************************
  2481. * @fn zclParseInDiscCmd
  2482. *
  2483. * @brief Parse the "Profile" Discovery Commands
  2484. *
  2485. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2486. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2487. *
  2488. * @param pCmd - pointer to incoming data to parse
  2489. *
  2490. * @return pointer to the parsed command structure
  2491. */
  2492. void *zclParseInDiscCmd( zclParseCmd_t *pCmd )
  2493. {
  2494. zclDiscoverCmd_t *discoverCmd;
  2495. uint8 *pBuf = pCmd->pData;
  2496. discoverCmd = (zclDiscoverCmd_t *)osal_mem_alloc( sizeof ( zclDiscoverCmd_t ) );
  2497. if ( discoverCmd != NULL )
  2498. {
  2499. discoverCmd->startAttr = BUILD_UINT16( pBuf[0], pBuf[1] );
  2500. pBuf += 2;
  2501. discoverCmd->maxAttrIDs = *pBuf;
  2502. }
  2503. return ( (void *)discoverCmd );
  2504. }
  2505. /*********************************************************************
  2506. * @fn zclParseInDiscRspCmd
  2507. *
  2508. * @brief Parse the "Profile" Discovery Response Commands
  2509. *
  2510. * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING
  2511. * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY.
  2512. *
  2513. * @param pCmd - pointer to incoming data to parse
  2514. *
  2515. * @return pointer to the parsed command structure
  2516. */
  2517. #define ZCLDISCRSPCMD_DATALEN(a) ((a)-1) // data len - Discovery Complete
  2518. static void *zclParseInDiscRspCmd( zclParseCmd_t *pCmd )
  2519. {
  2520. zclDiscoverRspCmd_t *discoverRspCmd;
  2521. uint8 *pBuf = pCmd->pData;
  2522. uint8 numAttr = ZCLDISCRSPCMD_DATALEN(pCmd->dataLen) / ( 2 + 1 ); // Attr ID + Data Type
  2523. uint8 i;
  2524. discoverRspCmd = (zclDiscoverRspCmd_t *)osal_mem_alloc( sizeof ( zclDiscoverRspCmd_t )
  2525. + ( numAttr * sizeof(zclDiscoverInfo_t) ) );
  2526. if ( discoverRspCmd != NULL )
  2527. {
  2528. discoverRspCmd->discComplete = *pBuf++;
  2529. discoverRspCmd->numAttr = numAttr;
  2530. for ( i = 0; i < numAttr; i++ )
  2531. {
  2532. discoverRspCmd->attrList[i].attrID = BUILD_UINT16( pBuf[0], pBuf[1] );
  2533. pBuf += 2;
  2534. discoverRspCmd->attrList[i].dataType = *pBuf++;;
  2535. }
  2536. }
  2537. return ( (void *)discoverRspCmd );
  2538. }
  2539. #endif // ZCL_DISCOVER
  2540. #ifdef ZCL_READ
  2541. /*********************************************************************
  2542. * @fn zclProcessInReadCmd
  2543. *
  2544. * @brief Process the "Profile" Read Command
  2545. *
  2546. * @param pInMsg - incoming message to process
  2547. *
  2548. * @return TRUE if command processed. FALSE, otherwise.
  2549. */
  2550. static uint8 zclProcessInReadCmd( zclIncoming_t *pInMsg )
  2551. {
  2552. zclReadCmd_t *readCmd;
  2553. zclReadRspCmd_t *readRspCmd;
  2554. zclReadRspStatus_t *statusRec;
  2555. zclAttrRec_t attrRec;
  2556. uint8 len;
  2557. uint8 i;
  2558. readCmd = (zclReadCmd_t *)pInMsg->attrCmd;
  2559. // calculate the length of the response status record
  2560. len = sizeof( zclReadRspCmd_t ) + (readCmd->numAttr * sizeof( zclReadRspStatus_t ));
  2561. readRspCmd = osal_mem_alloc( len );
  2562. if ( readRspCmd == NULL )
  2563. return FALSE; // EMBEDDED RETURN
  2564. readRspCmd->numAttr = readCmd->numAttr;
  2565. for (i = 0; i < readCmd->numAttr; i++)
  2566. {
  2567. statusRec = &(readRspCmd->attrList[i]);
  2568. statusRec->attrID = readCmd->attrID[i];
  2569. if ( zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, readCmd->attrID[i], &attrRec ) )
  2570. {
  2571. statusRec->data = attrRec.attr.dataPtr;
  2572. statusRec->status = ZCL_STATUS_SUCCESS;
  2573. statusRec->dataType = attrRec.attr.dataType;
  2574. }
  2575. else
  2576. {
  2577. statusRec->status = ZCL_STATUS_UNSUPPORTED_ATTRIBUTE;
  2578. }
  2579. }
  2580. // Build and send Read Response command
  2581. zcl_SendReadRsp( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr), pInMsg->msg->clusterId,
  2582. readRspCmd, ZCL_FRAME_SERVER_CLIENT_DIR,
  2583. true, pInMsg->hdr.transSeqNum );
  2584. osal_mem_free( readRspCmd );
  2585. return TRUE;
  2586. }
  2587. #endif // ZCL_READ
  2588. #ifdef ZCL_WRITE
  2589. /*********************************************************************
  2590. * @fn processInWriteCmd
  2591. *
  2592. * @brief Process the "Profile" Write and Write No Response Commands
  2593. *
  2594. * @param pInMsg - incoming message to process
  2595. *
  2596. * @return TRUE if command processed. FALSE, otherwise.
  2597. */
  2598. static uint8 zclProcessInWriteCmd( zclIncoming_t *pInMsg )
  2599. {
  2600. zclWriteCmd_t *writeCmd;
  2601. zclWriteRec_t *statusRec;
  2602. zclWriteRspCmd_t *writeRspCmd;
  2603. zclAttrRec_t attrRec;
  2604. uint8 sendRsp = FALSE;
  2605. uint8 status;
  2606. uint8 i, j = 0;
  2607. writeCmd = (zclWriteCmd_t *)pInMsg->attrCmd;
  2608. if ( pInMsg->hdr.commandID == ZCL_CMD_WRITE )
  2609. {
  2610. // We need to send a response back - allocate space for it
  2611. writeRspCmd = (zclWriteRspCmd_t *)osal_mem_alloc( sizeof( zclWriteRspCmd_t )
  2612. + sizeof( zclWriteRspStatus_t ) * writeCmd->numAttr );
  2613. if ( writeRspCmd == NULL )
  2614. return FALSE; // EMBEDDED RETURN
  2615. sendRsp = TRUE;
  2616. }
  2617. for (i = 0; i < writeCmd->numAttr; i++)
  2618. {
  2619. statusRec = &(writeCmd->attrList[i]);
  2620. if ( zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, statusRec->attrID, &attrRec ) )
  2621. {
  2622. if ( statusRec->dataType == attrRec.attr.dataType )
  2623. {
  2624. status = zclWriteAttrData( &attrRec, statusRec );
  2625. // If successful, a write attribute status record shall NOT be generated
  2626. if ( sendRsp && status != ZCL_STATUS_SUCCESS )
  2627. {
  2628. // Attribute is read only - move on to the next write attribute record
  2629. writeRspCmd->attrList[j].status = status;
  2630. writeRspCmd->attrList[j++].attrID = statusRec->attrID;
  2631. }
  2632. }
  2633. else
  2634. {
  2635. // Attribute data type is incorrect - move on to the next write attribute record
  2636. if ( sendRsp )
  2637. {
  2638. writeRspCmd->attrList[j].status = ZCL_STATUS_INVALID_DATA_TYPE;
  2639. writeRspCmd->attrList[j++].attrID = statusRec->attrID;
  2640. }
  2641. }
  2642. }
  2643. else
  2644. {
  2645. // Attribute is not supported - move on to the next write attribute record
  2646. if ( sendRsp )
  2647. {
  2648. writeRspCmd->attrList[j].status = ZCL_STATUS_UNSUPPORTED_ATTRIBUTE;
  2649. writeRspCmd->attrList[j++].attrID = statusRec->attrID;
  2650. }
  2651. }
  2652. } // for loop
  2653. if ( sendRsp )
  2654. {
  2655. writeRspCmd->numAttr = j;
  2656. if ( writeRspCmd->numAttr == 0 )
  2657. {
  2658. // Since all records were written successful, include a single status record
  2659. // in the resonse command with the status field set to SUCCESS and the
  2660. // attribute ID field omitted.
  2661. writeRspCmd->attrList[0].status = ZCL_STATUS_SUCCESS;
  2662. writeRspCmd->numAttr = 1;
  2663. }
  2664. zcl_SendWriteRsp( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
  2665. pInMsg->msg->clusterId, writeRspCmd, ZCL_FRAME_SERVER_CLIENT_DIR,
  2666. true, pInMsg->hdr.transSeqNum );
  2667. osal_mem_free( writeRspCmd );
  2668. }
  2669. return TRUE;
  2670. }
  2671. /*********************************************************************
  2672. * @fn zclRevertWriteUndividedCmd
  2673. *
  2674. * @brief Revert the "Profile" Write Undevided Command
  2675. *
  2676. * @param pInMsg - incoming message to process
  2677. * @param curWriteRec - old data
  2678. * @param numAttr - number of attributes to be reverted
  2679. *
  2680. * @return none
  2681. */
  2682. static void zclRevertWriteUndividedCmd( zclIncoming_t *pInMsg,
  2683. zclWriteRec_t *curWriteRec, uint16 numAttr )
  2684. {
  2685. zclWriteRec_t *statusRec;
  2686. zclAttrRec_t attrRec;
  2687. uint8 dataLen;
  2688. uint8 i;
  2689. statusRec = curWriteRec;
  2690. for (i = 0; i < numAttr; i++)
  2691. {
  2692. statusRec = &(curWriteRec[i]);
  2693. if ( !zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, statusRec->attrID, &attrRec ) )
  2694. break; // should never happen
  2695. // Just copy the old data back - no need to validate the data
  2696. dataLen = zclGetAttrDataLength( attrRec.attr.dataType, statusRec->attrData );
  2697. osal_memcpy( attrRec.attr.dataPtr, statusRec->attrData, dataLen );
  2698. } // for loop
  2699. }
  2700. /*********************************************************************
  2701. * @fn zclProcessInWriteUndividedCmd
  2702. *
  2703. * @brief Process the "Profile" Write Undivided Command
  2704. *
  2705. * @param pInMsg - incoming message to process
  2706. *
  2707. * @return TRUE if command processed. FALSE, otherwise.
  2708. */
  2709. static uint8 zclProcessInWriteUndividedCmd( zclIncoming_t *pInMsg )
  2710. {
  2711. zclWriteCmd_t *writeCmd;
  2712. zclWriteRec_t *statusRec;
  2713. zclWriteRec_t *curWriteRec;
  2714. zclWriteRec_t *curStatusRec;
  2715. zclWriteRspCmd_t *writeRspCmd;
  2716. zclAttrRec_t attrRec;
  2717. uint8 *curDataPtr;
  2718. uint8 hdrLen;
  2719. uint8 dataLen;
  2720. uint8 curLen = 0;
  2721. uint8 status;
  2722. uint8 i, j = 0;
  2723. writeCmd = (zclWriteCmd_t *)pInMsg->attrCmd;
  2724. // Allocate space for Write Response Command
  2725. writeRspCmd = (zclWriteRspCmd_t *)osal_mem_alloc( sizeof( zclWriteRspCmd_t )
  2726. + sizeof( zclWriteRspStatus_t )* writeCmd->numAttr );
  2727. if ( writeRspCmd == NULL )
  2728. return FALSE; // EMBEDDED RETURN
  2729. // If any attribute cannot be written, no attribute values are changed. Hence,
  2730. // make sure all the attributes are supported and writable
  2731. for (i = 0; i < writeCmd->numAttr; i++)
  2732. {
  2733. statusRec = &(writeCmd->attrList[i]);
  2734. if ( !zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, statusRec->attrID, &attrRec ) )
  2735. {
  2736. // Attribute is not supported - stop here
  2737. writeRspCmd->attrList[j].status = ZCL_STATUS_UNSUPPORTED_ATTRIBUTE;
  2738. writeRspCmd->attrList[j++].attrID = statusRec->attrID;
  2739. break;
  2740. }
  2741. if ( statusRec->dataType != attrRec.attr.dataType )
  2742. {
  2743. // Attribute data type is incorrect - stope here
  2744. writeRspCmd->attrList[j].status = ZCL_STATUS_INVALID_DATA_TYPE;
  2745. writeRspCmd->attrList[j++].attrID = statusRec->attrID;
  2746. break;
  2747. }
  2748. if ( !zcl_AccessCtrlWrite( attrRec.attr.accessControl ) )
  2749. {
  2750. // Attribute is not writable - stop here
  2751. writeRspCmd->attrList[j].status = ZCL_STATUS_READ_ONLY;
  2752. writeRspCmd->attrList[j++].attrID = statusRec->attrID;
  2753. break;
  2754. }
  2755. dataLen = zclGetAttrDataLength( statusRec->dataType, statusRec->attrData );
  2756. // add padding if needed
  2757. if ( PADDING_NEEDED( dataLen ) )
  2758. dataLen++;
  2759. curLen += dataLen;
  2760. } // for loop
  2761. writeRspCmd->numAttr = j;
  2762. if ( writeRspCmd->numAttr == 0 ) // All attributes can be written
  2763. {
  2764. // calculate the length of the current data header
  2765. hdrLen = j * sizeof( zclWriteRec_t );
  2766. // Allocate space to keep a copy of the current data
  2767. curWriteRec = (zclWriteRec_t *) osal_mem_alloc( hdrLen + curLen );
  2768. if ( curWriteRec == NULL )
  2769. {
  2770. osal_mem_free(writeRspCmd );
  2771. return FALSE; // EMBEDDED RETURN
  2772. }
  2773. curDataPtr = (uint8 *)((uint8 *)curWriteRec + hdrLen);
  2774. // Write the new data over
  2775. for (i = 0; i < writeCmd->numAttr; i++)
  2776. {
  2777. statusRec = &(writeCmd->attrList[i]);
  2778. curStatusRec = &(curWriteRec[i]);
  2779. if ( !zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, statusRec->attrID, &attrRec ) )
  2780. break; // should never happen
  2781. // Keep a copy of the current data before before writing the new data over
  2782. curStatusRec->attrID = statusRec->attrID;
  2783. zclReadAttrData( curDataPtr, &attrRec );
  2784. curStatusRec->attrData = curDataPtr;
  2785. status = zclWriteAttrData( &attrRec, statusRec );
  2786. // If successful, a write attribute status record shall NOT be generated
  2787. if ( status != ZCL_STATUS_SUCCESS )
  2788. {
  2789. writeRspCmd->attrList[j].status = status;
  2790. writeRspCmd->attrList[j++].attrID = statusRec->attrID;
  2791. // Since this write failed, we need to revert all the pervious writes
  2792. zclRevertWriteUndividedCmd( pInMsg, curWriteRec, i);
  2793. break;
  2794. }
  2795. dataLen = zclGetAttrDataLength( statusRec->dataType, statusRec->attrData );
  2796. // add padding if needed
  2797. if ( PADDING_NEEDED( dataLen ) )
  2798. dataLen++;
  2799. curDataPtr += dataLen;
  2800. } // for loop
  2801. writeRspCmd->numAttr = j;
  2802. if ( writeRspCmd->numAttr == 0 )
  2803. {
  2804. // Since all records were written successful, include a single status record
  2805. // in the resonse command with the status field set to SUCCESS and the
  2806. // attribute ID field omitted.
  2807. writeRspCmd->attrList[0].status = ZCL_STATUS_SUCCESS;
  2808. writeRspCmd->numAttr = 1;
  2809. }
  2810. osal_mem_free( curWriteRec );
  2811. }
  2812. zcl_SendWriteRsp( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
  2813. pInMsg->msg->clusterId, writeRspCmd, ZCL_FRAME_SERVER_CLIENT_DIR,
  2814. true, pInMsg->hdr.transSeqNum );
  2815. osal_mem_free( writeRspCmd );
  2816. return TRUE;
  2817. }
  2818. #endif // ZCL_WRITE
  2819. #ifdef ZCL_DISCOVER
  2820. /*********************************************************************
  2821. * @fn zclProcessInDiscCmd
  2822. *
  2823. * @brief Process the "Profile" Discover Command
  2824. *
  2825. * @param pInMsg - incoming message to process
  2826. *
  2827. * @return TRUE if command processed. FALSE, otherwise.
  2828. */
  2829. static uint8 zclProcessInDiscCmd( zclIncoming_t *pInMsg )
  2830. {
  2831. zclDiscoverCmd_t *discoverCmd;
  2832. zclDiscoverRspCmd_t *discoverRspCmd;
  2833. uint8 discComplete = TRUE;
  2834. zclAttrRec_t attrRec;
  2835. uint16 attrID;
  2836. uint8 i;
  2837. discoverCmd = (zclDiscoverCmd_t *)pInMsg->attrCmd;
  2838. // Find out the number of attributes supported within the specified range
  2839. for ( i = 0, attrID = discoverCmd->startAttr; i < discoverCmd->maxAttrIDs; i++, attrID++ )
  2840. {
  2841. if ( !zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, &attrID, &attrRec ) )
  2842. break;
  2843. }
  2844. // Allocate space for the response command
  2845. discoverRspCmd = (zclDiscoverRspCmd_t *)osal_mem_alloc( sizeof (zclDiscoverRspCmd_t)
  2846. + sizeof ( zclDiscoverInfo_t ) * i );
  2847. if ( discoverRspCmd == NULL )
  2848. return FALSE; // EMEDDED RETURN
  2849. discoverRspCmd->numAttr = i;
  2850. if ( discoverRspCmd->numAttr != 0 )
  2851. {
  2852. for ( i = 0, attrID = discoverCmd->startAttr; i < discoverRspCmd->numAttr; i++, attrID++ )
  2853. {
  2854. if ( !zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, &attrID, &attrRec ) )
  2855. break; // Attribute not supported
  2856. discoverRspCmd->attrList[i].attrID = attrRec.attr.attrId;
  2857. discoverRspCmd->attrList[i].dataType = attrRec.attr.dataType;
  2858. }
  2859. // Are there more attributes to be discovered?
  2860. if ( zclFindNextAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, &attrID, &attrRec ) )
  2861. discComplete = FALSE;
  2862. }
  2863. discoverRspCmd->discComplete = discComplete;
  2864. zcl_SendDiscoverRspCmd( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
  2865. pInMsg->msg->clusterId, discoverRspCmd, ZCL_FRAME_SERVER_CLIENT_DIR,
  2866. true, pInMsg->hdr.transSeqNum );
  2867. osal_mem_free( discoverRspCmd );
  2868. return TRUE;
  2869. }
  2870. #endif // ZCL_DISCOVER
  2871. /*********************************************************************
  2872. * @fn zclSendMsg
  2873. *
  2874. * @brief Send an incoming message to the Application
  2875. *
  2876. * @param pInMsg - incoming message to process
  2877. *
  2878. * @return TRUE
  2879. */
  2880. static uint8 zclSendMsg( zclIncoming_t *pInMsg )
  2881. {
  2882. zclIncomingMsg_t *pCmd;
  2883. if ( zcl_RegisteredMsgTaskID == TASK_NO_TASK )
  2884. return ( TRUE );
  2885. pCmd = (zclIncomingMsg_t *)osal_msg_allocate( sizeof ( zclIncomingMsg_t ) );
  2886. if ( pCmd != NULL )
  2887. {
  2888. // fill in the message
  2889. pCmd->hdr.event = ZCL_INCOMING_MSG;
  2890. pCmd->zclHdr = pInMsg->hdr;
  2891. pCmd->clusterId = pInMsg->msg->clusterId;
  2892. pCmd->srcAddr = pInMsg->msg->srcAddr;
  2893. pCmd->attrCmd = pInMsg->attrCmd;
  2894. // Application will free the attrCmd buffer
  2895. pInMsg->attrCmd = NULL;
  2896. /* send message through task message */
  2897. osal_msg_send( zcl_RegisteredMsgTaskID, (uint8 *)pCmd );
  2898. }
  2899. return ( TRUE );
  2900. }
  2901. /*********************************************************************
  2902. *********************************************************************/