diff options
Diffstat (limited to 'epan/dissectors/packet-zbee-zcl-misc.c')
-rw-r--r-- | epan/dissectors/packet-zbee-zcl-misc.c | 1033 |
1 files changed, 1033 insertions, 0 deletions
diff --git a/epan/dissectors/packet-zbee-zcl-misc.c b/epan/dissectors/packet-zbee-zcl-misc.c new file mode 100644 index 00000000..a7476b1c --- /dev/null +++ b/epan/dissectors/packet-zbee-zcl-misc.c @@ -0,0 +1,1033 @@ +/* packet-zbee-zcl-misc.c + * Dissector routines for the ZigBee ZCL SE clusters like + * Messaging + * By Fabio Tarabelloni <fabio.tarabelloni@reloc.it> + * Copyright 2013 RELOC s.r.l. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include Files */ +#include "config.h" + + +#include <epan/packet.h> + +#include "packet-zbee.h" +#include "packet-zbee-aps.h" +#include "packet-zbee-zcl.h" + +/* ########################################################################## */ +/* #### (0x0201) THERMOSTAT CLUSTER ######################################### */ +/* ########################################################################## */ + +/* Cluster-specific commands and parameters */ +#define ZBEE_ZCL_CSC_POLL_CONTROL_C_CIR 0x00 +#define ZBEE_ZCL_CSC_POLL_CONTROL_C_FPS 0x01 +#define ZBEE_ZCL_CSC_POLL_CONTROL_C_SLPI 0x02 +#define ZBEE_ZCL_CSC_POLL_CONTROL_C_SSPI 0x03 +#define ZBEE_ZCL_CSC_POLL_CONTROL_S_CI 0x00 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_CWS 0x03 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_GWS 0x02 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SRL 0x00 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS 0x01 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_DOW_AV 0x80 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_DOW_FR 0x20 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_DOW_MO 0x02 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_DOW_SA 0x40 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_DOW_SU 0x01 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_DOW_TH 0x10 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_DOW_TU 0x04 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_DOW_WE 0x08 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_SP_B 0x03 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_SP_C 0x02 +#define ZBEE_ZCL_CSC_THERMOSTAT_C_SWS_SP_H 0x01 +#define ZBEE_ZCL_CSC_THERMOSTAT_S_GWSR 0x00 + +#define ZBEE_ZCL_THERMOSTAT_NUM_ETT 3 + +/* Thermostat Information Attributes */ +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_LOCAL_TEMP 0x0000 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_OUTDOOR_TEMP 0x0001 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_OCCUPANCY 0x0002 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_ABS_MIN_HEAT_SETPOINT 0x0003 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_ABS_MAX_HEAT_SETPOINT 0x0004 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_ABS_MIN_COOL_SETPOINT 0x0005 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_ABS_MAX_COOL_SETPOINT 0x0006 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_PI_COOL_DEMAND 0x0007 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_PI_HEAT_DEMAND 0x0008 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_HVAC_TYPE_CONFIG 0x0009 +/* Thermostat Settings Attributes */ +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_LOCAL_TEMP_CALIBRATION 0x0010 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_OCCUPIED_COOL_SETPOINT 0x0011 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_OCCUPIED_HEAT_SETPOINT 0x0012 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_UNOCCUPIED_COOL_SETPOINT 0x0013 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_UNOCCUPIED_HEAT_SETPOINT 0x0014 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_MIN_HEAT_SETPOINT 0x0015 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_MAX_HEAT_SETPOINT 0x0016 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_MIN_COOL_SETPOINT 0x0017 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_MAX_COOL_SETPOINT 0x0018 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_MIN_SETPOINT_DEADBAND 0x0019 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_REMOTE_SENSING 0x001A +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_CONTROL_SEQUENCE 0x001B +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_SYSTEM_MODE 0x001C +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_ALARM_MASK 0x001D +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_RUNNING_MODE 0x001E +/* Schedule & HVAC Relay Attributes. */ +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_START_OF_WEEK 0x0020 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_NUM_WEEKLY_TRANSITIONS 0x0021 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_NUM_DAILY_TRANSITIONS 0x0022 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_SETPOINT_HOLD 0x0023 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_SETPOINT_HOLD_DURATION 0x0024 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_PROGRAMMING_MODE 0x0025 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_RUNNING_STATE 0x0029 +/* Setpoint Change Tracking Attributes. */ +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_SETPOINT_CHANGE_SOURCE 0x0030 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_SETPOINT_CHANGE_AMOUNT 0x0031 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_SETPOINT_CHANGE_TIME 0x0032 +/* Air Conditioning Atrributes. */ +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_AC_TYPE 0x0040 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_AC_CAPACITY 0x0041 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_AC_REFRIGERANT_TYPE 0x0042 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_AC_COMPRESSOR_TYPE 0x0043 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_AC_ERROR_CODE 0x0044 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_AC_LOUVER_POSITION 0x0045 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_AC_COIL_TEMPERATURE 0x0046 +#define ZBEE_ZCL_ATTR_ID_THERMOSTAT_AC_CAPACITY_FORMAT 0x0047 + +static const value_string zbee_zcl_thermostat_attr_names[] = { + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_LOCAL_TEMP, "LocalTemperature" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_OUTDOOR_TEMP, "OutdoorTemperature" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_OCCUPANCY, "Occupancy" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_ABS_MIN_HEAT_SETPOINT, "AbsMinHeatSetpointLimit" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_ABS_MAX_HEAT_SETPOINT, "AbsMaxHeatSetpointLimit" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_ABS_MIN_COOL_SETPOINT, "AbsMinCoolSetpointLimit" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_ABS_MAX_COOL_SETPOINT, "AbsMaxCoolSetpointLimit" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_PI_COOL_DEMAND, "PICoolingDemand" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_PI_HEAT_DEMAND, "PIHeatingDemand" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_HVAC_TYPE_CONFIG, "HVACSystemTypeConfiguration" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_LOCAL_TEMP_CALIBRATION, "LocalTemperatureCalibration" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_OCCUPIED_COOL_SETPOINT, "OccupiedCoolingSetpoint" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_OCCUPIED_HEAT_SETPOINT, "OccupiedHeatingSetpoint" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_UNOCCUPIED_COOL_SETPOINT, "UnoccupiedCoolingSetpoint" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_UNOCCUPIED_HEAT_SETPOINT, "UnoccupiedHeatingSetpoint" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_MIN_HEAT_SETPOINT, "MinHeatSetpointLimit" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_MAX_HEAT_SETPOINT, "MaxHeatSetpointLimit" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_MIN_COOL_SETPOINT, "MinCoolSetpointLimit" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_MAX_COOL_SETPOINT, "MaxCoolSetpointLimit" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_MIN_SETPOINT_DEADBAND, "MinSetpointDeadBand" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_REMOTE_SENSING, "RemoteSensing" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_CONTROL_SEQUENCE, "ControlSequenceOfOperation" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_SYSTEM_MODE, "SystemMode" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_ALARM_MASK, "AlarmMask" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_RUNNING_MODE, "ThermostatRunningMode" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_START_OF_WEEK, "StartOfWeek" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_NUM_WEEKLY_TRANSITIONS, "NumberOfWeeklyTransitions" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_NUM_DAILY_TRANSITIONS, "NumberOfDailyTransitions" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_SETPOINT_HOLD, "TemperatureSetpointHold" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_SETPOINT_HOLD_DURATION, "TemperatureSetpointHoldDuration" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_PROGRAMMING_MODE, "ThermostatProgrammingOperationMode" }, + { ZBEE_ZCL_ATTR_ID_THERMOSTAT_RUNNING_STATE, "ThermostatRunningState" }, + { 0, NULL } +}; + +/* RemoteSensing bitmask. */ +#define ZBEE_ZCL_THERMOSTAT_REMOTE_SENSE_LOCAL 0x01 +#define ZBEE_ZCL_THERMOSTAT_REMOTE_SENSE_OUTDOOR 0x02 +#define ZBEE_ZCL_THERMOSTAT_REMOTE_SENSE_OCCUPANCY 0x04 + +#define ZBEE_ZCL_THERMOSTAT_ALARM_INIT_FAILURE 0x01 +#define ZBEE_ZCL_THERMOSTAT_ALARM_HARDWARE_FAILURE 0x02 +#define ZBEE_ZCL_THERMOSTAT_ALARM_CALIBRATION_FAILURE 0x04 + +/* Programming operation mode bits. */ +#define ZBEE_ZCL_THERMOSTAT_PROGRAM_MODE_SCHEDULE 0x01 +#define ZBEE_ZCL_THERMOSTAT_PROGRAM_MODE_AUTO 0x02 +#define ZBEE_ZCL_THERMOSTAT_PROGRAM_MODE_ENERGY_STAR 0x04 + +/* HVAC Running State bits. */ +#define ZBEE_ZCL_THERMOSTAT_RUNNING_STATE_HEAT 0x0001 +#define ZBEE_ZCL_THERMOSTAT_RUNNING_STATE_COOL 0x0002 +#define ZBEE_ZCL_THERMOSTAT_RUNNING_STATE_FAN 0x0004 +#define ZBEE_ZCL_THERMOSTAT_RUNNING_STATE_HEAT2 0x0008 +#define ZBEE_ZCL_THERMOSTAT_RUNNING_STATE_COOL2 0x0010 +#define ZBEE_ZCL_THERMOSTAT_RUNNING_STATE_FAN2 0x0020 +#define ZBEE_ZCL_THERMOSTAT_RUNNING_STATE_FAN3 0x0040 + +/* Client-to-server commands. */ +#define ZBEE_ZCL_CMD_ID_THERMOSTAT_SETPOINT 0x00 +#define ZBEE_ZCL_CMD_ID_THERMOSTAT_SET_SCHEDULE 0x01 +#define ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_SCHEDULE 0x02 +#define ZBEE_ZCL_CMD_ID_THERMOSTAT_CLEAR_SCHEDULE 0x03 +#define ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_RELAY_LOG 0x04 +static const value_string zbee_zcl_thermostat_srv_rx_cmd_names[] = { + { ZBEE_ZCL_CMD_ID_THERMOSTAT_SETPOINT, "Setpoint Raise/Lower" }, + { ZBEE_ZCL_CMD_ID_THERMOSTAT_SET_SCHEDULE, "Set Weekly Schedule" }, + { ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_SCHEDULE, "Get Weekly Schedule" }, + { ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_RELAY_LOG, "Get Relay Status Log" }, + { 0, NULL } +}; + +#define ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_SCHEDULE_RESPONSE 0x00 +#define ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_RELAY_LOG_RESPONSE 0x01 +static const value_string zbee_zcl_thermostat_srv_tx_cmd_names[] = { + { ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_SCHEDULE_RESPONSE, "Get Weekly Schedule Response" }, + { ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_RELAY_LOG_RESPONSE,"Get Relay Status Log Response" }, + { 0, NULL } +}; + +#define ZBEE_ZCL_CMD_THERMOSTAT_SCHEDULE_MODE_SEQUENCE_HEAT 0x01 +#define ZBEE_ZCL_CMD_THERMOSTAT_SCHEDULE_MODE_SEQUENCE_COOL 0x02 + +/* Setpoint mode names. */ +static const value_string zbee_zcl_thermostat_setpoint_mode_names[] = { + { 0, "Heat" }, + { 1, "Cool" }, + { 2, "Both" }, + { 0, NULL } +}; + +/*************************/ +/* Global Variables */ +/*************************/ +static int proto_zbee_zcl_thermostat = -1; + +static int hf_zbee_zcl_thermostat_attr_id = -1; +static int hf_zbee_zcl_thermostat_srv_rx_cmd_id = -1; +static int hf_zbee_zcl_thermostat_srv_tx_cmd_id = -1; +static int hf_zbee_zcl_thermostat_setpoint_mode = -1; +static int hf_zbee_zcl_thermostat_setpoint_amount = -1; + +static int hf_zbee_zcl_thermostat_schedule_num_trans = -1; +static int hf_zbee_zcl_thermostat_schedule_day_sequence = -1; +static int hf_zbee_zcl_thermostat_schedule_day_sunday = -1; +static int hf_zbee_zcl_thermostat_schedule_day_monday = -1; +static int hf_zbee_zcl_thermostat_schedule_day_tuesday = -1; +static int hf_zbee_zcl_thermostat_schedule_day_wednesday = -1; +static int hf_zbee_zcl_thermostat_schedule_day_thursday = -1; +static int hf_zbee_zcl_thermostat_schedule_day_friday = -1; +static int hf_zbee_zcl_thermostat_schedule_day_saturday = -1; +static int hf_zbee_zcl_thermostat_schedule_day_vacation = -1; +static int hf_zbee_zcl_thermostat_schedule_mode_sequence = -1; +static int hf_zbee_zcl_thermostat_schedule_mode_heat = -1; +static int hf_zbee_zcl_thermostat_schedule_mode_cool = -1; +static int hf_zbee_zcl_thermostat_schedule_time = -1; +static int hf_zbee_zcl_thermostat_schedule_heat = -1; +static int hf_zbee_zcl_thermostat_schedule_cool = -1; + +static gint ett_zbee_zcl_thermostat = -1; +static gint ett_zbee_zcl_thermostat_schedule_days = -1; +static gint ett_zbee_zcl_thermostat_schedule_mode = -1; + +/*************************/ +/* Function Declarations */ +/*************************/ +void proto_register_zbee_zcl_thermostat(void); +void proto_reg_handoff_zbee_zcl_thermostat(void); + +/* Attribute Dissector Helpers */ +static void dissect_zcl_thermostat_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type, gboolean client_attr); + +static int dissect_zcl_thermostat_schedule(proto_tree *tree, tvbuff_t *tvb, guint offset); +static void dissect_zcl_thermostat_schedule_days(proto_tree *tree, tvbuff_t *tvb, guint offset); +static void dissect_zcl_thermostat_schedule_mode(proto_tree *tree, tvbuff_t *tvb, guint offset); + +/** + *Helper function to dissect a Thermostat scheduling days bitmask. + * + *@param tree pointer to data tree Wireshark uses to display packet. + *@param tvb pointer to buffer containing raw packet. + *@param offset payload offset of the ZoneStatus value. +*/ +static void +dissect_zcl_thermostat_schedule_days(proto_tree *tree, tvbuff_t *tvb, guint offset) +{ + + static int * const thermostat_schedule_days[] = { + &hf_zbee_zcl_thermostat_schedule_day_sunday, + &hf_zbee_zcl_thermostat_schedule_day_monday, + &hf_zbee_zcl_thermostat_schedule_day_tuesday, + &hf_zbee_zcl_thermostat_schedule_day_wednesday, + &hf_zbee_zcl_thermostat_schedule_day_thursday, + &hf_zbee_zcl_thermostat_schedule_day_friday, + &hf_zbee_zcl_thermostat_schedule_day_saturday, + &hf_zbee_zcl_thermostat_schedule_day_vacation, + NULL + }; + + proto_tree_add_bitmask(tree, tvb, offset, hf_zbee_zcl_thermostat_schedule_day_sequence, + ett_zbee_zcl_thermostat_schedule_days, thermostat_schedule_days, ENC_NA); + +} /* dissect_zcl_thermostat_schedule_days */ + +/** + *Helper function to dissect a Thermostat scheduling mode bitmask. + * + *@param tree pointer to data tree Wireshark uses to display packet. + *@param tvb pointer to buffer containing raw packet. + *@param offset payload offset of the ZoneStatus value. +*/ +static void +dissect_zcl_thermostat_schedule_mode(proto_tree *tree, tvbuff_t *tvb, guint offset) +{ + + static int * const thermostat_schedule_modes[] = { + &hf_zbee_zcl_thermostat_schedule_mode_heat, + &hf_zbee_zcl_thermostat_schedule_mode_cool, + NULL + }; + + proto_tree_add_bitmask(tree, tvb, offset, hf_zbee_zcl_thermostat_schedule_mode_sequence, + ett_zbee_zcl_thermostat_schedule_mode, thermostat_schedule_modes, ENC_NA); +} + +/** + *Helper function to dissect a Thermostat schedule, which has + * + *@param tree pointer to data tree Wireshark uses to display packet. + *@param tvb pointer to buffer containing raw packet. + *@param offset payload offset of the ZoneStatus value. + *@return length of parsed data. +*/ +static int +dissect_zcl_thermostat_schedule(proto_tree *tree, tvbuff_t *tvb, guint offset) +{ + guint start = offset; + guint8 num_transitions; + guint8 mode_sequence; + int i; + + num_transitions = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(tree, hf_zbee_zcl_thermostat_schedule_num_trans, tvb, offset, 1, + num_transitions); + offset++; + + dissect_zcl_thermostat_schedule_days(tree, tvb, offset); + offset++; + + mode_sequence = tvb_get_guint8(tvb, offset); + dissect_zcl_thermostat_schedule_mode(tree, tvb, offset); + offset++; + + /* Parse the list of setpoint transitions. */ + for (i = 0; i < num_transitions; i++) { + nstime_t tv; + tv.secs = tvb_get_letohs(tvb, offset) * 60; + tv.nsecs = 0; + proto_tree_add_time(tree, hf_zbee_zcl_thermostat_schedule_time, tvb, offset, 2, &tv); + offset += 2; + + if (mode_sequence & ZBEE_ZCL_CMD_THERMOSTAT_SCHEDULE_MODE_SEQUENCE_HEAT) { + float setpoint = tvb_get_letohis(tvb, offset); + proto_tree_add_float(tree, hf_zbee_zcl_thermostat_schedule_heat, + tvb, offset, 2, (setpoint / 100.0f)); + offset += 2; + } + if (mode_sequence & ZBEE_ZCL_CMD_THERMOSTAT_SCHEDULE_MODE_SEQUENCE_COOL) { + float setpoint = tvb_get_letohis(tvb, offset); + proto_tree_add_float(tree, hf_zbee_zcl_thermostat_schedule_cool, + tvb, offset, 2, (setpoint / 100.0f)); + offset += 2; + } + } /* for */ + + /* Return the number of bytes parsed. */ + return (offset - start); +} /* dissect_zcl_thermostat_cmd_schedule */ + +/** + *ZigBee ZCL Thermostat cluster dissector for wireshark. + * + *@param tvb pointer to buffer containing raw packet. + *@param pinfo pointer to packet information fields + *@param tree pointer to data tree Wireshark uses to display packet. + *@param data pointer to ZCL packet structure. + *@return length of parsed data. +*/ +static int +dissect_zbee_zcl_thermostat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + zbee_zcl_packet *zcl; + guint offset = 0; + guint8 cmd_id; + float amount; + + /* Reject the packet if data is NULL */ + if (data == NULL) + return 0; + zcl = (zbee_zcl_packet *)data; + cmd_id = zcl->cmd_id; + + if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) { + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_thermostat_srv_rx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_thermostat_srv_rx_cmd_id, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* Handle the command dissection. */ + switch (cmd_id) { + case ZBEE_ZCL_CMD_ID_THERMOSTAT_SETPOINT: + /* Setpoint Raise/Lower. */ + proto_tree_add_item(tree, hf_zbee_zcl_thermostat_setpoint_mode, + tvb, offset, 1, ENC_NA); + offset++; + amount = tvb_get_gint8(tvb, offset); + proto_tree_add_float(tree, hf_zbee_zcl_thermostat_setpoint_amount, + tvb, offset, 1, (amount / 100.0f)); + offset++; + break; + + case ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_SCHEDULE: + /* Get Weekly Schedule. */ + dissect_zcl_thermostat_schedule_days(tree, tvb, offset); + offset++; + dissect_zcl_thermostat_schedule_mode(tree, tvb, offset); + offset++; + break; + + case ZBEE_ZCL_CMD_ID_THERMOSTAT_SET_SCHEDULE: + /* Set Weekly Schedule. */ + dissect_zcl_thermostat_schedule(tree, tvb, offset); + break; + + case ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_RELAY_LOG: + /* No Payload - fall-through. */ + default: + break; + } /* switch */ + } else { + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_thermostat_srv_tx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_thermostat_srv_tx_cmd_id, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* Handle the command dissection. */ + switch (cmd_id) { + case ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_SCHEDULE_RESPONSE: + /* Get Weekly Schedule Response. */ + dissect_zcl_thermostat_schedule(tree, tvb, offset); + break; + + case ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_RELAY_LOG_RESPONSE: + /* TODO: Implement Me! */ + default: + break; + } /* switch */ + } + + return tvb_captured_length(tvb); +} /* dissect_zbee_zcl_thermostat */ + +/** + *This function is called by ZCL foundation dissector in order to decode + * + *@param tree pointer to data tree Wireshark uses to display packet. + *@param tvb pointer to buffer containing raw packet. + *@param offset pointer to buffer offset + *@param attr_id attribute identifier + *@param data_type attribute data type + *@param client_attr ZCL client +*/ +static void +dissect_zcl_thermostat_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type, gboolean client_attr) +{ + /* Dissect attribute data type and data */ + switch (attr_id) { + default: + dissect_zcl_attr_data(tvb, tree, offset, data_type, client_attr); + break; + } +} /*dissect_zcl_thermostat_attr_data*/ + +/** + *ZigBee ZCL IAS Zone cluste protocol registration. + * +*/ +void +proto_register_zbee_zcl_thermostat(void) +{ + /* Setup list of header fields */ + static hf_register_info hf[] = { + + { &hf_zbee_zcl_thermostat_attr_id, + { "Attribute", "zbee_zcl_hvac.thermostat.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_thermostat_attr_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_thermostat_srv_rx_cmd_id, + { "Command", "zbee_zcl_hvac.thermostat.cmd.srv_rx.id", FT_UINT8, BASE_HEX, + VALS(zbee_zcl_thermostat_srv_rx_cmd_names), 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_srv_tx_cmd_id, + { "Command", "zbee_zcl_hvac.thermostat.cmd.srv_tx.id", FT_UINT8, BASE_HEX, + VALS(zbee_zcl_thermostat_srv_tx_cmd_names), 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_setpoint_mode, + { "Mode", "zbee_zcl_hvac.thermostat.mode", FT_UINT8, BASE_HEX, + VALS(zbee_zcl_thermostat_setpoint_mode_names), 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_setpoint_amount, + { "Amount", "zbee_zcl_hvac.thermostat.amount", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_num_trans, + { "Number of Transitions for Sequence", "zbee_zcl_hvac.thermostat.num_trans", FT_UINT8, BASE_HEX, NULL, + 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_sequence, + { "Days of Week for Sequence", "zbee_zcl_hvac.thermostat.day_sequence", FT_UINT8, BASE_HEX, NULL, + 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_sunday, + { "Sunday", "zbee_zcl_hvac.thermostat.day.sunday", FT_BOOLEAN, 8, NULL, 0x01, NULL, + HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_monday, + { "Monday", "zbee_zcl_hvac.thermostat.day.monday", FT_BOOLEAN, 8, NULL, 0x02, NULL, + HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_tuesday, + { "Tuesday", "zbee_zcl_hvac.thermostat.day.tuesday", FT_BOOLEAN, 8, NULL, 0x04, NULL, + HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_wednesday, + { "Wednesday", "zbee_zcl_hvac.thermostat.day.wednesday", FT_BOOLEAN, 8, NULL, 0x08, NULL, + HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_thursday, + { "Thursday", "zbee_zcl_hvac.thermostat.day.thursday", FT_BOOLEAN, 8, NULL, 0x10, NULL, + HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_friday, + { "Friday", "zbee_zcl_hvac.thermostat.day.friday", FT_BOOLEAN, 8, NULL, 0x20, NULL, + HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_saturday, + { "Saturday", "zbee_zcl_hvac.thermostat.day.saturday", FT_BOOLEAN, 8, NULL, 0x40, NULL, + HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_day_vacation, + { "Away/Vacation", "zbee_zcl_hvac.thermostat.day.vacation", FT_BOOLEAN, 8, NULL, 0x80, NULL, + HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_mode_sequence, + { "Mode for Sequence", "zbee_zcl_hvac.thermostat.mode_sequence", FT_UINT8, BASE_HEX, NULL, + 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_mode_heat, + { "Heating", "zbee_zcl_hvac.thermostat.mode.heat", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_mode_cool, + { "Cooling", "zbee_zcl_hvac.thermostat.mode.cool", FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_time, + { "Transition Time", "zbee_zcl_hvac.thermostat.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + "Setpoint transition time relative to midnight of the scheduled day", HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_heat, + { "Heating Setpoint", "zbee_zcl_hvac.thermostat.heat", FT_FLOAT, BASE_NONE, NULL, 0x0, + "Heating setpoint in degrees Celsius", HFILL }}, + + { &hf_zbee_zcl_thermostat_schedule_cool, + { "Cooling Setpoint", "zbee_zcl_hvac.thermostat.cool", FT_FLOAT, BASE_NONE, NULL, 0x0, + "Cooling setpoint in degrees Celsius", HFILL }} + }; + + /* ZCL IAS Zone subtrees */ + static gint *ett[ZBEE_ZCL_THERMOSTAT_NUM_ETT]; + + ett[0] = &ett_zbee_zcl_thermostat; + ett[1] = &ett_zbee_zcl_thermostat_schedule_days; + ett[2] = &ett_zbee_zcl_thermostat_schedule_mode; + + /* Register the ZigBee ZCL IAS Zoben cluster protocol name and description */ + proto_zbee_zcl_thermostat = proto_register_protocol("ZigBee ZCL Thermostat", "ZCL Thermostat", ZBEE_PROTOABBREV_ZCL_THERMOSTAT); + proto_register_field_array(proto_zbee_zcl_thermostat, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register the ZigBee ZCL IAS Zone dissector. */ + register_dissector(ZBEE_PROTOABBREV_ZCL_THERMOSTAT, dissect_zbee_zcl_thermostat, proto_zbee_zcl_thermostat); +} /*proto_register_zbee_zcl_thermostat*/ + +/** + *Hands off the ZCL Thermostat dissector. + * +*/ +void +proto_reg_handoff_zbee_zcl_thermostat(void) +{ + zbee_zcl_init_cluster( ZBEE_PROTOABBREV_ZCL_THERMOSTAT, + proto_zbee_zcl_thermostat, + ett_zbee_zcl_thermostat, + ZBEE_ZCL_CID_THERMOSTAT, + ZBEE_MFG_CODE_NONE, + hf_zbee_zcl_thermostat_attr_id, + hf_zbee_zcl_thermostat_attr_id, + hf_zbee_zcl_thermostat_srv_rx_cmd_id, + hf_zbee_zcl_thermostat_srv_tx_cmd_id, + (zbee_zcl_fn_attr_data)dissect_zcl_thermostat_attr_data + ); +} /*proto_reg_handoff_zbee_zcl_thermostat*/ + +/* ########################################################################## */ +/* #### (0x0500) IAS ZONE CLUSTER ########################################### */ +/* ########################################################################## */ + +#define ZBEE_ZCL_IAS_ZONE_NUM_ETT 2 + +/* IAS Zone Server Attributes */ +#define ZBEE_ZCL_ATTR_ID_IAS_ZONE_STATE 0x0000 +#define ZBEE_ZCL_ATTR_ID_IAS_ZONE_TYPE 0x0001 +#define ZBEE_ZCL_ATTR_ID_IAS_ZONE_STATUS 0x0002 +#define ZBEE_ZCL_ATTR_ID_IAS_CIE_ADDRESS 0x0010 + +static const value_string zbee_zcl_ias_zone_attr_names[] = { + { ZBEE_ZCL_ATTR_ID_IAS_ZONE_STATE, "ZoneState" }, + { ZBEE_ZCL_ATTR_ID_IAS_ZONE_TYPE, "ZoneType" }, + { ZBEE_ZCL_ATTR_ID_IAS_ZONE_STATUS, "ZoneStatus" }, + { ZBEE_ZCL_ATTR_ID_IAS_CIE_ADDRESS, "IAS_CIE_Address" }, + { 0, NULL } +}; + +/* IAS Zone States */ +#define ZBEE_IAS_ZONE_STATE_NOT_ENROLLED 0x00 +#define ZBEE_IAS_ZONE_STATE_ENROLLED 0x01 +static const value_string zbee_ias_state_names[] = { + { ZBEE_IAS_ZONE_STATE_NOT_ENROLLED, "Not Enrolled" }, + { ZBEE_IAS_ZONE_STATE_ENROLLED, "Enrolled" }, + { 0, NULL } +}; + +/* IAS Zone Type values. */ +#define ZBEE_IAS_ZONE_TYPE_STANDARD_CIE 0x0000 +#define ZBEE_IAS_ZONE_TYPE_MOTION_SENSOR 0x000D +#define ZBEE_IAS_ZONE_TYPE_CONTACT_SWITCH 0x0015 +#define ZBEE_IAS_ZONE_TYPE_FIRE_SENSOR 0x0028 +#define ZBEE_IAS_ZONE_TYPE_WATER_SENSOR 0x002A +#define ZBEE_IAS_ZONE_TYPE_GAS_SENSOR 0x002B +#define ZBEE_IAS_ZONE_TYPE_PERSONAL_EMERGENCY 0x002C +#define ZBEE_IAS_ZONE_TYPE_VIBRATION_SENSOR 0x002D +#define ZBEE_IAS_ZONE_TYPE_REMOTE_CONTROL 0x010F +#define ZBEE_IAS_ZONE_TYPE_KEY_FOB 0x0115 +#define ZBEE_IAS_ZONE_TYPE_KEYPAD 0x021D +#define ZBEE_IAS_ZONE_TYPE_STANDARD_WARNING 0x0225 +#define ZBEE_IAS_ZONE_TYPE_INVALID_ZONE_TYPE 0xFFFF + +#define ZBEE_IAS_ZONE_STATUS_ALARM1 0x0001 +#define ZBEE_IAS_ZONE_STATUS_ALARM2 0x0002 +#define ZBEE_IAS_ZONE_STATUS_TAMPER 0x0004 +#define ZBEE_IAS_ZONE_STATUS_BATTERY 0x0008 +#define ZBEE_IAS_ZONE_STATUS_SUPERVISION 0x0010 +#define ZBEE_IAS_ZONE_STATUS_RESTORE 0x0020 +#define ZBEE_IAS_ZONE_STATUS_TROUBLE 0x0040 +#define ZBEE_IAS_ZONE_STATUS_AC_MAINS 0x0080 + +static const value_string zbee_ias_type_names[] = { + { ZBEE_IAS_ZONE_TYPE_STANDARD_CIE, "Standard CIE" }, + { ZBEE_IAS_ZONE_TYPE_MOTION_SENSOR, "Motion sensor" }, + { ZBEE_IAS_ZONE_TYPE_CONTACT_SWITCH, "Contact switch" }, + { ZBEE_IAS_ZONE_TYPE_FIRE_SENSOR, "Fire sensor" }, + { ZBEE_IAS_ZONE_TYPE_WATER_SENSOR, "Water sensor" }, + { ZBEE_IAS_ZONE_TYPE_GAS_SENSOR, "Gas sensor" }, + { ZBEE_IAS_ZONE_TYPE_PERSONAL_EMERGENCY, "Personal emergency device" }, + { ZBEE_IAS_ZONE_TYPE_VIBRATION_SENSOR, "Vibration/movement sensor" }, + { ZBEE_IAS_ZONE_TYPE_REMOTE_CONTROL, "Remote control" }, + { ZBEE_IAS_ZONE_TYPE_KEY_FOB, "Key fob" }, + { ZBEE_IAS_ZONE_TYPE_KEYPAD, "Keypad" }, + { ZBEE_IAS_ZONE_TYPE_STANDARD_WARNING, "Standard warning device" }, + { ZBEE_IAS_ZONE_TYPE_INVALID_ZONE_TYPE, "Invalid zone type" }, + { 0, NULL } +}; + +/* Server-to-client command IDs. */ +#define ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_NOTIFY 0x00 +#define ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_REQUEST 0x01 +static const value_string zbee_zcl_ias_zone_srv_tx_cmd_names[] = { + { ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_REQUEST, "Zone Enroll Request" }, + { ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_NOTIFY, "Zone Status Change Notification" }, + { 0, NULL } +}; + +/* Client-to-server command IDs. */ +#define ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_RESPONSE 0x00 +static const value_string zbee_zcl_ias_zone_srv_rx_cmd_names[] = { + { ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_RESPONSE, "Zone Enroll Response" }, + { 0, NULL } +}; + + +static const value_string zbee_zcl_ias_zone_enroll_code_names[] = { + { 0, "Success" }, + { 1, "Not Supported" }, + { 2, "No enroll permit" }, + { 3, "Too many zones" }, + { 0, NULL } +}; + +/*************************/ +/* Global Variables */ +/*************************/ +/* Initialize the protocol and registered fields */ +static int proto_zbee_zcl_ias_zone = -1; + +static int hf_zbee_zcl_ias_zone_attr_id = -1; +static int hf_zbee_zcl_ias_zone_srv_rx_cmd_id = -1; +static int hf_zbee_zcl_ias_zone_srv_tx_cmd_id = -1; +static int hf_zbee_zcl_ias_zone_enroll_code = -1; +static int hf_zbee_zcl_ias_zone_zone_id = -1; +static int hf_zbee_zcl_ias_zone_state = -1; +static int hf_zbee_zcl_ias_zone_type = -1; +static int hf_zbee_zcl_ias_zone_status = -1; +static int hf_zbee_zcl_ias_zone_delay = -1; +static int hf_zbee_zcl_ias_zone_ext_status = -1; +static int hf_zbee_zcl_ias_zone_manufacturer_code = -1; +static int hf_zbee_zcl_ias_zone_status_ac_mains = -1; +static int hf_zbee_zcl_ias_zone_status_alarm1 = -1; +static int hf_zbee_zcl_ias_zone_status_alarm2 = -1; +static int hf_zbee_zcl_ias_zone_status_battery = -1; +static int hf_zbee_zcl_ias_zone_status_restore_reports = -1; +static int hf_zbee_zcl_ias_zone_status_supervision_reports = -1; +static int hf_zbee_zcl_ias_zone_status_tamper = -1; +static int hf_zbee_zcl_ias_zone_status_trouble = -1; + +static const true_false_string tfs_ac_mains = { + "AC/Mains fault", + "AC/Mains OK" +}; + +static const true_false_string tfs_alarmed_or_not = { + "Opened or alarmed", + "Closed or not alarmed" +}; + +static const true_false_string tfs_battery = { + "Low battery", + "Battery OK" +}; + +static const true_false_string tfs_reports_or_not = { + "Reports", + "Does not report" +}; + +static const true_false_string tfs_reports_restore = { + "Reports restore", + "Does not report restore" +}; + +static const true_false_string tfs_tampered_or_not = { + "Tampered", + "Not tampered" +}; + +static const true_false_string tfs_trouble_failure = { + "Trouble/Failure", + "OK" +}; + +static gint ett_zbee_zcl_ias_zone = -1; +static gint ett_zbee_zcl_ias_zone_status = -1; + +/*************************/ +/* Function Declarations */ +/*************************/ +void proto_register_zbee_zcl_ias_zone(void); +void proto_reg_handoff_zbee_zcl_ias_zone(void); + +/* Command Dissector Helpers. */ +static int dissect_zbee_zcl_ias_zone (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); + +/* Attribute Dissector Helpers */ +static void dissect_zcl_ias_zone_attr_data (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type, gboolean client_attr); + +/* ZoneStatus bitmask helper */ +static void dissect_zcl_ias_zone_status (proto_tree *tree, tvbuff_t *tvb, guint offset); + +/** + *Helper function to dissect the IAS ZoneStatus bitmask. + * + *@param tree pointer to data tree Wireshark uses to display packet. + *@param tvb pointer to buffer containing raw packet. + *@param offset payload offset of the ZoneStatus value. +*/ +static void +dissect_zcl_ias_zone_status(proto_tree *tree, tvbuff_t *tvb, guint offset) +{ + static int * const ias_zone_statuses[] = { + &hf_zbee_zcl_ias_zone_status_alarm1, + &hf_zbee_zcl_ias_zone_status_alarm2, + &hf_zbee_zcl_ias_zone_status_tamper, + &hf_zbee_zcl_ias_zone_status_battery, + &hf_zbee_zcl_ias_zone_status_supervision_reports, + &hf_zbee_zcl_ias_zone_status_restore_reports, + &hf_zbee_zcl_ias_zone_status_trouble, + &hf_zbee_zcl_ias_zone_status_ac_mains, + NULL + }; + + proto_tree_add_bitmask(tree, tvb, offset, hf_zbee_zcl_ias_zone_status, ett_zbee_zcl_ias_zone_status, ias_zone_statuses, ENC_LITTLE_ENDIAN); + +} /* dissect_zcl_ias_zone_status */ + +/** + *ZigBee ZCL IAS Zone cluster dissector for wireshark. + * + *@param tvb pointer to buffer containing raw packet. + *@param pinfo pointer to packet information fields + *@param tree pointer to data tree Wireshark uses to display packet. + *@param data pointer to ZCL packet structure. + *@return length of parsed data. +*/ +static int +dissect_zbee_zcl_ias_zone(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + zbee_zcl_packet *zcl; + guint offset = 0; + guint8 cmd_id; + + /* Reject the packet if data is NULL */ + if (data == NULL) + return 0; + zcl = (zbee_zcl_packet *)data; + cmd_id = zcl->cmd_id; + + if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) { + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_ias_zone_srv_rx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_srv_rx_cmd_id, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* Handle the command dissection. */ + switch (cmd_id) { + case ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_RESPONSE: + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_enroll_code, tvb, offset, 1, ENC_NA); + offset++; + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_zone_id, tvb, offset, 1, ENC_NA); + offset++; + break; + + default: + break; + } /* switch */ + } else { + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_ias_zone_srv_tx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_srv_tx_cmd_id, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset++; + + /* Handle the command dissection. */ + switch (cmd_id) { + case ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_NOTIFY: + dissect_zcl_ias_zone_status(tree, tvb, offset); + offset += 2; + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_ext_status, tvb, offset, + 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_zone_id, tvb, offset, 1, + ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_delay, tvb, offset, 2, + ENC_LITTLE_ENDIAN); + break; + + case ZBEE_ZCL_CMD_ID_IAS_ZONE_ENROLL_REQUEST: + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_type, tvb, offset, 2, + ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_manufacturer_code, + tvb, offset, 2, ENC_LITTLE_ENDIAN); + break; + + default: + break; + } /* switch */ + } + + return tvb_reported_length(tvb); +} /* dissect_zbee_zcl_ias_zone */ + +/** + *This function is called by ZCL foundation dissector in order to decode + * + *@param tree pointer to data tree Wireshark uses to display packet. + *@param tvb pointer to buffer containing raw packet. + *@param offset pointer to buffer offset + *@param attr_id attribute identifier + *@param data_type attribute data type + *@param client_attr ZCL client +*/ +static void +dissect_zcl_ias_zone_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type, gboolean client_attr) +{ + /* Dissect attribute data type and data */ + switch (attr_id) { + case ZBEE_ZCL_ATTR_ID_IAS_ZONE_STATE: + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_state, tvb, *offset, 1, ENC_NA); + *offset += 1; + break; + + case ZBEE_ZCL_ATTR_ID_IAS_ZONE_TYPE: + proto_tree_add_item(tree, hf_zbee_zcl_ias_zone_type, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + break; + + case ZBEE_ZCL_ATTR_ID_IAS_ZONE_STATUS: + dissect_zcl_ias_zone_status(tree, tvb, *offset); + *offset += 2; + break; + + case ZBEE_ZCL_ATTR_ID_IAS_CIE_ADDRESS: + default: + dissect_zcl_attr_data(tvb, tree, offset, data_type, client_attr); + break; + } +} /*dissect_zcl_ias_zone_attr_data*/ + +/** + *Hands off the ZCL IAS Zone dissector. + * +*/ +void +proto_reg_handoff_zbee_zcl_ias_zone(void) +{ + zbee_zcl_init_cluster( ZBEE_PROTOABBREV_ZCL_IAS_ZONE, + proto_zbee_zcl_ias_zone, + ett_zbee_zcl_ias_zone, + ZBEE_ZCL_CID_IAS_ZONE, + ZBEE_MFG_CODE_NONE, + hf_zbee_zcl_ias_zone_attr_id, + hf_zbee_zcl_ias_zone_attr_id, + hf_zbee_zcl_ias_zone_srv_rx_cmd_id, + hf_zbee_zcl_ias_zone_srv_tx_cmd_id, + (zbee_zcl_fn_attr_data)dissect_zcl_ias_zone_attr_data + ); +} /*proto_reg_handoff_zbee_zcl_ias_zone*/ + +/** + *ZigBee ZCL IAS Zone cluste protocol registration. + * +*/ +void +proto_register_zbee_zcl_ias_zone(void) +{ + /* Setup list of header fields */ + static hf_register_info hf[] = { + + { &hf_zbee_zcl_ias_zone_attr_id, + { "Attribute", "zbee_zcl_ias.zone.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_ias_zone_attr_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_ias_zone_srv_rx_cmd_id, + { "Command", "zbee_zcl_ias.zone.cmd.srv_rx.id", FT_UINT8, BASE_HEX, + VALS(zbee_zcl_ias_zone_srv_rx_cmd_names), 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_srv_tx_cmd_id, + { "Command", "zbee_zcl_ias.zone.cmd.srv_tx.id", FT_UINT8, BASE_HEX, + VALS(zbee_zcl_ias_zone_srv_tx_cmd_names), 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_enroll_code, + { "Enroll response code", "zbee_zcl_ias.zone.enroll_code", FT_UINT8, BASE_HEX, + VALS(zbee_zcl_ias_zone_enroll_code_names), 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_zone_id, + { "Zone ID", "zbee_zcl_ias.zone.zone_id", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_state, + { "ZoneState", "zbee_zcl_ias.zone.state", FT_UINT16, BASE_HEX, VALS(zbee_ias_state_names), 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_type, + { "ZoneType", "zbee_zcl_ias.zone.type", FT_UINT16, BASE_HEX, VALS(zbee_ias_type_names), 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_manufacturer_code, + { "ManufacturerCode", "zbee_zcl_ias.zone.manufacturer_code", FT_UINT16, BASE_HEX, VALS(zbee_mfr_code_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_ias_zone_status, + { "ZoneStatus", "zbee_zcl_ias.zone.status", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_delay, + { "Delay (in quarterseconds)", "zbee_zcl_ias.zone.delay", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, + HFILL }}, + + { &hf_zbee_zcl_ias_zone_ext_status, + { "Extended Status", "zbee_zcl_ias.zone.ext_status", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, + HFILL }}, + + { &hf_zbee_zcl_ias_zone_status_alarm1, + { "Alarm 1", "zbee_zcl_ias.zone.status.alarm_1", FT_BOOLEAN, 16, TFS(&tfs_alarmed_or_not), ZBEE_IAS_ZONE_STATUS_ALARM1, NULL, + HFILL }}, + + { &hf_zbee_zcl_ias_zone_status_alarm2, + { "Alarm 2", "zbee_zcl_ias.zone.status.alarm_2", FT_BOOLEAN, 16, TFS(&tfs_alarmed_or_not), ZBEE_IAS_ZONE_STATUS_ALARM2, NULL, + HFILL }}, + + { &hf_zbee_zcl_ias_zone_status_battery, + { "Battery", "zbee_zcl_ias.zone.status.battery", FT_BOOLEAN, 16, TFS(&tfs_battery), ZBEE_IAS_ZONE_STATUS_BATTERY, NULL, + HFILL }}, + + { &hf_zbee_zcl_ias_zone_status_tamper, + { "Tamper", "zbee_zcl_ias.zone.status.tamper", FT_BOOLEAN, 16, TFS(&tfs_tampered_or_not), ZBEE_IAS_ZONE_STATUS_TAMPER, NULL, + HFILL }}, + + { &hf_zbee_zcl_ias_zone_status_supervision_reports, + { "Supervision Reports", "zbee_zcl_ias.zone.status.supervision_reports", FT_BOOLEAN, 16, + TFS(&tfs_reports_or_not), ZBEE_IAS_ZONE_STATUS_SUPERVISION, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_status_restore_reports, + { "Restore Reports", "zbee_zcl_ias.zone.status.restore_reports", FT_BOOLEAN, 16, + TFS(&tfs_reports_restore), ZBEE_IAS_ZONE_STATUS_RESTORE, NULL, HFILL }}, + + { &hf_zbee_zcl_ias_zone_status_trouble, + { "Trouble", "zbee_zcl_ias.zone.status.trouble", FT_BOOLEAN, 16, TFS(&tfs_trouble_failure), ZBEE_IAS_ZONE_STATUS_TROUBLE, NULL, + HFILL }}, + + { &hf_zbee_zcl_ias_zone_status_ac_mains, + { "AC (mains)", "zbee_zcl_ias.zone.status.ac_mains", FT_BOOLEAN, 16, TFS(&tfs_ac_mains), ZBEE_IAS_ZONE_STATUS_AC_MAINS, NULL, + HFILL }} + }; + + /* ZCL IAS Zone subtrees */ + static gint *ett[ZBEE_ZCL_IAS_ZONE_NUM_ETT]; + + ett[0] = &ett_zbee_zcl_ias_zone; + ett[1] = &ett_zbee_zcl_ias_zone_status; + + /* Register the ZigBee ZCL IAS Zoben cluster protocol name and description */ + proto_zbee_zcl_ias_zone = proto_register_protocol("ZigBee ZCL IAS Zone", "ZCL IAS Zone", ZBEE_PROTOABBREV_ZCL_IAS_ZONE); + proto_register_field_array(proto_zbee_zcl_ias_zone, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register the ZigBee ZCL IAS Zone dissector. */ + register_dissector(ZBEE_PROTOABBREV_ZCL_IAS_ZONE, dissect_zbee_zcl_ias_zone, proto_zbee_zcl_ias_zone); +} /*proto_register_zbee_zcl_ias_zone*/ + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |