| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153 |
- /**************************************************************************************************
- Filename: zcl_general.c
- Revised: $Date: 2009-01-06 13:51:37 -0800 (Tue, 06 Jan 2009) $
- Revision: $Revision: 18695 $
- Description: Zigbee Cluster Library - General. This application receives all
- ZCL messages and initially parses them before passing to application.
- Copyright 2006-2008 Texas Instruments Incorporated. All rights reserved.
- IMPORTANT: Your use of this Software is limited to those specific rights
- granted under the terms of a software license agreement between the user
- who downloaded the software, his/her employer (which must be your employer)
- and Texas Instruments Incorporated (the "License"). You may not use this
- Software unless you agree to abide by the terms of the License. The License
- limits your use, and you acknowledge, that the Software may not be modified,
- copied or distributed unless embedded on a Texas Instruments microcontroller
- or used solely and exclusively in conjunction with a Texas Instruments radio
- frequency transceiver, which is integrated into your product. Other than for
- the foregoing purpose, you may not use, reproduce, copy, prepare derivative
- works of, modify, distribute, perform, display or sell this Software and/or
- its documentation for any purpose.
- YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
- PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
- INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
- NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
- TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
- NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
- LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
- INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
- OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
- OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
- (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
- Should you have any questions regarding your right to use this Software,
- contact Texas Instruments Incorporated at www.TI.com.
- **************************************************************************************************/
- /*********************************************************************
- * INCLUDES
- */
- #include "ZComDef.h"
- #include "OSAL.h"
- #include "OSAL_Nv.h"
- #include "zcl.h"
- #include "zcl_general.h"
- #include "ZDApp.h"
- #if defined ( INTER_PAN )
- #include "stub_aps.h"
- #endif
- /*********************************************************************
- * MACROS
- */
- #define locationTypeAbsolute( a ) ( (a) & LOCATION_TYPE_ABSOLUTE )
- #define locationType2D( a ) ( (a) & LOCATION_TYPE_2_D )
- #define locationTypeCoordinateSystem( a ) ( (a) & LOCATION_TYPE_COORDINATE_SYSTEM )
- #ifdef ZCL_SCENES
- #define zclGeneral_ScenesRemaingCapacity() ( ZCL_GEN_MAX_SCENES - zclGeneral_CountAllScenes() )
- #endif // ZCL_SCENES
- /*********************************************************************
- * CONSTANTS
- */
- /*********************************************************************
- * TYPEDEFS
- */
- typedef struct zclGenCBRec
- {
- struct zclGenCBRec *next;
- uint8 endpoint; // Used to link it into the endpoint descriptor
- zclGeneral_AppCallbacks_t *CBs; // Pointer to Callback function
- } zclGenCBRec_t;
- typedef struct zclGenSceneItem
- {
- struct zclGenSceneItem *next;
- uint8 endpoint; // Used to link it into the endpoint descriptor
- zclGeneral_Scene_t scene; // Scene info
- } zclGenSceneItem_t;
- typedef struct zclGenAlarmItem
- {
- struct zclGenAlarmItem *next;
- uint8 endpoint; // Used to link it into the endpoint descriptor
- zclGeneral_Alarm_t alarm; // Alarm info
- } zclGenAlarmItem_t;
- // Scene NV types
- typedef struct
- {
- uint16 numRecs;
- } nvGenScenesHdr_t;
- typedef struct zclGenSceneNVItem
- {
- uint8 endpoint;
- zclGeneral_Scene_t scene;
- } zclGenSceneNVItem_t;
- /*********************************************************************
- * GLOBAL VARIABLES
- */
- /*********************************************************************
- * GLOBAL FUNCTIONS
- */
- /*********************************************************************
- * LOCAL VARIABLES
- */
- static zclGenCBRec_t *zclGenCBs = (zclGenCBRec_t *)NULL;
- static uint8 zclGenPluginRegisted = FALSE;
- #ifdef ZCL_SCENES
- static zclGenSceneItem_t *zclGenSceneTable = (zclGenSceneItem_t *)NULL;
- #endif // ZCL_SCENES
- #ifdef ZCL_ALARMS
- static zclGenAlarmItem_t *zclGenAlarmTable = (zclGenAlarmItem_t *)NULL;
- #endif // ZCL_ALARMS
- /*********************************************************************
- * LOCAL FUNCTIONS
- */
- static ZStatus_t zclGeneral_HdlIncoming( zclIncoming_t *pInMsg );
- static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg );
- static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint );
- // Device Configuration and Installation clusters
- #ifdef ZCL_BASIC
- static ZStatus_t zclGeneral_ProcessInBasic( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- #endif // ZCL_BASIC
- #ifdef ZCL_IDENTIFY
- static ZStatus_t zclGeneral_ProcessInIdentity( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- #endif // ZCL_IDENTIFY
- // Groups and Scenes clusters
- #ifdef ZCL_GROUPS
- static ZStatus_t zclGeneral_ProcessInGroupsServer( zclIncoming_t *pInMsg );
- static ZStatus_t zclGeneral_ProcessInGroupsClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- static ZStatus_t zclGeneral_AddGroup( uint8 endPoint, aps_Group_t *group, uint8 *pData );
- #endif // ZCL_GROUPS
- #ifdef ZCL_SCENES
- static ZStatus_t zclGeneral_ProcessInScenesServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- static ZStatus_t zclGeneral_ProcessInScenesClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- #endif // ZCL_SCENES
- // On/Off and Level Control Configuration clusters
- #ifdef ZCL_ON_OFF
- static ZStatus_t zclGeneral_ProcessInOnOff( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- #endif // ZCL_ONOFF
- #ifdef ZCL_LEVEL_CTRL
- static ZStatus_t zclGeneral_ProcessInLevelControl( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- #endif // ZCL_LEVEL_CTRL
- // Alarms cluster
- #ifdef ZCL_ALARMS
- static ZStatus_t zclGeneral_ProcessInAlarmsServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- static ZStatus_t zclGeneral_ProcessInAlarmsClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- #endif // ZCL_ALARMS
- // Location cluster
- #ifdef ZCL_LOCATION
- static ZStatus_t zclGeneral_ProcessInLocationServer( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- static ZStatus_t zclGeneral_ProcessInLocationClient( zclIncoming_t *pInMsg, zclGeneral_AppCallbacks_t *pCBs );
- #endif // ZCL_LOCATION
- #ifdef ZCL_SCENES
- static uint8 zclGeneral_ScenesInitNV( void );
- static void zclGeneral_ScenesSetDefaultNV( void );
- static void zclGeneral_ScenesWriteNV( void );
- static uint16 zclGeneral_ScenesRestoreFromNV( void );
- #endif // ZCL_SCENES
- /*********************************************************************
- * @fn zclGeneral_RegisterCmdCallbacks
- *
- * @brief Register an applications command callbacks
- *
- * @param endpoint - application's endpoint
- * @param callbacks - pointer to the callback record.
- *
- * @return ZMemError if not able to allocate
- */
- ZStatus_t zclGeneral_RegisterCmdCallbacks( uint8 endpoint, zclGeneral_AppCallbacks_t *callbacks )
- {
- zclGenCBRec_t *pNewItem;
- zclGenCBRec_t *pLoop;
- // Register as a ZCL Plugin
- if ( zclGenPluginRegisted == FALSE )
- {
- zcl_registerPlugin( ZCL_CLUSTER_ID_GEN_BASIC,
- ZCL_CLUSTER_ID_GEN_LOCATION,
- zclGeneral_HdlIncoming );
- #ifdef ZCL_SCENES
- // Initialize NV items
- zclGeneral_ScenesInitNV();
- // Restore the Scene table
- zclGeneral_ScenesRestoreFromNV();
- #endif // ZCL_SCENES
- zclGenPluginRegisted = TRUE;
- }
- // Fill in the new profile list
- pNewItem = osal_mem_alloc( sizeof( zclGenCBRec_t ) );
- if ( pNewItem == NULL )
- return (ZMemError);
- pNewItem->next = (zclGenCBRec_t *)NULL;
- pNewItem->endpoint = endpoint;
- pNewItem->CBs = callbacks;
- // Find spot in list
- if ( zclGenCBs == NULL )
- {
- zclGenCBs = pNewItem;
- }
- else
- {
- // Look for end of list
- pLoop = zclGenCBs;
- while ( pLoop->next != NULL )
- pLoop = pLoop->next;
- // Put new item at end of list
- pLoop->next = pNewItem;
- }
- return ( ZSuccess );
- }
- #ifdef ZCL_IDENTIFY
- /*********************************************************************
- * @fn zclGeneral_SendIdentify
- *
- * @brief Call to send out an Identify Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param identifyTime - how long the device will continue to identify itself (in seconds)
- * @param seqNum - identification number for the transaction
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendIdentify( uint8 srcEP, afAddrType_t *dstAddr,
- uint16 identifyTime, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[2];
- buf[0] = LO_UINT16( identifyTime );
- buf[1] = HI_UINT16( identifyTime );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
- COMMAND_IDENTIFY, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, 2, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendIdentifyQueryResponse
- *
- * @brief Call to send out an Identify Query Response Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param timeout - how long the device will continue to identify itself (in seconds)
- * @param seqNum - identification number for the transaction
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendIdentifyQueryResponse( uint8 srcEP, afAddrType_t *dstAddr,
- uint16 timeout, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[2];
- buf[0] = LO_UINT16( timeout );
- buf[1] = HI_UINT16( timeout );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_IDENTIFY,
- COMMAND_IDENTIFY_QUERY_RSP, TRUE,
- ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, 2, buf );
- }
- #endif // ZCL_IDENTIFY
- #ifdef ZCL_GROUPS
- /*********************************************************************
- * @fn zclGeneral_SendGroupRequest
- *
- * @brief Send a Group Request to a device. You can also use the
- * appropriate macro.
- *
- * @param srcEP - Sending Apps endpoint
- * @param dstAddr - where to send the request
- * @param cmd - one of the following:
- * COMMAND_GROUP_VIEW
- * COMMAND_GROUP_REMOVE
- * @param groupID -
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendGroupRequest( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint16 groupID, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[2];
- buf[0] = LO_UINT16( groupID );
- buf[1] = HI_UINT16( groupID );
- return ( zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
- cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, 2, buf ) );
- }
- /*********************************************************************
- * @fn zclGeneral_SendAddGroupRequest
- *
- * @brief Send the Add Group Request to a device
- *
- * @param srcEP - Sending Apps endpoint
- * @param dstAddr - where to send the request
- * @param cmd - one of the following:
- * COMMAND_GROUP_ADD
- * COMMAND_GROUP_ADD_IF_IDENTIFYING
- * @param groupID - pointer to the group structure
- * @param groupName - pointer to Group Name. This is a Zigbee
- * string data type, so the first byte is the length of the
- * name (in bytes), then the name.
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendAddGroupRequest( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint16 groupID, uint8 *groupName,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 *buf;
- uint8 *pBuf;
- uint8 len;
- ZStatus_t status;
- len = 2; // Group ID
- len += groupName[0] + 1; // String + 1 for length
- buf = osal_mem_alloc( len );
- if ( buf )
- {
- pBuf = buf;
- *pBuf++ = LO_UINT16( groupID );
- *pBuf++ = HI_UINT16( groupID );
- *pBuf++ = groupName[0]; // string length
- osal_memcpy( pBuf, &(groupName[1]), groupName[0] );
- status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
- cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, len, buf );
- osal_mem_free( buf );
- }
- else
- status = ZMemError;
- return ( status );
- }
- /*********************************************************************
- * @fn zclGeneral_SendGroupGetMembershipRequest
- *
- * @brief Send a Get Group Membership (Resposne) Command to a device
- *
- * @param srcEP - Sending Apps endpoint
- * @param dstAddr - where to send the request
- * @param cmd - one of the following:
- * COMMAND_GROUP_GET_MEMBERSHIP
- * COMMAND_GROUP_GET_MEMBERSHIP_RSP
- * @param groupID - pointer to the group structure
- * @param groupName - pointer to Group Name. This is a Zigbee
- * string data type, so the first byte is the length of the
- * name (in bytes), then the name.
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendGroupGetMembershipRequest( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint8 rspCmd, uint8 direction, uint8 capacity,
- uint8 grpCnt, uint16 *grpList, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 *buf;
- uint8 *pBuf;
- uint8 len = 0;
- uint8 i;
- ZStatus_t status;
- if ( rspCmd )
- len++; // Capacity
- len++; // Group Count
- len += sizeof ( uint16 ) * grpCnt; // Group List
- buf = osal_mem_alloc( len );
- if ( buf )
- {
- pBuf = buf;
- if ( rspCmd )
- *pBuf++ = capacity;
- *pBuf++ = grpCnt;
- for ( i = 0; i < grpCnt; i++ )
- {
- *pBuf++ = LO_UINT16( grpList[i] );
- *pBuf++ = HI_UINT16( grpList[i] );
- }
- status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
- cmd, TRUE, direction,
- disableDefaultRsp, 0, seqNum, len, buf );
- osal_mem_free( buf );
- }
- else
- status = ZMemError;
- return ( status );
- }
- /*********************************************************************
- * @fn zclGeneral_SendGroupResponse
- *
- * @brief Send Group Response (not Group View Response)
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param cmd - either COMMAND_GROUP_ADD_RSP or COMMAND_GROUP_REMOVE_RSP
- * @param status - group command status
- * @param groupID - what group
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendGroupResponse( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint8 status, uint16 groupID,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[3];
- buf[0] = status;
- buf[1] = LO_UINT16( groupID );
- buf[2] = HI_UINT16( groupID );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
- cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
- disableDefaultRsp, 0, seqNum, 3, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendGroupViewResponse
- *
- * @brief Call to send Group Response Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param cmd - either COMMAND_GROUP_ADD_RSP or COMMAND_GROUP_REMOVE_RSP
- * @param status - group command status
- * @param grp - group info
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendGroupViewResponse( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 status, aps_Group_t *grp, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 *buf;
- uint8 len;
- ZStatus_t stat;
- len = 1 + 2; // Status + Group ID
- if ( status == ZCL_STATUS_SUCCESS )
- len += grp->name[0] + 1; // String + 1 for length
- buf = osal_mem_alloc( len );
- if ( buf )
- {
- buf[0] = status;
- buf[1] = LO_UINT16( grp->ID );
- buf[2] = HI_UINT16( grp->ID );
- if ( status == ZCL_STATUS_SUCCESS )
- {
- buf[3] = grp->name[0]; // string length
- osal_memcpy( &buf[4], (&grp->name[1]), grp->name[0] );
- }
- stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_GROUPS,
- COMMAND_GROUP_VIEW_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
- disableDefaultRsp, 0, seqNum, len, buf );
- osal_mem_free( buf );
- }
- else
- stat = ZMemError;
- return ( stat );
- }
- #endif // ZCL_GROUPS
- #ifdef ZCL_SCENES
- /*********************************************************************
- * @fn zclGeneral_SendAddScene
- *
- * @brief Send the Add Scene Request to a device
- *
- * @param srcEP - Sending Apps endpoint
- * @param dstAddr - where to send the request
- * @param scene - pointer to the scene structure
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendAddScene( uint8 srcEP, afAddrType_t *dstAddr,
- zclGeneral_Scene_t *scene, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 *buf;
- uint8 *pBuf;
- uint8 len;
- ZStatus_t status;
- len = 2 + 1 + 2; // Group ID + Scene ID + transition time
- len += scene->name[0] + 1; // String + 1 for length
- // Add something for the extension field length
- len += scene->extLen;
- buf = osal_mem_alloc( len );
- if ( buf )
- {
- pBuf = buf;
- *pBuf++ = LO_UINT16( scene->groupID );
- *pBuf++ = HI_UINT16( scene->groupID );
- *pBuf++ = scene->ID;
- *pBuf++ = LO_UINT16( scene->transTime );
- *pBuf++ = HI_UINT16( scene->transTime );
- *pBuf++ = scene->name[0]; // string length
- osal_memcpy( pBuf, &(scene->name[1]), scene->name[0] );
- pBuf += scene->name[0]; // move pass name
- // Add the extension fields
- if ( scene->extLen > 0 )
- osal_memcpy( pBuf, scene->extField, scene->extLen );
- status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
- COMMAND_SCENE_ADD, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, len, buf );
- osal_mem_free( buf );
- }
- else
- status = ZMemError;
- return ( status );
- }
- /*********************************************************************
- * @fn zclGeneral_SendSceneRequest
- *
- * @brief Send a Scene Request to a device. You can also use the
- * appropriate macro.
- *
- * @param srcEP - Sending Apps endpoint
- * @param dstAddr - where to send the request
- * @param cmd - one of the following:
- * COMMAND_SCENE_VIEW
- * COMMAND_SCENE_REMOVE
- * COMMAND_SCENE_REMOVE_ALL
- * COMMAND_SCENE_STORE
- * COMMAND_SCENE_RECALL
- * COMMAND_SCENE_GET_MEMBERSHIP
- * @param groupID - group ID
- * @param sceneID - scene ID (not applicable to COMMAND_SCENE_REMOVE_ALL and
- * COMMAND_SCENE_GET_MEMBERSHIP)
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendSceneRequest( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint16 groupID, uint8 sceneID,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[3];
- uint8 len = 2;
- buf[0] = LO_UINT16( groupID );
- buf[1] = HI_UINT16( groupID );
- if ( cmd != COMMAND_SCENE_REMOVE_ALL && cmd != COMMAND_SCENE_GET_MEMBERSHIP )
- {
- buf[2] = sceneID;
- len++;
- }
- return ( zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
- cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, len, buf ) );
- }
- /*********************************************************************
- * @fn zclGeneral_SendSceneResponse
- *
- * @brief Send Group Response (not Group View Response)
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param cmd - either COMMAND_SCENE_ADD_RSP, COMMAND_SCENE_REMOVE_RSP
- * COMMAND_SCENE_STORE_RSP, or COMMAND_SCENE_REMOVE_ALL_RSP
- * @param status - scene command status
- * @param groupID - what group
- * @param sceneID - what scene (not applicable to COMMAND_SCENE_REMOVE_ALL_RSP)
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendSceneResponse( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint8 status, uint16 groupID,
- uint8 sceneID, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[4];
- uint8 len = 1 + 2; // Status + Group ID
- buf[0] = status;
- buf[1] = LO_UINT16( groupID );
- buf[2] = HI_UINT16( groupID );
- if ( cmd != COMMAND_SCENE_REMOVE_ALL_RSP )
- {
- buf[3] = sceneID;
- len++;
- }
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
- cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
- disableDefaultRsp, 0, seqNum, len, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendSceneViewResponse
- *
- * @brief Call to send Scene Response Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param status - scene command status
- * @param scene - scene info
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendSceneViewResponse( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 status, zclGeneral_Scene_t *scene,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 *buf;
- uint8 *pBuf;
- uint8 len = 1 + 2 + 1; // Status + Group ID + Scene ID
- ZStatus_t stat;
- if ( status == ZCL_STATUS_SUCCESS )
- {
- len += 2; // Transition Time
- len += scene->name[0] + 1; // string + 1 for length
- // Add something for the extension field length
- len += scene->extLen;
- }
- buf = osal_mem_alloc( len );
- if ( buf )
- {
- pBuf = buf;
- *pBuf++ = status;
- *pBuf++ = LO_UINT16( scene->groupID );
- *pBuf++ = HI_UINT16( scene->groupID );
- *pBuf++ = scene->ID;
- if ( status == ZCL_STATUS_SUCCESS )
- {
- *pBuf++ = LO_UINT16( scene->transTime );
- *pBuf++ = HI_UINT16( scene->transTime );
- *pBuf++ = scene->name[0]; // string length
- if ( scene->name[0] != 0 )
- {
- osal_memcpy( pBuf, &(scene->name[1]), scene->name[0] );
- pBuf += scene->name[0]; // move pass name
- }
- // Add the extension fields
- if ( scene->extLen > 0 )
- osal_memcpy( pBuf, scene->extField, scene->extLen );
- }
- stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
- COMMAND_SCENE_VIEW_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
- disableDefaultRsp, 0, seqNum, len, buf );
- osal_mem_free( buf );
- }
- else
- stat = ZMemError;
- return ( stat );
- }
- /*********************************************************************
- * @fn zclGeneral_SendSceneGetMembershipResponse
- *
- * @brief Call to send Scene Get Membership Response Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param status - scene command status
- * @param capacity - remaining capacity of the scene table
- * @param sceneCnt - number of scenes in the scene list
- * @param sceneList - list of scene IDs
- * @param groupID - group ID that scene belongs to
- * @param seqNum - sequence number
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendSceneGetMembershipResponse( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 status, uint8 capacity, uint8 sceneCnt, uint8 *sceneList,
- uint16 groupID, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 *buf;
- uint8 *pBuf;
- uint8 len = 1 + 1 + 2; // Status + Capacity + Group ID;
- uint8 i;
- ZStatus_t stat;
- if ( status == ZCL_STATUS_SUCCESS )
- {
- len++; // Scene Count
- len += sceneCnt; // Scene List (Scene ID is a single octet)
- }
- buf = osal_mem_alloc( len );
- if ( buf )
- {
- pBuf = buf;
- *pBuf++ = status;
- *pBuf++ = capacity;
- *pBuf++ = LO_UINT16( groupID );
- *pBuf++ = HI_UINT16( groupID );
- if ( status == ZCL_STATUS_SUCCESS )
- {
- *pBuf++ = sceneCnt;
- for ( i = 0; i < sceneCnt; i++ )
- *pBuf++ = sceneList[i];
- }
- stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_SCENES,
- COMMAND_SCENE_GET_MEMBERSHIP_RSP, TRUE,
- ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
- osal_mem_free( buf );
- }
- else
- stat = ZMemError;
- return ( stat );
- }
- #endif // ZCL_SCENES
- #ifdef ZCL_LEVEL_CTRL
- /*********************************************************************
- * @fn zclGeneral_SendLevelControlMoveToLevelRequest
- *
- * @brief Call to send out a Level Control Request. You can also use
- * the appropriate macro.
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param cmd - one of the following:
- * COMMAND_LEVEL_MOVE_TO_LEVEL or
- * COMMAND_LEVEL_MOVE_TO_LEVEL_WITH_ON_OFF
- * @param level - what level to move to
- * @param transitionTime - how long to take to get to the level (in seconds)
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLevelControlMoveToLevelRequest( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint8 level, uint16 transTime,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[3];
- buf[0] = level;
- buf[1] = LO_UINT16( transTime );
- buf[2] = HI_UINT16( transTime );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
- cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, 3, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendLevelControlMoveRequest
- *
- * @brief Call to send out a Level Control Request. You can also use
- * the appropriate macro.
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param cmd - one of the following:
- * COMMAND_LEVEL_MOVE or
- * COMMAND_LEVEL_MOVE_WITH_ON_OFF
- * @param moveMode - LEVEL_MOVE_UP or
- * LEVEL_MOVE_DOWN
- * @param rate - number of steps to take per second
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLevelControlMoveRequest( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint8 moveMode, uint8 rate,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[2];
- buf[0] = moveMode;
- buf[1] = rate;
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
- cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, 2, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendLevelControlStepRequest
- *
- * @brief Call to send out a Level Control Request. You can also use
- * the appropriate macro.
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param cmd - one of the following:
- * COMMAND_LEVEL_STEP
- * COMMAND_LEVEL_STEP_WITH_ON_OFF
- * @param stepMode - LEVEL_STEP_UP or
- * LEVEL_STEP_DOWN
- * @param amount - number of levels to step
- * @param transitionTime - time, in 1/10ths of a second, to take to perform the step
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLevelControlStepRequest( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint8 stepMode, uint8 stepSize, uint16 transTime,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[4];
- buf[0] = stepMode;
- buf[1] = stepSize;
- buf[2] = LO_UINT16( transTime );
- buf[3] = HI_UINT16( transTime );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
- cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, 4, buf );
- }
- #endif // ZCL_LEVEL_CTRL
- #ifdef ZCL_ALARMS
- /*********************************************************************
- * @fn zclGeneral_SendAlarmRequest
- *
- * @brief Call to send out an Alarm Request Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param cmd - either COMMAND_ALARMS_RESET or COMMAND_ALARMS_ALARM
- * @param alarmCode - code for the cause of the alarm
- * @param clusterID - cluster whose attribute generate the alarm
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendAlarmRequest( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 cmd, uint8 alarmCode, uint16 clusterID,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[3];
- buf[0] = alarmCode;
- buf[1] = LO_UINT16( clusterID );
- buf[2] = HI_UINT16( clusterID );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
- cmd, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR,
- disableDefaultRsp, 0, seqNum, 3, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendAlarmGetRespnose
- *
- * @brief Call to send out an Alarm Get Response Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param status - SUCCESS or NOT_FOUND
- * @param alarmCode - code for the cause of the alarm
- * @param clusterID - cluster whose attribute generate the alarm
- * @param timeStamp - time at which the alarm occured
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendAlarmGetRespnose( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 status, uint8 alarmCode, uint16 clusterID,
- uint32 timeStamp, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[8];
- uint8 len = 1; // Status
- buf[0] = status;
- if ( status == ZCL_STATUS_SUCCESS )
- {
- len += 1 + 2 + 4; // Alarm code + Cluster ID + Time stamp
- buf[1] = alarmCode;
- buf[2] = LO_UINT16( clusterID );
- buf[3] = HI_UINT16( clusterID );
- osal_buffer_uint32( &buf[4], timeStamp );
- }
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_ALARMS,
- COMMAND_ALARMS_GET_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
- disableDefaultRsp, 0, seqNum, len, buf );
- }
- #endif // ZCL_ALARMS
- #ifdef ZCL_LOCATION
- /*********************************************************************
- * @fn zclGeneral_SendLocationSetAbsolute
- *
- * @brief Call to send out a Set Absolute Location Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param absLoc - absolute location info
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLocationSetAbsolute( uint8 srcEP, afAddrType_t *dstAddr,
- zclLocationAbsolute_t *absLoc,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[10]; // 5 fields (2 octects each)
- buf[0] = LO_UINT16( absLoc->coordinate1 );
- buf[1] = HI_UINT16( absLoc->coordinate1 );
- buf[2] = LO_UINT16( absLoc->coordinate2 );
- buf[3] = HI_UINT16( absLoc->coordinate2 );
- buf[4] = LO_UINT16( absLoc->coordinate3 );
- buf[5] = HI_UINT16( absLoc->coordinate3 );
- buf[6] = LO_UINT16( absLoc->power );
- buf[7] = HI_UINT16( absLoc->power );
- buf[8] = LO_UINT16( absLoc->pathLossExponent );
- buf[9] = HI_UINT16( absLoc->pathLossExponent );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
- COMMAND_LOCATION_SET_ABSOLUTE, TRUE,
- ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 10, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendLocationSetDevCfg
- *
- * @brief Call to send out a Set Device Configuration Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param devCfg - device configuration info
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLocationSetDevCfg( uint8 srcEP, afAddrType_t *dstAddr,
- zclLocationDevCfg_t *devCfg,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[9]; // 4 fields (2 octects each) + 1 field with 1 octect
- buf[0] = LO_UINT16( devCfg->power );
- buf[1] = HI_UINT16( devCfg->power );
- buf[2] = LO_UINT16( devCfg->pathLossExponent );
- buf[3] = HI_UINT16( devCfg->pathLossExponent );
- buf[4] = LO_UINT16( devCfg->calcPeriod );
- buf[5] = HI_UINT16( devCfg->calcPeriod );
- buf[6] = devCfg->numMeasurements;
- buf[7] = LO_UINT16( devCfg->reportPeriod );
- buf[8] = HI_UINT16( devCfg->reportPeriod );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
- COMMAND_LOCATION_SET_DEV_CFG, TRUE,
- ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 9, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendLocationGetDevCfg
- *
- * @brief Call to send out a Get Device Configuration Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param targetAddr - device for which location parameters are being requested
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLocationGetDevCfg( uint8 srcEP, afAddrType_t *dstAddr,
- uint8 *targetAddr, uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[8];
- osal_cpyExtAddr( buf, targetAddr );
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
- COMMAND_LOCATION_GET_DEV_CFG, TRUE,
- ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 8, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendLocationGetData
- *
- * @brief Call to send out a Get Location Data Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param locaData - location information and channel parameters that are requested.
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLocationGetData( uint8 srcEP, afAddrType_t *dstAddr,
- zclLocationGetData_t *locData,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[10]; // bitmap (1) + number responses (1) + IEEE Address (8)
- uint8 *pBuf = buf;
- uint8 len = 2; // bitmap + number responses
- *pBuf = locData->absoluteOnly;
- *pBuf |= locData->recalculate << 1;
- *pBuf |= locData->brdcastIndicator << 2;
- *pBuf |= locData->brdcastResponse << 3;
- *pBuf |= locData->compactResponse << 4;
- pBuf++; // move past the bitmap field
- *pBuf++ = locData->numResponses;
- if ( locData->brdcastIndicator == 0 )
- {
- osal_cpyExtAddr( pBuf, locData->targetAddr );
- len += 8; // ieee addr
- }
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
- COMMAND_LOCATION_GET_DATA, TRUE,
- ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, len, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendLocationDevCfgResponse
- *
- * @brief Call to send out a Device Configuration Response Command
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param devCfg - device's location parameters that are requested
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLocationDevCfgResponse( uint8 srcEP, afAddrType_t *dstAddr,
- zclLocationDevCfgRsp_t *devCfg,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[10]; // 4 fields (2 octects each) + 2 fields (1 octect each)
- uint8 len = 1; // Status
- buf[0] = devCfg->status;
- if ( devCfg->status == ZCL_STATUS_SUCCESS )
- {
- buf[1] = LO_UINT16( devCfg->data.power );
- buf[2] = HI_UINT16( devCfg->data.power );
- buf[3] = LO_UINT16( devCfg->data.pathLossExponent );
- buf[4] = HI_UINT16( devCfg->data.pathLossExponent );
- buf[5] = LO_UINT16( devCfg->data.calcPeriod );
- buf[6] = HI_UINT16( devCfg->data.calcPeriod );
- buf[7] = devCfg->data.numMeasurements;
- buf[8] = LO_UINT16( devCfg->data.reportPeriod );
- buf[9] = HI_UINT16( devCfg->data.reportPeriod );
- len += 9;
- }
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
- COMMAND_LOCATION_DEV_CFG_RSP, TRUE,
- ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
- }
- /*********************************************************************
- * @fn zclGeneral_SendLocationData
- *
- * @brief Call to send out location data
- *
- * @param srcEP - Sending application's endpoint
- * @param dstAddr - where you want the message to go
- * @param status - indicates whether response to request was successful or not
- * @param locData - location information and channel parameters being sent
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_SendLocationData( uint8 srcEP, afAddrType_t *dstAddr, uint8 cmd,
- uint8 status, zclLocationData_t *locData,
- uint8 disableDefaultRsp, uint8 seqNum )
- {
- uint8 buf[16];
- uint8 *pBuf = buf;
- uint8 len = 0;
- if ( cmd == COMMAND_LOCATION_DATA_RSP )
- {
- // Only response command includes a status field
- *pBuf++ = status;
- len++;
- }
- if ( cmd != COMMAND_LOCATION_DATA_RSP || status == ZCL_STATUS_SUCCESS )
- {
- // Notification or Response with successful status
- *pBuf++ = locData->type;
- *pBuf++ = LO_UINT16( locData->absLoc.coordinate1 );
- *pBuf++ = HI_UINT16( locData->absLoc.coordinate1 );
- *pBuf++ = LO_UINT16( locData->absLoc.coordinate2 );
- *pBuf++ = HI_UINT16( locData->absLoc.coordinate2 );
- len += 5;
- if ( locationType2D(locData->type) == 0 )
- {
- // 2D location doesn't have coordinate 3
- *pBuf++ = LO_UINT16( locData->absLoc.coordinate3 );
- *pBuf++ = HI_UINT16( locData->absLoc.coordinate3 );
- len += 2;
- }
- if ( cmd != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
- {
- // Compact notification doesn't include these fields
- *pBuf++ = LO_UINT16( locData->absLoc.power );
- *pBuf++ = HI_UINT16( locData->absLoc.power );
- *pBuf++ = LO_UINT16( locData->absLoc.pathLossExponent );
- *pBuf++ = HI_UINT16( locData->absLoc.pathLossExponent );
- len += 4;
- }
- if ( locationTypeAbsolute(locData->type) == 0 )
- {
- // Absolute location doesn't include these fields
- if ( cmd != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
- {
- // Compact notification doesn't include this field
- *pBuf++ = locData->calcLoc.locationMethod;
- len++;
- }
- *pBuf++ = locData->calcLoc.qualityMeasure;
- *pBuf++ = LO_UINT16( locData->calcLoc.locationAge );
- *pBuf++ = HI_UINT16( locData->calcLoc.locationAge );
- len += 3;
- }
- }
- return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_LOCATION,
- cmd, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR,
- disableDefaultRsp, 0, seqNum, len, buf );
- }
- #endif // ZCL_LOCATION
- /*********************************************************************
- * @fn zclGeneral_FindCallbacks
- *
- * @brief Find the callbacks for an endpoint
- *
- * @param endpoint - endpoint to find the application callbacks for
- *
- * @return pointer to the callbacks
- */
- static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint )
- {
- zclGenCBRec_t *pCBs;
- pCBs = zclGenCBs;
- while ( pCBs )
- {
- if ( pCBs->endpoint == endpoint )
- return ( pCBs->CBs );
- pCBs = pCBs->next;
- }
- return ( (zclGeneral_AppCallbacks_t *)NULL );
- }
- /*********************************************************************
- * @fn zclGeneral_HdlIncoming
- *
- * @brief Callback from ZCL to process incoming Commands specific
- * to this cluster library or Profile commands for attributes
- * that aren't in the attribute list
- *
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_HdlIncoming( zclIncoming_t *pInMsg )
- {
- ZStatus_t stat = ZSuccess;
- #if defined ( INTER_PAN )
- if ( StubAPS_InterPan( pInMsg->msg->srcAddr.panId, pInMsg->msg->srcAddr.endPoint ) )
- return ( stat ); // Cluster not supported thru Inter-PAN
- #endif
- if ( zcl_ClusterCmd( pInMsg->hdr.fc.type ) )
- {
- // Is this a manufacturer specific command?
- if ( pInMsg->hdr.fc.manuSpecific == 0 )
- {
- stat = zclGeneral_HdlInSpecificCommands( pInMsg );
- }
- else
- {
- // We don't support any manufacturer specific command.
- stat = ZFailure;
- }
- }
- else
- {
- // Handle all the normal (Read, Write...) commands -- should never get here
- stat = ZFailure;
- }
- return ( stat );
- }
- /*********************************************************************
- * @fn zclGeneral_HdlInSpecificCommands
- *
- * @brief Callback from ZCL to process incoming Commands specific
- * to this cluster library
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg )
- {
- ZStatus_t stat;
- zclGeneral_AppCallbacks_t *pCBs;
- // make sure endpoint exists
- pCBs = zclGeneral_FindCallbacks( pInMsg->msg->endPoint );
- if ( pCBs == NULL )
- return ( ZFailure );
- switch ( pInMsg->msg->clusterId )
- {
- #ifdef ZCL_BASIC
- case ZCL_CLUSTER_ID_GEN_BASIC:
- stat = zclGeneral_ProcessInBasic( pInMsg, pCBs );
- break;
- #endif // ZCL_BASIC
- #ifdef ZCL_IDENTIFY
- case ZCL_CLUSTER_ID_GEN_IDENTIFY:
- stat = zclGeneral_ProcessInIdentity( pInMsg, pCBs );
- break;
- #endif // ZCL_IDENTIFY
- #ifdef ZCL_GROUPS
- case ZCL_CLUSTER_ID_GEN_GROUPS:
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- stat = zclGeneral_ProcessInGroupsServer( pInMsg );
- else
- stat = zclGeneral_ProcessInGroupsClient( pInMsg, pCBs );
- break;
- #endif // ZCL_GROUPS
- #ifdef ZCL_SCENES
- case ZCL_CLUSTER_ID_GEN_SCENES:
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- stat = zclGeneral_ProcessInScenesServer( pInMsg, pCBs );
- else
- stat = zclGeneral_ProcessInScenesClient( pInMsg, pCBs );
- break;
- #endif // ZCL_SCENES
- #ifdef ZCL_ON_OFF
- case ZCL_CLUSTER_ID_GEN_ON_OFF:
- stat = zclGeneral_ProcessInOnOff( pInMsg, pCBs );
- break;
- #endif // ZCL_ON_OFF
- #ifdef ZCL_LEVEL_CTRL
- case ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL:
- stat = zclGeneral_ProcessInLevelControl( pInMsg, pCBs );
- break;
- #endif // ZCL_LEVEL_CTRL
- #ifdef ZCL_ALARMS
- case ZCL_CLUSTER_ID_GEN_ALARMS:
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- stat = zclGeneral_ProcessInAlarmsServer( pInMsg, pCBs );
- else
- stat = zclGeneral_ProcessInAlarmsClient( pInMsg, pCBs );
- break;
- #endif // ZCL_ALARMS
- #ifdef ZCL_LOCATION
- case ZCL_CLUSTER_ID_GEN_LOCATION:
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- stat = zclGeneral_ProcessInLocationServer( pInMsg, pCBs );
- else
- stat = zclGeneral_ProcessInLocationClient( pInMsg, pCBs );
- break;
- #endif // ZCL_LOCATION
- case ZCL_CLUSTER_ID_GEN_POWER_CFG:
- case ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG:
- case ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG:
- case ZCL_CLUSTER_ID_GEN_TIME:
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- #ifdef ZCL_BASIC
- /*********************************************************************
- * @fn zclGeneral_ProcessInBasic
- *
- * @brief Process in the received Basic Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInBasic( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- {
- if ( pInMsg->hdr.commandID > COMMAND_BASIC_RESET_FACT_DEFAULT )
- return ( ZFailure ); // Error ignore the command
- if ( pCBs->pfnBasicReset )
- pCBs->pfnBasicReset();
- }
- // no Client command
- return ( ZSuccess );
- }
- #endif // ZCL_BASIC
- #ifdef ZCL_IDENTIFY
- /*********************************************************************
- * @fn zclGeneral_ProcessInIdentity
- *
- * @brief Process in the received Identity Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInIdentity( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- {
- if ( pInMsg->hdr.commandID > COMMAND_IDENTIFY_QUERY )
- return ( ZFailure ); // Error ignore the command
- if ( pInMsg->hdr.commandID == COMMAND_IDENTIFY )
- {
- if ( pCBs->pfnIdentify )
- {
- zclIdentify_t cmd;
- cmd.srcAddr = &(pInMsg->msg->srcAddr);
- cmd.identifyTime = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
- pCBs->pfnIdentify( &cmd );
- }
- }
- else
- {
- zclAttrRec_t attrRec;
- uint16 identifyTime = 0;
- // Retrieve Identify Time
- if ( zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, ATTRID_IDENTIFY_TIME, &attrRec ) )
- zclReadAttrData( (uint8 *)&identifyTime, &attrRec );
- // Is device identifying itself?
- if ( identifyTime > 0 )
- {
- zclGeneral_SendIdentifyQueryResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- identifyTime, true, pInMsg->hdr.transSeqNum );
- }
- return ( ZCL_STATUS_CMD_HAS_RSP );
- }
- }
- else // Client Command
- {
- if ( pInMsg->hdr.commandID > COMMAND_IDENTIFY_QUERY_RSP )
- return ( ZFailure ); // Error ignore the command
- if ( pCBs->pfnIdentifyQueryRsp )
- {
- zclIdentifyQueryRsp_t rsp;
- rsp.srcAddr = &(pInMsg->msg->srcAddr);
- rsp.timeout = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
- pCBs->pfnIdentifyQueryRsp( &rsp );
- }
- }
- return ( ZSuccess );
- }
- #endif // ZCL_IDENTIFY
- #ifdef ZCL_GROUPS
- /*********************************************************************
- * @fn zclGeneral_AddGroup
- *
- * @brief Add a Group.
- *
- * @param endPoint - application endpoint
- * @param group - group to be added
- * @param pData - pointer to the group info
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_AddGroup( uint8 endPoint, aps_Group_t *group, uint8 *pData )
- {
- zclAttrRec_t attrRec;
- uint8 nameLen;
- uint8 nameSupport = FALSE;
- pData += 2; // Move past group ID
- nameLen = *pData++;
- // Retrieve Name Support attribute
- if ( zclFindAttrRec( endPoint, ZCL_CLUSTER_ID_GEN_GROUPS, ATTRID_GROUP_NAME_SUPPORT, &attrRec ) )
- zclReadAttrData( &nameSupport, &attrRec );
- if ( nameSupport )
- {
- if ( nameLen > (APS_GROUP_NAME_LEN-1) )
- nameLen = (APS_GROUP_NAME_LEN-1);
- group->name[0] = nameLen;
- osal_memcpy( &(group->name[1]), pData, nameLen );
- }
- return ( aps_AddGroup( endPoint, group ) );
- }
- /*********************************************************************
- * @fn zclGeneral_ProcessInGroupsServer
- *
- * @brief Process in the received Groups Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInGroupsServer( zclIncoming_t *pInMsg )
- {
- zclAttrRec_t attrRec;
- aps_Group_t group;
- aps_Group_t *pGroup;
- uint8 *pData;
- uint8 status;
- uint8 grpCnt;
- uint8 grpRspCnt = 0;
- uint16 *grpList;
- uint16 identifyTime = 0;
- uint8 i;
- ZStatus_t stat = ZSuccess;
- osal_memset( (uint8*)&group, 0, sizeof( aps_Group_t ) );
- pData = pInMsg->pData;
- group.ID = BUILD_UINT16( pData[0], pData[1] );
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_GROUP_ADD:
- status = zclGeneral_AddGroup( pInMsg->msg->endPoint, &group, pData );
- if ( status != ZSuccess )
- {
- if ( status == ZApsDuplicateEntry )
- status = ZCL_STATUS_DUPLICATE_EXISTS;
- else
- status = ZCL_STATUS_INSUFFICIENT_SPACE;
- }
- zclGeneral_SendGroupAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, group.ID, true, pInMsg->hdr.transSeqNum );
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_GROUP_VIEW:
- pGroup = aps_FindGroup( pInMsg->msg->endPoint, group.ID );
- if ( pGroup )
- {
- status = ZCL_STATUS_SUCCESS;
- }
- else
- {
- // Group not found
- status = ZCL_STATUS_NOT_FOUND;
- pGroup = &group;
- }
- zclGeneral_SendGroupViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, pGroup, true, pInMsg->hdr.transSeqNum );
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_GROUP_GET_MEMBERSHIP:
- grpCnt = *pData++;
-
- // Allocate space for the group list
- grpList = osal_mem_alloc( sizeof( uint16 ) * APS_MAX_GROUPS );
- if ( grpList != NULL )
- {
- if ( grpCnt == 0 )
- {
- // Find out all the groups of which the endpoint is a member.
- grpRspCnt = aps_FindAllGroupsForEndpoint( pInMsg->msg->endPoint, grpList );
- }
- else
- {
- // Find out the groups (in the list) of which the endpoint is a member.
- for ( i = 0; i < grpCnt; i++ )
- {
- group.ID = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- if ( aps_FindGroup( pInMsg->msg->endPoint, group.ID ) )
- grpList[grpRspCnt++] = group.ID;
- }
- }
-
- if ( grpCnt == 0 || grpRspCnt != 0 )
- {
- zclGeneral_SendGroupGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- aps_GroupsRemaingCapacity(), grpRspCnt,
- grpList, true, pInMsg->hdr.transSeqNum );
- }
- osal_mem_free( grpList );
- }
- else
- {
- // Couldn't allocate space for the group list -- send a Default Response command back.
- zclDefaultRspCmd_t defaultRspCmd;
-
- defaultRspCmd.commandID = pInMsg->hdr.commandID;
- defaultRspCmd.statusCode = ZCL_STATUS_INSUFFICIENT_SPACE;
- zcl_SendDefaultRspCmd( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
- pInMsg->msg->clusterId, &defaultRspCmd,
- ZCL_FRAME_SERVER_CLIENT_DIR, true, pInMsg->hdr.transSeqNum );
- }
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_GROUP_REMOVE:
- if ( aps_RemoveGroup( pInMsg->msg->endPoint, group.ID ) )
- status = ZCL_STATUS_SUCCESS;
- else
- status = ZCL_STATUS_NOT_FOUND;
- zclGeneral_SendGroupRemoveResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, group.ID, true, pInMsg->hdr.transSeqNum );
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_GROUP_REMOVE_ALL:
- aps_RemoveAllGroup( pInMsg->msg->endPoint );
- break;
- case COMMAND_GROUP_ADD_IF_IDENTIFYING:
- // Retrieve Identify Time
- if ( zclFindAttrRec( pInMsg->msg->endPoint, ZCL_CLUSTER_ID_GEN_IDENTIFY, ATTRID_IDENTIFY_TIME, &attrRec ) )
- zclReadAttrData( (uint8 *)&identifyTime, &attrRec );
- // Is device identifying itself?
- if ( identifyTime > 0 )
- zclGeneral_AddGroup( pInMsg->msg->endPoint, &group, pData );
- break;
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- /*********************************************************************
- * @fn zclGeneral_ProcessInGroupsClient
- *
- * @brief Process in the received Groups Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInGroupsClient( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- aps_Group_t group;
- uint8 *pData = pInMsg->pData;
- uint16 *grpList;
- uint8 grpCnt;
- uint8 nameLen;
- zclGroupRsp_t rsp;
- uint8 i;
- ZStatus_t stat = ZSuccess;
- osal_memset( (uint8*)&group, 0, sizeof( aps_Group_t ) );
- osal_memset( (uint8*)&rsp, 0, sizeof( zclGroupRsp_t ) );
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_GROUP_ADD_RSP:
- case COMMAND_GROUP_VIEW_RSP:
- case COMMAND_GROUP_REMOVE_RSP:
- rsp.status = *pData++;
- group.ID = BUILD_UINT16( pData[0], pData[1] );
- if ( rsp.status == ZCL_STATUS_SUCCESS && pInMsg->hdr.commandID == COMMAND_GROUP_VIEW_RSP )
- {
- pData += 2; // Move past ID
- nameLen = *pData++;
- if ( nameLen > (APS_GROUP_NAME_LEN-1) )
- nameLen = (APS_GROUP_NAME_LEN-1);
- group.name[0] = nameLen;
- osal_memcpy( &(group.name[1]), pData, nameLen );
- rsp.grpName = group.name;
- }
- if ( pCBs->pfnGroupRsp )
- {
- rsp.srcAddr = &(pInMsg->msg->srcAddr);
- rsp.cmdID = pInMsg->hdr.commandID;
- rsp.grpCnt = 1;
- rsp.grpList = &group.ID;
- rsp.capacity = 0;
- pCBs->pfnGroupRsp( &rsp );
- }
- break;
- case COMMAND_GROUP_GET_MEMBERSHIP_RSP:
- rsp.capacity = *pData++;
- grpCnt = *pData++;
- if ( grpCnt > 0 )
- {
- // Allocate space for the group list
- grpList = osal_mem_alloc( sizeof( uint16 ) * grpCnt );
- if ( grpList != NULL )
- {
- rsp.grpCnt = grpCnt;
- for ( i = 0; i < grpCnt; i++ )
- {
- grpList[i] = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- }
- }
- }
- if ( pCBs->pfnGroupRsp )
- {
- rsp.srcAddr = &(pInMsg->msg->srcAddr);
- rsp.cmdID = pInMsg->hdr.commandID;
- rsp.grpList = grpList;
- pCBs->pfnGroupRsp( &rsp );
- }
-
- if ( grpList != NULL )
- osal_mem_free( grpList );
- break;
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- #endif // ZCL_GROUPS
- #ifdef ZCL_SCENES
- /*********************************************************************
- * @fn zclGeneral_AddScene
- *
- * @brief Add a scene for an endpoint
- *
- * @param endpoint -
- * @param scene - new scene item
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_AddScene( uint8 endpoint, zclGeneral_Scene_t *scene )
- {
- zclGenSceneItem_t *pNewItem;
- zclGenSceneItem_t *pLoop;
- // Fill in the new profile list
- pNewItem = osal_mem_alloc( sizeof( zclGenSceneItem_t ) );
- if ( pNewItem == NULL )
- return ( ZMemError );
- // Fill in the plugin record.
- pNewItem->next = (zclGenSceneItem_t *)NULL;
- pNewItem->endpoint = endpoint;
- osal_memcpy( (uint8*)&(pNewItem->scene), (uint8*)scene, sizeof ( zclGeneral_Scene_t ));
- // Find spot in list
- if ( zclGenSceneTable == NULL )
- {
- zclGenSceneTable = pNewItem;
- }
- else
- {
- // Look for end of list
- pLoop = zclGenSceneTable;
- while ( pLoop->next != NULL )
- pLoop = pLoop->next;
- // Put new item at end of list
- pLoop->next = pNewItem;
- }
- // Update NV
- zclGeneral_ScenesWriteNV();
- return ( ZSuccess );
- }
- /*********************************************************************
- * @fn zclGeneral_FindScene
- *
- * @brief Find a scene with endpoint and sceneID
- *
- * @param endpoint -
- * @param groupID - what group the scene belongs to
- * @param sceneID - ID to look for scene
- *
- * @return a pointer to the scene information, NULL if not found
- */
- zclGeneral_Scene_t *zclGeneral_FindScene( uint8 endpoint, uint16 groupID, uint8 sceneID )
- {
- zclGenSceneItem_t *pLoop;
- // Look for end of list
- pLoop = zclGenSceneTable;
- while ( pLoop )
- {
- if ( (pLoop->endpoint == endpoint || endpoint == 0xFF)
- && pLoop->scene.groupID == groupID && pLoop->scene.ID == sceneID )
- {
- return ( &(pLoop->scene) );
- }
- pLoop = pLoop->next;
- }
- return ( (zclGeneral_Scene_t *)NULL );
- }
- /*********************************************************************
- * @fn aps_FindAllScensForGroup
- *
- * @brief Find all the scenes with groupID
- *
- * @param endpoint - endpoint to look for
- * @param sceneList - List to hold scene IDs (should hold APS_MAX_SCENES entries)
- *
- * @return number of scenes copied to sceneList
- */
- uint8 zclGeneral_FindAllScenesForGroup( uint8 endpoint, uint16 groupID, uint8 *sceneList )
- {
- zclGenSceneItem_t *pLoop;
- uint8 cnt = 0;
- // Look for end of list
- pLoop = zclGenSceneTable;
- while ( pLoop )
- {
- if ( pLoop->endpoint == endpoint && pLoop->scene.groupID == groupID )
- sceneList[cnt++] = pLoop->scene.ID;
- pLoop = pLoop->next;
- }
- return ( cnt );
- }
- /*********************************************************************
- * @fn zclGeneral_RemoveScene
- *
- * @brief Remove a scene with endpoint and sceneID
- *
- * @param endpoint -
- * @param groupID - what group the scene belongs to
- * @param sceneID - ID to look for scene
- *
- * @return TRUE if removed, FALSE if not found
- */
- uint8 zclGeneral_RemoveScene( uint8 endpoint, uint16 groupID, uint8 sceneID )
- {
- zclGenSceneItem_t *pLoop;
- zclGenSceneItem_t *pPrev;
- // Look for end of list
- pLoop = zclGenSceneTable;
- pPrev = NULL;
- while ( pLoop )
- {
- if ( pLoop->endpoint == endpoint
- && pLoop->scene.groupID == groupID && pLoop->scene.ID == sceneID )
- {
- if ( pPrev == NULL )
- zclGenSceneTable = pLoop->next;
- else
- pPrev->next = pLoop->next;
- // Free the memory
- osal_mem_free( pLoop );
- // Update NV
- zclGeneral_ScenesWriteNV();
- return ( TRUE );
- }
- pPrev = pLoop;
- pLoop = pLoop->next;
- }
- return ( FALSE );
- }
- /*********************************************************************
- * @fn zclGeneral_RemoveAllScenes
- *
- * @brief Remove all scenes with endpoint and group Id
- *
- * @param endpoint -
- * @param groupID - ID to look for group
- *
- * @return none
- */
- void zclGeneral_RemoveAllScenes( uint8 endpoint, uint16 groupID )
- {
- zclGenSceneItem_t *pLoop;
- zclGenSceneItem_t *pPrev;
- zclGenSceneItem_t *pNext;
- // Look for end of list
- pLoop = zclGenSceneTable;
- pPrev = NULL;
- while ( pLoop )
- {
- if ( pLoop->endpoint == endpoint && pLoop->scene.groupID == groupID )
- {
- if ( pPrev == NULL )
- zclGenSceneTable = pLoop->next;
- else
- pPrev->next = pLoop->next;
- pNext = pLoop->next;
- // Free the memory
- osal_mem_free( pLoop );
- pLoop = pNext;
- }
- else
- {
- pPrev = pLoop;
- pLoop = pLoop->next;
- }
- }
- // Update NV
- zclGeneral_ScenesWriteNV();
- }
- /*********************************************************************
- * @fn zclGeneral_CountScenes
- *
- * @brief Count the number of scenes for an endpoint
- *
- * @param endpoint -
- *
- * @return number of scenes assigned to an endpoint
- */
- uint8 zclGeneral_CountScenes( uint8 endpoint )
- {
- zclGenSceneItem_t *pLoop;
- uint8 cnt = 0;
- // Look for end of list
- pLoop = zclGenSceneTable;
- while ( pLoop )
- {
- if ( pLoop->endpoint == endpoint )
- cnt++;
- pLoop = pLoop->next;
- }
- return ( cnt );
- }
- /*********************************************************************
- * @fn zclGeneral_CountAllScenes
- *
- * @brief Count the total number of scenes
- *
- * @param none
- *
- * @return number of scenes
- */
- uint8 zclGeneral_CountAllScenes( void )
- {
- zclGenSceneItem_t *pLoop;
- uint8 cnt = 0;
- // Look for end of list
- pLoop = zclGenSceneTable;
- while ( pLoop )
- {
- cnt++;
- pLoop = pLoop->next;
- }
- return ( cnt );
- }
- /*********************************************************************
- * @fn zclGeneral_ProcessInScenesServer
- *
- * @brief Process in the received Scenes Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInScenesServer( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- zclAttrRec_t attrRec;
- zclGeneral_Scene_t scene;
- zclGeneral_Scene_t *pScene;
- uint8 *pData = pInMsg->pData;
- uint8 nameLen;
- uint8 status;
- uint8 sceneCnt = 0;
- uint8 *sceneList = NULL;
- uint8 sendRsp = FALSE;
- uint8 nameSupport = FALSE;
- ZStatus_t stat = ZSuccess;
- osal_memset( (uint8*)&scene, 0, sizeof( zclGeneral_Scene_t ) );
- scene.groupID = BUILD_UINT16( pData[0], pData[1] );
- pData += 2; // Move past group ID
- scene.ID = *pData++;
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_SCENE_ADD:
- // Parse the rest of the incoming message
- scene.transTime = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- nameLen= *pData++; // Name length
- // Retrieve Name Support attribute
- if ( zclFindAttrRec( pInMsg->msg->endPoint, ZCL_CLUSTER_ID_GEN_SCENES, ATTRID_SCENES_NAME_SUPPORT, &attrRec ) )
- zclReadAttrData( &nameSupport, &attrRec );
- if ( nameSupport )
- {
- if ( nameLen > (ZCL_GEN_SCENE_NAME_LEN-1) )
- nameLen = (ZCL_GEN_SCENE_NAME_LEN-1);
- scene.name[0] = nameLen;
- osal_memcpy( &(scene.name[1]), pData, nameLen );
- }
- pData += nameLen; // move pass name
- scene.extLen = pInMsg->pDataLen - ( (uint8)( pData - pInMsg->pData ) );
- if ( scene.extLen > 0 )
- {
- // Copy the extention field(s)
- if ( scene.extLen > ZCL_GEN_SCENE_EXT_LEN )
- scene.extLen = ZCL_GEN_SCENE_EXT_LEN;
- osal_memcpy( scene.extField, pData, scene.extLen );
- }
- if ( scene.groupID == 0x0000 ||
- aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
- {
- // Either the Scene doesn't belong to a Group (Group ID = 0x0000) or it
- // does and the corresponding Group exits
- pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
- if ( pScene || ( zclGeneral_CountAllScenes() < ZCL_GEN_MAX_SCENES ) )
- {
- status = ZCL_STATUS_SUCCESS;
- if ( pScene != NULL )
- {
- // The Scene already exists so update it
- pScene->transTime = scene.transTime;
- osal_memcpy( pScene->name, scene.name, ZCL_GEN_SCENE_NAME_LEN );
- // Use the new extention field(s)
- osal_memcpy( pScene->extField, scene.extField, scene.extLen );
- pScene->extLen = scene.extLen;
- // Update NV
- zclGeneral_ScenesWriteNV();
- }
- else
- {
- // The Scene doesn't exist so add it
- zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
- }
- }
- else
- status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
- }
- else
- status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
- zclGeneral_SendSceneAddResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, scene.groupID, scene.ID,
- true, pInMsg->hdr.transSeqNum );
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_SCENE_VIEW:
- pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
- if ( pScene != NULL )
- {
- status = ZCL_STATUS_SUCCESS;
- }
- else
- {
- // Scene not found
- if ( scene.groupID != 0x0000 &&
- aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) == NULL )
- {
- status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
- }
- else
- status = ZCL_STATUS_NOT_FOUND;
- pScene = &scene;
- }
- zclGeneral_SendSceneViewResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, pScene, true, pInMsg->hdr.transSeqNum );
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_SCENE_REMOVE:
- if ( zclGeneral_RemoveScene( pInMsg->msg->endPoint, scene.groupID, scene.ID ) )
- {
- status = ZCL_STATUS_SUCCESS;
- }
- else
- {
- // Scene not found
- if ( aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) == NULL )
- {
- // The Group is not in the Group Table
- status = ZCL_STATUS_INVALID_FIELD;
- }
- else
- status = ZCL_STATUS_NOT_FOUND;
- }
- if ( UNICAST_MSG( pInMsg->msg ) )
- {
- // Addressed to this device (not to a group) - send a response back
- zclGeneral_SendSceneRemoveResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, scene.groupID,
- scene.ID, true, pInMsg->hdr.transSeqNum );
- }
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_SCENE_REMOVE_ALL:
- if ( scene.groupID == 0x0000 ||
- aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
- {
- zclGeneral_RemoveAllScenes( pInMsg->msg->endPoint, scene.groupID );
- status = ZCL_STATUS_SUCCESS;
- }
- else
- status = ZCL_STATUS_INVALID_FIELD;
- if ( UNICAST_MSG( pInMsg->msg ) )
- {
- // Addressed to this device (not to a group) - send a response back
- zclGeneral_SendSceneRemoveAllResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, scene.groupID, true, pInMsg->hdr.transSeqNum );
- }
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_SCENE_STORE:
- if ( scene.groupID == 0x0000 ||
- aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
- {
- // Either the Scene doesn't belong to a Group (Group ID = 0x0000) or it
- // does and the corresponding Group exits
- pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
- if ( pScene || ( zclGeneral_CountAllScenes() < ZCL_GEN_MAX_SCENES ) )
- {
- uint8 sceneChanged = FALSE;
- status = ZCL_STATUS_SUCCESS;
- if ( pScene == NULL )
- {
- // Haven't been added yet
- pScene = &scene;
- }
- if ( pCBs->pfnSceneStoreReq )
- {
- zclSceneReq_t req;
- req.srcAddr = &(pInMsg->msg->srcAddr);
- req.scene = pScene;
- // Get the latest Scene info
- if ( pCBs->pfnSceneStoreReq( &req ) )
- sceneChanged = TRUE;
- }
- if ( pScene == &scene )
- {
- // The Scene doesn't exist so add it
- zclGeneral_AddScene( pInMsg->msg->endPoint, &scene );
- }
- else if ( sceneChanged )
- {
- // The Scene already exists so update only NV
- zclGeneral_ScenesWriteNV();
- }
- }
- else
- status = ZCL_STATUS_INSUFFICIENT_SPACE; // The Scene Table is full
- }
- else
- status = ZCL_STATUS_INVALID_FIELD; // The Group is not in the Group Table
- if ( UNICAST_MSG( pInMsg->msg ) )
- {
- // Addressed to this device (not to a group) - send a response back
- zclGeneral_SendSceneStoreResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, scene.groupID, scene.ID,
- true, pInMsg->hdr.transSeqNum );
- }
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_SCENE_RECALL:
- pScene = zclGeneral_FindScene( pInMsg->msg->endPoint, scene.groupID, scene.ID );
- if ( pScene && pCBs->pfnSceneRecallReq )
- {
- zclSceneReq_t req;
- req.srcAddr = &(pInMsg->msg->srcAddr);
- req.scene = pScene;
- pCBs->pfnSceneRecallReq( &req );
- }
- // No response
- break;
- case COMMAND_SCENE_GET_MEMBERSHIP:
- // Find all the Scenes corresponding to the Group ID
- if ( scene.groupID == 0x0000 ||
- aps_FindGroup( pInMsg->msg->endPoint, scene.groupID ) != NULL )
- {
- // Allocate space for the scene list
- sceneList = osal_mem_alloc( ZCL_GEN_MAX_SCENES );
- if ( sceneList != NULL )
- {
- sceneCnt = zclGeneral_FindAllScenesForGroup( pInMsg->msg->endPoint,
- scene.groupID, sceneList );
- status = ZCL_STATUS_SUCCESS;
- if ( UNICAST_MSG( pInMsg->msg ) )
- {
- // Addressed only to this device - send a response back
- sendRsp = TRUE;
- }
- else
- {
- // Addressed to the Group - ONLY send a response if an entry within the
- // Scene Table corresponds to the Group ID
- if ( sceneCnt != 0 )
- sendRsp = TRUE;
- }
- }
- else
- {
- // Couldn't allocate space for the scene list!
- status = ZCL_STATUS_INSUFFICIENT_SPACE;
- sendRsp = TRUE;
- }
- }
- else
- {
- // The Group is not in the Group Table - send a response back
- status = ZCL_STATUS_INVALID_FIELD;
- sendRsp = TRUE;
- }
- if ( sendRsp )
- {
- zclGeneral_SendSceneGetMembershipResponse( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- status, zclGeneral_ScenesRemaingCapacity(), sceneCnt, sceneList,
- scene.groupID, true, pInMsg->hdr.transSeqNum );
- }
-
- if ( sceneList != NULL )
- osal_mem_free( sceneList );
-
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- /*********************************************************************
- * @fn zclGeneral_ProcessInScenesClient
- *
- * @brief Process in the received Scenes Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInScenesClient( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- zclGeneral_Scene_t scene;
- uint8 *pData = pInMsg->pData;
- uint8 nameLen;
- uint8 *sceneList = NULL;
- zclSceneRsp_t rsp;
- uint8 i;
- ZStatus_t stat = ZSuccess;
- osal_memset( (uint8*)&scene, 0, sizeof( zclGeneral_Scene_t ) );
- osal_memset( (uint8*)&rsp, 0, sizeof( zclSceneRsp_t ) );
- // Get the status field first
- rsp.status = *pData++;
- if ( pInMsg->hdr.commandID == COMMAND_SCENE_GET_MEMBERSHIP_RSP )
- rsp.capacity = *pData++;
- scene.groupID = BUILD_UINT16( pData[0], pData[1] );
- pData += 2; // Move past group ID
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_SCENE_VIEW_RSP:
- // Parse the rest of the incoming message
- scene.ID = *pData++; // Not applicable to Remove All Response command
- scene.transTime = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- nameLen = *pData++; // Name length
- if ( nameLen > (ZCL_GEN_SCENE_NAME_LEN-1) )
- nameLen = (ZCL_GEN_SCENE_NAME_LEN-1);
- scene.name[0] = nameLen;
- osal_memcpy( &(scene.name[1]), pData, nameLen );
- pData += nameLen; // move pass name
- //*** Do something with the extension field(s)
- // Fall through to callback - break is left off intentionally
- case COMMAND_SCENE_ADD_RSP:
- case COMMAND_SCENE_REMOVE_RSP:
- case COMMAND_SCENE_REMOVE_ALL_RSP:
- case COMMAND_SCENE_STORE_RSP:
- if ( pCBs->pfnSceneRsp )
- {
- rsp.srcAddr = &(pInMsg->msg->srcAddr);
- rsp.cmdID = pInMsg->hdr.commandID;
- rsp.scene = &scene;
- pCBs->pfnSceneRsp( &rsp );
- }
- break;
- case COMMAND_SCENE_GET_MEMBERSHIP_RSP:
- if ( rsp.status == ZCL_STATUS_SUCCESS )
- {
- uint8 sceneCnt = *pData++;
-
- if ( sceneCnt > 0 )
- {
- // Allocate space for the scene list
- sceneList = osal_mem_alloc( sceneCnt );
- if ( sceneList != NULL )
- {
- rsp.sceneCnt = sceneCnt;
- for ( i = 0; i < sceneCnt; i++ )
- sceneList[i] = *pData++;
- }
- }
- }
- if ( pCBs->pfnSceneRsp )
- {
- rsp.srcAddr = &(pInMsg->msg->srcAddr);
- rsp.cmdID = pInMsg->hdr.commandID;
- rsp.sceneList = sceneList;
- rsp.scene = &scene;
- pCBs->pfnSceneRsp( &rsp);
- }
-
- if ( sceneList != NULL )
- osal_mem_free( sceneList );
- break;
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- #endif // ZCL_SCENES
- #ifdef ZCL_ON_OFF
- /*********************************************************************
- * @fn zclGeneral_ProcessInCmdOnOff
- *
- * @brief Process in the received On/Off Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInOnOff( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- {
- if ( pInMsg->hdr.commandID > COMMAND_TOGGLE )
- return ( ZFailure ); // Error ignore the command
- if ( pCBs->pfnOnOff )
- pCBs->pfnOnOff( pInMsg->hdr.commandID );
- }
- // no Client command
- return ( ZSuccess );
- }
- #endif // ZCL_ON_OFF
- #ifdef ZCL_LEVEL_CTRL
- /*********************************************************************
- * @fn zclGeneral_ProcessInLevelControl
- *
- * @brief Process in the received Level Control Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInLevelControl( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- uint8 withOnOff = FALSE;
- ZStatus_t stat = ZSuccess;
- if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
- {
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_LEVEL_MOVE_TO_LEVEL_WITH_ON_OFF:
- withOnOff = TRUE;
- // fall through
- case COMMAND_LEVEL_MOVE_TO_LEVEL:
- if ( pCBs->pfnLevelControlMoveToLevel )
- {
- zclLCMoveToLevel_t cmd;
- cmd.level = pInMsg->pData[0];
- cmd.transitionTime = BUILD_UINT16( pInMsg->pData[1], pInMsg->pData[2] );
- cmd.withOnOff = withOnOff;
- pCBs->pfnLevelControlMoveToLevel( &cmd );
- }
- break;
- case COMMAND_LEVEL_MOVE_WITH_ON_OFF:
- withOnOff = TRUE;
- // fall through
- case COMMAND_LEVEL_MOVE:
- if ( pCBs->pfnLevelControlMove )
- {
- zclLCMove_t cmd;
- cmd.moveMode = pInMsg->pData[0];
- cmd.rate = pInMsg->pData[1];
- cmd.withOnOff = withOnOff;
- pCBs->pfnLevelControlMove( &cmd );
- }
- break;
- case COMMAND_LEVEL_STEP_WITH_ON_OFF:
- withOnOff = TRUE;
- // fall through
- case COMMAND_LEVEL_STEP:
- if ( pCBs->pfnLevelControlStep )
- {
- zclLCStep_t cmd;
- cmd.stepMode = pInMsg->pData[0];
- cmd.amount = pInMsg->pData[1];
- cmd.transitionTime = BUILD_UINT16( pInMsg->pData[2], pInMsg->pData[3] );
- cmd.withOnOff = withOnOff;
- pCBs->pfnLevelControlStep( &cmd );
- }
- break;
- case COMMAND_LEVEL_STOP:
- case COMMAND_LEVEL_STOP_WITH_ON_OFF:
- // Both Stop commands are identical
- if ( pCBs->pfnLevelControlStop )
- {
- pCBs->pfnLevelControlStop();
- }
- break;
- default:
- stat = ZFailure;
- break;
- }
- }
- // no Client command
- return ( stat );
- }
- #endif // ZCL_LEVEL_CTRL
- #ifdef ZCL_ALARMS
- /*********************************************************************
- * @fn zclGeneral_AddAlarm
- *
- * @brief Add an alarm for a cluster
- *
- * @param endpoint -
- * @param alarm - new alarm item
- *
- * @return ZStatus_t
- */
- ZStatus_t zclGeneral_AddAlarm( uint8 endpoint, zclGeneral_Alarm_t *alarm )
- {
- zclGenAlarmItem_t *pNewItem;
- zclGenAlarmItem_t *pLoop;
- // Fill in the new profile list
- pNewItem = osal_mem_alloc( sizeof( zclGenAlarmItem_t ) );
- if ( pNewItem == NULL )
- return ( ZMemError );
- // Fill in the plugin record.
- pNewItem->next = (zclGenAlarmItem_t *)NULL;
- pNewItem->endpoint = endpoint;
- osal_memcpy( (uint8*)(&pNewItem->alarm), (uint8*)alarm, sizeof ( zclGeneral_Alarm_t ) );
- // Find spot in list
- if ( zclGenAlarmTable == NULL )
- {
- zclGenAlarmTable = pNewItem;
- }
- else
- {
- // Look for end of list
- pLoop = zclGenAlarmTable;
- while ( pLoop->next != NULL )
- pLoop = pLoop->next;
- // Put new item at end of list
- pLoop->next = pNewItem;
- }
- return ( ZSuccess );
- }
- /*********************************************************************
- * @fn zclGeneral_FindAlarm
- *
- * @brief Find an alarm with alarmCode and clusterID
- *
- * @param endpoint -
- * @param groupID - what group the scene belongs to
- * @param sceneID - ID to look for scene
- *
- * @return a pointer to the alarm information, NULL if not found
- */
- zclGeneral_Alarm_t *zclGeneral_FindAlarm( uint8 endpoint, uint8 alarmCode, uint16 clusterID )
- {
- zclGenAlarmItem_t *pLoop;
- // Look for the alarm
- pLoop = zclGenAlarmTable;
- while ( pLoop )
- {
- if ( pLoop->endpoint == endpoint &&
- pLoop->alarm.code == alarmCode && pLoop->alarm.clusterID == clusterID )
- {
- return ( &(pLoop->alarm) );
- }
- pLoop = pLoop->next;
- }
- return ( (zclGeneral_Alarm_t *)NULL );
- }
- /*********************************************************************
- * @fn zclGeneral_FindEarliestAlarm
- *
- * @brief Find an alarm with the earliest timestamp
- *
- * @param endpoint -
- *
- * @return a pointer to the alarm information, NULL if not found
- */
- zclGeneral_Alarm_t *zclGeneral_FindEarliestAlarm( uint8 endpoint )
- {
- zclGenAlarmItem_t *pLoop;
- zclGenAlarmItem_t earliestAlarm;
- zclGenAlarmItem_t *pEarliestAlarm = &earliestAlarm;
- pEarliestAlarm->alarm.timeStamp = 0xFFFFFFFF;
- // Look for alarm with earliest time
- pLoop = zclGenAlarmTable;
- while ( pLoop )
- {
- if ( pLoop->endpoint == endpoint &&
- pLoop->alarm.timeStamp < pEarliestAlarm->alarm.timeStamp )
- {
- pEarliestAlarm = pLoop;
- }
- pLoop = pLoop->next;
- }
- if ( pEarliestAlarm->alarm.timeStamp != 0xFFFFFFFF )
- return ( &(pEarliestAlarm->alarm) );
- // No alarm
- return ( (zclGeneral_Alarm_t *)NULL );
- }
- /*********************************************************************
- * @fn zclGeneral_ResetAlarm
- *
- * @brief Remove a scene with endpoint and sceneID
- *
- * @param endpoint -
- * @param alarmCode -
- * @param clusterID -
- *
- * @return TRUE if removed, FALSE if not found
- */
- void zclGeneral_ResetAlarm( uint8 endpoint, uint8 alarmCode, uint16 clusterID )
- {
- zclGenAlarmItem_t *pLoop;
- zclGenAlarmItem_t *pPrev;
- // Look for end of list
- pLoop = zclGenAlarmTable;
- pPrev = NULL;
- while ( pLoop )
- {
- if ( pLoop->endpoint == endpoint &&
- pLoop->alarm.code == alarmCode && pLoop->alarm.clusterID == clusterID )
- {
- if ( pPrev == NULL )
- zclGenAlarmTable = pLoop->next;
- else
- pPrev->next = pLoop->next;
- // Free the memory
- osal_mem_free( pLoop );
- // Notify the Application so that if the alarm condition still active then
- // a new notification will be generated, and a new alarm record will be
- // added to the alarm log
- // zclGeneral_NotifyReset( alarmCode, clusterID ); // callback function?
- return;
- }
- pPrev = pLoop;
- pLoop = pLoop->next;
- }
- }
- /*********************************************************************
- * @fn zclGeneral_ResetAllAlarms
- *
- * @brief Remove all alarms with endpoint
- *
- * @param endpoint -
- * @param notifyApp -
- *
- * @return none
- */
- void zclGeneral_ResetAllAlarms( uint8 endpoint, uint8 notifyApp )
- {
- zclGenAlarmItem_t *pLoop;
- zclGenAlarmItem_t *pPrev;
- zclGenAlarmItem_t *pNext;
- // Look for end of list
- pLoop = zclGenAlarmTable;
- pPrev = NULL;
- while ( pLoop )
- {
- if ( pLoop->endpoint == endpoint )
- {
- if ( pPrev == NULL )
- zclGenAlarmTable = pLoop->next;
- else
- pPrev->next = pLoop->next;
- pNext = pLoop->next;
- // Free the memory
- osal_mem_free( pLoop );
- pLoop = pNext;
- }
- else
- {
- pPrev = pLoop;
- pLoop = pLoop->next;
- }
- }
- if ( notifyApp )
- {
- // Notify the Application so that if any alarm conditions still active then
- // a new notification will be generated, and a new alarm record will be
- // added to the alarm log
- // zclGeneral_NotifyResetAll(); // callback function?
- }
- }
- /*********************************************************************
- * @fn zclGeneral_ProcessInAlarmsServer
- *
- * @brief Process in the received Alarms Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInAlarmsServer( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- zclGeneral_Alarm_t *pAlarm;
- uint8 *pData = pInMsg->pData;
- ZStatus_t stat = ZSuccess;
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_ALARMS_RESET:
- zclGeneral_ResetAlarm( pInMsg->msg->endPoint, pData[0],
- BUILD_UINT16( pData[1], pData[2] ) );
- break;
- case COMMAND_ALARMS_RESET_ALL:
- zclGeneral_ResetAllAlarms( pInMsg->msg->endPoint, TRUE );
- break;
- case COMMAND_ALARMS_GET:
- pAlarm = zclGeneral_FindEarliestAlarm( pInMsg->msg->endPoint );
- if ( pAlarm )
- {
- // Send a response back
- zclGeneral_SendAlarmGetRespnose( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- ZCL_STATUS_SUCCESS, pAlarm->code,
- pAlarm->clusterID, pAlarm->timeStamp,
- true, pInMsg->hdr.transSeqNum );
- // Remove the entry from the Alarm table
- zclGeneral_ResetAlarm( pInMsg->msg->endPoint, pAlarm->code, pAlarm->clusterID );
- }
- else
- {
- // Send a response back
- zclGeneral_SendAlarmGetRespnose( pInMsg->msg->endPoint, &pInMsg->msg->srcAddr,
- ZCL_STATUS_NOT_FOUND, 0, 0, 0,
- true, pInMsg->hdr.transSeqNum );
- }
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_ALARMS_RESET_LOG:
- zclGeneral_ResetAllAlarms( pInMsg->msg->endPoint, FALSE );
- break;
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- /*********************************************************************
- * @fn zclGeneral_ProcessInAlarmsClient
- *
- * @brief Process in the received Alarms Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInAlarmsClient( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- uint8 *pData = pInMsg->pData;
- zclAlarm_t alarm;
- ZStatus_t stat = ZSuccess;
- osal_memset( (uint8*)&alarm, 0, sizeof( zclAlarm_t ) );
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_ALARMS_ALARM:
- if ( pCBs->pfnAlarm )
- {
- alarm.srcAddr = &(pInMsg->msg->srcAddr);
- alarm.cmdID = pInMsg->hdr.commandID;
- alarm.status = *pData++;
- alarm.alarmCode = *pData++;
- alarm.clusterID = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- alarm.timeStamp = osal_build_uint32( pData, 4 );
- pCBs->pfnAlarm( &alarm );
- }
- break;
- case COMMAND_ALARMS_GET_RSP:
- if ( pCBs->pfnAlarm )
- {
- alarm.srcAddr = &(pInMsg->msg->srcAddr);
- alarm.cmdID = pInMsg->hdr.commandID;
- alarm.alarmCode = *pData++;
- alarm.clusterID = BUILD_UINT16( pData[0], pData[1] );
- pCBs->pfnAlarm( &alarm );
- }
- break;
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- #endif // ZCL_ALARMS
- #ifdef ZCL_LOCATION
- /*********************************************************************
- * @fn zclGeneral_ProcessInLocationServer
- *
- * @brief Process in the received Location Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInLocationServer( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- uint8 *pData = pInMsg->pData;
- zclLocation_t cmd;
- ZStatus_t stat = ZSuccess;
- osal_memset( (uint8*)&cmd, 0, sizeof( zclLocation_t ) );
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_LOCATION_SET_ABSOLUTE:
- cmd.un.absLoc.coordinate1 = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- cmd.un.absLoc.coordinate2 = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- cmd.un.absLoc.coordinate3 = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- cmd.un.absLoc.power = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- cmd.un.absLoc.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
- if ( pCBs->pfnLocation )
- {
- cmd.srcAddr = &(pInMsg->msg->srcAddr);
- cmd.cmdID = pInMsg->hdr.commandID;
- // Update the absolute location info
- pCBs->pfnLocation( &cmd );
- }
- break;
- case COMMAND_LOCATION_SET_DEV_CFG:
- cmd.un.devCfg.power = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- cmd.un.devCfg.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- cmd.un.devCfg.calcPeriod = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- cmd.un.devCfg.numMeasurements = *pData++;
- cmd.un.devCfg.reportPeriod = BUILD_UINT16( pData[0], pData[1] );
- if ( pCBs->pfnLocation )
- {
- cmd.srcAddr = &(pInMsg->msg->srcAddr);
- cmd.cmdID = pInMsg->hdr.commandID;
- // Update the device configuration info
- pCBs->pfnLocation( &cmd );
- }
- break;
- case COMMAND_LOCATION_GET_DEV_CFG:
- cmd.un.ieeeAddr = pData;
- if ( pCBs->pfnLocation )
- {
- cmd.srcAddr = &(pInMsg->msg->srcAddr);
- cmd.cmdID = pInMsg->hdr.commandID;
- cmd.seqNum = pInMsg->hdr.transSeqNum;
- // Retreive the Device Configuration
- pCBs->pfnLocation( &cmd );
- }
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- case COMMAND_LOCATION_GET_DATA:
- cmd.un.loc.bitmap.locByte = *pData++;
- cmd.un.loc.numResponses = *pData++;
- if ( cmd.un.loc.brdcastResponse == 0 ) // command is sent as a unicast
- osal_cpyExtAddr( cmd.un.loc.targetAddr, pData );
- if ( pCBs->pfnLocation )
- {
- cmd.srcAddr = &(pInMsg->msg->srcAddr);
- cmd.cmdID = pInMsg->hdr.commandID;
- cmd.seqNum = pInMsg->hdr.transSeqNum;
- // Retreive the Location Data
- pCBs->pfnLocation( &cmd );
- }
- stat = ZCL_STATUS_CMD_HAS_RSP;
- break;
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- /*********************************************************************
- * @fn zclGeneral_ProcessInLocationDataRsp
- *
- * @brief Process in the received Location Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static void zclGeneral_ProcessInLocationDataRsp( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- uint8 *pData = pInMsg->pData;
- zclLocationRsp_t rsp;
- osal_memset( (uint8*)&rsp, 0, sizeof( zclLocationRsp_t ) );
- if ( pCBs->pfnLocationRsp )
- {
- if ( pInMsg->hdr.commandID == COMMAND_LOCATION_DATA_RSP )
- rsp.un.loc.status = *pData++;
- if ( pInMsg->hdr.commandID != COMMAND_LOCATION_DATA_RSP ||
- rsp.un.loc.status == ZCL_STATUS_SUCCESS )
- {
- rsp.un.loc.data.type = *pData++;
- rsp.un.loc.data.absLoc.coordinate1 = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- rsp.un.loc.data.absLoc.coordinate2 = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- if ( locationType2D( rsp.un.loc.data.type ) == 0 )
- {
- rsp.un.loc.data.absLoc.coordinate3 = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- }
- if ( pInMsg->hdr.commandID != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
- {
- rsp.un.loc.data.absLoc.power = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- rsp.un.loc.data.absLoc.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- }
- if ( locationTypeAbsolute( rsp.un.loc.data.type ) == 0 )
- {
- if ( pInMsg->hdr.commandID != COMMAND_LOCATION_COMPACT_DATA_NOTIF )
- rsp.un.loc.data.calcLoc.locationMethod = *pData++;
- rsp.un.loc.data.calcLoc.qualityMeasure = *pData++;
- rsp.un.loc.data.calcLoc.locationAge = BUILD_UINT16( pData[0], pData[1] );
- }
- }
- rsp.srcAddr = &(pInMsg->msg->srcAddr);
- rsp.cmdID = pInMsg->hdr.commandID;
- // Notify the Application
- pCBs->pfnLocationRsp( &rsp );
- }
- }
- /*********************************************************************
- * @fn zclGeneral_ProcessInLocationClient
- *
- * @brief Process in the received Location Command.
- *
- * @param pInMsg - pointer to the incoming message
- *
- * @return ZStatus_t
- */
- static ZStatus_t zclGeneral_ProcessInLocationClient( zclIncoming_t *pInMsg,
- zclGeneral_AppCallbacks_t *pCBs )
- {
- uint8 *pData = pInMsg->pData;
- zclLocationRsp_t rsp;
- ZStatus_t stat = ZSuccess;
- osal_memset( (uint8*)&rsp, 0, sizeof( zclLocationRsp_t ) );
- switch ( pInMsg->hdr.commandID )
- {
- case COMMAND_LOCATION_DEV_CFG_RSP:
- if ( pCBs->pfnLocationRsp )
- {
- rsp.un.devCfg.status = *pData++;
- if ( rsp.un.devCfg.status == ZCL_STATUS_SUCCESS )
- {
- rsp.un.devCfg.data.power = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- rsp.un.devCfg.data.pathLossExponent = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- rsp.un.devCfg.data.calcPeriod = BUILD_UINT16( pData[0], pData[1] );
- pData += 2;
- rsp.un.devCfg.data.numMeasurements = *pData++;
- rsp.un.devCfg.data.reportPeriod = BUILD_UINT16( pData[0], pData[1] );
- rsp.srcAddr = &(pInMsg->msg->srcAddr);
- rsp.cmdID = pInMsg->hdr.commandID;
- // Notify the Application
- pCBs->pfnLocationRsp( &rsp );
- }
- }
- break;
- case COMMAND_LOCATION_DATA_RSP:
- case COMMAND_LOCATION_DATA_NOTIF:
- case COMMAND_LOCATION_COMPACT_DATA_NOTIF:
- zclGeneral_ProcessInLocationDataRsp( pInMsg, pCBs );
- break;
- case COMMAND_LOCATION_RSSI_PING:
- if ( pCBs->pfnLocationRsp )
- {
- rsp.un.locationType = *pData;
- rsp.srcAddr = &(pInMsg->msg->srcAddr);
- rsp.cmdID = pInMsg->hdr.commandID;
- // Notify the Application
- pCBs->pfnLocationRsp( &rsp );
- }
- break;
- default:
- stat = ZFailure;
- break;
- }
- return ( stat );
- }
- #endif // ZCL_LOCATION
- #ifdef ZCL_SCENES
- /*********************************************************************
- * @fn zclGeneral_ScenesInitNV
- *
- * @brief Initialize the NV Scene Table Items
- *
- * @param none
- *
- * @return number of scenes
- */
- static uint8 zclGeneral_ScenesInitNV( void )
- {
- uint8 status;
- uint16 size;
- size = (uint16)((sizeof ( nvGenScenesHdr_t ))
- + ( sizeof( zclGenSceneNVItem_t ) * ZCL_GEN_MAX_SCENES ));
- status = osal_nv_item_init( ZCD_NV_SCENE_TABLE, size, NULL );
- if ( status != ZSUCCESS )
- {
- zclGeneral_ScenesSetDefaultNV();
- }
- return status;
- }
- /*********************************************************************
- * @fn zclGeneral_ScenesSetDefaultNV
- *
- * @brief Write the defaults to NV
- *
- * @param none
- *
- * @return none
- */
- static void zclGeneral_ScenesSetDefaultNV( void )
- {
- nvGenScenesHdr_t hdr;
- // Initialize the header
- hdr.numRecs = 0;
- // Save off the header
- osal_nv_write( ZCD_NV_SCENE_TABLE, 0, sizeof( nvGenScenesHdr_t ), &hdr );
- }
- /*********************************************************************
- * @fn zclGeneral_ScenesWriteNV
- *
- * @brief Save the Scene Table in NV
- *
- * @param none
- *
- * @return none
- */
- static void zclGeneral_ScenesWriteNV( void )
- {
- nvGenScenesHdr_t hdr;
- zclGenSceneItem_t *pLoop;
- zclGenSceneNVItem_t item;
- hdr.numRecs = 0;
- // Look for end of list
- pLoop = zclGenSceneTable;
- while ( pLoop )
- {
- // Build the record
- item.endpoint = pLoop->endpoint;
- osal_memcpy( &(item.scene), &(pLoop->scene), sizeof ( zclGeneral_Scene_t ) );
- // Save the record to NV
- osal_nv_write( ZCD_NV_SCENE_TABLE,
- (uint16)((sizeof( nvGenScenesHdr_t )) + (hdr.numRecs * sizeof ( zclGenSceneNVItem_t ))),
- sizeof ( zclGenSceneNVItem_t ), &item );
- hdr.numRecs++;
- pLoop = pLoop->next;
- }
- // Save off the header
- osal_nv_write( ZCD_NV_SCENE_TABLE, 0, sizeof( nvGenScenesHdr_t ), &hdr );
- }
- /*********************************************************************
- * @fn zclGeneral_ScenesRestoreFromNV
- *
- * @brief Restore the Scene table from NV
- *
- * @param none
- *
- * @return Number of entries restored
- */
- static uint16 zclGeneral_ScenesRestoreFromNV( void )
- {
- uint16 x;
- nvGenScenesHdr_t hdr;
- zclGenSceneNVItem_t item;
- uint16 numAdded = 0;
- if ( osal_nv_read( ZCD_NV_SCENE_TABLE, 0, sizeof(nvGenScenesHdr_t), &hdr ) == ZSuccess )
- {
- // Read in the device list
- for ( x = 0; x < hdr.numRecs; x++ )
- {
- if ( osal_nv_read( ZCD_NV_SCENE_TABLE,
- (uint16)(sizeof(nvGenScenesHdr_t) + (x * sizeof ( zclGenSceneNVItem_t ))),
- sizeof ( zclGenSceneNVItem_t ), &item ) == ZSUCCESS )
- {
- // Add the scene
- if ( zclGeneral_AddScene( item.endpoint, &(item.scene) ) == ZSuccess )
- {
- numAdded++;
- }
- }
- }
- }
- return ( numAdded );
- }
- #endif // ZCL_SCENES
- /***************************************************************************
- ****************************************************************************/
|