1521 lines
46 KiB
C
1521 lines
46 KiB
C
/**************************************************************************************************
|
|
Filename: zcl_ss.c
|
|
Revised: $Date: 2010-02-09 15:28:14 -0800 (Tue, 09 Feb 2010) $
|
|
Revision: $Revision: 21679 $
|
|
|
|
Description: Zigbee Cluster Library - Security and Safety ( SS )
|
|
|
|
|
|
Copyright 2006-2010 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 "zcl.h"
|
|
#include "zcl_general.h"
|
|
#include "zcl_ss.h"
|
|
|
|
#if defined ( INTER_PAN )
|
|
#include "stub_aps.h"
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* MACROS
|
|
*/
|
|
#define zclSS_ZoneTypeSupported( a ) ( (a) == SS_IAS_ZONE_TYPE_STANDARD_CIE || \
|
|
(a) == SS_IAS_ZONE_TYPE_MOTION_SENSOR || \
|
|
(a) == SS_IAS_ZONE_TYPE_CONTACT_SWITCH || \
|
|
(a) == SS_IAS_ZONE_TYPE_FIRE_SENSOR || \
|
|
(a) == SS_IAS_ZONE_TYPE_WATER_SENSOR || \
|
|
(a) == SS_IAS_ZONE_TYPE_GAS_SENSOR || \
|
|
(a) == SS_IAS_ZONE_TYPE_PERSONAL_EMERGENCY_DEVICE || \
|
|
(a) == SS_IAS_ZONE_TYPE_VIBRATION_MOVEMENT_SENSOR || \
|
|
(a) == SS_IAS_ZONE_TYPE_REMOTE_CONTROL || \
|
|
(a) == SS_IAS_ZONE_TYPE_KEY_FOB || \
|
|
(a) == SS_IAS_ZONE_TYPE_KEYPAD || \
|
|
(a) == SS_IAS_ZONE_TYPE_STANDARD_WARNING_DEVICE )
|
|
|
|
/*******************************************************************************
|
|
* CONSTANTS
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
* TYPEDEFS
|
|
*/
|
|
typedef struct zclSSCBRec
|
|
{
|
|
struct zclSSCBRec *next;
|
|
uint8 endpoint; // Used to link it into the endpoint descriptor
|
|
zclSS_AppCallbacks_t *CBs; // Pointer to Callback function
|
|
} zclSSCBRec_t;
|
|
|
|
typedef struct zclSS_ZoneItem
|
|
{
|
|
struct zclSS_ZoneItem *next;
|
|
uint8 endpoint; // Used to link it into the endpoint descriptor
|
|
IAS_ACE_ZoneTable_t zone; // Zone info
|
|
} zclSS_ZoneItem_t;
|
|
|
|
/*******************************************************************************
|
|
* GLOBAL VARIABLES
|
|
*/
|
|
const uint8 zclSS_UknownIeeeAddress[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
|
|
|
/*******************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
* LOCAL VARIABLES
|
|
*/
|
|
static zclSSCBRec_t *zclSSCBs = (zclSSCBRec_t *)NULL;
|
|
static uint8 zclSSPluginRegisted = FALSE;
|
|
|
|
#if defined(ZCL_ZONE) || defined(ZCL_ACE)
|
|
static zclSS_ZoneItem_t *zclSS_ZoneTable = (zclSS_ZoneItem_t *)NULL;
|
|
#endif // ZCL_ZONE || ZCL_ACE
|
|
|
|
/*******************************************************************************
|
|
* LOCAL FUNCTIONS
|
|
*/
|
|
static ZStatus_t zclSS_HdlIncoming( zclIncoming_t *pInHdlrMsg );
|
|
static ZStatus_t zclSS_HdlInSpecificCommands( zclIncoming_t *pInMsg );
|
|
static zclSS_AppCallbacks_t *zclSS_FindCallbacks( uint8 endpoint );
|
|
|
|
#ifdef ZCL_ZONE
|
|
static ZStatus_t zclSS_ProcessInZoneStatusCmdsServer( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static ZStatus_t zclSS_ProcessInZoneStatusCmdsClient( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
|
|
static void zclSS_ProcessInCmd_ZoneStatus_ChangeNotification( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static ZStatus_t zclSS_ProcessInCmd_ZoneStatus_EnrollRequest( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static void zclSS_ProcessInCmd_ZoneStatus_EnrollResponse( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
#endif // ZCL_ZONE
|
|
|
|
#ifdef ZCL_ACE
|
|
static ZStatus_t zclSS_ProcessInACECmdsServer( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static ZStatus_t zclSS_ProcessInACECmdsClient( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
|
|
static ZStatus_t zclSS_ProcessInCmd_ACE_Arm( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static void zclSS_ProcessInCmd_ACE_Bypass( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static void zclSS_ProcessInCmd_ACE_Emergency( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static void zclSS_ProcessInCmd_ACE_Fire( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static void zclSS_ProcessInCmd_ACE_Panic( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static ZStatus_t zclSS_ProcessInCmd_ACE_GetZoneIDMap( zclIncoming_t *pInMsg );
|
|
static ZStatus_t zclSS_ProcessInCmd_ACE_GetZoneInformation( zclIncoming_t *pInMsg );
|
|
static void zclSS_ProcessInCmd_ACE_ArmResponse( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static void zclSS_ProcessInCmd_ACE_GetZoneIDMapResponse( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static void zclSS_ProcessInCmd_ACE_GetZoneInformationResponse( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
#endif // ZCL_ACE
|
|
|
|
#ifdef ZCL_WD
|
|
static ZStatus_t zclSS_ProcessInWDCmds( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
|
|
static void zclSS_ProcessInCmd_WD_StartWarning( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
static void zclSS_ProcessInCmd_WD_Squawk( zclIncoming_t *pInMsg, zclSS_AppCallbacks_t *pCBs );
|
|
#endif // ZCL_WD
|
|
|
|
#ifdef ZCL_ZONE
|
|
static uint8 zclSS_GetNextFreeZoneID( void );
|
|
static ZStatus_t zclSS_AddZone( uint8 endpoint, IAS_ACE_ZoneTable_t *zone );
|
|
static uint8 zclSS_CountAllZones( void );
|
|
static uint8 zclSS_ZoneIDAvailable( uint8 zoneID );
|
|
#endif // ZCL_ZONE
|
|
|
|
#if defined(ZCL_ZONE) || defined(ZCL_ACE)
|
|
static IAS_ACE_ZoneTable_t *zclSS_FindZone( uint8 endpoint, uint8 zoneID );
|
|
#endif // ZCL_ZONE || ZCL_ACE
|
|
|
|
/******************************************************************************
|
|
* @fn zclSS_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 zclSS_RegisterCmdCallbacks( uint8 endpoint, zclSS_AppCallbacks_t *callbacks )
|
|
{
|
|
zclSSCBRec_t *pNewItem;
|
|
zclSSCBRec_t *pLoop;
|
|
|
|
// Register as a ZCL Plugin
|
|
if ( !zclSSPluginRegisted )
|
|
{
|
|
zcl_registerPlugin( ZCL_CLUSTER_ID_SS_IAS_ZONE,
|
|
ZCL_CLUSTER_ID_SS_IAS_WD,
|
|
zclSS_HdlIncoming );
|
|
zclSSPluginRegisted = TRUE;
|
|
}
|
|
|
|
// Fill in the new profile list
|
|
pNewItem = osal_mem_alloc( sizeof( zclSSCBRec_t ) );
|
|
if ( pNewItem == NULL )
|
|
return (ZMemError);
|
|
|
|
pNewItem->next = (zclSSCBRec_t *)NULL;
|
|
pNewItem->endpoint = endpoint;
|
|
pNewItem->CBs = callbacks;
|
|
|
|
// Find spot in list
|
|
if ( zclSSCBs == NULL )
|
|
{
|
|
zclSSCBs = pNewItem;
|
|
}
|
|
else
|
|
{
|
|
// Look for end of list
|
|
pLoop = zclSSCBs;
|
|
while ( pLoop->next != NULL )
|
|
pLoop = pLoop->next;
|
|
|
|
// Put new item at end of list
|
|
pLoop->next = pNewItem;
|
|
}
|
|
return ( ZSuccess );
|
|
}
|
|
|
|
#ifdef ZCL_ZONE
|
|
/*******************************************************************************
|
|
* @fn zclSS_Send_IAS_ZoneStatusChangeNotificationCmd
|
|
*
|
|
* @brief Call to send out a Change Notification Command
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param zoneStatus - current zone status - bit map
|
|
* @param extendedStatus - bit map, currently set to All zeros ( reserved)
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_IAS_Send_ZoneStatusChangeNotificationCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint16 zoneStatus, uint8 extendedStatus,
|
|
uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 buf[3];
|
|
|
|
buf[0] = LO_UINT16( zoneStatus );
|
|
buf[1] = HI_UINT16( zoneStatus );
|
|
buf[2] = extendedStatus;
|
|
|
|
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ZONE,
|
|
COMMAND_SS_IAS_ZONE_STATUS_CHANGE_NOTIFICATION, TRUE,
|
|
ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, 3, buf );
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn zclSS_Send_IAS_ZoneStatusEnrollRequestCmd
|
|
*
|
|
* @brief Call to send out a Enroll Request Command
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param zoneType - current value of Zone Type attribute
|
|
* @param manufacturerCode - manuf. code from node descriptor for the device
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_IAS_Send_ZoneStatusEnrollRequestCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint16 zoneType, uint16 manufacturerCode,
|
|
uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 buf[4];
|
|
|
|
buf[0] = LO_UINT16( zoneType );
|
|
buf[1] = HI_UINT16( zoneType );
|
|
buf[2] = LO_UINT16( manufacturerCode );
|
|
buf[3] = HI_UINT16( manufacturerCode );
|
|
|
|
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ZONE,
|
|
COMMAND_SS_IAS_ZONE_STATUS_ENROLL_REQUEST, TRUE,
|
|
ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, 4, buf );
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn zclSS_IAS_Send_ZoneStatusEnrollResponseCmd
|
|
*
|
|
* @brief Call to send out a Enroll Response Command
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param responseCode - value of response Code
|
|
* @param zoneID - index to the zone table of the CIE
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_IAS_Send_ZoneStatusEnrollResponseCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint8 responseCode, uint8 zoneID,
|
|
uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 buf[2];
|
|
|
|
buf[0] = responseCode;
|
|
buf[1] = zoneID;
|
|
|
|
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ZONE,
|
|
COMMAND_SS_IAS_ZONE_STATUS_ENROLL_RESPONSE, TRUE,
|
|
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 2, buf );
|
|
}
|
|
#endif // ZCL_ZONE
|
|
|
|
#ifdef ZCL_ACE
|
|
/*******************************************************************************
|
|
* @fn zclSS_Send_IAS_ACE_ArmCmd
|
|
*
|
|
* @brief Call to send out a Arm Command ( IAS ACE Cluster )
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param armMode - value of armMode
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_Send_IAS_ACE_ArmCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint8 armMode, uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 buf[1];
|
|
|
|
buf[0] = armMode;
|
|
|
|
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ACE,
|
|
COMMAND_SS_IAS_ACE_ARM, TRUE,
|
|
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 1, buf );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_Send_IAS_ACE_BypassCmd
|
|
*
|
|
* @brief Call to send out a Bypass Command ( IAS ACE Cluster )
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param numberOfZones - one byte
|
|
* @param bypassBuf - zone IDs array of 256 entries one byte each
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_Send_IAS_ACE_BypassCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint8 numberOfZones, uint8 *bypassBuf,
|
|
uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 *buf;
|
|
uint8 *pBuf;
|
|
uint8 len = 1 + numberOfZones;
|
|
ZStatus_t stat;
|
|
|
|
buf = osal_mem_alloc( len );
|
|
if ( buf )
|
|
{
|
|
pBuf = buf;
|
|
|
|
*pBuf++ = numberOfZones;
|
|
osal_memcpy( pBuf, bypassBuf, numberOfZones );
|
|
|
|
stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ACE,
|
|
COMMAND_SS_IAS_ACE_BYPASS, TRUE,
|
|
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, len, buf );
|
|
osal_mem_free( buf );
|
|
}
|
|
else
|
|
stat = ZFailure;
|
|
|
|
return ( stat );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_Send_IAS_ACE_GetZoneInformationCmd
|
|
*
|
|
* @brief Call to send out a Get Zone Information Command ( IAS ACE Cluster )
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param zoneID - 8 bit value from 0 to 255
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_Send_IAS_ACE_GetZoneInformationCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint8 zoneID, uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 buf[1];
|
|
|
|
buf[0] = zoneID;
|
|
|
|
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ACE,
|
|
COMMAND_SS_IAS_ACE_GET_ZONE_INFORMATION, TRUE,
|
|
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 1, buf );
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn zclSS_Send_IAS_ACE_ArmRespponse
|
|
*
|
|
* @brief Call to send out a Arm Response Command ( IAS ACE Cluster )
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param armNotification
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_Send_IAS_ACE_ArmResponse( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint8 armNotification, uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 buf[1];
|
|
|
|
buf[0] = armNotification;
|
|
|
|
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ACE,
|
|
COMMAND_SS_IAS_ACE_ARM_RESPONSE, TRUE,
|
|
ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, 1, buf );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_Send_IAS_ACE_GetZoneIDMapResponseCmd
|
|
*
|
|
* @brief Call to send out a Get Zone ID Map Response Cmd ( IAS ACE Cluster )
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param zoneIDMap - pointer to an array of 16 uint16
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_Send_IAS_ACE_GetZoneIDMapResponseCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint16 *zoneIDMap, uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 *buf;
|
|
uint8 *pIndex;
|
|
uint8 j,len = 32;
|
|
ZStatus_t stat;
|
|
|
|
buf = osal_mem_alloc( len );
|
|
|
|
if ( buf )
|
|
{
|
|
pIndex = buf;
|
|
|
|
for( j = 0; j < 16; j++ )
|
|
{
|
|
*pIndex++ = LO_UINT16( *zoneIDMap );
|
|
*pIndex++ = HI_UINT16( *zoneIDMap++ );
|
|
}
|
|
|
|
stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ACE,
|
|
COMMAND_SS_IAS_ACE_GET_ZONE_ID_MAP_RESPONSE, TRUE,
|
|
ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
|
|
osal_mem_free( buf );
|
|
}
|
|
else
|
|
stat = ZMemError;
|
|
|
|
return ( stat );
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn zclSS_Send_IAS_ACE_GetZoneInformationResponseCmd
|
|
*
|
|
* @brief Call to send out Get Zone Information Response Cmd (IAS ACE Cluster)
|
|
*
|
|
* @param srcEP - Sending application's endpoint
|
|
* @param dstAddr - where you want the message to go
|
|
* @param zoneID - 8 bit value from 0 to 255
|
|
* @param zoneType - 16 bit
|
|
* @param ieeeAddress - pointer to 64 bit address ( 8bytes*8)
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_Send_IAS_ACE_GetZoneInformationResponseCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
uint8 zoneID, uint16 zoneType, uint8 *ieeeAddress,
|
|
uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 *buf;
|
|
uint8 len = 11; // zoneID (1) + zoneType (2) + zoneAddress (8)
|
|
ZStatus_t stat;
|
|
|
|
buf = osal_mem_alloc( len );
|
|
|
|
if ( buf )
|
|
{
|
|
buf[0] = zoneID;
|
|
buf[1] = LO_UINT16( zoneType);
|
|
buf[2] = HI_UINT16( zoneType);
|
|
osal_cpyExtAddr( &buf[3], ieeeAddress );
|
|
|
|
stat = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_ACE,
|
|
COMMAND_SS_IAS_ACE_GET_ZONE_INFORMATION_RESPONSE, TRUE,
|
|
ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, len, buf );
|
|
osal_mem_free( buf );
|
|
}
|
|
else
|
|
stat = ZMemError;
|
|
|
|
return ( stat );
|
|
}
|
|
#endif // ZCL_ACE
|
|
|
|
#ifdef ZCL_WD
|
|
/*******************************************************************************
|
|
* @fn zclSS_Send_IAS_WD_StartWarningCmd
|
|
*
|
|
* @brief Call to send out a Start Warning Command (IAS WD Cluster)
|
|
*
|
|
* @param warning - 3 bytes of type zclCmdSSWDStartWarningPayload_t
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_Send_IAS_WD_StartWarningCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
zclCmdSSWDStartWarningPayload_t *warning,
|
|
uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 buf[3];
|
|
|
|
buf[0] = warning->warningmessage.warningbyte;
|
|
buf[1] = LO_UINT16( warning->duration );
|
|
buf[2] = HI_UINT16( warning->duration );
|
|
|
|
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_WD,
|
|
COMMAND_SS_IAS_WD_START_WARNING, TRUE,
|
|
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 3, buf );
|
|
}
|
|
|
|
/******************************************************************************
|
|
* @fn zclSS_Send_IAS_WD_StartWarningCmd
|
|
*
|
|
* @brief Call to send out a Squawk Command ( IAS WD Cluster )
|
|
*
|
|
* @param squawk - one byte of type zclCmdSSWDSquawkPayload_t
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
ZStatus_t zclSS_Send_IAS_WD_SquawkCmd( uint8 srcEP, afAddrType_t *dstAddr,
|
|
zclCmdSSWDSquawkPayload_t *squawk,
|
|
uint8 disableDefaultRsp, uint8 seqNum )
|
|
{
|
|
uint8 buf[1];
|
|
buf[0] = squawk->squawkbyte;
|
|
|
|
return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_SS_IAS_WD,
|
|
COMMAND_SS_IAS_WD_SQUAWK, TRUE,
|
|
ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, 1, buf);
|
|
}
|
|
#endif // ZCL_WD
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_FindCallbacks
|
|
*
|
|
* @brief Find the callbacks for an endpoint
|
|
*
|
|
* @param endpoint
|
|
*
|
|
* @return pointer to the callbacks
|
|
*/
|
|
static zclSS_AppCallbacks_t *zclSS_FindCallbacks( uint8 endpoint )
|
|
{
|
|
zclSSCBRec_t *pCBs;
|
|
|
|
pCBs = zclSSCBs;
|
|
while ( pCBs )
|
|
{
|
|
if ( pCBs->endpoint == endpoint )
|
|
return ( pCBs->CBs );
|
|
pCBs = pCBs->next;
|
|
}
|
|
return ( (zclSS_AppCallbacks_t *)NULL );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_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
|
|
* @param logicalClusterID
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static ZStatus_t zclSS_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 = zclSS_HdlInSpecificCommands( pInMsg );
|
|
}
|
|
else
|
|
{
|
|
// We don't support any manufacturer specific command -- ignore it.
|
|
stat = ZFailure;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Handle all the normal (Read, Write...) commands
|
|
stat = ZFailure;
|
|
}
|
|
return ( stat );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_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 zclSS_HdlInSpecificCommands( zclIncoming_t *pInMsg )
|
|
{
|
|
ZStatus_t stat = ZSuccess;
|
|
zclSS_AppCallbacks_t *pCBs;
|
|
|
|
// make sure endpoint exists
|
|
pCBs = (void*)zclSS_FindCallbacks( pInMsg->msg->endPoint );
|
|
if ( pCBs == NULL )
|
|
return ( ZFailure );
|
|
|
|
switch ( pInMsg->msg->clusterId )
|
|
{
|
|
#ifdef ZCL_ZONE
|
|
case ZCL_CLUSTER_ID_SS_IAS_ZONE:
|
|
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
|
|
stat = zclSS_ProcessInZoneStatusCmdsServer( pInMsg, pCBs );
|
|
else
|
|
stat = zclSS_ProcessInZoneStatusCmdsClient( pInMsg, pCBs );
|
|
break;
|
|
#endif // ZCL_ZONE
|
|
|
|
#ifdef ZCL_ACE
|
|
case ZCL_CLUSTER_ID_SS_IAS_ACE:
|
|
if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
|
|
stat = zclSS_ProcessInACECmdsServer( pInMsg, pCBs );
|
|
else
|
|
stat = zclSS_ProcessInACECmdsClient( pInMsg, pCBs );
|
|
break;
|
|
#endif // ZCL_ACE
|
|
|
|
#ifdef ZCL_WD
|
|
case ZCL_CLUSTER_ID_SS_IAS_WD:
|
|
stat = zclSS_ProcessInWDCmds( pInMsg, pCBs );
|
|
break;
|
|
#endif // ZCL_WD
|
|
|
|
default:
|
|
stat = ZFailure;
|
|
break;
|
|
}
|
|
|
|
return ( stat );
|
|
}
|
|
|
|
#ifdef ZCL_ZONE
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInZoneStatusCmdsServer
|
|
*
|
|
* @brief Callback from ZCL to process incoming Commands specific
|
|
* to this cluster library on a command ID basis
|
|
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInZoneStatusCmdsServer( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
ZStatus_t stat = ZSuccess;
|
|
|
|
if ( pInMsg->hdr.commandID == COMMAND_SS_IAS_ZONE_STATUS_ENROLL_RESPONSE )
|
|
zclSS_ProcessInCmd_ZoneStatus_EnrollResponse( pInMsg, pCBs );
|
|
else
|
|
stat = ZFailure;
|
|
|
|
return ( stat );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInZoneStatusCmdsClient
|
|
*
|
|
* @brief Callback from ZCL to process incoming Commands specific
|
|
* to this cluster library on a command ID basis
|
|
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInZoneStatusCmdsClient( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
ZStatus_t stat = ZSuccess;
|
|
|
|
switch ( pInMsg->hdr.commandID )
|
|
{
|
|
case COMMAND_SS_IAS_ZONE_STATUS_CHANGE_NOTIFICATION:
|
|
zclSS_ProcessInCmd_ZoneStatus_ChangeNotification( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ZONE_STATUS_ENROLL_REQUEST:
|
|
stat = zclSS_ProcessInCmd_ZoneStatus_EnrollRequest( pInMsg, pCBs );
|
|
break;
|
|
|
|
default:
|
|
stat = ZFailure;
|
|
break;
|
|
}
|
|
|
|
return ( stat );
|
|
}
|
|
#endif // ZCL_ZONE
|
|
|
|
#ifdef ZCL_ACE
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInACECmdsServer
|
|
*
|
|
* @brief Callback from ZCL to process incoming Commands specific
|
|
* to this cluster library on a command ID basis
|
|
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInACECmdsServer( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
ZStatus_t stat = ZSuccess;
|
|
|
|
switch ( pInMsg->hdr.commandID )
|
|
{
|
|
case COMMAND_SS_IAS_ACE_ARM:
|
|
stat = zclSS_ProcessInCmd_ACE_Arm( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ACE_BYPASS:
|
|
zclSS_ProcessInCmd_ACE_Bypass( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ACE_EMERGENCY:
|
|
zclSS_ProcessInCmd_ACE_Emergency( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ACE_FIRE:
|
|
zclSS_ProcessInCmd_ACE_Fire( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ACE_PANIC:
|
|
zclSS_ProcessInCmd_ACE_Panic( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ACE_GET_ZONE_ID_MAP:
|
|
stat = zclSS_ProcessInCmd_ACE_GetZoneIDMap( pInMsg );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ACE_GET_ZONE_INFORMATION:
|
|
stat = zclSS_ProcessInCmd_ACE_GetZoneInformation( pInMsg );
|
|
break;
|
|
|
|
default:
|
|
stat = ZFailure;
|
|
break;
|
|
}
|
|
|
|
return ( stat );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInACECmdsClient
|
|
*
|
|
* @brief Callback from ZCL to process incoming Commands specific
|
|
* to this cluster library on a command ID basis
|
|
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInACECmdsClient( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
ZStatus_t stat = ZSuccess;
|
|
|
|
switch ( pInMsg->hdr.commandID )
|
|
{
|
|
case COMMAND_SS_IAS_ACE_ARM_RESPONSE:
|
|
zclSS_ProcessInCmd_ACE_ArmResponse( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ACE_GET_ZONE_ID_MAP_RESPONSE:
|
|
zclSS_ProcessInCmd_ACE_GetZoneIDMapResponse( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_ACE_GET_ZONE_INFORMATION_RESPONSE:
|
|
zclSS_ProcessInCmd_ACE_GetZoneInformationResponse( pInMsg, pCBs );
|
|
break;
|
|
|
|
default:
|
|
stat = ZFailure;
|
|
break;
|
|
}
|
|
|
|
return ( stat );
|
|
}
|
|
#endif // ZCL_ACE
|
|
|
|
#ifdef ZCL_ZONE
|
|
/*********************************************************************
|
|
* @fn zclSS_AddZone
|
|
*
|
|
* @brief Add a zone for an endpoint
|
|
*
|
|
* @param endpoint -
|
|
* @param zone - new zone item
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static ZStatus_t zclSS_AddZone( uint8 endpoint, IAS_ACE_ZoneTable_t *zone )
|
|
{
|
|
zclSS_ZoneItem_t *pNewItem;
|
|
zclSS_ZoneItem_t *pLoop;
|
|
|
|
// Fill in the new profile list
|
|
pNewItem = osal_mem_alloc( sizeof( zclSS_ZoneItem_t ) );
|
|
if ( pNewItem == NULL )
|
|
return ( ZMemError );
|
|
|
|
// Fill in the plugin record.
|
|
pNewItem->next = (zclSS_ZoneItem_t *)NULL;
|
|
pNewItem->endpoint = endpoint;
|
|
osal_memcpy( (uint8*)&(pNewItem->zone), (uint8*)zone, sizeof ( IAS_ACE_ZoneTable_t ));
|
|
|
|
// Find spot in list
|
|
if ( zclSS_ZoneTable == NULL )
|
|
{
|
|
zclSS_ZoneTable = pNewItem;
|
|
}
|
|
else
|
|
{
|
|
// Look for end of list
|
|
pLoop = zclSS_ZoneTable;
|
|
while ( pLoop->next != NULL )
|
|
pLoop = pLoop->next;
|
|
|
|
// Put new item at end of list
|
|
pLoop->next = pNewItem;
|
|
}
|
|
|
|
return ( ZSuccess );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_CountAllZones
|
|
*
|
|
* @brief Count the total number of zones
|
|
*
|
|
* @param none
|
|
*
|
|
* @return number of zones
|
|
*/
|
|
uint8 zclSS_CountAllZones( void )
|
|
{
|
|
zclSS_ZoneItem_t *pLoop;
|
|
uint8 cnt = 0;
|
|
|
|
// Look for end of list
|
|
pLoop = zclSS_ZoneTable;
|
|
while ( pLoop )
|
|
{
|
|
cnt++;
|
|
pLoop = pLoop->next;
|
|
}
|
|
return ( cnt );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_GetNextFreeZoneID
|
|
*
|
|
* @brief Get the next free zone ID
|
|
*
|
|
* @param none
|
|
*
|
|
* @return free zone ID (0-254)
|
|
*/
|
|
static uint8 zclSS_GetNextFreeZoneID( void )
|
|
{
|
|
static uint8 nextAvailZoneID = 0;
|
|
|
|
if ( zclSS_ZoneIDAvailable( nextAvailZoneID ) == FALSE )
|
|
{
|
|
uint8 zoneID = nextAvailZoneID;
|
|
|
|
// Look for next available zone ID
|
|
do
|
|
{
|
|
if ( ++zoneID == ZCL_SS_MAX_ZONE_ID )
|
|
zoneID = 0; // roll over
|
|
|
|
} while ( (zoneID != nextAvailZoneID) && (zclSS_ZoneIDAvailable( nextAvailZoneID ) == FALSE) );
|
|
|
|
// Did we found a free zone ID?
|
|
if ( zoneID != nextAvailZoneID )
|
|
nextAvailZoneID = zoneID;
|
|
}
|
|
|
|
return ( nextAvailZoneID );
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ZoneIDAvailable
|
|
*
|
|
* @brief Check to see whether zoneID is available for use
|
|
*
|
|
* @param zoneID - ID to look for zone
|
|
*
|
|
* @return TRUE if zoneID is available, FALSE otherwise
|
|
*/
|
|
static uint8 zclSS_ZoneIDAvailable( uint8 zoneID )
|
|
{
|
|
zclSS_ZoneItem_t *pLoop;
|
|
|
|
if ( zoneID < ZCL_SS_MAX_ZONE_ID )
|
|
{
|
|
pLoop = zclSS_ZoneTable;
|
|
while ( pLoop )
|
|
{
|
|
if ( pLoop->zone.zoneID == zoneID )
|
|
{
|
|
return ( FALSE );
|
|
}
|
|
pLoop = pLoop->next;
|
|
}
|
|
|
|
// Zone ID not in use
|
|
return ( TRUE );
|
|
}
|
|
|
|
return ( FALSE );
|
|
}
|
|
#endif // ZCL_ZONE
|
|
|
|
#if defined(ZCL_ZONE) || defined(ZCL_ACE)
|
|
/*********************************************************************
|
|
* @fn zclSS_FindZone
|
|
*
|
|
* @brief Find a zone with endpoint and ZoneID
|
|
*
|
|
* @param endpoint -
|
|
* @param zoneID - ID to look for zone
|
|
*
|
|
* @return a pointer to the zone information, NULL if not found
|
|
*/
|
|
static IAS_ACE_ZoneTable_t *zclSS_FindZone( uint8 endpoint, uint8 zoneID )
|
|
{
|
|
zclSS_ZoneItem_t *pLoop;
|
|
|
|
// Look for end of list
|
|
pLoop = zclSS_ZoneTable;
|
|
while ( pLoop )
|
|
{
|
|
if ( pLoop->endpoint == endpoint && pLoop->zone.zoneID == zoneID )
|
|
{
|
|
return ( &(pLoop->zone) );
|
|
}
|
|
pLoop = pLoop->next;
|
|
}
|
|
|
|
return ( (IAS_ACE_ZoneTable_t *)NULL );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_RemoveZone
|
|
*
|
|
* @brief Remove a zone with endpoint and zoneID
|
|
*
|
|
* @param endpoint -
|
|
* @param zoneID - ID to look for zone
|
|
*
|
|
* @return TRUE if removed, FALSE if not found
|
|
*/
|
|
uint8 zclSS_RemoveZone( uint8 endpoint, uint8 zoneID )
|
|
{
|
|
zclSS_ZoneItem_t *pLoop;
|
|
zclSS_ZoneItem_t *pPrev;
|
|
|
|
// Look for end of list
|
|
pLoop = zclSS_ZoneTable;
|
|
pPrev = NULL;
|
|
while ( pLoop )
|
|
{
|
|
if ( pLoop->endpoint == endpoint && pLoop->zone.zoneID == zoneID )
|
|
{
|
|
if ( pPrev == NULL )
|
|
zclSS_ZoneTable = pLoop->next;
|
|
else
|
|
pPrev->next = pLoop->next;
|
|
|
|
// Free the memory
|
|
osal_mem_free( pLoop );
|
|
|
|
return ( TRUE );
|
|
}
|
|
pPrev = pLoop;
|
|
pLoop = pLoop->next;
|
|
}
|
|
|
|
return ( FALSE );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_UpdateZoneAddress
|
|
*
|
|
* @brief Update Zone Address for zoneID
|
|
*
|
|
* @param endpoint -
|
|
* @param zoneID - ID to look for zone
|
|
* @param ieeeAddr - Device IEEE Address
|
|
*
|
|
* @return none
|
|
*/
|
|
void zclSS_UpdateZoneAddress( uint8 endpoint, uint8 zoneID, uint8 *ieeeAddr )
|
|
{
|
|
IAS_ACE_ZoneTable_t *zone;
|
|
|
|
zone = zclSS_FindZone( endpoint, zoneID );
|
|
if ( zone != NULL )
|
|
{
|
|
// Update the zone address
|
|
osal_cpyExtAddr( zone->zoneAddress, ieeeAddr );
|
|
}
|
|
}
|
|
#endif // ZCL_ZONE || ZCL_ACE
|
|
|
|
#ifdef ZCL_ZONE
|
|
/*******************************************************************************
|
|
* @fn zclSS_ProcessInCmd_ZoneStatus_ChangeNotification
|
|
*
|
|
* @brief Process in the received StatusChangeNotification Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static void zclSS_ProcessInCmd_ZoneStatus_ChangeNotification( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ZONE_STATUS_CHANGE_NOTIFICATION )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnChangeNotification )
|
|
{
|
|
zclZoneChangeNotif_t cmd;
|
|
|
|
cmd.zoneStatus = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
|
|
cmd.extendedStatus = pInMsg->pData[2];
|
|
|
|
pCBs->pfnChangeNotification( &cmd );
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn zclSS_ProcessInCmd_ZoneStatus_EnrollRequest
|
|
*
|
|
* @brief Process in the received StatusEnrollRequest Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInCmd_ZoneStatus_EnrollRequest( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
IAS_ACE_ZoneTable_t zone;
|
|
uint16 zoneType;
|
|
uint16 manuCode;
|
|
uint8 zoneID;
|
|
uint8 status;
|
|
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ZONE_STATUS_ENROLL_REQUEST )
|
|
return ( ZFailure ); // Error ignore the command
|
|
|
|
zoneType = BUILD_UINT16( pInMsg->pData[0], pInMsg->pData[1] );
|
|
manuCode = BUILD_UINT16( pInMsg->pData[2], pInMsg->pData[3] );
|
|
|
|
if ( zclSS_ZoneTypeSupported( zoneType ) )
|
|
{
|
|
// What if the entry already exists?????
|
|
if ( zclSS_CountAllZones() < ZCL_SS_MAX_ZONES-1 )
|
|
{
|
|
// Add zone to the table
|
|
zoneID = zclSS_GetNextFreeZoneID();
|
|
|
|
zone.zoneID = zoneID;
|
|
zone.zoneType = zoneType;
|
|
|
|
// The application will fill in the right IEEE Address later
|
|
osal_cpyExtAddr( zone.zoneAddress, (void *)zclSS_UknownIeeeAddress );
|
|
|
|
if ( zclSS_AddZone( pInMsg->msg->endPoint, &zone ) == ZSuccess )
|
|
{
|
|
status = ZCL_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
// CIE does not permit new zones to enroll at this time
|
|
status = SS_IAS_ZONE_STATUS_ENROLL_RESPONSE_CODE_NO_ENROLL_PERMIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// CIE reached its limit of number of enrolled zones
|
|
status = SS_IAS_ZONE_STATUS_ENROLL_RESPONSE_CODE_TOO_MANY_ZONES;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Zone type is not known to CIE and is not supported
|
|
status = SS_IAS_ZONE_STATUS_ENROLL_RESPONSE_CODE_NOT_SUPPORTED;
|
|
}
|
|
|
|
// Send a response back
|
|
zclSS_IAS_Send_ZoneStatusEnrollResponseCmd( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
|
|
status, zoneID, true, pInMsg->hdr.transSeqNum );
|
|
if ( status == ZCL_STATUS_SUCCESS )
|
|
{
|
|
// Callback the application so it can fill in the Device IEEE Address
|
|
if ( pCBs->pfnEnrollRequest )
|
|
{
|
|
zclZoneEnrollReq_t req;
|
|
|
|
req.srcAddr = &(pInMsg->msg->srcAddr);
|
|
req.zoneID = zoneID;
|
|
req.zoneType = zoneType;
|
|
req.manufacturerCode = manuCode;
|
|
|
|
pCBs->pfnEnrollRequest( &req );
|
|
}
|
|
}
|
|
|
|
return ( ZCL_STATUS_CMD_HAS_RSP );
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn zclSS_ProcessInCmd_ZoneStatus_EnrollResponse
|
|
*
|
|
* @brief Process in the received STATUS_ENROLL_RESPONSE Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static void zclSS_ProcessInCmd_ZoneStatus_EnrollResponse( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ZONE_STATUS_ENROLL_RESPONSE )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnEnrollResponse )
|
|
{
|
|
zclZoneEnrollRsp_t rsp;
|
|
|
|
rsp.responseCode = pInMsg->pData[0];
|
|
rsp.zoneID = pInMsg->pData[1];
|
|
|
|
pCBs->pfnEnrollResponse( &rsp );
|
|
}
|
|
}
|
|
#endif // ZCL_ZONE
|
|
|
|
#ifdef ZCL_ACE
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_Arm
|
|
*
|
|
* @brief Process in the received Arm Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInCmd_ACE_Arm( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
uint8 armNotification;
|
|
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_ARM )
|
|
return ( ZFailure ); // Error ignore the command
|
|
|
|
if ( pCBs->pfnACE_Arm )
|
|
{
|
|
armNotification = pCBs->pfnACE_Arm( pInMsg->pData[0] );
|
|
|
|
// Send a response back
|
|
zclSS_Send_IAS_ACE_ArmResponse( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
|
|
armNotification, true, pInMsg->hdr.transSeqNum );
|
|
}
|
|
|
|
return ( ZCL_STATUS_CMD_HAS_RSP );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_Bypass
|
|
*
|
|
* @brief Process in the received Bypass Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_ACE_Bypass( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_BYPASS )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnACE_Bypass )
|
|
{
|
|
zclACEBypass_t cmd;
|
|
|
|
cmd.numberOfZones = pInMsg->pData[0];
|
|
cmd.bypassBuf = &(pInMsg->pData[1]);
|
|
|
|
pCBs->pfnACE_Bypass( &cmd ) ;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_Emergency
|
|
*
|
|
* @brief Process in the received Emergency Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_ACE_Emergency( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_EMERGENCY )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnACE_Emergency )
|
|
pCBs->pfnACE_Emergency();
|
|
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_Fire
|
|
*
|
|
* @brief Process in the received Fire Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_ACE_Fire( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_FIRE )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnACE_Fire )
|
|
pCBs->pfnACE_Fire();
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_Panic
|
|
*
|
|
* @brief Process in the received Panic Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_ACE_Panic( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_PANIC )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnACE_Panic )
|
|
pCBs->pfnACE_Panic();
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_GetZoneIDMap
|
|
*
|
|
* @brief Process in the received GetZoneIDMap Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInCmd_ACE_GetZoneIDMap( zclIncoming_t *pInMsg )
|
|
{
|
|
uint16 zoneIDMap[16];
|
|
uint16 mapSection;
|
|
uint8 zoneID;
|
|
uint8 i, j;
|
|
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_GET_ZONE_ID_MAP )
|
|
return ( ZFailure ); // Error ignore the command
|
|
|
|
for ( i = 0; i < 16; i++ )
|
|
{
|
|
mapSection = 0;
|
|
|
|
// Find out Zone IDs that are allocated for this map section
|
|
for ( j = 0; j < 16; j++ )
|
|
{
|
|
zoneID = 16 * i + j;
|
|
if ( zclSS_FindZone( pInMsg->msg->endPoint, zoneID ) != NULL )
|
|
{
|
|
// Set the corresponding bit
|
|
mapSection |= (0x01 << j );
|
|
}
|
|
}
|
|
zoneIDMap[i] = mapSection;
|
|
}
|
|
|
|
// Send a response back
|
|
zclSS_Send_IAS_ACE_GetZoneIDMapResponseCmd( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
|
|
zoneIDMap, true, pInMsg->hdr.transSeqNum );
|
|
return ( ZCL_STATUS_CMD_HAS_RSP );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_GetZoneInformation
|
|
*
|
|
* @brief Process in the received GetZoneInformation Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInCmd_ACE_GetZoneInformation( zclIncoming_t *pInMsg )
|
|
{
|
|
IAS_ACE_ZoneTable_t zone;
|
|
IAS_ACE_ZoneTable_t *pZone;
|
|
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_GET_ZONE_INFORMATION )
|
|
return ( ZFailure ); // Error ignore the command
|
|
|
|
pZone = zclSS_FindZone( pInMsg->msg->endPoint, pInMsg->pData[0] );
|
|
if ( pZone == NULL )
|
|
{
|
|
// Zone not found
|
|
pZone = &zone;
|
|
pZone->zoneID = pInMsg->pData[0];
|
|
pZone->zoneType = SS_IAS_ZONE_TYPE_INVALID_ZONE_TYPE;
|
|
osal_cpyExtAddr( pZone->zoneAddress, (void *)zclSS_UknownIeeeAddress );
|
|
}
|
|
|
|
// Send a response back
|
|
zclSS_Send_IAS_ACE_GetZoneInformationResponseCmd( pInMsg->msg->endPoint, &(pInMsg->msg->srcAddr),
|
|
pZone->zoneID, pZone->zoneType,
|
|
pZone->zoneAddress, true, pInMsg->hdr.transSeqNum );
|
|
return ( ZCL_STATUS_CMD_HAS_RSP );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_ArmResponse
|
|
*
|
|
* @brief Process in the received Arm Response Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_ACE_ArmResponse( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_ARM_RESPONSE )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnACE_ArmResponse )
|
|
pCBs->pfnACE_ArmResponse(pInMsg->pData[0]);
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_GetZoneIDMapResponse
|
|
*
|
|
* @brief Process in the received GetZoneIDMapResponse Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_ACE_GetZoneIDMapResponse( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
uint16 *buf;
|
|
uint16 *pIndex;
|
|
uint8 *pData;
|
|
uint8 i, len = 32; // 16 fields of 2 octects
|
|
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_GET_ZONE_ID_MAP_RESPONSE )
|
|
return; // Error ignore the command
|
|
|
|
buf = osal_mem_alloc( len );
|
|
|
|
if ( buf )
|
|
{
|
|
pIndex = buf;
|
|
pData = pInMsg->pData;
|
|
|
|
for ( i = 0; i < 16; i++ )
|
|
{
|
|
*pIndex++ = BUILD_UINT16( pData[0], pData[1] );
|
|
pData += 2;
|
|
}
|
|
|
|
if ( pCBs->pfnACE_GetZoneIDMapResponse )
|
|
pCBs->pfnACE_GetZoneIDMapResponse( buf );
|
|
|
|
osal_mem_free( buf );
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_ACE_GetZoneInformationResponse
|
|
*
|
|
* @brief Process in the received GetZoneInformationResponse Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_ACE_GetZoneInformationResponse( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_ACE_GET_ZONE_INFORMATION_RESPONSE )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnACE_GetZoneInformationResponse )
|
|
{
|
|
zclACEGetZoneInfoRsp_t rsp;
|
|
|
|
rsp.zoneID = pInMsg->pData[0];
|
|
rsp.zoneType = BUILD_UINT16( pInMsg->pData[1], pInMsg->pData[2] );
|
|
rsp.ieeeAddr = &(pInMsg->pData[3]);
|
|
|
|
pCBs->pfnACE_GetZoneInformationResponse( &rsp );
|
|
}
|
|
}
|
|
#endif // ZCL_ACE
|
|
|
|
#ifdef ZCL_WD
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInWDCmds
|
|
*
|
|
* @brief Callback from ZCL to process incoming Commands specific
|
|
* to this cluster library on a command ID basis
|
|
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
* @return ZStatus_t
|
|
*/
|
|
static ZStatus_t zclSS_ProcessInWDCmds( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
ZStatus_t stat = ZSuccess;
|
|
|
|
switch ( pInMsg->hdr.commandID )
|
|
{
|
|
case COMMAND_SS_IAS_WD_START_WARNING:
|
|
zclSS_ProcessInCmd_WD_StartWarning( pInMsg, pCBs );
|
|
break;
|
|
|
|
case COMMAND_SS_IAS_WD_SQUAWK:
|
|
zclSS_ProcessInCmd_WD_Squawk( pInMsg, pCBs );
|
|
break;
|
|
|
|
default:
|
|
stat = ZFailure;
|
|
break;
|
|
}
|
|
|
|
return ( stat );
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_WD_StartWarning
|
|
*
|
|
* @brief Process in the received StartWarning Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_WD_StartWarning( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_WD_START_WARNING )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnWD_StartWarning )
|
|
{
|
|
zclWDStartWarning_t cmd;
|
|
|
|
cmd.warnings.warningbyte = pInMsg->pData[0];
|
|
cmd.duration = BUILD_UINT16( pInMsg->pData[1], pInMsg->pData[2] );
|
|
|
|
pCBs->pfnWD_StartWarning( &cmd );
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn zclSS_ProcessInCmd_WD_Squawk
|
|
*
|
|
* @brief Process in the received Squawk Command.
|
|
*
|
|
* @param pInMsg - pointer to the incoming message
|
|
*
|
|
*/
|
|
static void zclSS_ProcessInCmd_WD_Squawk( zclIncoming_t *pInMsg,
|
|
zclSS_AppCallbacks_t *pCBs )
|
|
{
|
|
zclCmdSSWDSquawkPayload_t squawk;
|
|
|
|
if ( pInMsg->hdr.commandID != COMMAND_SS_IAS_WD_SQUAWK )
|
|
return; // Error ignore the command
|
|
|
|
if ( pCBs->pfnWD_Squawk )
|
|
{
|
|
squawk.squawkbyte = pInMsg->pData[0];
|
|
pCBs->pfnWD_Squawk( squawk );
|
|
}
|
|
}
|
|
#endif // ZCL_WD
|
|
|
|
/*******************************************************************************
|
|
*******************************************************************************/
|
|
|