aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Zander <p.j.zander@lighting.com>2018-04-10 13:46:13 +0200
committerMartin Kaiser <wireshark@kaiser.cx>2018-04-11 02:06:54 +0000
commitcaea93df95ec507d09371ab232e61c0122cb044c (patch)
treee5cb650c60cddf6417bff6094a190f1557c5921b
parent6208796b9ed08e81c4411e9463e2f9c9c85ef711 (diff)
Zigbee: Decode the ZCL extension field sets in the scenes cluster.
Change-Id: Ida564e8c292819508fd2dd0fb5b650e95356459a Reviewed-on: https://code.wireshark.org/review/26852 Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Martin Kaiser <wireshark@kaiser.cx>
-rw-r--r--epan/dissectors/packet-zbee-aps.h1
-rw-r--r--epan/dissectors/packet-zbee-zcl-general.c291
2 files changed, 286 insertions, 6 deletions
diff --git a/epan/dissectors/packet-zbee-aps.h b/epan/dissectors/packet-zbee-aps.h
index 62d9d6beca..8a8f9cfe07 100644
--- a/epan/dissectors/packet-zbee-aps.h
+++ b/epan/dissectors/packet-zbee-aps.h
@@ -147,6 +147,7 @@
/* ZCL Cluster IDs - Closures */
#define ZBEE_ZCL_CID_SHADE_CONFIG 0x0100
#define ZBEE_ZCL_CID_DOOR_LOCK 0X0101
+#define ZBEE_ZCL_CID_WINDOW_COVERING 0X0102
/* ZCL Cluster IDs - HVAC */
#define ZBEE_ZCL_CID_PUMP_CONFIG_CONTROL 0x0200
diff --git a/epan/dissectors/packet-zbee-zcl-general.c b/epan/dissectors/packet-zbee-zcl-general.c
index 72e22642f9..8b01703efe 100644
--- a/epan/dissectors/packet-zbee-zcl-general.c
+++ b/epan/dissectors/packet-zbee-zcl-general.c
@@ -18,6 +18,7 @@
#include <epan/packet.h>
#include <epan/to_str.h>
#include <wsutil/bits_ctz.h>
+#include <wsutil/utf8_entities.h>
#include "packet-zbee.h"
#include "packet-zbee-aps.h"
@@ -2100,8 +2101,8 @@ proto_reg_handoff_zbee_zcl_groups(void)
/* Defines */
/*************************/
-#define ZBEE_ZCL_SCENES_NUM_ETT 2
-#define ZBEE_ZCL_ATTR_SCENES_SCENE_VALID_MASK 0x01 /* bit 0 */
+#define ZBEE_ZCL_SCENES_NUM_ETT 3
+#define ZBEE_ZCL_ATTR_SCENES_SCENE_VALID_MASK 0x01 /* bit 0 */
/* Attributes */
#define ZBEE_ZCL_ATTR_ID_SCENES_SCENE_COUNT 0x0000 /* Scene Count */
@@ -2165,6 +2166,7 @@ static void dissect_zcl_scenes_remove_all_scenes_response (tvb
static void dissect_zcl_scenes_get_scene_membership_response (tvbuff_t *tvb, proto_tree *tree, guint *offset);
static void dissect_zcl_scenes_copy_scene_response (tvbuff_t *tvb, proto_tree *tree, guint *offset);
+static void dissect_zcl_scenes_extension_fields (tvbuff_t *tvb, proto_tree *tree, guint *offset);
static void dissect_zcl_scenes_attr_data (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type, gboolean client_attr);
/* Private functions prototype */
@@ -2186,7 +2188,24 @@ static int hf_zbee_zcl_scenes_scene_id_from = -1;
static int hf_zbee_zcl_scenes_scene_id_to = -1;
static int hf_zbee_zcl_scenes_transit_time = -1;
static int hf_zbee_zcl_scenes_enh_transit_time = -1;
-static int hf_zbee_zcl_scenes_extension_set_field = -1;
+static int hf_zbee_zcl_scenes_extension_set= -1;
+static int hf_zbee_zcl_scenes_extension_set_cluster = -1;
+static int hf_zbee_zcl_scenes_extension_set_onoff = -1;
+static int hf_zbee_zcl_scenes_extension_set_level = -1;
+static int hf_zbee_zcl_scenes_extension_set_x = -1;
+static int hf_zbee_zcl_scenes_extension_set_y = -1;
+static int hf_zbee_zcl_scenes_extension_set_hue = -1;
+static int hf_zbee_zcl_scenes_extension_set_saturation = -1;
+static int hf_zbee_zcl_scenes_extension_set_color_loop_active = -1;
+static int hf_zbee_zcl_scenes_extension_set_color_loop_direction = -1;
+static int hf_zbee_zcl_scenes_extension_set_color_loop_time = -1;
+static int hf_zbee_zcl_scenes_extension_set_cooling_setpoint = -1;
+static int hf_zbee_zcl_scenes_extension_set_heating_setpoint = -1;
+static int hf_zbee_zcl_scenes_extension_set_system_mode = -1;
+static int hf_zbee_zcl_scenes_extension_set_lock_state = -1;
+static int hf_zbee_zcl_scenes_extension_set_lift_percentage = -1;
+static int hf_zbee_zcl_scenes_extension_set_tilt_percentage = -1;
+
static int hf_zbee_zcl_scenes_status = -1;
static int hf_zbee_zcl_scenes_capacity = -1;
static int hf_zbee_zcl_scenes_scene_count = -1;
@@ -2196,9 +2215,11 @@ static int hf_zbee_zcl_scenes_srv_rx_cmd_id = -1;
static int hf_zbee_zcl_scenes_srv_tx_cmd_id = -1;
static int hf_zbee_zcl_scenes_scene_list = -1;
static int hf_zbee_zcl_scenes_copy_mode = -1;
+
/* Initialize the subtree pointers */
static gint ett_zbee_zcl_scenes = -1;
static gint ett_zbee_zcl_scenes_scene_ctrl = -1;
+static gint ett_zbee_zcl_scenes_extension_field_set = -1;
/* Attributes */
static const value_string zbee_zcl_scenes_attr_names[] = {
@@ -2254,12 +2275,56 @@ static const value_string zbee_zcl_scenes_copy_mode_values[] = {
{ 0, NULL }
};
+/* Color Loop Directions */
+static const value_string zbee_zcl_scenes_color_loop_direction_values[] = {
+ { 0x00, "Hue is Decrementing" },
+ { 0x01, "Hue is Incrementing" },
+ { 0, NULL }
+};
+
+
/*************************/
/* Function Bodies */
/*************************/
/*FUNCTION:------------------------------------------------------
* NAME
+ * decode_color_xy
+ * DESCRIPTION
+ * this function decodes color xy values
+ * PARAMETERS
+ * guint *s - string to display
+ * guint16 value - value to decode
+ * RETURNS
+ * none
+ *---------------------------------------------------------------
+ */
+static void
+decode_color_xy(gchar *s, guint16 value)
+{
+ g_snprintf(s, ITEM_LABEL_LENGTH, "%.4lf", value/65535.0);
+ return;
+} /*decode_power_conf_voltage*/
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * decode_setpoint
+ * DESCRIPTION
+ * this function decodes the setpoint
+ * PARAMETERS
+ * guint *s - string to display
+ * guint16 value - value to decode
+ * RETURNS
+ * none
+ *---------------------------------------------------------------
+ */
+void decode_setpoint(gchar *s, gint16 value)
+{
+ g_snprintf(s, ITEM_LABEL_LENGTH, "%.2lf [" UTF8_DEGREE_SIGN "C]", value/100.0);
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
* dissect_zbee_zcl_scenes
* DESCRIPTION
* ZigBee ZCL Scenes cluster dissector for wireshark.
@@ -2434,7 +2499,7 @@ dissect_zcl_scenes_add_scene(tvbuff_t *tvb, proto_tree *tree, guint *offset, gbo
*offset += attr_uint;
/* Retrieve "Extension Set" field */
- proto_tree_add_item(tree, hf_zbee_zcl_scenes_extension_set_field, tvb, *offset, -1, ENC_NA);
+ dissect_zcl_scenes_extension_fields(tvb, tree, offset);
} /*dissect_zcl_scenes_add_scene*/
@@ -2614,7 +2679,7 @@ dissect_zcl_scenes_view_scene_response(tvbuff_t *tvb, proto_tree *tree, guint *o
*offset += attr_uint;
/* Retrieve "Extension Set" field */
- proto_tree_add_item(tree, hf_zbee_zcl_scenes_extension_set_field, tvb, *offset, -1, ENC_NA);
+ dissect_zcl_scenes_extension_fields(tvb, tree, offset);
}
@@ -2737,6 +2802,155 @@ dissect_zcl_scenes_copy_scene_response(tvbuff_t *tvb, proto_tree *tree, guint *o
/*FUNCTION:------------------------------------------------------
* NAME
+ * dissect_zcl_scenes_extension_fields
+ * DESCRIPTION
+ * this function decodes the extension set fields
+ * PARAMETERS
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * guint *offset - pointer to buffer offset
+ * RETURNS
+ * none
+ *---------------------------------------------------------------
+ */
+static void dissect_zcl_scenes_extension_fields(tvbuff_t *tvb, proto_tree *tree, guint *offset)
+{
+ guint8 set = 1;
+ proto_tree *subtree;
+
+ // Is there an extension field?
+ gboolean hasExtensionField = hasExtensionField = tvb_offset_exists(tvb, *offset+2);
+
+ while (hasExtensionField)
+ {
+ // Retrieve the cluster and the length
+ guint32 cluster = tvb_get_guint16(tvb, *offset, ENC_LITTLE_ENDIAN);
+ guint8 length = tvb_get_guint8 (tvb, *offset+2);
+
+ // Create a subtree
+ subtree = proto_tree_add_subtree_format(tree, tvb, *offset, length, ett_zbee_zcl_scenes_extension_field_set, NULL, "Extension field set %d", set++);
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_cluster, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ *offset += 3;
+
+ switch (cluster)
+ {
+ case ZBEE_ZCL_CID_ON_OFF:
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_onoff, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ break;
+
+ case ZBEE_ZCL_CID_LEVEL_CONTROL:
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_level, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ break;
+
+ case ZBEE_ZCL_CID_COLOR_CONTROL:
+ if (length >= 2)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_x, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ length -= 2;
+ *offset += 2;
+ }
+ if (length >= 2)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_y, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ length -= 2;
+ *offset += 2;
+ }
+ if (length >= 2)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_hue, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ length -= 2;
+ *offset += 2;
+ }
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_saturation, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_color_loop_active, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_color_loop_direction, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ if (length >= 2)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_color_loop_time, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ length -= 2;
+ *offset += 2;
+ }
+ break;
+
+ case ZBEE_ZCL_CID_DOOR_LOCK:
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_lock_state, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ break;
+
+ case ZBEE_ZCL_CID_WINDOW_COVERING:
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_lift_percentage, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_tilt_percentage, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ break;
+
+ case ZBEE_ZCL_CID_THERMOSTAT:
+ if (length >= 2)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_cooling_setpoint, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ length -= 2;
+ *offset += 2;
+ }
+ if (length >= 2)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_heating_setpoint, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ length -= 2;
+ *offset += 2;
+ }
+ if (length >= 1)
+ {
+ proto_tree_add_item(subtree, hf_zbee_zcl_scenes_extension_set_system_mode, tvb, *offset, 1, ENC_NA);
+ length -= 1;
+ *offset += 1;
+ }
+ break;
+ }
+
+ *offset += length;
+ hasExtensionField = tvb_offset_exists(tvb, *offset+2);
+ }
+}
+
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
* dissect_zcl_scenes_attr_data
* DESCRIPTION
* this function is called by ZCL foundation dissector in order to decode
@@ -2865,10 +3079,74 @@ proto_register_zbee_zcl_scenes(void)
{ "String", "zbee_zcl_general.scenes.attr_str", FT_STRING, BASE_NONE, NULL,
0x00, NULL, HFILL }},
- { &hf_zbee_zcl_scenes_extension_set_field,
+ { &hf_zbee_zcl_scenes_extension_set,
{ "Extension Set", "zbee_zcl_general.scenes.extension_set", FT_BYTES, BASE_NONE, NULL,
0x00, NULL, HFILL }},
+ { &hf_zbee_zcl_scenes_extension_set_cluster,
+ { "Cluster", "zbee_zcl_general.scenes.extension_set.cluster", FT_UINT16, BASE_HEX, VALS(zbee_aps_cid_names),
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_onoff,
+ { "On/Off", "zbee_zcl_general.scenes.extension_set.onoff", FT_UINT8, BASE_DEC, NULL,
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_level,
+ { "Level", "zbee_zcl_general.scenes.extension_set.level", FT_UINT8, BASE_DEC, NULL,
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_x,
+ { "Color X", "zbee_zcl_general.scenes.extension_set.color_x", FT_UINT16, BASE_CUSTOM, CF_FUNC(decode_color_xy),
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_y,
+ { "Color Y", "zbee_zcl_general.scenes.extension_set.color_y", FT_UINT16, BASE_CUSTOM, CF_FUNC(decode_color_xy),
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_hue,
+ { "Enhanced Hue", "zbee_zcl_general.scenes.extension_set.hue", FT_UINT16, BASE_DEC, NULL,
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_saturation,
+ { "Saturation", "zbee_zcl_general.scenes.extension_set.saturation", FT_UINT8, BASE_DEC, NULL,
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_color_loop_active,
+ { "Color Loop Active", "zbee_zcl_general.scenes.extension_set.color_loop_active", FT_BOOLEAN, 8, TFS(&tfs_true_false),
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_color_loop_direction,
+ { "Color Loop Direction", "zbee_zcl_general.scenes.extension_set.color_loop_direction", FT_UINT8, BASE_DEC, VALS(zbee_zcl_scenes_color_loop_direction_values),
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_color_loop_time,
+ { "Color Loop Time", "zbee_zcl_general.scenes.extension_set.color_loop_time", FT_UINT16, BASE_CUSTOM, CF_FUNC(decode_zcl_time_in_seconds),
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_lock_state,
+ { "Lock State", "zbee_zcl_general.scenes.extension_set.lock_state", FT_UINT8, BASE_DEC, NULL,
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_lift_percentage,
+ { "Current Position Lift Percentage", "zbee_zcl_general.scenes.extension_set.current_position_lift_percentage", FT_UINT8, BASE_DEC, NULL,
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_tilt_percentage,
+ { "Current Position Tilt Percentage", "zbee_zcl_general.scenes.extension_set.current_position_tilt_percentage", FT_UINT8, BASE_DEC, NULL,
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_cooling_setpoint,
+ { "Occupied Cooling Setpoint", "zbee_zcl_general.scenes.extension_set.occupied_cooling_setpoint", FT_INT16, BASE_CUSTOM, CF_FUNC(decode_setpoint),
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_heating_setpoint,
+ { "Occupied Heating Setpoint", "zbee_zcl_general.scenes.extension_set.occupied_heating_setpoint", FT_INT16, BASE_CUSTOM, CF_FUNC(decode_setpoint),
+ 0x00, NULL, HFILL }},
+
+ { &hf_zbee_zcl_scenes_extension_set_system_mode,
+ { "System Mode", "zbee_zcl_general.scenes.extension_set.system_mode", FT_UINT8, BASE_DEC, NULL,
+ 0x00, NULL, HFILL }},
+
{ &hf_zbee_zcl_scenes_copy_mode,
{ "Scene Copy Mode", "zbee_zcl_general.scenes.copy_mode", FT_UINT8, BASE_DEC, VALS(zbee_zcl_scenes_copy_mode_values),
0x00, NULL, HFILL } },
@@ -2887,6 +3165,7 @@ proto_register_zbee_zcl_scenes(void)
static gint *ett[ZBEE_ZCL_SCENES_NUM_ETT];
ett[0] = &ett_zbee_zcl_scenes;
ett[1] = &ett_zbee_zcl_scenes_scene_ctrl;
+ ett[2] = &ett_zbee_zcl_scenes_extension_field_set;
/* Register the ZigBee ZCL Scenes cluster protocol name and description */
proto_zbee_zcl_scenes = proto_register_protocol("ZigBee ZCL Scenes", "ZCL Scenes", ZBEE_PROTOABBREV_ZCL_SCENES);