MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-zbee-zcl.c
blobd432fd9446653fc1d7f80e3dd8efdf1c2759d65e
1 /* packet-zbee-zcl.c
2 * Dissector routines for the ZigBee Cluster Library (ZCL)
3 * By Fred Fierling <fff@exegin.com>
4 * Copyright 2009 Exegin Technologies Limited
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Used Owen Kirby's packet-zbee-aps module as a template. Based
13 * on ZigBee Cluster Library Specification document 075123r02ZB
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 /* Include Files */
31 #include "config.h"
33 #include <glib.h>
34 #include <epan/packet.h>
36 #include "packet-zbee.h"
37 #include "packet-zbee-nwk.h"
38 #include "packet-zbee-aps.h"
39 #include "packet-zbee-zcl.h"
41 /*************************
42 * Function Declarations *
43 *************************
46 /* Command Dissector Helpers */
47 static void dissect_zcl_read_attr (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset);
48 static void dissect_zcl_write_attr_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
49 guint *offset);
50 static void dissect_zcl_config_report (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset);
51 static void dissect_zcl_config_report_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
52 guint *offset);
53 static void dissect_zcl_read_report_config (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
54 guint *offset);
55 static void dissect_zcl_read_report_config_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
56 guint *offset);
57 static void dissect_zcl_default_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset);
58 static void dissect_zcl_discover_attr (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset);
59 static void dissect_zcl_discover_attr_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
60 guint *offset);
62 /* Helper routines */
63 guint zbee_apf_transaction_len (tvbuff_t *tvb, guint offset, guint8 type);
64 static void dissect_zcl_attr_data_general(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 attr_id, guint data_type);
65 static void dissect_zcl_attr_data_type_val (tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 cmd_id);
66 static void dissect_zcl_attr_bytes (tvbuff_t *tvb, proto_tree *tree, guint *offset, guint length);
67 static guint dissect_zcl_attr_uint8 (tvbuff_t *tvb, proto_tree *tree, guint *offset, int *length);
68 static guint dissect_zcl_attr_uint16 (tvbuff_t *tvb, proto_tree *tree, guint *offset, int *length);
69 static void dissect_zcl_attr_id (tvbuff_t *tvb, proto_tree *tree, guint *offset);
70 static void dissect_zcl_big_int (tvbuff_t *tvb, proto_tree *tree, guint *offset, guint length,
71 gboolean signed_flag);
72 static void zcl_dump_data(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree);
74 static guint64 tvb_get_letohi (tvbuff_t *tvb, guint offset, guint length, gboolean signed_flag);
76 static void dissect_zcl_array_type(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint8 elements_type, guint16 elements_num);
78 /********************
79 * Global Variables *
80 ********************
82 /* Header Field Indices. */
83 static int proto_zbee_zcl = -1;
84 static int hf_zbee_zcl_fcf_frame_type = -1;
85 static int hf_zbee_zcl_fcf_mfr_spec = -1;
86 static int hf_zbee_zcl_fcf_dir = -1;
87 static int hf_zbee_zcl_fcf_disable_default_resp = -1;
88 static int hf_zbee_zcl_mfr_code = -1;
89 static int hf_zbee_zcl_tran_seqno = -1;
91 static int hf_zbee_zcl_cmd_id = -1;
92 static int hf_zbee_zcl_cs_cmd_id = -1;
93 static int hf_zbee_zcl_attr_id = -1;
94 static int hf_zbee_zcl_attr_data_type = -1;
95 static int hf_zbee_zcl_attr_boolean = -1;
96 static int hf_zbee_zcl_attr_uint8 = -1;
97 static int hf_zbee_zcl_attr_uint16 = -1;
98 static int hf_zbee_zcl_attr_uint24 = -1;
99 static int hf_zbee_zcl_attr_uint32 = -1;
100 static int hf_zbee_zcl_attr_uint64 = -1;
101 static int hf_zbee_zcl_attr_int8 = -1;
102 static int hf_zbee_zcl_attr_int16 = -1;
103 static int hf_zbee_zcl_attr_int24 = -1;
104 static int hf_zbee_zcl_attr_int32 = -1;
105 static int hf_zbee_zcl_attr_int64 = -1;
106 /* static int hf_zbee_zcl_attr_semi = -1; */
107 static int hf_zbee_zcl_attr_float = -1;
108 static int hf_zbee_zcl_attr_double = -1;
109 static int hf_zbee_zcl_attr_bytes = -1;
110 static int hf_zbee_zcl_attr_minint = -1;
111 static int hf_zbee_zcl_attr_maxint = -1;
112 static int hf_zbee_zcl_attr_timeout = -1;
113 static int hf_zbee_zcl_attr_cid = -1;
114 static int hf_zbee_zcl_attr_hours = -1;
115 static int hf_zbee_zcl_attr_mins = -1;
116 static int hf_zbee_zcl_attr_secs = -1;
117 static int hf_zbee_zcl_attr_csecs = -1;
118 static int hf_zbee_zcl_attr_yy = -1;
119 static int hf_zbee_zcl_attr_mm = -1;
120 static int hf_zbee_zcl_attr_md = -1;
121 static int hf_zbee_zcl_attr_wd = -1;
122 static int hf_zbee_zcl_attr_utc = -1;
123 static int hf_zbee_zcl_attr_status = -1;
124 static int hf_zbee_zcl_attr_dir = -1;
125 static int hf_zbee_zcl_attr_dis = -1;
126 static int hf_zbee_zcl_attr_start = -1;
127 static int hf_zbee_zcl_attr_maxnum = -1;
128 static int hf_zbee_zcl_attr_str_len = -1;
129 static int hf_zbee_zcl_attr_str = -1;
130 static int hf_zbee_zcl_attr_ostr = -1;
131 static int hf_zbee_zcl_attr_array_elements_type = -1;
132 static int hf_zbee_zcl_attr_array_elements_num = -1;
134 /* Subtree indices. */
135 static gint ett_zbee_zcl = -1;
136 static gint ett_zbee_zcl_fcf = -1;
137 static gint ett_zbee_zcl_attr[ZBEE_ZCL_NUM_ATTR_ETT];
138 static gint ett_zbee_zcl_array_elements[ZBEE_ZCL_NUM_ARRAY_ELEM_ETT];
140 /* Dissector Handles. */
141 static dissector_handle_t data_handle;
143 /* Dissector List. */
144 static dissector_table_t zbee_zcl_dissector_table;
146 /* Global variables */
147 static guint16 zcl_cluster_id = -1;
149 static GList *acluster_desc = NULL;
151 /********************/
152 /* Field Names */
153 /********************/
154 /* Frame Type Names */
155 static const value_string zbee_zcl_frame_types[] = {
156 { ZBEE_ZCL_FCF_PROFILE_WIDE, "Profile-wide" },
157 { ZBEE_ZCL_FCF_CLUSTER_SPEC, "Cluster-specific" },
158 { 0, NULL }
161 /* ZCL Command Names */
162 static const value_string zbee_zcl_cmd_names[] = {
163 { ZBEE_ZCL_CMD_READ_ATTR, "Read Attributes" },
164 { ZBEE_ZCL_CMD_READ_ATTR_RESP, "Read Attributes Response" },
165 { ZBEE_ZCL_CMD_WRITE_ATTR, "Write Attributes" },
166 { ZBEE_ZCL_CMD_WRITE_ATTR_UNDIVIDED, "Write Attributes Undivided" },
167 { ZBEE_ZCL_CMD_WRITE_ATTR_RESP, "Write Attributes Response" },
168 { ZBEE_ZCL_CMD_WRITE_ATTR_NO_RESP, "Write Attributes No Response" },
169 { ZBEE_ZCL_CMD_CONFIG_REPORT, "Configure Reporting" },
170 { ZBEE_ZCL_CMD_CONFIG_REPORT_RESP, "Configure Reporting Response" },
171 { ZBEE_ZCL_CMD_READ_REPORT_CONFIG, "Read Reporting Configuration" },
172 { ZBEE_ZCL_CMD_READ_REPORT_CONFIG_RESP, "Read Reporting Configuration Response" },
173 { ZBEE_ZCL_CMD_REPORT_ATTR, "Report Attributes" },
174 { ZBEE_ZCL_CMD_DEFAULT_RESP, "Default Response" },
175 { ZBEE_ZCL_CMD_DISCOVER_ATTR, "Discover Attributes" },
176 { ZBEE_ZCL_CMD_DISCOVER_ATTR_RESP, "Discover Attributes Response" },
177 { ZBEE_ZCL_CMD_READ_ATTR_STRUCT, "Read Attributes Structured" },
178 { ZBEE_ZCL_CMD_WRITE_ATTR_STRUCT, "Write Attributes Structured" },
179 { ZBEE_ZCL_CMD_WRITE_ATTR_STRUCT_RESP, "Write Attributes Structured Response" },
181 { 0, NULL }
183 static value_string_ext zbee_zcl_cmd_names_ext = VALUE_STRING_EXT_INIT(zbee_zcl_cmd_names);
185 /* ZCL Cluster-Specific Command Names */
186 static const value_string zbee_zcl_cs_cmd_names[] = {
187 { 0, NULL }
191 /* ZigBee Manufacturer Name Table */
192 /* Per: 053298r19, December 2011 */
193 static const value_string zbee_mfr_code_names[] = {
195 { ZBEE_MFG_CODE_SAMSUNG, ZBEE_MFG_SAMSUNG },
196 { ZBEE_MFG_CODE_CIRRONET, ZBEE_MFG_CIRRONET },
197 { ZBEE_MFG_CODE_CHIPCON, ZBEE_MFG_CHIPCON },
198 { ZBEE_MFG_CODE_EMBER, ZBEE_MFG_EMBER },
199 { ZBEE_MFG_CODE_NTS, ZBEE_MFG_NTS },
200 { ZBEE_MFG_CODE_FREESCALE, ZBEE_MFG_FREESCALE },
201 { ZBEE_MFG_CODE_IPCOM, ZBEE_MFG_IPCOM },
202 { ZBEE_MFG_CODE_SAN_JUAN, ZBEE_MFG_SAN_JUAN },
203 { ZBEE_MFG_CODE_TUV, ZBEE_MFG_TUV },
204 { ZBEE_MFG_CODE_COMPXS, ZBEE_MFG_COMPXS },
205 { ZBEE_MFG_CODE_BM, ZBEE_MFG_BM },
206 { ZBEE_MFG_CODE_AWAREPOINT, ZBEE_MFG_AWAREPOINT },
207 { ZBEE_MFG_CODE_PHILIPS, ZBEE_MFG_PHILIPS },
208 { ZBEE_MFG_CODE_LUXOFT, ZBEE_MFG_LUXOFT },
209 { ZBEE_MFG_CODE_KORWIN, ZBEE_MFG_KORWIN },
210 { ZBEE_MFG_CODE_1_RF, ZBEE_MFG_1_RF },
211 { ZBEE_MFG_CODE_STG, ZBEE_MFG_STG },
213 { ZBEE_MFG_CODE_TELEGESIS, ZBEE_MFG_TELEGESIS },
214 { ZBEE_MFG_CODE_VISIONIC, ZBEE_MFG_VISIONIC },
215 { ZBEE_MFG_CODE_INSTA, ZBEE_MFG_INSTA },
216 { ZBEE_MFG_CODE_ATALUM, ZBEE_MFG_ATALUM },
217 { ZBEE_MFG_CODE_ATMEL, ZBEE_MFG_ATMEL },
218 { ZBEE_MFG_CODE_DEVELCO, ZBEE_MFG_DEVELCO },
219 { ZBEE_MFG_CODE_HONEYWELL, ZBEE_MFG_HONEYWELL },
220 { 0x1017, "Unknown" }, /**/
221 { ZBEE_MFG_CODE_RENESAS, ZBEE_MFG_RENESAS },
222 { ZBEE_MFG_CODE_XANADU, ZBEE_MFG_XANADU },
223 { ZBEE_MFG_CODE_NEC, ZBEE_MFG_NEC },
224 { ZBEE_MFG_CODE_YAMATAKE, ZBEE_MFG_YAMATAKE },
225 { ZBEE_MFG_CODE_TENDRIL, ZBEE_MFG_TENDRIL },
226 { ZBEE_MFG_CODE_ASSA, ZBEE_MFG_ASSA },
227 { ZBEE_MFG_CODE_MAXSTREAM, ZBEE_MFG_MAXSTREAM },
228 { ZBEE_MFG_CODE_NEUROCOM, ZBEE_MFG_NEUROCOM },
230 { ZBEE_MFG_CODE_III, ZBEE_MFG_III },
231 { ZBEE_MFG_CODE_VANTAGE, ZBEE_MFG_VANTAGE },
232 { ZBEE_MFG_CODE_ICONTROL, ZBEE_MFG_ICONTROL },
233 { ZBEE_MFG_CODE_RAYMARINE, ZBEE_MFG_RAYMARINE },
234 { ZBEE_MFG_CODE_LSR, ZBEE_MFG_LSR },
235 { ZBEE_MFG_CODE_ONITY, ZBEE_MFG_ONITY },
236 { ZBEE_MFG_CODE_MONO, ZBEE_MFG_MONO },
237 { ZBEE_MFG_CODE_RFT, ZBEE_MFG_RFT },
238 { ZBEE_MFG_CODE_ITRON, ZBEE_MFG_ITRON },
239 { ZBEE_MFG_CODE_TRITECH, ZBEE_MFG_TRITECH },
240 { ZBEE_MFG_CODE_EMBEDIT, ZBEE_MFG_EMBEDIT },
241 { ZBEE_MFG_CODE_S3C, ZBEE_MFG_S3C },
242 { ZBEE_MFG_CODE_SIEMENS, ZBEE_MFG_SIEMENS },
243 { ZBEE_MFG_CODE_MINDTECH, ZBEE_MFG_MINDTECH },
244 { ZBEE_MFG_CODE_LGE, ZBEE_MFG_LGE },
245 { ZBEE_MFG_CODE_MITSUBISHI, ZBEE_MFG_MITSUBISHI },
247 { ZBEE_MFG_CODE_JOHNSON, ZBEE_MFG_JOHNSON },
248 { ZBEE_MFG_CODE_PRI, ZBEE_MFG_PRI },
249 { ZBEE_MFG_CODE_KNICK, ZBEE_MFG_KNICK },
250 { ZBEE_MFG_CODE_VICONICS, ZBEE_MFG_VICONICS },
251 { ZBEE_MFG_CODE_FLEXIPANEL, ZBEE_MFG_FLEXIPANEL },
252 { 0x1035, "Unknown" }, /**/
253 { ZBEE_MFG_CODE_TRANE, ZBEE_MFG_TRANE },
254 { ZBEE_MFG_CODE_JENNIC, ZBEE_MFG_JENNIC },
255 { ZBEE_MFG_CODE_LIG, ZBEE_MFG_LIG },
256 { ZBEE_MFG_CODE_ALERTME, ZBEE_MFG_ALERTME },
257 { ZBEE_MFG_CODE_DAINTREE, ZBEE_MFG_DAINTREE },
258 { ZBEE_MFG_CODE_AIJI, ZBEE_MFG_AIJI },
259 { ZBEE_MFG_CODE_TEL_ITALIA, ZBEE_MFG_TEL_ITALIA },
260 { ZBEE_MFG_CODE_MIKROKRETS, ZBEE_MFG_MIKROKRETS },
261 { ZBEE_MFG_CODE_OKI, ZBEE_MFG_OKI },
262 { ZBEE_MFG_CODE_NEWPORT, ZBEE_MFG_NEWPORT },
264 { ZBEE_MFG_CODE_C4, ZBEE_MFG_C4 },
265 { ZBEE_MFG_CODE_STM, ZBEE_MFG_STM },
266 { ZBEE_MFG_CODE_ASN, ZBEE_MFG_ASN },
267 { ZBEE_MFG_CODE_DCSI, ZBEE_MFG_DCSI },
268 { ZBEE_MFG_CODE_FRANCE_TEL, ZBEE_MFG_FRANCE_TEL },
269 { ZBEE_MFG_CODE_MUNET, ZBEE_MFG_MUNET },
270 { ZBEE_MFG_CODE_AUTANI, ZBEE_MFG_AUTANI },
271 { ZBEE_MFG_CODE_COL_VNET, ZBEE_MFG_COL_VNET },
272 { ZBEE_MFG_CODE_AEROCOMM, ZBEE_MFG_AEROCOMM },
273 { ZBEE_MFG_CODE_SI_LABS, ZBEE_MFG_SI_LABS },
274 { ZBEE_MFG_CODE_INNCOM, ZBEE_MFG_INNCOM },
275 { ZBEE_MFG_CODE_CANNON, ZBEE_MFG_CANNON },
276 { ZBEE_MFG_CODE_SYNAPSE, ZBEE_MFG_SYNAPSE },
277 { ZBEE_MFG_CODE_FPS, ZBEE_MFG_FPS },
278 { ZBEE_MFG_CODE_CLS, ZBEE_MFG_CLS },
279 { ZBEE_MFG_CODE_CRANE, ZBEE_MFG_CRANE },
281 { ZBEE_MFG_CODE_MOBILARM, ZBEE_MFG_MOBILARM },
282 { ZBEE_MFG_CODE_IMONITOR, ZBEE_MFG_IMONITOR },
283 { ZBEE_MFG_CODE_BARTECH, ZBEE_MFG_BARTECH },
284 { ZBEE_MFG_CODE_MESHNETICS, ZBEE_MFG_MESHNETICS },
285 { ZBEE_MFG_CODE_LS_IND, ZBEE_MFG_LS_IND },
286 { ZBEE_MFG_CODE_CASON, ZBEE_MFG_CASON },
287 { ZBEE_MFG_CODE_WLESS_GLUE, ZBEE_MFG_WLESS_GLUE },
288 { ZBEE_MFG_CODE_ELSTER, ZBEE_MFG_ELSTER },
289 { ZBEE_MFG_CODE_SMS_TEC, ZBEE_MFG_SMS_TEC },
290 { ZBEE_MFG_CODE_ONSET, ZBEE_MFG_ONSET },
291 { ZBEE_MFG_CODE_RIGA, ZBEE_MFG_RIGA },
292 { ZBEE_MFG_CODE_ENERGATE, ZBEE_MFG_ENERGATE },
293 { ZBEE_MFG_CODE_CONMED, ZBEE_MFG_CONMED },
294 { ZBEE_MFG_CODE_POWERMAND, ZBEE_MFG_POWERMAND },
295 { ZBEE_MFG_CODE_SCHNEIDER, ZBEE_MFG_SCHNEIDER },
296 { ZBEE_MFG_CODE_EATON, ZBEE_MFG_EATON },
298 { ZBEE_MFG_CODE_TELULAR, ZBEE_MFG_TELULAR },
299 { ZBEE_MFG_CODE_DELPHI, ZBEE_MFG_DELPHI },
300 { ZBEE_MFG_CODE_EPISENSOR, ZBEE_MFG_EPISENSOR },
301 { ZBEE_MFG_CODE_LANDIS_GYR, ZBEE_MFG_LANDIS_GYR },
302 { ZBEE_MFG_CODE_KABA, ZBEE_MFG_KABA },
303 { ZBEE_MFG_CODE_SHURE, ZBEE_MFG_SHURE },
304 { ZBEE_MFG_CODE_COMVERGE, ZBEE_MFG_COMVERGE },
305 { 0x1067, "Unknown" }, /**/
306 { 0x1068, "Unknown" }, /**/
307 { ZBEE_MFG_CODE_HIDALGO, ZBEE_MFG_HIDALGO },
308 { ZBEE_MFG_CODE_AIR2APP, ZBEE_MFG_AIR2APP },
309 { ZBEE_MFG_CODE_AMX, ZBEE_MFG_AMX },
310 { ZBEE_MFG_CODE_EDMI, ZBEE_MFG_EDMI },
311 { ZBEE_MFG_CODE_CYAN, ZBEE_MFG_CYAN },
312 { ZBEE_MFG_CODE_SYS_SPA, ZBEE_MFG_SYS_SPA },
313 { ZBEE_MFG_CODE_TELIT, ZBEE_MFG_TELIT },
315 { ZBEE_MFG_CODE_KAGA, ZBEE_MFG_KAGA },
316 { ZBEE_MFG_CODE_4_NOKS, ZBEE_MFG_4_NOKS },
317 { 0x1072, "Unknown" }, /**/
318 { 0x1073, "Unknown" }, /**/
319 { ZBEE_MFG_CODE_PROFILE_SYS,ZBEE_MFG_PROFILE_SYS },
320 { 0x1075, "Unknown" }, /**/
321 { ZBEE_MFG_CODE_FREESTYLE, ZBEE_MFG_FREESTYLE },
322 { 0x1077, "Unknown" }, /**/
323 { 0x1078, "Unknown" }, /**/
324 { ZBEE_MFG_CODE_REMOTE ,ZBEE_MFG_REMOTE },
325 { ZBEE_MFG_CODE_WAVECOM, ZBEE_MFG_WAVECOM },
326 { ZBEE_MFG_CODE_ENERGY_OPT, ZBEE_MFG_ENERGY_OPT },
327 { ZBEE_MFG_CODE_GE, ZBEE_MFG_GE },
328 { 0x107d, "Unknown" }, /**/
329 { 0x107e, "Unknown" }, /**/
330 { 0x107f, "Unknown" }, /**/
332 { 0x1080, "Unknown" }, /**/
333 { 0x1081, "Unknown" }, /**/
334 { ZBEE_MFG_CODE_MESHWORKS, ZBEE_MFG_MESHWORKS },
335 { ZBEE_MFG_CODE_ELLIPS, ZBEE_MFG_ELLIPS },
336 { 0x1084, "Unknown" }, /**/
337 { ZBEE_MFG_CODE_CEDO, ZBEE_MFG_CEDO },
338 { 0x1086, "Unknown" }, /**/
339 { ZBEE_MFG_CODE_DIGI, ZBEE_MFG_DIGI },
340 { 0x1088, "Unknown" }, /**/
341 { 0x1089, "Unknown" }, /**/
342 { 0x108a, "Unknown" }, /**/
343 { 0x108b, "Unknown" }, /**/
344 { 0x108c, "Unknown" }, /**/
345 { 0x108d, "Unknown" }, /**/
346 { 0x108e, "Unknown" }, /**/
347 { 0x108f, "Unknown" }, /**/
349 { 0x1090, "Unknown" }, /**/
350 { 0x1091, "Unknown" }, /**/
351 { 0x1092, "Unknown" }, /**/
352 { 0x1093, "Unknown" }, /**/
353 { ZBEE_MFG_CODE_A_D, ZBEE_MFG_A_D },
354 { 0x1095, "Unknown" }, /**/
355 { ZBEE_MFG_CODE_CARRIER, ZBEE_MFG_CARRIER },
356 { ZBEE_MFG_CODE_SYCHIP, ZBEE_MFG_SYCHIP },
357 { 0x1098, "Unknown" }, /**/
358 { ZBEE_MFG_CODE_PASSIVESYS, ZBEE_MFG_PASSIVESYS },
359 { ZBEE_MFG_CODE_MMB, ZBEE_MFG_MMB },
360 { ZBEE_MFG_CODE_HOME_AUTO, ZBEE_MFG_HOME_AUTO },
361 { 0x109c, "Unknown" }, /**/
362 { 0x109d, "Unknown" }, /**/
363 { 0x109e, "Unknown" }, /**/
364 { 0x109f, "Unknown" }, /**/
366 { 0x10a0, "Unknown" }, /**/
367 { 0x10a1, "Unknown" }, /**/
368 { 0x10a2, "Unknown" }, /**/
369 { ZBEE_MFG_CODE_SUNRISE, ZBEE_MFG_SUNRISE },
370 { ZBEE_MFG_CODE_MEMTEC, ZBEE_MFG_MEMTEC },
371 { 0x10a5, "Unknown" }, /**/
372 { 0x10a6, "Unknown" }, /**/
373 { ZBEE_MFG_CODE_BRITISH_GAS,ZBEE_MFG_BRITISH_GAS },
374 { ZBEE_MFG_CODE_SENTEC, ZBEE_MFG_SENTEC },
375 { ZBEE_MFG_CODE_NAVETAS, ZBEE_MFG_NAVETAS },
376 { 0x10aa, "Unknown" }, /**/
377 { 0x10ab, "Unknown" }, /**/
378 { 0x10ac, "Unknown" }, /**/
379 { 0x10ad, "Unknown" }, /**/
380 { 0x10ae, "Unknown" }, /**/
381 { 0x10af, "Unknown" }, /**/
383 { 0x10b0, "Unknown" }, /**/
384 { 0x10b1, "Unknown" }, /**/
385 { ZBEE_MFG_CODE_ENERNOC, ZBEE_MFG_ENERNOC },
386 { ZBEE_MFG_CODE_ELTAV, ZBEE_MFG_ELTAV },
387 { 0x10b4, "Unknown" }, /**/
388 { ZBEE_MFG_CODE_XSTREAMHD, ZBEE_MFG_XSTREAMHD },
389 { 0x10b6, "Unknown" }, /**/
390 { ZBEE_MFG_CODE_GREEN, ZBEE_MFG_GREEN },
391 { 0x10b8, "Unknown" }, /**/
392 { 0x10b9, "Unknown" }, /**/
393 { 0x10ba, "Unknown" }, /**/
394 { 0x10bb, "Unknown" }, /**/
395 { 0x10bc, "Unknown" }, /**/
396 { 0x10bd, "Unknown" }, /**/
397 { 0x10be, "Unknown" }, /**/
398 { ZBEE_MFG_CODE_OMRON, ZBEE_MFG_OMRON },
399 { 0x10c0, "Unknown" }, /**/
400 { 0x10c1, "Unknown" }, /**/
401 { ZBEE_MFG_CODE_PEEL, ZBEE_MFG_PEEL },
402 { 0x10c3, "Unknown" }, /**/
403 { 0x10c4, "Unknown" }, /**/
404 { ZBEE_MFG_CODE_NEC_TOKIN, ZBEE_MFG_NEC_TOKIN },
405 { ZBEE_MFG_CODE_G4S_JUSTICE,ZBEE_MFG_G4S_JUSTICE },
406 { 0x10c7, "Unknown" }, /**/
407 { ZBEE_MFG_CODE_ELECTROLUX, ZBEE_MFG_ELECTROLUX },
408 { 0x10c9, "Unknown" }, /**/
409 { 0x10ca, "Unknown" }, /**/
410 { 0x10cb, "Unknown" }, /**/
411 { ZBEE_MFG_CODE_MAINSTREAM, ZBEE_MFG_MAINSTREAM },
412 { ZBEE_MFG_CODE_INDESIT_C, ZBEE_MFG_INDESIT_C },
413 { 0x10ce, "Unknown" }, /**/
414 { 0x10cf, "Unknown" }, /**/
415 { 0x10d0, "Unknown" }, /**/
416 { 0x10d1, "Unknown" }, /**/
417 { 0x10d2, "Unknown" }, /**/
418 { 0x10d3, "Unknown" }, /**/
419 { 0x10d4, "Unknown" }, /**/
420 { 0x10d5, "Unknown" }, /**/
421 { 0x10d6, "Unknown" }, /**/
422 { 0x10d7, "Unknown" }, /**/
423 { 0x10d8, "Unknown" }, /**/
424 { 0x10d9, "Unknown" }, /**/
425 { 0x10da, "Unknown" }, /**/
426 { 0x10db, "Unknown" }, /**/
427 { 0x10dc, "Unknown" }, /**/
428 { ZBEE_MFG_CODE_RADIOCRAFTS,ZBEE_MFG_RADIOCRAFTS },
429 { 0x10de, "Unknown" }, /**/
430 { 0x10df, "Unknown" }, /**/
431 { 0x10e0, "Unknown" }, /**/
432 { 0x10e1, "Unknown" }, /**/
433 { 0x10e2, "Unknown" }, /**/
434 { ZBEE_MFG_CODE_HUAWEI_1, ZBEE_MFG_HUAWEI },
435 { ZBEE_MFG_CODE_HUAWEI_2, ZBEE_MFG_HUAWEI },
436 { 0x10e5, "Unknown" }, /**/
437 { ZBEE_MFG_CODE_BGLOBAL, ZBEE_MFG_BGLOBAL },
438 { 0x10e7, "Unknown" }, /**/
439 { 0x10e8, "Unknown" }, /**/
440 { 0x10e9, "Unknown" }, /**/
441 { 0x10ea, "Unknown" }, /**/
442 { ZBEE_MFG_CODE_ABB, ZBEE_MFG_ABB },
443 { 0x10ec, "Unknown" }, /**/
444 { ZBEE_MFG_CODE_GENUS, ZBEE_MFG_GENUS },
445 { 0x10ee, "Unknown" }, /**/
446 { 0x10ef, "Unknown" }, /**/
447 { 0x10f0, "Unknown" }, /**/
448 { 0x10f1, "Unknown" }, /**/
449 { 0x10f2, "Unknown" }, /**/
450 { 0x10f3, "Unknown" }, /**/
451 { 0x10f4, "Unknown" }, /**/
452 { 0x10f5, "Unknown" }, /**/
453 { 0x10f6, "Unknown" }, /**/
454 { 0x10f7, "Unknown" }, /**/
455 { 0x10f8, "Unknown" }, /**/
456 { 0x10f9, "Unknown" }, /**/
457 { 0x10fa, "Unknown" }, /**/
458 { 0x10fb, "Unknown" }, /**/
459 { 0x10fc, "Unknown" }, /**/
460 { 0x10fd, "Unknown" }, /**/
461 { 0x10fe, "Unknown" }, /**/
462 { 0x10ff, "Unknown" }, /**/
463 { ZBEE_MFG_CODE_RELOC, ZBEE_MFG_RELOC },
464 { 0, NULL }
466 static value_string_ext zbee_mfr_code_names_ext = VALUE_STRING_EXT_INIT(zbee_mfr_code_names);
468 /* ZCL Attribute Status Names */
469 static const value_string zbee_zcl_status_names[] = {
470 { ZBEE_ZCL_STAT_SUCCESS, "Success"},
471 { ZBEE_ZCL_STAT_FAILURE, "Failure"},
473 { ZBEE_ZCL_STAT_NOT_AUTHORIZED, "Not Authorized"},
474 { ZBEE_ZCL_STAT_RESERVED_FIELD_NOT_ZERO, "Reserved Field Not Zero"},
475 { ZBEE_ZCL_STAT_MALFORMED_CMD, "Malformed Command"},
476 { ZBEE_ZCL_STAT_UNSUP_CLUSTER_CMD, "Unsupported Cluster Command"},
477 { ZBEE_ZCL_STAT_UNSUP_GENERAL_CMD, "Unsupported General Command"},
478 { ZBEE_ZCL_STAT_UNSUP_MFR_CLUSTER_CMD, "Unsupported Manufacturer Cluster Command"},
479 { ZBEE_ZCL_STAT_UNSUP_MFR_GENERAL_CMD, "Unsupported Manufacturer General Command"},
480 { ZBEE_ZCL_STAT_INVALID_FIELD, "Invalid Field"},
481 { ZBEE_ZCL_STAT_UNSUPPORTED_ATTR, "Unsupported Attribute"},
482 { ZBEE_ZCL_STAT_INVALID_VALUE, "Invalid Value"},
483 { ZBEE_ZCL_STAT_READ_ONLY, "Read Only"},
484 { ZBEE_ZCL_STAT_INSUFFICIENT_SPACE, "Insufficient Space"},
485 { ZBEE_ZCL_STAT_DUPLICATE_EXISTS, "Duplicate Exists"},
486 { ZBEE_ZCL_STAT_NOT_FOUND, "Not Found"},
487 { ZBEE_ZCL_STAT_UNREPORTABLE_ATTR, "Unreportable Attribute"},
488 { ZBEE_ZCL_STAT_INVALID_DATA_TYPE, "Invalid Data Type"},
489 { ZBEE_ZCL_STAT_INVALID_SELECTOR, "Invalid Selector"},
490 { ZBEE_ZCL_STAT_WRITE_ONLY, "Write Only"},
491 { ZBEE_ZCL_STAT_INCONSISTENT_STARTUP_STATE, "Inconsistent Startup State"},
492 { ZBEE_ZCL_STAT_DEFINED_OUT_OF_BAND, "Defined Out of Band"},
493 { ZBEE_ZCL_STAT_HARDWARE_FAILURE, "Hardware Failure"},
494 { ZBEE_ZCL_STAT_SOFTWARE_FAILURE, "Software Failure"},
495 { ZBEE_ZCL_STAT_CALIBRATION_ERROR, "Calibration Error"},
497 { 0, NULL }
499 static value_string_ext zbee_zcl_status_names_ext = VALUE_STRING_EXT_INIT(zbee_zcl_status_names);
501 /* ZCL Attribute Data Names */
502 static const value_string zbee_zcl_data_type_names[] = {
503 { ZBEE_ZCL_NO_DATA, "No Data" },
504 { ZBEE_ZCL_8_BIT_DATA, "8-Bit Data" },
505 { ZBEE_ZCL_16_BIT_DATA, "16-Bit Data" },
506 { ZBEE_ZCL_24_BIT_DATA, "24-Bit Data" },
507 { ZBEE_ZCL_32_BIT_DATA, "32-Bit Data" },
508 { ZBEE_ZCL_40_BIT_DATA, "40-Bit Data" },
509 { ZBEE_ZCL_48_BIT_DATA, "48-Bit Data" },
510 { ZBEE_ZCL_56_BIT_DATA, "56-Bit Data" },
511 { ZBEE_ZCL_64_BIT_DATA, "64-Bit Data" },
513 { ZBEE_ZCL_BOOLEAN, "Boolean" },
515 { ZBEE_ZCL_8_BIT_BITMAP, "8-Bit Bitmap" },
516 { ZBEE_ZCL_16_BIT_BITMAP, "16-Bit Bitmap" },
517 { ZBEE_ZCL_24_BIT_BITMAP, "24-Bit Bitmap" },
518 { ZBEE_ZCL_32_BIT_BITMAP, "32-Bit Bitmap" },
519 { ZBEE_ZCL_40_BIT_BITMAP, "40-Bit Bitmap" },
520 { ZBEE_ZCL_48_BIT_BITMAP, "48-Bit Bitmap" },
521 { ZBEE_ZCL_56_BIT_BITMAP, "56-Bit Bitmap" },
522 { ZBEE_ZCL_64_BIT_BITMAP, "64-Bit Bitmap" },
524 { ZBEE_ZCL_8_BIT_UINT, "8-Bit Unsigned Integer" },
525 { ZBEE_ZCL_16_BIT_UINT, "16-Bit Unsigned Integer" },
526 { ZBEE_ZCL_24_BIT_UINT, "24-Bit Unsigned Integer" },
527 { ZBEE_ZCL_32_BIT_UINT, "32-Bit Unsigned Integer" },
528 { ZBEE_ZCL_40_BIT_UINT, "40-Bit Unsigned Integer" },
529 { ZBEE_ZCL_48_BIT_UINT, "48-Bit Unsigned Integer" },
530 { ZBEE_ZCL_56_BIT_UINT, "56-Bit Unsigned Integer" },
531 { ZBEE_ZCL_64_BIT_UINT, "64-Bit Unsigned Integer" },
533 { ZBEE_ZCL_8_BIT_INT, "8-Bit Signed Integer" },
534 { ZBEE_ZCL_16_BIT_INT, "16-Bit Signed Integer" },
535 { ZBEE_ZCL_24_BIT_INT, "24-Bit Signed Integer" },
536 { ZBEE_ZCL_32_BIT_INT, "32-Bit Signed Integer" },
537 { ZBEE_ZCL_40_BIT_INT, "40-Bit Signed Integer" },
538 { ZBEE_ZCL_48_BIT_INT, "48-Bit Signed Integer" },
539 { ZBEE_ZCL_56_BIT_INT, "56-Bit Signed Integer" },
540 { ZBEE_ZCL_64_BIT_INT, "64-Bit Signed Integer" },
542 { ZBEE_ZCL_8_BIT_ENUM, "8-Bit Enumeration" },
543 { ZBEE_ZCL_16_BIT_ENUM, "16-Bit Enumeration" },
545 { ZBEE_ZCL_SEMI_FLOAT, "Semi-precision Floating Point" },
546 { ZBEE_ZCL_SINGLE_FLOAT, "Single Precision Floating Point" },
547 { ZBEE_ZCL_DOUBLE_FLOAT, "Double Precision Floating Point" },
549 { ZBEE_ZCL_OCTET_STRING, "Octet String" },
550 { ZBEE_ZCL_CHAR_STRING, "Character String" },
551 { ZBEE_ZCL_LONG_OCTET_STRING, "Long Octet String" },
552 { ZBEE_ZCL_LONG_CHAR_STRING, "Long Character String" },
554 { ZBEE_ZCL_ARRAY, "Array" },
555 { ZBEE_ZCL_STRUCT, "Structure" },
557 { ZBEE_ZCL_SET, "Set Collection" },
558 { ZBEE_ZCL_BAG, "Bag Collection" },
560 { ZBEE_ZCL_TIME, "Time of Day" },
561 { ZBEE_ZCL_DATE, "Date" },
562 { ZBEE_ZCL_UTC, "UTC Time" },
564 { ZBEE_ZCL_CLUSTER_ID, "Cluster ID" },
565 { ZBEE_ZCL_ATTR_ID, "Attribute ID" },
566 { ZBEE_ZCL_BACNET_OID, "BACnet OID" },
568 { ZBEE_ZCL_IEEE_ADDR, "IEEE Address" },
569 { ZBEE_ZCL_SECURITY_KEY, "128-Bit Security Key" },
571 { ZBEE_ZCL_UNKNOWN, "Unknown" },
573 { 0, NULL }
575 static value_string_ext zbee_zcl_data_type_names_ext = VALUE_STRING_EXT_INIT(zbee_zcl_data_type_names);
577 /* ZCL Attribute Short Data Names */
578 const value_string zbee_zcl_short_data_type_names[] = {
579 { ZBEE_ZCL_NO_DATA, "No Data" },
580 { ZBEE_ZCL_8_BIT_DATA, "Data8" },
581 { ZBEE_ZCL_16_BIT_DATA, "Data16" },
582 { ZBEE_ZCL_24_BIT_DATA, "Data24" },
583 { ZBEE_ZCL_32_BIT_DATA, "Data32" },
584 { ZBEE_ZCL_40_BIT_DATA, "Data40" },
585 { ZBEE_ZCL_48_BIT_DATA, "Data48" },
586 { ZBEE_ZCL_56_BIT_DATA, "Data56" },
587 { ZBEE_ZCL_64_BIT_DATA, "Data64" },
589 { ZBEE_ZCL_BOOLEAN, "Boolean" },
591 { ZBEE_ZCL_8_BIT_BITMAP, "Bit8" },
592 { ZBEE_ZCL_16_BIT_BITMAP, "Bit16" },
593 { ZBEE_ZCL_24_BIT_BITMAP, "Bit24" },
594 { ZBEE_ZCL_32_BIT_BITMAP, "Bit32" },
595 { ZBEE_ZCL_40_BIT_BITMAP, "Bit40" },
596 { ZBEE_ZCL_48_BIT_BITMAP, "Bit48" },
597 { ZBEE_ZCL_56_BIT_BITMAP, "Bit56" },
598 { ZBEE_ZCL_64_BIT_BITMAP, "Bit64" },
600 { ZBEE_ZCL_8_BIT_UINT, "Uint8" },
601 { ZBEE_ZCL_16_BIT_UINT, "Uint16" },
602 { ZBEE_ZCL_24_BIT_UINT, "Uint24" },
603 { ZBEE_ZCL_32_BIT_UINT, "Uint32" },
604 { ZBEE_ZCL_40_BIT_UINT, "Uint40" },
605 { ZBEE_ZCL_48_BIT_UINT, "Uint48" },
606 { ZBEE_ZCL_56_BIT_UINT, "Uint56" },
607 { ZBEE_ZCL_64_BIT_UINT, "Uint64" },
609 { ZBEE_ZCL_8_BIT_INT, "Int8" },
610 { ZBEE_ZCL_16_BIT_INT, "Int16" },
611 { ZBEE_ZCL_24_BIT_INT, "Int24" },
612 { ZBEE_ZCL_32_BIT_INT, "Int32" },
613 { ZBEE_ZCL_40_BIT_INT, "Int40" },
614 { ZBEE_ZCL_48_BIT_INT, "Int48" },
615 { ZBEE_ZCL_56_BIT_INT, "Int56" },
616 { ZBEE_ZCL_64_BIT_INT, "Int64" },
618 { ZBEE_ZCL_8_BIT_ENUM, "Enum8" },
619 { ZBEE_ZCL_16_BIT_ENUM, "Enum16" },
621 { ZBEE_ZCL_SEMI_FLOAT, "Semi Float" },
622 { ZBEE_ZCL_SINGLE_FLOAT, "Float" },
623 { ZBEE_ZCL_DOUBLE_FLOAT, "Double Float" },
625 { ZBEE_ZCL_OCTET_STRING, "Oct String" },
626 { ZBEE_ZCL_CHAR_STRING, "Char String" },
627 { ZBEE_ZCL_LONG_OCTET_STRING, "Long Oct String" },
628 { ZBEE_ZCL_LONG_CHAR_STRING, "Long Char String" },
630 { ZBEE_ZCL_ARRAY, "Array" },
631 { ZBEE_ZCL_STRUCT, "Structure" },
633 { ZBEE_ZCL_SET, "Set" },
634 { ZBEE_ZCL_BAG, "Bag" },
636 { ZBEE_ZCL_TIME, "Time" },
637 { ZBEE_ZCL_DATE, "Date" },
638 { ZBEE_ZCL_UTC, "UTC" },
640 { ZBEE_ZCL_CLUSTER_ID, "Cluster" },
641 { ZBEE_ZCL_ATTR_ID, "Attribute" },
642 { ZBEE_ZCL_BACNET_OID, "BACnet" },
644 { ZBEE_ZCL_IEEE_ADDR, "EUI" },
645 { ZBEE_ZCL_SECURITY_KEY, "Key" },
647 { ZBEE_ZCL_UNKNOWN, "Unknown" },
649 { 0, NULL }
651 static value_string_ext zbee_zcl_short_data_type_names_ext = VALUE_STRING_EXT_INIT(zbee_zcl_short_data_type_names);
653 /* ZCL Attribute English Weekday Names */
654 static const value_string zbee_zcl_wd_names[] = {
655 { 1, "Monday" },
656 { 2, "Tuesday" },
657 { 3, "Wednesday" },
658 { 4, "Thursday" },
659 { 5, "Friday" },
660 { 6, "Saturday" },
661 { 7, "Sunday" },
663 { 0, NULL }
665 static value_string_ext zbee_zcl_wd_names_ext = VALUE_STRING_EXT_INIT(zbee_zcl_wd_names);
667 /* Attribute Direction Names */
668 static const value_string zbee_zcl_dir_names[] = {
669 { 0, "Reported" },
670 { 1, "Received" },
672 { 0, NULL }
675 /* Attribute Discovery Names */
676 static const value_string zbee_zcl_dis_names[] = {
677 { 0, "Incomplete" },
678 { 1, "Complete" },
680 { 0, NULL }
683 /*FUNCTION:------------------------------------------------------
684 * NAME
685 * dissect_zbee_zcl
686 * DESCRIPTION
687 * ZigBee Cluster Library dissector for wireshark.
688 * PARAMETERS
689 * tvbuff_t *tvb - pointer to buffer containing raw packet.
690 * packet_into *pinfo - pointer to packet information fields
691 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
692 * RETURNS
693 * void
694 *---------------------------------------------------------------
696 static int dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
698 tvbuff_t *payload_tvb = NULL;
699 dissector_handle_t cluster_handle = NULL;
701 proto_tree *zcl_tree = NULL;
702 proto_tree *sub_tree = NULL;
704 proto_item *proto_root = NULL;
705 proto_item *ti;
707 zbee_nwk_packet *nwk = (zbee_nwk_packet *)data;
708 zbee_zcl_packet packet;
709 zbee_zcl_cluster_desc *desc;
711 guint8 fcf;
712 guint offset = 0;
714 /* Init. */
715 memset(&packet, 0, sizeof(zbee_zcl_packet));
717 /* Fill the zcl cluster id */
718 zcl_cluster_id = nwk->cluster_id;
719 cluster_handle = dissector_get_uint_handle(zbee_zcl_dissector_table, zcl_cluster_id);
721 /* Create the protocol tree */
722 if ( tree ) {
723 proto_root = proto_tree_add_protocol_format(tree, proto_zbee_zcl, tvb, offset,
724 tvb_length(tvb), "ZigBee Cluster Library Frame");
726 zcl_tree = proto_item_add_subtree(proto_root, ett_zbee_zcl);
729 /* Clear info column */
730 col_clear(pinfo->cinfo, COL_INFO);
732 /* Get the FCF */
733 fcf = tvb_get_guint8(tvb, offset);
734 packet.frame_type = zbee_get_bit_field(fcf, ZBEE_ZCL_FCF_FRAME_TYPE);
735 packet.mfr_spec = zbee_get_bit_field(fcf, ZBEE_ZCL_FCF_MFR_SPEC);
736 packet.direction = zbee_get_bit_field(fcf, ZBEE_ZCL_FCF_DIRECTION);
737 packet.disable_default_resp = zbee_get_bit_field(fcf, ZBEE_ZCL_FCF_DISABLE_DEFAULT_RESP);
739 /* Display the FCF */
740 if ( tree ) {
741 /* Create the subtree */
742 ti = proto_tree_add_text(zcl_tree, tvb, offset, 1,
743 "Frame Control Field: %s (0x%02x)",
744 val_to_str_const(packet.frame_type, zbee_zcl_frame_types, "Unknown"), fcf);
745 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_fcf);
747 /* Add the frame type */
748 proto_tree_add_uint(sub_tree, hf_zbee_zcl_fcf_frame_type, tvb, offset, 1,
749 fcf & ZBEE_ZCL_FCF_FRAME_TYPE);
751 /* Add the manufacturer specific, direction, and disable default response flags */
752 proto_tree_add_boolean(sub_tree, hf_zbee_zcl_fcf_mfr_spec, tvb, offset,
753 1, fcf & ZBEE_ZCL_FCF_MFR_SPEC);
755 proto_tree_add_boolean(sub_tree, hf_zbee_zcl_fcf_dir, tvb, offset, 1,
756 fcf & ZBEE_ZCL_FCF_DIRECTION);
758 proto_tree_add_boolean(sub_tree, hf_zbee_zcl_fcf_disable_default_resp, tvb, offset,
759 1, fcf & ZBEE_ZCL_FCF_DISABLE_DEFAULT_RESP);
761 offset += (int)1;
763 /* If the manufacturer code is present, get and display it. */
764 if (packet.mfr_spec) {
765 packet.mfr_code = tvb_get_letohs(tvb, offset);
767 if ( tree ) {
768 proto_tree_add_uint(zcl_tree, hf_zbee_zcl_mfr_code, tvb, offset, (int)2,
769 packet.mfr_code);
771 proto_item_append_text(proto_root, ", Mfr: %s (0x%04x)",
772 val_to_str_ext_const(packet.mfr_code, &zbee_mfr_code_names_ext, "Unknown"),
773 packet.mfr_code);
775 offset += (int)2;
778 /* Add the transaction sequence number to the tree */
779 packet.tran_seqno = tvb_get_guint8(tvb, offset);
781 if ( zcl_tree ) {
782 proto_tree_add_uint(zcl_tree, hf_zbee_zcl_tran_seqno, tvb, offset, (int)1,
783 packet.tran_seqno);
785 offset += (int)1;
787 /* Display the command and sequence number on the proto root and info column. */
788 packet.cmd_id = tvb_get_guint8(tvb, offset);
790 desc = zbee_zcl_get_cluster_desc(zcl_cluster_id);
791 if (desc != NULL) {
792 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: ", desc->name);
795 /* Add command ID to the tree. */
796 if ( packet.frame_type == ZBEE_ZCL_FCF_PROFILE_WIDE ) {
797 if ( tree ) {
798 proto_item_append_text(proto_root, ", Command: %s, Seq: %u",
799 val_to_str_ext_const(packet.cmd_id, &zbee_zcl_cmd_names_ext, "Unknown Command"),
800 packet.tran_seqno);
803 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u",
804 val_to_str_ext_const(packet.cmd_id, &zbee_zcl_cmd_names_ext, "Unknown Command"),
805 packet.tran_seqno);
807 if ( zcl_tree ) {
808 proto_tree_add_uint(zcl_tree, hf_zbee_zcl_cmd_id, tvb, offset, (int)1,
809 packet.cmd_id);
811 offset += (int)1;
813 else {
814 /* Cluster Specific */
815 payload_tvb = tvb_new_subset_remaining(tvb, offset);
817 if (cluster_handle != NULL) {
818 /* Call the specific cluster dissector registered */
819 call_dissector_with_data(cluster_handle, payload_tvb, pinfo, zcl_tree, &packet);
821 else {
822 proto_item_append_text(proto_root, ", Cluster-specific Command: 0x%02x, Seq: %u",
823 packet.cmd_id, packet.tran_seqno);
825 col_append_fstr(pinfo->cinfo, COL_INFO, "Command: 0x%02x, Seq: %u",
826 packet.cmd_id, packet.tran_seqno);
828 proto_tree_add_uint(zcl_tree, hf_zbee_zcl_cs_cmd_id, tvb, offset, (int)1,
829 packet.cmd_id);
830 offset += (int)1;
832 /* Don't decode cluster-specific commands */
833 zcl_dump_data(tvb, offset, pinfo, zcl_tree);
835 return tvb_length(tvb);
838 if ( zcl_tree ) {
839 /* Handle the contents of the command frame. */
840 switch ( packet.cmd_id ) {
841 case ZBEE_ZCL_CMD_READ_ATTR:
842 dissect_zcl_read_attr(tvb, pinfo, zcl_tree, &offset);
843 break;
845 case ZBEE_ZCL_CMD_READ_ATTR_RESP:
846 dissect_zcl_read_attr_resp(tvb, pinfo, zcl_tree, &offset);
847 break;
849 case ZBEE_ZCL_CMD_WRITE_ATTR:
850 case ZBEE_ZCL_CMD_WRITE_ATTR_UNDIVIDED:
851 case ZBEE_ZCL_CMD_WRITE_ATTR_NO_RESP:
852 case ZBEE_ZCL_CMD_REPORT_ATTR:
853 dissect_zcl_write_attr(tvb, pinfo, zcl_tree, &offset);
854 break;
856 case ZBEE_ZCL_CMD_WRITE_ATTR_RESP:
857 dissect_zcl_write_attr_resp(tvb, pinfo, zcl_tree, &offset);
858 break;
860 case ZBEE_ZCL_CMD_CONFIG_REPORT:
861 dissect_zcl_config_report(tvb, pinfo, zcl_tree, &offset);
862 break;
864 case ZBEE_ZCL_CMD_CONFIG_REPORT_RESP:
865 dissect_zcl_config_report_resp(tvb, pinfo, zcl_tree, &offset);
866 break;
868 case ZBEE_ZCL_CMD_READ_REPORT_CONFIG:
869 dissect_zcl_read_report_config(tvb, pinfo, zcl_tree, &offset);
870 break;
872 case ZBEE_ZCL_CMD_READ_REPORT_CONFIG_RESP:
873 dissect_zcl_read_report_config_resp(tvb, pinfo, zcl_tree, &offset);
874 break;
876 case ZBEE_ZCL_CMD_DEFAULT_RESP:
877 dissect_zcl_default_resp(tvb, pinfo, zcl_tree, &offset);
878 break;
880 case ZBEE_ZCL_CMD_DISCOVER_ATTR:
881 dissect_zcl_discover_attr(tvb, pinfo, zcl_tree, &offset);
882 break;
884 case ZBEE_ZCL_CMD_DISCOVER_ATTR_RESP:
885 dissect_zcl_discover_attr_resp(tvb, pinfo, zcl_tree, &offset);
886 break;
888 /* BUGBUG: don't dissect these for now */
889 case ZBEE_ZCL_CMD_READ_ATTR_STRUCT:
890 case ZBEE_ZCL_CMD_WRITE_ATTR_STRUCT:
891 case ZBEE_ZCL_CMD_WRITE_ATTR_STRUCT_RESP:
892 default:
893 zcl_dump_data(tvb, offset, pinfo, zcl_tree);
894 break;
895 } /* switch */
898 return tvb_length(tvb);
899 } /* dissect_zbee_zcl */
901 /*FUNCTION:------------------------------------------------------
902 * NAME
903 * dissect_zcl_read_attr
904 * DESCRIPTION
905 * Helper dissector for ZCL Read Attributes and
906 * Write Attributes No Response commands.
907 * PARAMETERS
908 * tvbuff_t *tvb - pointer to buffer containing raw packet.
909 * packet_info *pinfo - pointer to packet information fields
910 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
911 * offset - pointer to offset from caller
912 * RETURNS
913 * guint - offset after command dissection.
914 *---------------------------------------------------------------
916 static void dissect_zcl_read_attr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
918 guint tvb_len;
920 tvb_len = tvb_length(tvb);
921 while ( *offset < tvb_len ) {
922 /* Dissect the attribute identifier */
923 dissect_zcl_attr_id(tvb, tree, offset);
926 return;
927 } /* dissect_zcl_read_attr */
929 /*FUNCTION:------------------------------------------------------
930 * NAME
931 * dissect_zcl_read_attr_resp
932 * DESCRIPTION
933 * Helper dissector for ZCL Read Attributes Response command.
934 * PARAMETERS
935 * tvbuff_t *tvb - pointer to buffer containing raw packet.
936 * packet_info *pinfo - pointer to packet information fields
937 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
938 * offset - pointer to offset from caller
939 * RETURNS
940 * guint - offset after command dissection.
941 *---------------------------------------------------------------
943 void dissect_zcl_read_attr_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
945 proto_item *ti = NULL;
946 proto_tree *sub_tree = NULL;
948 guint tvb_len;
949 guint i = 0;
950 guint16 attr_id;
952 tvb_len = tvb_length(tvb);
953 while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) {
955 /* Create subtree for attribute status field */
956 ti = proto_tree_add_text(tree, tvb, *offset, 0, "Status Record");
957 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_attr[i]);
958 i++;
960 /* Dissect the attribute identifier */
961 attr_id = tvb_get_letohs(tvb, *offset);
962 dissect_zcl_attr_id(tvb, sub_tree, offset);
964 /* Dissect the status and optionally the data type and value */
965 if ( dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_status)
966 == ZBEE_ZCL_STAT_SUCCESS ) {
968 /* Dissect the attribute data type and data */
969 dissect_zcl_attr_data_type_val(tvb, sub_tree, offset, attr_id);
973 return;
974 } /* dissect_zcl_read_attr_resp */
976 /*FUNCTION:------------------------------------------------------
977 * NAME
978 * dissect_zcl_write_attr
979 * DESCRIPTION
980 * Helper dissector for ZCL Report Attribute commands.
981 * PARAMETERS
982 * tvbuff_t *tvb - pointer to buffer containing raw packet.
983 * packet_info *pinfo - pointer to packet information fields
984 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
985 * offset - pointer to offset from caller
986 * RETURNS
987 * guint - offset after command dissection.
988 *---------------------------------------------------------------
990 void dissect_zcl_write_attr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
992 proto_item *ti = NULL;
993 proto_tree *sub_tree = NULL;
995 guint tvb_len;
996 guint i = 0;
997 guint16 attr_id;
999 tvb_len = tvb_length(tvb);
1000 while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) {
1002 /* Create subtree for attribute status field */
1003 ti = proto_tree_add_text(tree, tvb, *offset, 0, "Attribute Field");
1004 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_attr[i]);
1005 i++;
1007 /* Dissect the attribute identifier */
1008 attr_id = tvb_get_letohs(tvb, *offset);
1009 dissect_zcl_attr_id(tvb, sub_tree, offset);
1011 /* Dissect the attribute data type and data */
1012 dissect_zcl_attr_data_type_val(tvb, sub_tree, offset, attr_id);
1015 return;
1016 } /* dissect_zcl_write_attr */
1018 /*FUNCTION:------------------------------------------------------
1019 * NAME
1020 * dissect_zcl_write_attr_resp
1021 * DESCRIPTION
1022 * Helper dissector for ZCL Write Attribute Response command.
1023 * PARAMETERS
1024 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1025 * packet_info *pinfo - pointer to packet information fields
1026 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1027 * offset - pointer to offset from caller
1028 * RETURNS
1029 * guint - offset after command dissection.
1030 *---------------------------------------------------------------
1032 static void dissect_zcl_write_attr_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
1034 proto_item *ti = NULL;
1035 proto_tree *sub_tree = NULL;
1037 guint tvb_len;
1038 guint i = 0;
1040 tvb_len = tvb_length(tvb);
1041 while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) {
1043 /* Create subtree for attribute status field */
1044 ti = proto_tree_add_text(tree, tvb, *offset, 0, "Status Record");
1045 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_attr[i]);
1046 i++;
1048 /* Dissect the status */
1049 if ( dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_status) !=
1050 ZBEE_ZCL_STAT_SUCCESS ) {
1052 /* Dissect the failed attribute identifier */
1053 dissect_zcl_attr_id(tvb, sub_tree, offset);
1057 return;
1058 } /* dissect_zcl_write_attr_resp */
1060 /*FUNCTION:------------------------------------------------------
1061 * NAME
1062 * dissect_zcl_read_report_config_resp
1063 * DESCRIPTION
1064 * Helper dissector for ZCL Report Attribute commands.
1065 * PARAMETERS
1066 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1067 * packet_info *pinfo - pointer to packet information fields
1068 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1069 * offset - pointer to offset from caller
1070 *---------------------------------------------------------------
1072 static void dissect_zcl_read_report_config_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1073 guint *offset)
1075 proto_item *ti = NULL;
1076 proto_tree *sub_tree = NULL;
1078 guint tvb_len;
1079 guint i = 0;
1080 guint data_type;
1081 guint attr_status;
1082 guint attr_dir;
1083 guint16 attr_id;
1085 tvb_len = tvb_length(tvb);
1086 while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) {
1088 /* Create subtree for attribute status field */
1089 ti = proto_tree_add_text(tree, tvb, *offset, 3, "Reporting Configuration Record");
1090 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_attr[i]);
1091 i++;
1093 /* Dissect the status */
1094 attr_status = dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_status);
1096 /* Dissect the direction and any reported configuration */
1097 attr_dir = dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_dir);
1099 /* Dissect the attribute id */
1100 attr_id = tvb_get_letohs(tvb, *offset);
1101 dissect_zcl_attr_id(tvb, sub_tree, offset);
1103 if ( attr_status == ZBEE_ZCL_STAT_SUCCESS ) {
1104 if ( attr_dir == ZBEE_ZCL_DIR_REPORTED ) {
1106 /* Dissect the attribute data type */
1107 data_type = dissect_zcl_attr_uint8(tvb, sub_tree, offset,
1108 &hf_zbee_zcl_attr_data_type);
1110 /* Dissect minimum reporting interval */
1111 dissect_zcl_attr_uint16(tvb, sub_tree, offset, &hf_zbee_zcl_attr_minint);
1113 /* Dissect maximum reporting interval */
1114 dissect_zcl_attr_uint16(tvb, sub_tree, offset, &hf_zbee_zcl_attr_maxint);
1116 if ( IS_ANALOG_SUBTYPE(data_type) ) {
1117 /* Dissect reportable change */
1118 dissect_zcl_attr_data_general(tvb, sub_tree, offset, attr_id, data_type);
1121 } else {
1122 /* Dissect timeout period */
1123 dissect_zcl_attr_uint16(tvb, sub_tree, offset, &hf_zbee_zcl_attr_timeout);
1128 return;
1129 } /* dissect_zcl_read_report_config_resp */
1131 /*FUNCTION:------------------------------------------------------
1132 * NAME
1133 * dissect_zcl_config_report
1134 * DESCRIPTION
1135 * Helper dissector for ZCL Report Attribute commands.
1136 * PARAMETERS
1137 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1138 * packet_info *pinfo - pointer to packet information fields
1139 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1140 * offset - pointer to offset from caller
1141 *---------------------------------------------------------------
1143 static void dissect_zcl_config_report(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
1145 proto_item *ti = NULL;
1146 proto_tree *sub_tree = NULL;
1148 guint tvb_len;
1149 guint i = 0;
1150 guint data_type;
1151 guint16 attr_id;
1153 tvb_len = tvb_length(tvb);
1154 while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) {
1156 /* Create subtree for attribute status field */
1157 ti = proto_tree_add_text(tree, tvb, *offset, 3, "Reporting Configuration Record");
1158 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_attr[i]);
1159 i++;
1161 /* Dissect the direction and any reported configuration */
1162 if ( dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_dir)
1163 == ZBEE_ZCL_DIR_REPORTED ) {
1165 /* Dissect the attribute id */
1166 attr_id = tvb_get_letohs(tvb, *offset);
1167 dissect_zcl_attr_id(tvb, sub_tree, offset);
1169 /* Dissect the attribute data type */
1170 data_type = dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_data_type);
1172 /* Dissect minimum reporting interval */
1173 dissect_zcl_attr_uint16(tvb, sub_tree, offset, &hf_zbee_zcl_attr_minint);
1175 /* Dissect maximum reporting interval */
1176 dissect_zcl_attr_uint16(tvb, sub_tree, offset, &hf_zbee_zcl_attr_maxint);
1178 if ( IS_ANALOG_SUBTYPE(data_type) ) {
1179 /* Dissect reportable change */
1180 dissect_zcl_attr_data_general(tvb, sub_tree, offset, attr_id, data_type);
1182 } else {
1184 /* Dissect the attribute id */
1185 dissect_zcl_attr_id(tvb, sub_tree, offset);
1187 /* Dissect timeout period */
1188 dissect_zcl_attr_uint16(tvb, sub_tree, offset, &hf_zbee_zcl_attr_timeout);
1192 return;
1193 } /* dissect_zcl_config_report */
1195 /*FUNCTION:------------------------------------------------------
1196 * NAME
1197 * dissect_zcl_config_report_resp
1198 * DESCRIPTION
1199 * Helper dissector for ZCL Report Attribute commands.
1200 * PARAMETERS
1201 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1202 * packet_info *pinfo - pointer to packet information fields
1203 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1204 * offset - pointer to offset from caller
1205 * RETURNS
1206 * guint - offset after command dissection.
1207 *---------------------------------------------------------------
1209 static void dissect_zcl_config_report_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1210 guint *offset)
1212 proto_item *ti = NULL;
1213 proto_tree *sub_tree = NULL;
1215 guint tvb_len;
1216 guint i = 0;
1218 tvb_len = tvb_length(tvb);
1219 while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) {
1221 /* Create subtree for attribute status field */
1222 ti = proto_tree_add_text(tree, tvb, *offset, 3, "Attribute Status Record");
1223 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_attr[i]);
1224 i++;
1226 /* Dissect the status */
1227 if ( dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_status) !=
1228 ZBEE_ZCL_STAT_SUCCESS ) {
1229 /* Dissect the direction on error */
1230 dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_dir);
1232 /* Dissect the attribute identifier on error */
1233 dissect_zcl_attr_id(tvb, sub_tree, offset);
1237 return;
1238 } /* dissect_zcl_config_report_resp */
1240 /*FUNCTION:------------------------------------------------------
1241 * NAME
1242 * dissect_zcl_read_report_config
1243 * DESCRIPTION
1244 * Helper dissector for ZCL Read Report Configuration command.
1245 * PARAMETERS
1246 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1247 * packet_info *pinfo - pointer to packet information fields
1248 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1249 * offset - pointer to offset from caller
1250 * RETURNS
1251 * guint - offset after command dissection.
1252 *---------------------------------------------------------------
1254 static void dissect_zcl_read_report_config(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1255 guint *offset)
1257 proto_item *ti = NULL;
1258 proto_tree *sub_tree = NULL;
1260 guint tvb_len;
1261 guint i = 0;
1263 tvb_len = tvb_length(tvb);
1264 while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) {
1266 /* Create subtree for attribute status field */
1267 ti = proto_tree_add_text(tree, tvb, *offset, 3, "Attribute Status Record");
1268 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_attr[i]);
1269 i++;
1271 /* Dissect the direction */
1272 dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_dir);
1274 /* Dissect the attribute identifier */
1275 dissect_zcl_attr_id(tvb, sub_tree, offset);
1278 return;
1279 } /* dissect_zcl_read_report_config */
1281 /*FUNCTION:------------------------------------------------------
1282 * NAME
1283 * dissect_zcl_default_resp
1284 * DESCRIPTION
1285 * Helper dissector for ZCL Default Response command.
1286 * PARAMETERS
1287 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1288 * packet_info *pinfo - pointer to packet information fields
1289 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1290 * offset - pointer to offset from caller
1291 * RETURNS
1292 * void
1293 *---------------------------------------------------------------
1295 static void dissect_zcl_default_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
1297 guint cmd_id;
1299 /* Dissect the command identifier */
1300 cmd_id = tvb_get_guint8(tvb, *offset);
1302 proto_tree_add_uint(tree, hf_zbee_zcl_cmd_id, tvb, *offset, (int)1, cmd_id);
1303 *offset += (int)1;
1305 /* Dissect the status */
1306 dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_status);
1308 return;
1309 } /* dissect_zcl_default_resp */
1311 /*FUNCTION:------------------------------------------------------
1312 * NAME
1313 * dissect_zcl_discover_attr
1314 * DESCRIPTION
1315 * Helper dissector for ZCL Discover Attributes command.
1316 * PARAMETERS
1317 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1318 * packet_info *pinfo - pointer to packet information fields
1319 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1320 * offset - pointer to offset from caller
1321 * RETURNS
1322 * void
1323 *---------------------------------------------------------------
1325 static void dissect_zcl_discover_attr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
1327 /* Dissect the starting attribute identifier */
1328 dissect_zcl_attr_uint16(tvb, tree, offset, &hf_zbee_zcl_attr_start);
1330 /* Dissect the number of maximum attribute identifiers */
1331 dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_maxnum);
1333 return;
1334 } /* dissect_zcl_discover_attr */
1337 /*FUNCTION:------------------------------------------------------
1338 * NAME
1339 * dissect_zcl_discover_attr_resp
1340 * DESCRIPTION
1341 * Helper dissector for ZCL Discover Attributes command.
1342 * PARAMETERS
1343 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1344 * packet_info *pinfo - pointer to packet information fields
1345 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1346 * offset - pointer to offset from caller
1347 * RETURNS
1348 * void
1349 *---------------------------------------------------------------
1351 static void dissect_zcl_discover_attr_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1352 guint *offset)
1354 proto_item *ti = NULL;
1355 proto_tree *sub_tree = NULL;
1357 guint tvb_len;
1358 guint i = 0;
1360 dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_dis);
1362 tvb_len = tvb_length(tvb);
1363 while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) {
1365 /* Create subtree for attribute status field */
1366 ti = proto_tree_add_text(tree, tvb, *offset, 3, "Attribute Status Record");
1367 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_attr[i]);
1368 i++;
1370 /* Dissect the attribute identifier */
1371 dissect_zcl_attr_id(tvb, sub_tree, offset);
1373 /* Dissect the number of maximum attribute identifiers */
1374 dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_data_type);
1377 return;
1378 } /* dissect_zcl_discover_attr_resp */
1381 /*FUNCTION:------------------------------------------------------
1382 * NAME
1383 * dissect_zcl_attr_id
1384 * DESCRIPTION
1385 * Dissects Attribute ID field. This could be done with the
1386 * dissect_zcl_attr_uint16 function, but we leave it separate
1387 * so we can dissect the attr_id with a hash in the future.
1388 * PARAMETERS
1389 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1390 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1391 * offset - offset into the tvb to begin dissection.
1392 * RETURNS
1393 * void
1394 *---------------------------------------------------------------
1396 static void dissect_zcl_attr_id(tvbuff_t *tvb, proto_tree *tree, guint *offset)
1398 guint16 attr_id;
1399 zbee_zcl_cluster_desc *desc;
1401 attr_id = tvb_get_letohs(tvb, *offset);
1402 desc = zbee_zcl_get_cluster_desc(zcl_cluster_id);
1403 if ((desc != NULL) && (desc->fn_attr_id != NULL)) {
1404 desc->fn_attr_id(tree, tvb, offset, attr_id);
1406 else {
1407 /* Add the identifier */
1408 proto_tree_add_uint(tree,
1409 hf_zbee_zcl_attr_id,
1410 tvb,
1411 *offset,
1412 (int)2,
1413 attr_id);
1416 *offset += (int)2;
1418 return;
1419 } /* dissect_zcl_attr_id */
1421 /*FUNCTION:------------------------------------------------------
1422 * NAME
1423 * dissect_zcl_attr_data_type_val
1424 * DESCRIPTION
1425 * Helper dissector for ZCL Attribute commands.
1426 * PARAMETERS
1427 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1428 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1429 * offset - offset into the tvb to begin dissection.
1430 * RETURNS
1431 * void
1432 *---------------------------------------------------------------
1434 static void dissect_zcl_attr_data_type_val(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 attr_id)
1436 zbee_zcl_cluster_desc *desc;
1438 desc = zbee_zcl_get_cluster_desc(zcl_cluster_id);
1439 if ((desc != NULL) && (desc->fn_attr_data != NULL)) {
1440 desc->fn_attr_data(tree, tvb, offset, attr_id,
1441 dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_data_type));
1443 else {
1444 dissect_zcl_attr_data(tvb, tree, offset,
1445 dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_data_type) );
1448 return;
1449 } /* dissect_zcl_attr_data_type_val */
1452 /*FUNCTION:------------------------------------------------------
1453 * NAME
1454 * dissect_zcl_attr_data_general
1455 * DESCRIPTION
1456 * Helper dissector for ZCL Attribute commands.
1457 * PARAMETERS
1458 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1459 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1460 * offset - offset into the tvb to begin dissection.
1461 * attr_id - attribute identification
1462 * data_type - type of data
1463 * RETURNS
1464 * void
1465 *---------------------------------------------------------------
1467 static void dissect_zcl_attr_data_general(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 attr_id, guint data_type)
1469 zbee_zcl_cluster_desc *desc;
1471 desc = zbee_zcl_get_cluster_desc(zcl_cluster_id);
1472 if ((desc != NULL) && (desc->fn_attr_data != NULL)) {
1473 desc->fn_attr_data(tree, tvb, offset, attr_id, data_type);
1475 else {
1476 dissect_zcl_attr_data(tvb, tree, offset, data_type);
1479 return;
1480 } /*dissect_zcl_attr_data_general*/
1482 /*FUNCTION:------------------------------------------------------
1483 * NAME
1484 * dissect_zcl_attr_data
1485 * DESCRIPTION
1486 * Dissects the various types of ZCL attribute data.
1487 * PARAMETERS
1488 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1489 * packet_info *pinfo - pointer to packet information fields
1490 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1491 * offset - offset into the tvb to begin dissection.
1492 * data_type - the type of ZCL data in the packet buffer
1493 * RETURNS
1494 * void
1495 *---------------------------------------------------------------
1497 void dissect_zcl_attr_data(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint data_type)
1499 guint attr_uint;
1500 gint attr_int;
1501 guint8 *attr_string;
1502 guint8 attr_uint8[4];
1503 guint8 elements_type;
1504 guint16 elements_num;
1505 gfloat attr_float;
1506 gdouble attr_double;
1507 nstime_t attr_time;
1509 /* Dissect attribute data type and data */
1510 switch ( data_type ) {
1511 case ZBEE_ZCL_NO_DATA:
1512 break;
1514 case ZBEE_ZCL_8_BIT_DATA:
1515 case ZBEE_ZCL_8_BIT_BITMAP:
1516 dissect_zcl_attr_bytes(tvb, tree, offset, 1);
1517 break;
1519 case ZBEE_ZCL_8_BIT_UINT:
1520 case ZBEE_ZCL_8_BIT_ENUM:
1522 /* Display 8 bit unsigned integer */
1523 attr_uint = tvb_get_guint8(tvb, *offset);
1525 proto_item_append_text(tree, ", %s: %u",
1526 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_uint);
1528 proto_tree_add_uint(tree, hf_zbee_zcl_attr_uint8, tvb, *offset, (int)1,
1529 attr_uint);
1530 *offset += (int)1;
1531 break;
1533 case ZBEE_ZCL_8_BIT_INT:
1534 /* Display 8 bit integer */
1536 attr_int = (gint8)tvb_get_guint8(tvb, *offset);
1538 proto_item_append_text(tree, ", %s: %-d",
1539 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_int);
1541 proto_tree_add_int(tree, hf_zbee_zcl_attr_int8, tvb, *offset, (int)sizeof(gint8),
1542 (gint)attr_int);
1544 *offset += (int)sizeof(gint8);
1545 break;
1547 case ZBEE_ZCL_BOOLEAN:
1549 attr_uint = tvb_get_guint8(tvb, *offset);
1551 proto_item_append_text(tree, ", %s: 0x%02x",
1552 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_uint);
1554 proto_tree_add_item(tree, hf_zbee_zcl_attr_boolean, tvb, *offset, 1, ENC_BIG_ENDIAN);
1556 *offset += (int)1;
1557 break;
1559 case ZBEE_ZCL_16_BIT_DATA:
1560 case ZBEE_ZCL_16_BIT_BITMAP:
1561 dissect_zcl_attr_bytes(tvb, tree, offset, 2);
1562 break;
1564 case ZBEE_ZCL_16_BIT_UINT:
1565 case ZBEE_ZCL_16_BIT_ENUM:
1566 /* Display 16 bit unsigned integer */
1568 attr_uint = tvb_get_letohs(tvb, *offset);
1570 proto_item_append_text(tree, ", %s: %u",
1571 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_uint);
1573 proto_tree_add_uint(tree, hf_zbee_zcl_attr_uint16, tvb, *offset, (int)2,
1574 attr_uint);
1576 *offset += (int)2;
1577 break;
1579 case ZBEE_ZCL_16_BIT_INT:
1580 /* Display 16 bit integer */
1582 attr_int = (gint16)tvb_get_letohs(tvb, *offset);
1584 proto_item_append_text(tree, ", %s: %-d",
1585 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_int);
1587 proto_tree_add_int(tree, hf_zbee_zcl_attr_int16, tvb, *offset, (int)sizeof(gint16),
1588 attr_int);
1590 *offset += (int)sizeof(gint16);
1591 break;
1593 case ZBEE_ZCL_24_BIT_DATA:
1594 case ZBEE_ZCL_24_BIT_BITMAP:
1595 dissect_zcl_attr_bytes(tvb, tree, offset, 3);
1596 break;
1598 case ZBEE_ZCL_24_BIT_UINT:
1599 /* Display 24 bit unsigned integer */
1601 attr_uint = tvb_get_letoh24(tvb, *offset);
1603 proto_item_append_text(tree, ", %s: %u",
1604 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_uint);
1606 proto_tree_add_uint(tree, hf_zbee_zcl_attr_uint24, tvb, *offset, 3,
1607 attr_uint);
1609 *offset += 3;
1610 break;
1612 case ZBEE_ZCL_24_BIT_INT:
1613 /* Display 24 bit signed integer */
1615 attr_int = (gint)tvb_get_letoh24(tvb, *offset);
1616 /* sign extend into int32 */
1617 if (attr_int & INT24_SIGN_BITS) attr_int |= INT24_SIGN_BITS;
1619 proto_item_append_text(tree, ", %s: %-d",
1620 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_int);
1622 proto_tree_add_int(tree, hf_zbee_zcl_attr_int24, tvb, *offset, 3,
1623 attr_int);
1625 *offset += 3;
1626 break;
1628 case ZBEE_ZCL_32_BIT_DATA:
1629 case ZBEE_ZCL_32_BIT_BITMAP:
1630 dissect_zcl_attr_bytes(tvb, tree, offset, 4);
1631 break;
1633 case ZBEE_ZCL_32_BIT_UINT:
1634 /* Display 32 bit unsigned integer */
1636 attr_uint = tvb_get_letohl(tvb, *offset);
1638 proto_item_append_text(tree, ", %s: %u",
1639 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_uint);
1641 proto_tree_add_uint(tree, hf_zbee_zcl_attr_uint32, tvb, *offset, (int)sizeof(guint),
1642 attr_uint);
1644 *offset += (int)sizeof(guint);
1645 break;
1647 case ZBEE_ZCL_32_BIT_INT:
1648 /* Display 32 bit signed integer */
1650 attr_int = (gint)tvb_get_letohl(tvb, *offset);
1652 proto_item_append_text(tree, ", %s: %-d",
1653 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_int);
1655 proto_tree_add_int(tree, hf_zbee_zcl_attr_int32, tvb, *offset, (int)sizeof(gint),
1656 attr_int);
1658 *offset += (int)sizeof(gint);
1659 break;
1661 case ZBEE_ZCL_40_BIT_DATA:
1662 case ZBEE_ZCL_40_BIT_BITMAP:
1663 dissect_zcl_attr_bytes(tvb, tree, offset, 5);
1664 break;
1666 case ZBEE_ZCL_40_BIT_UINT:
1667 dissect_zcl_big_int(tvb, tree, offset, 5, FALSE);
1668 break;
1670 case ZBEE_ZCL_40_BIT_INT:
1671 dissect_zcl_big_int(tvb, tree, offset, 5, TRUE);
1672 break;
1674 case ZBEE_ZCL_48_BIT_DATA:
1675 case ZBEE_ZCL_48_BIT_BITMAP:
1676 dissect_zcl_attr_bytes(tvb, tree, offset, 6);
1677 break;
1679 case ZBEE_ZCL_48_BIT_UINT:
1680 dissect_zcl_big_int(tvb, tree, offset, 6, FALSE);
1681 break;
1683 case ZBEE_ZCL_48_BIT_INT:
1684 dissect_zcl_big_int(tvb, tree, offset, 6, TRUE);
1685 break;
1687 case ZBEE_ZCL_56_BIT_DATA:
1688 case ZBEE_ZCL_56_BIT_BITMAP:
1689 dissect_zcl_attr_bytes(tvb, tree, offset, 7);
1690 break;
1692 case ZBEE_ZCL_56_BIT_UINT:
1693 dissect_zcl_big_int(tvb, tree, offset, 7, FALSE);
1694 break;
1696 case ZBEE_ZCL_56_BIT_INT:
1697 dissect_zcl_big_int(tvb, tree, offset, 7, TRUE);
1698 break;
1700 case ZBEE_ZCL_64_BIT_DATA:
1701 case ZBEE_ZCL_64_BIT_BITMAP:
1702 dissect_zcl_attr_bytes(tvb, tree, offset, 8);
1703 break;
1705 case ZBEE_ZCL_64_BIT_UINT:
1706 dissect_zcl_big_int(tvb, tree, offset, 8, FALSE);
1707 break;
1709 case ZBEE_ZCL_64_BIT_INT:
1710 dissect_zcl_big_int(tvb, tree, offset, 8, TRUE);
1711 break;
1713 case ZBEE_ZCL_SEMI_FLOAT:
1714 /* BUGBUG */
1715 dissect_zcl_attr_bytes(tvb, tree, offset, 2);
1716 break;
1718 case ZBEE_ZCL_SINGLE_FLOAT:
1719 attr_float = tvb_get_letohieee_float(tvb, *offset);
1722 proto_item_append_text(tree, ", %s: %g",
1723 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved"), attr_float);
1725 proto_tree_add_item(tree, hf_zbee_zcl_attr_float, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1727 *offset += 4;
1728 break;
1730 case ZBEE_ZCL_DOUBLE_FLOAT:
1731 attr_double = tvb_get_letohieee_double(tvb, *offset);
1733 proto_item_append_text(tree, ", Double: %lg", attr_double);
1734 proto_tree_add_item(tree, hf_zbee_zcl_attr_double, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
1736 *offset += 8;
1737 break;
1739 case ZBEE_ZCL_OCTET_STRING:
1741 /* Display octet string */
1742 attr_uint = tvb_get_guint8(tvb, *offset); /* string length */
1743 if (attr_uint == ZBEE_ZCL_INVALID_STR_LENGTH) attr_uint = 0;
1745 proto_tree_add_uint(tree, hf_zbee_zcl_attr_str_len, tvb, *offset, (int)1,
1746 attr_uint);
1748 *offset += (int)1;
1750 attr_string = tvb_bytes_to_str_punct(tvb, *offset, attr_uint, ':');
1751 proto_item_append_text(tree, ", Octets: %s", attr_string);
1752 proto_tree_add_string(tree, hf_zbee_zcl_attr_ostr, tvb, *offset, attr_uint,
1753 attr_string);
1755 *offset += attr_uint;
1756 break;
1758 case ZBEE_ZCL_CHAR_STRING:
1760 /* Display string */
1761 attr_uint = tvb_get_guint8(tvb, *offset); /* string length */
1762 if (attr_uint == ZBEE_ZCL_INVALID_STR_LENGTH) attr_uint = 0;
1764 proto_tree_add_uint(tree, hf_zbee_zcl_attr_str_len, tvb, *offset, (int)1,
1765 attr_uint);
1767 *offset += (int)1;
1769 attr_string = tvb_get_string(wmem_packet_scope(), tvb, *offset, attr_uint);
1771 proto_item_append_text(tree, ", String: %s", attr_string);
1772 proto_tree_add_string(tree, hf_zbee_zcl_attr_str, tvb, *offset, attr_uint, attr_string);
1774 *offset += attr_uint;
1775 break;
1777 case ZBEE_ZCL_LONG_OCTET_STRING:
1779 /* Display long octet string */
1780 attr_uint = tvb_get_letohs(tvb, *offset); /* string length */
1781 if (attr_uint == ZBEE_ZCL_INVALID_LONG_STR_LENGTH) attr_uint = 0;
1782 proto_tree_add_uint(tree, hf_zbee_zcl_attr_str_len, tvb, *offset, (int)2, attr_uint);
1784 *offset += (int)2;
1786 attr_string = tvb_bytes_to_str_punct(tvb, *offset, attr_uint, ':');
1787 proto_item_append_text(tree, ", Octets: %s", attr_string);
1788 proto_tree_add_string(tree, hf_zbee_zcl_attr_ostr, tvb, *offset, attr_uint, attr_string);
1790 *offset += attr_uint;
1791 break;
1793 case ZBEE_ZCL_LONG_CHAR_STRING:
1795 /* Display long string */
1796 attr_uint = tvb_get_letohs(tvb, *offset); /* string length */
1797 if (attr_uint == ZBEE_ZCL_INVALID_LONG_STR_LENGTH) attr_uint = 0;
1799 proto_tree_add_uint(tree, hf_zbee_zcl_attr_str_len, tvb, *offset, (int)2, attr_uint);
1801 *offset += (int)2;
1803 attr_string = tvb_get_string(wmem_packet_scope(), tvb, *offset, attr_uint);
1804 proto_item_append_text(tree, ", String: %s", attr_string);
1805 proto_tree_add_string(tree, hf_zbee_zcl_attr_str, tvb, *offset, attr_uint, attr_string);
1807 *offset += attr_uint;
1808 break;
1810 case ZBEE_ZCL_ARRAY:
1811 /* BYTE 0 - Elements type */
1812 elements_type = tvb_get_guint8(tvb, *offset);
1813 proto_tree_add_uint(tree, hf_zbee_zcl_attr_array_elements_type, tvb, *offset, (int)1, elements_type);
1814 *offset += (int)1;
1815 /* BYTE 1-2 - Element number */
1816 elements_num = tvb_get_letohs(tvb, *offset);
1817 proto_tree_add_uint(tree, hf_zbee_zcl_attr_array_elements_num, tvb, *offset, (int)2, elements_num);
1818 *offset += (int)2;
1819 /* BYTE ... - Elements */
1820 dissect_zcl_array_type(tvb, tree, offset, elements_type, elements_num);
1821 break;
1823 case ZBEE_ZCL_SET:
1824 /* ToDo */
1825 break;
1827 case ZBEE_ZCL_STRUCT:
1828 /* ToDo */
1829 break;
1831 case ZBEE_ZCL_BAG:
1832 /* ToDo */
1833 break;
1835 case ZBEE_ZCL_TIME:
1836 /* Dissect Time of Day */
1837 attr_uint8[0] = dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_hours);
1838 attr_uint8[1] = dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_mins);
1839 attr_uint8[2] = dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_secs);
1840 attr_uint8[3] = dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_csecs);
1842 proto_item_append_text(tree, ", Time: %u:%u:%u.%u",
1843 attr_uint8[0], attr_uint8[1], attr_uint8[2], attr_uint8[3]);
1844 break;
1846 case ZBEE_ZCL_DATE:
1847 /* Dissect Date */
1848 attr_uint8[0] = dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_yy);
1849 attr_uint8[1] = dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_mm);
1850 attr_uint8[2] = dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_md);
1851 attr_uint8[3] = dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_wd);
1853 proto_item_append_text(tree, ", Date: %u/%u/%u %s",
1854 attr_uint8[0]+1900, attr_uint8[1], attr_uint8[2],
1855 val_to_str_ext_const(attr_uint8[3], &zbee_zcl_wd_names_ext, "Invalid Weekday") );
1856 break;
1858 case ZBEE_ZCL_UTC:
1859 /* Display UTC */
1860 attr_time.secs = tvb_get_letohl(tvb, *offset);
1861 attr_time.secs += ZBEE_ZCL_NSTIME_UTC_OFFSET;
1862 attr_time.nsecs = 0;
1864 proto_item_append_text(tree, ", %s",
1865 val_to_str_ext_const(data_type, &zbee_zcl_short_data_type_names_ext, "Reserved") );
1866 proto_tree_add_time(tree, hf_zbee_zcl_attr_utc, tvb, *offset, 4, &attr_time);
1868 *offset += 4;
1869 break;
1871 case ZBEE_ZCL_CLUSTER_ID:
1872 dissect_zcl_attr_uint16(tvb, tree, offset, &hf_zbee_zcl_attr_cid);
1873 break;
1875 case ZBEE_ZCL_ATTR_ID:
1876 dissect_zcl_attr_id(tvb, tree, offset);
1877 break;
1879 case ZBEE_ZCL_BACNET_OID:
1880 dissect_zcl_attr_bytes(tvb, tree, offset, 4);
1881 break;
1883 case ZBEE_ZCL_IEEE_ADDR:
1884 dissect_zcl_attr_bytes(tvb, tree, offset, 8);
1885 break;
1887 case ZBEE_ZCL_SECURITY_KEY:
1888 dissect_zcl_attr_bytes(tvb, tree, offset, 16);
1889 break;
1891 default:
1892 break;
1895 return;
1896 } /* dissect_zcl_attr_data */
1898 /*FUNCTION:------------------------------------------------------
1899 * NAME
1900 * dissect_zcl_big_int
1901 * DESCRIPTION
1902 * Dissects int or uint of up to 64 bits.
1903 * PARAMETERS
1904 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1905 * packet_info *pinfo - pointer to packet information fields
1906 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1907 * offset - offset into the tvb to begin dissection.
1908 * signed_flag - if TRUE, dissect a signed int
1909 * RETURNS
1910 * void
1911 *---------------------------------------------------------------
1913 static void dissect_zcl_big_int(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint length,
1914 gboolean signed_flag)
1916 guint64 attr_uint64;
1918 attr_uint64 = tvb_get_letohi(tvb, *offset, length, signed_flag);
1920 /* add it to tree */
1922 if ( signed_flag ) {
1923 proto_item_append_text(tree, ", Int: %" G_GINT64_MODIFIER "d", (gint64)attr_uint64);
1925 proto_tree_add_int64(tree, hf_zbee_zcl_attr_int64, tvb, *offset, length,
1926 (gint64)attr_uint64);
1927 } else {
1928 proto_item_append_text(tree, ", Uint: %" G_GINT64_MODIFIER "u", attr_uint64);
1930 proto_tree_add_uint64(tree, hf_zbee_zcl_attr_uint64, tvb, *offset, length,
1931 attr_uint64);
1934 *offset += length;
1936 return;
1937 } /* dissect_zcl_big_int */
1939 /*FUNCTION:------------------------------------------------------
1940 * NAME
1941 * dissect_zcl_attr_uint8
1942 * DESCRIPTION
1943 * Helper dissector for ZCL Attribute commands.
1944 * PARAMETERS
1945 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1946 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1947 * offset - offset into the tvb to begin dissection.
1948 * hf_zbee_zcl - pointer to header field index
1949 * RETURNS
1950 * guint - dissected data
1951 *---------------------------------------------------------------
1953 static guint dissect_zcl_attr_uint8(tvbuff_t *tvb, proto_tree *tree, guint *offset, int *hf_zbee_zcl)
1955 guint attr_uint;
1957 attr_uint = tvb_get_guint8(tvb, *offset);
1958 proto_tree_add_uint(tree, *hf_zbee_zcl, tvb, *offset, (int)1, attr_uint);
1959 (*offset)++;
1961 return attr_uint;
1962 } /* dissect_zcl_attr_uint8 */
1964 /*FUNCTION:------------------------------------------------------
1965 * NAME
1966 * dissect_zcl_attr_uint16
1967 * DESCRIPTION
1968 * Helper dissector for ZCL Attribute commands.
1969 * PARAMETERS
1970 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1971 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1972 * offset - offset into the tvb to begin dissection.
1973 * hf_zbee_zcl - pointer to header field index
1974 * RETURNS
1975 * guint - field value
1976 *---------------------------------------------------------------
1978 static guint dissect_zcl_attr_uint16(tvbuff_t *tvb, proto_tree *tree, guint *offset, int *hf_zbee_zcl)
1980 guint attr_uint;
1982 attr_uint = tvb_get_letohs(tvb, *offset);
1983 proto_tree_add_uint(tree, *hf_zbee_zcl, tvb, *offset, (int)2, attr_uint);
1984 *offset += (int)2;
1986 return attr_uint;
1987 } /* dissect_zcl_attr_uint16 */
1989 /*FUNCTION:------------------------------------------------------
1990 * NAME
1991 * dissect_zcl_attr_bytes
1992 * DESCRIPTION
1993 * Helper dissector for ZCL Attribute commands.
1994 * PARAMETERS
1995 * tvbuff_t *tvb - pointer to buffer containing raw packet.
1996 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
1997 * offset - offset into the tvb to begin dissection.
1998 * length - number of bytes to dissect
1999 * RETURNS
2000 * void
2001 *---------------------------------------------------------------
2003 static void dissect_zcl_attr_bytes(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint length)
2005 proto_tree_add_item(tree, hf_zbee_zcl_attr_bytes, tvb, *offset, length, ENC_NA);
2006 *offset += length;
2008 return;
2009 } /* dissect_dcl_attr_bytes */
2011 /*FUNCTION:------------------------------------------------------
2012 * NAME
2013 * dissect_zcl_array_type
2014 * DESCRIPTION
2015 * Helper dissector for ZCL attribute array type.
2016 * PARAMETERS
2017 * tvbuff_t *tvb - pointer to buffer containing raw packet.
2018 * proto_tree *tree - pointer to data tree wireshark uses to display packet.
2019 * offset - offset into the tvb to begin dissection.
2020 * elements_type - element type
2021 * elements_num - elements number
2022 * RETURNS
2023 * void
2024 *---------------------------------------------------------------
2026 static void
2027 dissect_zcl_array_type(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint8 elements_type, guint16 elements_num)
2029 proto_item *ti = NULL;
2030 proto_tree *sub_tree = NULL;
2032 guint tvb_len;
2033 guint i = 1; /* First element has a 1-index value */
2035 tvb_len = tvb_length(tvb);
2036 while ( (*offset < tvb_len) && (i < ZBEE_ZCL_NUM_ARRAY_ELEM_ETT) && (elements_num != 0) ) {
2037 /* Create subtree for array element field */
2038 ti = proto_tree_add_text(tree, tvb, *offset, 0, "Element #%d", i);
2039 sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_array_elements[i]);
2040 dissect_zcl_attr_data(tvb, sub_tree, offset, elements_type);
2041 elements_num--;
2042 i++;
2045 return;
2046 } /* dissect_zcl_array_type */
2048 /*FUNCTION:------------------------------------------------------
2049 * NAME
2050 * zcl_dump_data
2051 * DESCRIPTION
2052 * Helper functions dumps any remaining data into the data dissector.
2053 * PARAMETERS
2054 * tvbuff_t *tvb - pointer to buffer containing raw packet.
2055 * guint offset - offset after parsing last item.
2056 * packet_info *pinfo - packet information structure.
2057 * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
2058 * RETURNS
2059 * void
2060 *---------------------------------------------------------------
2062 static void zcl_dump_data(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
2064 proto_tree *root = proto_tree_get_root(tree);
2065 guint length = tvb_length_remaining(tvb, offset);
2066 tvbuff_t *remainder;
2068 if (length > 0) {
2069 remainder = tvb_new_subset(tvb, offset, length, length);
2070 call_dissector(data_handle, remainder, pinfo, root);
2073 return;
2074 } /* zcl_dump_data */
2076 /*FUNCTION:------------------------------------------------------
2077 * NAME
2078 * tvb_get_letohi
2079 * DESCRIPTION
2080 * Gets little endian int or uint of up to 8 bytes from tvb buffer.
2081 * PARAMETERS
2082 * tvbuff_t *tvb - pointer to buffer containing raw packet.
2083 * offset - offset into the tvb to begin dissection.
2084 * length - length of int or uint in bytes
2085 * signed_flag - if TRUE, get a signed int
2086 * RETURNS
2087 * guint64 - value retrieved from tvb buffer
2088 *---------------------------------------------------------------
2090 static guint64 tvb_get_letohi(tvbuff_t *tvb, guint offset, guint length, gboolean signed_flag)
2092 guint64 result;
2093 guint shift;
2095 DISSECTOR_ASSERT((length>=1) && (length<=8));
2097 result = 0;
2098 shift = 0;
2099 /* build big int of length bytes */
2100 while ( length-- ) {
2101 result += (guint64)tvb_get_guint8(tvb, offset) << shift;
2102 offset += (int)1;
2103 shift += 8;
2106 if ( signed_flag && (result >> (shift - 1)) ) {
2107 /* sign extend remaining bytes */
2108 while ( shift < ((int)sizeof(guint64) * 8) ) {
2109 result += (guint64)0xff << shift;
2110 shift += 8;
2114 return result;
2115 } /* tvb_get_letohi */
2118 /*FUNCTION:------------------------------------------------------
2119 * NAME
2120 * decode_zcl_time_in_seconds
2121 * DESCRIPTION
2122 * this function decodes second time type variable
2123 * PARAMETERS
2124 * RETURNS
2125 * none
2126 *---------------------------------------------------------------
2128 void decode_zcl_time_in_seconds(gchar *s, guint16 value)
2130 g_snprintf(s, ITEM_LABEL_LENGTH, "%d seconds", value);
2131 return;
2132 } /* decode_zcl_time_in_seconds*/
2134 /*FUNCTION:------------------------------------------------------
2135 * NAME
2136 * decode_zcl_time_in_minutes
2137 * DESCRIPTION
2138 * this function decodes minute time type variable
2139 * PARAMETERS
2140 * RETURNS
2141 * none
2142 *---------------------------------------------------------------
2144 void decode_zcl_time_in_minutes(gchar *s, guint16 value)
2146 g_snprintf(s, ITEM_LABEL_LENGTH, "%d minutes", value);
2147 return;
2148 } /*decode_zcl_time_in_minutes*/
2150 /*FUNCTION:------------------------------------------------------
2151 * NAME
2152 * proto_register_zbee_zcl
2153 * DESCRIPTION
2154 * ZigBee ZCL protocol registration routine.
2155 * PARAMETERS
2156 * none
2157 * RETURNS
2158 * void
2159 *---------------------------------------------------------------
2161 void proto_register_zbee_zcl(void)
2163 guint i, j;
2165 static const true_false_string tfs_client_server = {
2166 "To Client",
2167 "To Server"
2170 static hf_register_info hf[] = {
2171 { &hf_zbee_zcl_fcf_frame_type,
2172 { "Frame Type", "zbee_zcl.type", FT_UINT8, BASE_HEX, VALS(zbee_zcl_frame_types),
2173 ZBEE_ZCL_FCF_FRAME_TYPE, NULL, HFILL }},
2175 { &hf_zbee_zcl_fcf_mfr_spec,
2176 { "Manufacturer Specific", "zbee_zcl.ms", FT_BOOLEAN, 8, NULL,
2177 ZBEE_ZCL_FCF_MFR_SPEC, NULL, HFILL }},
2179 { &hf_zbee_zcl_fcf_dir,
2180 { "Direction", "zbee_zcl.dir", FT_BOOLEAN, 8, TFS(&tfs_client_server),
2181 ZBEE_ZCL_FCF_DIRECTION, NULL, HFILL }},
2183 { &hf_zbee_zcl_fcf_disable_default_resp,
2184 { "Disable Default Response", "zbee_zcl.ddr", FT_BOOLEAN, 8, NULL,
2185 ZBEE_ZCL_FCF_DISABLE_DEFAULT_RESP, NULL, HFILL }},
2187 { &hf_zbee_zcl_mfr_code,
2188 { "Manufacturer Code", "zbee_zcl.cmd.mc", FT_UINT16, BASE_HEX|BASE_EXT_STRING,
2189 &zbee_mfr_code_names_ext, 0x0, "Assigned manufacturer code.", HFILL }},
2191 { &hf_zbee_zcl_tran_seqno,
2192 { "Sequence Number", "zbee_zcl.cmd.tsn", FT_UINT8, BASE_DEC, NULL, 0x0,
2193 NULL, HFILL }},
2195 { &hf_zbee_zcl_cmd_id,
2196 { "Command", "zbee_zcl.cmd.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &zbee_zcl_cmd_names_ext,
2197 0x0, NULL, HFILL }},
2199 { &hf_zbee_zcl_cs_cmd_id,
2200 { "Command", "zbee_zcl.cs.cmd.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_cs_cmd_names) /*"Unknown"*/,
2201 0x0, NULL, HFILL }},
2203 { &hf_zbee_zcl_attr_id,
2204 { "Attribute", "zbee_zcl.attr.id", FT_UINT16, BASE_HEX, NULL, 0x0,
2205 NULL, HFILL }},
2207 { &hf_zbee_zcl_attr_data_type,
2208 { "Data Type", "zbee_zcl.attr.data.type", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
2209 &zbee_zcl_data_type_names_ext, 0x0, NULL, HFILL }},
2211 { &hf_zbee_zcl_attr_boolean,
2212 { "Boolean", "zbee_zcl.attr.boolean", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0xff,
2213 NULL, HFILL }},
2215 { &hf_zbee_zcl_attr_uint8,
2216 { "Uint8", "zbee_zcl.attr.uint8", FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
2217 NULL, HFILL }},
2219 { &hf_zbee_zcl_attr_uint16,
2220 { "Uint16", "zbee_zcl.attr.uint16", FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2221 NULL, HFILL }},
2223 { &hf_zbee_zcl_attr_uint24,
2224 { "Uint24", "zbee_zcl.attr.uint24", FT_UINT24, BASE_DEC_HEX, NULL, 0x0,
2225 NULL, HFILL }},
2227 { &hf_zbee_zcl_attr_uint32,
2228 { "Uint32", "zbee_zcl.attr.uint32", FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2229 NULL, HFILL }},
2231 { &hf_zbee_zcl_attr_uint64,
2232 { "Uint64", "zbee_zcl.attr.uint64", FT_UINT64, BASE_DEC_HEX, NULL, 0x0,
2233 NULL, HFILL }},
2235 { &hf_zbee_zcl_attr_int8,
2236 { "Int8", "zbee_zcl.attr.int8", FT_INT8, BASE_DEC, NULL, 0x0,
2237 NULL, HFILL }},
2239 { &hf_zbee_zcl_attr_int16,
2240 { "Int16", "zbee_zcl.attr.int16", FT_INT16, BASE_DEC, NULL, 0x0,
2241 NULL, HFILL }},
2243 { &hf_zbee_zcl_attr_int24,
2244 { "Int24", "zbee_zcl.attr.int24", FT_INT24, BASE_DEC, NULL, 0x0,
2245 NULL, HFILL }},
2247 { &hf_zbee_zcl_attr_int32,
2248 { "Int32", "zbee_zcl.attr.int32", FT_INT32, BASE_DEC, NULL, 0x0,
2249 NULL, HFILL }},
2251 { &hf_zbee_zcl_attr_int64,
2252 { "Int64", "zbee_zcl.attr.int64", FT_INT64, BASE_DEC, NULL, 0x0,
2253 NULL, HFILL }},
2255 { &hf_zbee_zcl_attr_float,
2256 { "Float", "zbee_zcl.attr.float", FT_FLOAT, BASE_NONE, NULL, 0x0,
2257 NULL, HFILL }},
2259 { &hf_zbee_zcl_attr_double,
2260 { "Double Float", "zbee_zcl.attr.float", FT_DOUBLE, BASE_NONE, NULL, 0x0,
2261 NULL, HFILL }},
2263 { &hf_zbee_zcl_attr_bytes,
2264 { "Bytes", "zbee_zcl.attr.bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
2265 NULL, HFILL }},
2267 { &hf_zbee_zcl_attr_minint,
2268 { "Minimum Interval", "zbee_zcl.attr.minint", FT_UINT16, BASE_DEC, NULL, 0x0,
2269 NULL, HFILL }},
2271 { &hf_zbee_zcl_attr_maxint,
2272 { "Maximum Interval", "zbee_zcl.attr.maxint", FT_UINT16, BASE_DEC, NULL, 0x0,
2273 NULL, HFILL }},
2275 { &hf_zbee_zcl_attr_timeout,
2276 { "Timeout", "zbee_zcl.attr.timeout", FT_UINT16, BASE_DEC, NULL, 0x0,
2277 NULL, HFILL }},
2279 { &hf_zbee_zcl_attr_hours,
2280 { "Hours", "zbee_zcl.attr.hours", FT_UINT8, BASE_DEC, NULL, 0x0,
2281 NULL, HFILL }},
2283 { &hf_zbee_zcl_attr_mins,
2284 { "Minutes", "zbee_zcl.attr.mins", FT_UINT8, BASE_DEC, NULL, 0x0,
2285 NULL, HFILL }},
2287 { &hf_zbee_zcl_attr_secs,
2288 { "Seconds", "zbee_zcl.attr.secs", FT_UINT8, BASE_DEC, NULL, 0x0,
2289 NULL, HFILL }},
2291 { &hf_zbee_zcl_attr_csecs,
2292 { "Centiseconds", "zbee_zcl.attr.csecs", FT_UINT8, BASE_DEC, NULL, 0x0,
2293 NULL, HFILL }},
2295 { &hf_zbee_zcl_attr_yy,
2296 { "Year", "zbee_zcl.attr.yy", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2298 { &hf_zbee_zcl_attr_mm,
2299 { "Month", "zbee_zcl.attr.mm", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2301 { &hf_zbee_zcl_attr_md,
2302 { "Day of Month", "zbee_zcl.attr.md", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2304 { &hf_zbee_zcl_attr_wd,
2305 { "Day of Week", "zbee_zcl.attr.wd", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2307 { &hf_zbee_zcl_attr_utc,
2308 { "UTC", "zbee_zcl.attr.utc", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL }},
2310 { &hf_zbee_zcl_attr_status,
2311 { "Status", "zbee_zcl.attr.status", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &zbee_zcl_status_names_ext,
2312 0x0, NULL, HFILL }},
2314 { &hf_zbee_zcl_attr_dir,
2315 { "Direction", "zbee_zcl.attr.dir", FT_UINT8, BASE_HEX, VALS(zbee_zcl_dir_names),
2316 0x0, NULL, HFILL }},
2318 { &hf_zbee_zcl_attr_dis,
2319 { "Discovery", "zbee_zcl.attr.dis", FT_UINT8, BASE_HEX, VALS(zbee_zcl_dis_names),
2320 0x0, NULL, HFILL }},
2322 { &hf_zbee_zcl_attr_cid,
2323 { "Cluster", "zbee_zcl.attr.cid", FT_UINT16, BASE_HEX, NULL, 0x0,
2324 NULL, HFILL }},
2326 { &hf_zbee_zcl_attr_start,
2327 { "Start Attribute", "zbee_zcl.attr.start", FT_UINT16, BASE_HEX, NULL, 0x0,
2328 NULL, HFILL }},
2330 { &hf_zbee_zcl_attr_maxnum,
2331 { "Maxiumum Number", "zbee_zcl.attr.maxnum", FT_UINT8, BASE_DEC, NULL, 0x0,
2332 NULL, HFILL }},
2334 { &hf_zbee_zcl_attr_str_len,
2335 { "Length", "zbee_zcl.attr.str.len", FT_UINT8, BASE_DEC, NULL, 0x0,
2336 NULL, HFILL }},
2338 { &hf_zbee_zcl_attr_str,
2339 { "String", "zbee_zcl.attr.str", FT_STRING, BASE_NONE, NULL, 0x0,
2340 NULL, HFILL }},
2342 { &hf_zbee_zcl_attr_ostr,
2343 { "Octet String", "zbee_zcl.attr.ostr", FT_STRING, BASE_NONE, NULL, 0x0,
2344 NULL, HFILL }},
2346 { &hf_zbee_zcl_attr_array_elements_type,
2347 { "Elements Type", "zbee_zcl.attr.array.elements_type", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
2348 &zbee_zcl_data_type_names_ext, 0x0,
2349 NULL, HFILL }},
2351 { &hf_zbee_zcl_attr_array_elements_num,
2352 { "Elements Number", "zbee_zcl.attr.array.elements_num", FT_UINT16, BASE_DEC, NULL, 0x0,
2353 NULL, HFILL }}
2356 /* ZCL subtrees */
2357 gint *ett[ZBEE_ZCL_NUM_TOTAL_ETT];
2359 ett[0] = &ett_zbee_zcl;
2360 ett[1] = &ett_zbee_zcl_fcf;
2362 j = ZBEE_ZCL_NUM_INDIVIDUAL_ETT;
2364 /* initialize attribute subtree types */
2365 for ( i = 0; i < ZBEE_ZCL_NUM_ATTR_ETT; i++, j++) {
2366 ett_zbee_zcl_attr[i] = -1;
2367 ett[j] = &ett_zbee_zcl_attr[i];
2370 for ( i = 0; i < ZBEE_ZCL_NUM_ARRAY_ELEM_ETT; i++, j++ ) {
2371 ett_zbee_zcl_array_elements[i] = -1;
2372 ett[j] = &ett_zbee_zcl_array_elements[i];
2375 /* Register ZigBee ZCL protocol with Wireshark. */
2376 proto_zbee_zcl = proto_register_protocol("ZigBee Cluster Library", "ZigBee ZCL", "zbee_zcl");
2377 proto_register_field_array(proto_zbee_zcl, hf, array_length(hf));
2378 proto_register_subtree_array(ett, array_length(ett));
2380 /* Register the ZCL dissector and subdissector list. */
2381 zbee_zcl_dissector_table = register_dissector_table("zbee.zcl.cluster", "ZigBee ZCL Cluster ID", FT_UINT16, BASE_HEX);
2382 new_register_dissector(ZBEE_PROTOABBREV_ZCL, dissect_zbee_zcl, proto_zbee_zcl);
2384 } /* proto_register_zbee_zcl */
2386 /*FUNCTION:------------------------------------------------------
2387 * NAME
2388 * proto_reg_handoff_zbee_zcl
2389 * DESCRIPTION
2390 * Finds the dissectors used in this module.
2391 * PARAMETERS
2392 * none
2393 * RETURNS
2394 * void
2395 *---------------------------------------------------------------
2397 void proto_reg_handoff_zbee_zcl(void)
2399 dissector_handle_t zbee_zcl_handle;
2401 /* Find the dissectors we need. */
2402 data_handle = find_dissector("data");
2404 /* Register our dissector for the appropriate profiles. */
2405 zbee_zcl_handle = find_dissector(ZBEE_PROTOABBREV_ZCL);
2406 dissector_add_uint("zbee.profile", ZBEE_PROFILE_IPM, zbee_zcl_handle);
2407 dissector_add_uint("zbee.profile", ZBEE_PROFILE_T1, zbee_zcl_handle);
2408 dissector_add_uint("zbee.profile", ZBEE_PROFILE_HA, zbee_zcl_handle);
2409 dissector_add_uint("zbee.profile", ZBEE_PROFILE_CBA, zbee_zcl_handle);
2410 dissector_add_uint("zbee.profile", ZBEE_PROFILE_WSN, zbee_zcl_handle);
2411 dissector_add_uint("zbee.profile", ZBEE_PROFILE_TA, zbee_zcl_handle);
2412 dissector_add_uint("zbee.profile", ZBEE_PROFILE_HC, zbee_zcl_handle);
2413 dissector_add_uint("zbee.profile", ZBEE_PROFILE_SE, zbee_zcl_handle);
2415 dissector_add_uint("zbee.profile", ZBEE_PROFILE_C4_CL, zbee_zcl_handle);
2416 } /* proto_reg_handoff_zbee_zcl */
2419 /*FUNCTION:------------------------------------------------------
2420 * NAME
2421 * zbee_zcl_init_cluster
2422 * DESCRIPTION
2423 * Register the specific cluster.
2424 * PARAMETERS
2425 * proto - dissector proto
2426 * ett - ett proto (not used at the moment)
2427 * cluster_id - cluster id
2428 * fn_attr_id - specific cluster attribute id decode function
2429 * fn_attr_data - specific cluster attribute data decode function
2430 * RETURNS
2431 * void
2432 *---------------------------------------------------------------
2434 void
2435 zbee_zcl_init_cluster(int proto, gint ett, guint16 cluster_id, zbee_zcl_fn_attr_id fn_attr_id, zbee_zcl_fn_attr_data fn_attr_data)
2437 zbee_zcl_cluster_desc *cluster_desc;
2438 cluster_desc = g_new(zbee_zcl_cluster_desc, 1);
2440 cluster_desc->proto = find_protocol_by_id(proto);
2441 cluster_desc->name = proto_get_protocol_short_name(cluster_desc->proto);
2442 cluster_desc->cluster_id = cluster_id;
2443 cluster_desc->fn_attr_id = fn_attr_id;
2444 cluster_desc->fn_attr_data = fn_attr_data;
2445 acluster_desc = g_list_append(acluster_desc, cluster_desc);
2447 cluster_desc->proto_id = proto;
2448 cluster_desc->ett = ett;
2450 return;
2453 /*FUNCTION:------------------------------------------------------
2454 * NAME
2455 * zbee_zcl_get_cluster_desc
2456 * DESCRIPTION
2457 * Retrieves the registered specific cluster descriptor.
2458 * PARAMETERS
2459 * cluster_id - cluster id
2460 * RETURNS
2461 * zbee_zcl_cluster_desc - cluster descriptor pointer
2462 *---------------------------------------------------------------
2464 zbee_zcl_cluster_desc
2465 *zbee_zcl_get_cluster_desc(guint16 cluster_id)
2467 GList *gl;
2468 gl = acluster_desc;
2470 while (gl) {
2471 zbee_zcl_cluster_desc *cluster_desc = (zbee_zcl_cluster_desc *)gl->data;
2472 if(cluster_desc->cluster_id == cluster_id) {
2473 return cluster_desc;
2475 gl = gl->next;
2478 return NULL;