zcl.c 113 KB

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