2 * Dissector routines for the ZigBee Cluster Library (ZCL)
3 * By Fred Fierling <fff@exegin.com>
4 * Copyright 2009 Exegin Technologies Limited
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.
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
,
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
,
53 static void dissect_zcl_read_report_config (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
55 static void dissect_zcl_read_report_config_resp (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
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
,
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
);
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 /********************/
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" },
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" },
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
[] = {
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
},
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"},
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" },
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" },
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
[] = {
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
[] = {
675 /* Attribute Discovery Names */
676 static const value_string zbee_zcl_dis_names
[] = {
683 /*FUNCTION:------------------------------------------------------
687 * ZigBee Cluster Library dissector for wireshark.
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.
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
;
707 zbee_nwk_packet
*nwk
= (zbee_nwk_packet
*)data
;
708 zbee_zcl_packet packet
;
709 zbee_zcl_cluster_desc
*desc
;
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 */
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
);
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 */
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
);
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
);
768 proto_tree_add_uint(zcl_tree
, hf_zbee_zcl_mfr_code
, tvb
, offset
, (int)2,
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"),
778 /* Add the transaction sequence number to the tree */
779 packet
.tran_seqno
= tvb_get_guint8(tvb
, offset
);
782 proto_tree_add_uint(zcl_tree
, hf_zbee_zcl_tran_seqno
, tvb
, 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
);
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
) {
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"),
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"),
808 proto_tree_add_uint(zcl_tree
, hf_zbee_zcl_cmd_id
, tvb
, offset
, (int)1,
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
);
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,
832 /* Don't decode cluster-specific commands */
833 zcl_dump_data(tvb
, offset
, pinfo
, zcl_tree
);
835 return tvb_length(tvb
);
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
);
845 case ZBEE_ZCL_CMD_READ_ATTR_RESP
:
846 dissect_zcl_read_attr_resp(tvb
, pinfo
, zcl_tree
, &offset
);
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
);
856 case ZBEE_ZCL_CMD_WRITE_ATTR_RESP
:
857 dissect_zcl_write_attr_resp(tvb
, pinfo
, zcl_tree
, &offset
);
860 case ZBEE_ZCL_CMD_CONFIG_REPORT
:
861 dissect_zcl_config_report(tvb
, pinfo
, zcl_tree
, &offset
);
864 case ZBEE_ZCL_CMD_CONFIG_REPORT_RESP
:
865 dissect_zcl_config_report_resp(tvb
, pinfo
, zcl_tree
, &offset
);
868 case ZBEE_ZCL_CMD_READ_REPORT_CONFIG
:
869 dissect_zcl_read_report_config(tvb
, pinfo
, zcl_tree
, &offset
);
872 case ZBEE_ZCL_CMD_READ_REPORT_CONFIG_RESP
:
873 dissect_zcl_read_report_config_resp(tvb
, pinfo
, zcl_tree
, &offset
);
876 case ZBEE_ZCL_CMD_DEFAULT_RESP
:
877 dissect_zcl_default_resp(tvb
, pinfo
, zcl_tree
, &offset
);
880 case ZBEE_ZCL_CMD_DISCOVER_ATTR
:
881 dissect_zcl_discover_attr(tvb
, pinfo
, zcl_tree
, &offset
);
884 case ZBEE_ZCL_CMD_DISCOVER_ATTR_RESP
:
885 dissect_zcl_discover_attr_resp(tvb
, pinfo
, zcl_tree
, &offset
);
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
:
893 zcl_dump_data(tvb
, offset
, pinfo
, zcl_tree
);
898 return tvb_length(tvb
);
899 } /* dissect_zbee_zcl */
901 /*FUNCTION:------------------------------------------------------
903 * dissect_zcl_read_attr
905 * Helper dissector for ZCL Read Attributes and
906 * Write Attributes No Response commands.
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
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
)
920 tvb_len
= tvb_length(tvb
);
921 while ( *offset
< tvb_len
) {
922 /* Dissect the attribute identifier */
923 dissect_zcl_attr_id(tvb
, tree
, offset
);
927 } /* dissect_zcl_read_attr */
929 /*FUNCTION:------------------------------------------------------
931 * dissect_zcl_read_attr_resp
933 * Helper dissector for ZCL Read Attributes Response command.
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
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
;
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
]);
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
);
974 } /* dissect_zcl_read_attr_resp */
976 /*FUNCTION:------------------------------------------------------
978 * dissect_zcl_write_attr
980 * Helper dissector for ZCL Report Attribute commands.
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
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
;
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
]);
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
);
1016 } /* dissect_zcl_write_attr */
1018 /*FUNCTION:------------------------------------------------------
1020 * dissect_zcl_write_attr_resp
1022 * Helper dissector for ZCL Write Attribute Response command.
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
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
;
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
]);
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
);
1058 } /* dissect_zcl_write_attr_resp */
1060 /*FUNCTION:------------------------------------------------------
1062 * dissect_zcl_read_report_config_resp
1064 * Helper dissector for ZCL Report Attribute commands.
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
,
1075 proto_item
*ti
= NULL
;
1076 proto_tree
*sub_tree
= NULL
;
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
]);
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
);
1122 /* Dissect timeout period */
1123 dissect_zcl_attr_uint16(tvb
, sub_tree
, offset
, &hf_zbee_zcl_attr_timeout
);
1129 } /* dissect_zcl_read_report_config_resp */
1131 /*FUNCTION:------------------------------------------------------
1133 * dissect_zcl_config_report
1135 * Helper dissector for ZCL Report Attribute commands.
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
;
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
]);
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
);
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
);
1193 } /* dissect_zcl_config_report */
1195 /*FUNCTION:------------------------------------------------------
1197 * dissect_zcl_config_report_resp
1199 * Helper dissector for ZCL Report Attribute commands.
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
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
,
1212 proto_item
*ti
= NULL
;
1213 proto_tree
*sub_tree
= NULL
;
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
]);
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
);
1238 } /* dissect_zcl_config_report_resp */
1240 /*FUNCTION:------------------------------------------------------
1242 * dissect_zcl_read_report_config
1244 * Helper dissector for ZCL Read Report Configuration command.
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
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
,
1257 proto_item
*ti
= NULL
;
1258 proto_tree
*sub_tree
= NULL
;
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
]);
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
);
1279 } /* dissect_zcl_read_report_config */
1281 /*FUNCTION:------------------------------------------------------
1283 * dissect_zcl_default_resp
1285 * Helper dissector for ZCL Default Response command.
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
1293 *---------------------------------------------------------------
1295 static void dissect_zcl_default_resp(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, guint
*offset
)
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
);
1305 /* Dissect the status */
1306 dissect_zcl_attr_uint8(tvb
, tree
, offset
, &hf_zbee_zcl_attr_status
);
1309 } /* dissect_zcl_default_resp */
1311 /*FUNCTION:------------------------------------------------------
1313 * dissect_zcl_discover_attr
1315 * Helper dissector for ZCL Discover Attributes command.
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
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
);
1334 } /* dissect_zcl_discover_attr */
1337 /*FUNCTION:------------------------------------------------------
1339 * dissect_zcl_discover_attr_resp
1341 * Helper dissector for ZCL Discover Attributes command.
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
1349 *---------------------------------------------------------------
1351 static void dissect_zcl_discover_attr_resp(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
,
1354 proto_item
*ti
= NULL
;
1355 proto_tree
*sub_tree
= NULL
;
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
]);
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
);
1378 } /* dissect_zcl_discover_attr_resp */
1381 /*FUNCTION:------------------------------------------------------
1383 * dissect_zcl_attr_id
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.
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.
1394 *---------------------------------------------------------------
1396 static void dissect_zcl_attr_id(tvbuff_t
*tvb
, proto_tree
*tree
, guint
*offset
)
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
);
1407 /* Add the identifier */
1408 proto_tree_add_uint(tree
,
1409 hf_zbee_zcl_attr_id
,
1419 } /* dissect_zcl_attr_id */
1421 /*FUNCTION:------------------------------------------------------
1423 * dissect_zcl_attr_data_type_val
1425 * Helper dissector for ZCL Attribute commands.
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.
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
));
1444 dissect_zcl_attr_data(tvb
, tree
, offset
,
1445 dissect_zcl_attr_uint8(tvb
, tree
, offset
, &hf_zbee_zcl_attr_data_type
) );
1449 } /* dissect_zcl_attr_data_type_val */
1452 /*FUNCTION:------------------------------------------------------
1454 * dissect_zcl_attr_data_general
1456 * Helper dissector for ZCL Attribute commands.
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
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
);
1476 dissect_zcl_attr_data(tvb
, tree
, offset
, data_type
);
1480 } /*dissect_zcl_attr_data_general*/
1482 /*FUNCTION:------------------------------------------------------
1484 * dissect_zcl_attr_data
1486 * Dissects the various types of ZCL attribute data.
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
1495 *---------------------------------------------------------------
1497 void dissect_zcl_attr_data(tvbuff_t
*tvb
, proto_tree
*tree
, guint
*offset
, guint data_type
)
1501 guint8
*attr_string
;
1502 guint8 attr_uint8
[4];
1503 guint8 elements_type
;
1504 guint16 elements_num
;
1506 gdouble attr_double
;
1509 /* Dissect attribute data type and data */
1510 switch ( data_type
) {
1511 case ZBEE_ZCL_NO_DATA
:
1514 case ZBEE_ZCL_8_BIT_DATA
:
1515 case ZBEE_ZCL_8_BIT_BITMAP
:
1516 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 1);
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,
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
),
1544 *offset
+= (int)sizeof(gint8
);
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
);
1559 case ZBEE_ZCL_16_BIT_DATA
:
1560 case ZBEE_ZCL_16_BIT_BITMAP
:
1561 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 2);
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,
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
),
1590 *offset
+= (int)sizeof(gint16
);
1593 case ZBEE_ZCL_24_BIT_DATA
:
1594 case ZBEE_ZCL_24_BIT_BITMAP
:
1595 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 3);
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,
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,
1628 case ZBEE_ZCL_32_BIT_DATA
:
1629 case ZBEE_ZCL_32_BIT_BITMAP
:
1630 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 4);
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
),
1644 *offset
+= (int)sizeof(guint
);
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
),
1658 *offset
+= (int)sizeof(gint
);
1661 case ZBEE_ZCL_40_BIT_DATA
:
1662 case ZBEE_ZCL_40_BIT_BITMAP
:
1663 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 5);
1666 case ZBEE_ZCL_40_BIT_UINT
:
1667 dissect_zcl_big_int(tvb
, tree
, offset
, 5, FALSE
);
1670 case ZBEE_ZCL_40_BIT_INT
:
1671 dissect_zcl_big_int(tvb
, tree
, offset
, 5, TRUE
);
1674 case ZBEE_ZCL_48_BIT_DATA
:
1675 case ZBEE_ZCL_48_BIT_BITMAP
:
1676 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 6);
1679 case ZBEE_ZCL_48_BIT_UINT
:
1680 dissect_zcl_big_int(tvb
, tree
, offset
, 6, FALSE
);
1683 case ZBEE_ZCL_48_BIT_INT
:
1684 dissect_zcl_big_int(tvb
, tree
, offset
, 6, TRUE
);
1687 case ZBEE_ZCL_56_BIT_DATA
:
1688 case ZBEE_ZCL_56_BIT_BITMAP
:
1689 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 7);
1692 case ZBEE_ZCL_56_BIT_UINT
:
1693 dissect_zcl_big_int(tvb
, tree
, offset
, 7, FALSE
);
1696 case ZBEE_ZCL_56_BIT_INT
:
1697 dissect_zcl_big_int(tvb
, tree
, offset
, 7, TRUE
);
1700 case ZBEE_ZCL_64_BIT_DATA
:
1701 case ZBEE_ZCL_64_BIT_BITMAP
:
1702 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 8);
1705 case ZBEE_ZCL_64_BIT_UINT
:
1706 dissect_zcl_big_int(tvb
, tree
, offset
, 8, FALSE
);
1709 case ZBEE_ZCL_64_BIT_INT
:
1710 dissect_zcl_big_int(tvb
, tree
, offset
, 8, TRUE
);
1713 case ZBEE_ZCL_SEMI_FLOAT
:
1715 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 2);
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
);
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
);
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,
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
,
1755 *offset
+= attr_uint
;
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,
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
;
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
);
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
;
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
);
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
;
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
);
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
);
1819 /* BYTE ... - Elements */
1820 dissect_zcl_array_type(tvb
, tree
, offset
, elements_type
, elements_num
);
1827 case ZBEE_ZCL_STRUCT
:
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]);
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") );
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
);
1871 case ZBEE_ZCL_CLUSTER_ID
:
1872 dissect_zcl_attr_uint16(tvb
, tree
, offset
, &hf_zbee_zcl_attr_cid
);
1875 case ZBEE_ZCL_ATTR_ID
:
1876 dissect_zcl_attr_id(tvb
, tree
, offset
);
1879 case ZBEE_ZCL_BACNET_OID
:
1880 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 4);
1883 case ZBEE_ZCL_IEEE_ADDR
:
1884 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 8);
1887 case ZBEE_ZCL_SECURITY_KEY
:
1888 dissect_zcl_attr_bytes(tvb
, tree
, offset
, 16);
1896 } /* dissect_zcl_attr_data */
1898 /*FUNCTION:------------------------------------------------------
1900 * dissect_zcl_big_int
1902 * Dissects int or uint of up to 64 bits.
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
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
);
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
,
1937 } /* dissect_zcl_big_int */
1939 /*FUNCTION:------------------------------------------------------
1941 * dissect_zcl_attr_uint8
1943 * Helper dissector for ZCL Attribute commands.
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
1950 * guint - dissected data
1951 *---------------------------------------------------------------
1953 static guint
dissect_zcl_attr_uint8(tvbuff_t
*tvb
, proto_tree
*tree
, guint
*offset
, int *hf_zbee_zcl
)
1957 attr_uint
= tvb_get_guint8(tvb
, *offset
);
1958 proto_tree_add_uint(tree
, *hf_zbee_zcl
, tvb
, *offset
, (int)1, attr_uint
);
1962 } /* dissect_zcl_attr_uint8 */
1964 /*FUNCTION:------------------------------------------------------
1966 * dissect_zcl_attr_uint16
1968 * Helper dissector for ZCL Attribute commands.
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
1975 * guint - field value
1976 *---------------------------------------------------------------
1978 static guint
dissect_zcl_attr_uint16(tvbuff_t
*tvb
, proto_tree
*tree
, guint
*offset
, int *hf_zbee_zcl
)
1982 attr_uint
= tvb_get_letohs(tvb
, *offset
);
1983 proto_tree_add_uint(tree
, *hf_zbee_zcl
, tvb
, *offset
, (int)2, attr_uint
);
1987 } /* dissect_zcl_attr_uint16 */
1989 /*FUNCTION:------------------------------------------------------
1991 * dissect_zcl_attr_bytes
1993 * Helper dissector for ZCL Attribute commands.
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
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
);
2009 } /* dissect_dcl_attr_bytes */
2011 /*FUNCTION:------------------------------------------------------
2013 * dissect_zcl_array_type
2015 * Helper dissector for ZCL attribute array type.
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
2024 *---------------------------------------------------------------
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
;
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
);
2046 } /* dissect_zcl_array_type */
2048 /*FUNCTION:------------------------------------------------------
2052 * Helper functions dumps any remaining data into the data dissector.
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.
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
;
2069 remainder
= tvb_new_subset(tvb
, offset
, length
, length
);
2070 call_dissector(data_handle
, remainder
, pinfo
, root
);
2074 } /* zcl_dump_data */
2076 /*FUNCTION:------------------------------------------------------
2080 * Gets little endian int or uint of up to 8 bytes from tvb buffer.
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
2087 * guint64 - value retrieved from tvb buffer
2088 *---------------------------------------------------------------
2090 static guint64
tvb_get_letohi(tvbuff_t
*tvb
, guint offset
, guint length
, gboolean signed_flag
)
2095 DISSECTOR_ASSERT((length
>=1) && (length
<=8));
2099 /* build big int of length bytes */
2100 while ( length
-- ) {
2101 result
+= (guint64
)tvb_get_guint8(tvb
, offset
) << shift
;
2106 if ( signed_flag
&& (result
>> (shift
- 1)) ) {
2107 /* sign extend remaining bytes */
2108 while ( shift
< ((int)sizeof(guint64
) * 8) ) {
2109 result
+= (guint64
)0xff << shift
;
2115 } /* tvb_get_letohi */
2118 /*FUNCTION:------------------------------------------------------
2120 * decode_zcl_time_in_seconds
2122 * this function decodes second time type variable
2126 *---------------------------------------------------------------
2128 void decode_zcl_time_in_seconds(gchar
*s
, guint16 value
)
2130 g_snprintf(s
, ITEM_LABEL_LENGTH
, "%d seconds", value
);
2132 } /* decode_zcl_time_in_seconds*/
2134 /*FUNCTION:------------------------------------------------------
2136 * decode_zcl_time_in_minutes
2138 * this function decodes minute time type variable
2142 *---------------------------------------------------------------
2144 void decode_zcl_time_in_minutes(gchar
*s
, guint16 value
)
2146 g_snprintf(s
, ITEM_LABEL_LENGTH
, "%d minutes", value
);
2148 } /*decode_zcl_time_in_minutes*/
2150 /*FUNCTION:------------------------------------------------------
2152 * proto_register_zbee_zcl
2154 * ZigBee ZCL protocol registration routine.
2159 *---------------------------------------------------------------
2161 void proto_register_zbee_zcl(void)
2165 static const true_false_string tfs_client_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,
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,
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,
2215 { &hf_zbee_zcl_attr_uint8
,
2216 { "Uint8", "zbee_zcl.attr.uint8", FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x0,
2219 { &hf_zbee_zcl_attr_uint16
,
2220 { "Uint16", "zbee_zcl.attr.uint16", FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2223 { &hf_zbee_zcl_attr_uint24
,
2224 { "Uint24", "zbee_zcl.attr.uint24", FT_UINT24
, BASE_DEC_HEX
, NULL
, 0x0,
2227 { &hf_zbee_zcl_attr_uint32
,
2228 { "Uint32", "zbee_zcl.attr.uint32", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
2231 { &hf_zbee_zcl_attr_uint64
,
2232 { "Uint64", "zbee_zcl.attr.uint64", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0,
2235 { &hf_zbee_zcl_attr_int8
,
2236 { "Int8", "zbee_zcl.attr.int8", FT_INT8
, BASE_DEC
, NULL
, 0x0,
2239 { &hf_zbee_zcl_attr_int16
,
2240 { "Int16", "zbee_zcl.attr.int16", FT_INT16
, BASE_DEC
, NULL
, 0x0,
2243 { &hf_zbee_zcl_attr_int24
,
2244 { "Int24", "zbee_zcl.attr.int24", FT_INT24
, BASE_DEC
, NULL
, 0x0,
2247 { &hf_zbee_zcl_attr_int32
,
2248 { "Int32", "zbee_zcl.attr.int32", FT_INT32
, BASE_DEC
, NULL
, 0x0,
2251 { &hf_zbee_zcl_attr_int64
,
2252 { "Int64", "zbee_zcl.attr.int64", FT_INT64
, BASE_DEC
, NULL
, 0x0,
2255 { &hf_zbee_zcl_attr_float
,
2256 { "Float", "zbee_zcl.attr.float", FT_FLOAT
, BASE_NONE
, NULL
, 0x0,
2259 { &hf_zbee_zcl_attr_double
,
2260 { "Double Float", "zbee_zcl.attr.float", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0,
2263 { &hf_zbee_zcl_attr_bytes
,
2264 { "Bytes", "zbee_zcl.attr.bytes", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2267 { &hf_zbee_zcl_attr_minint
,
2268 { "Minimum Interval", "zbee_zcl.attr.minint", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2271 { &hf_zbee_zcl_attr_maxint
,
2272 { "Maximum Interval", "zbee_zcl.attr.maxint", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2275 { &hf_zbee_zcl_attr_timeout
,
2276 { "Timeout", "zbee_zcl.attr.timeout", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2279 { &hf_zbee_zcl_attr_hours
,
2280 { "Hours", "zbee_zcl.attr.hours", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2283 { &hf_zbee_zcl_attr_mins
,
2284 { "Minutes", "zbee_zcl.attr.mins", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2287 { &hf_zbee_zcl_attr_secs
,
2288 { "Seconds", "zbee_zcl.attr.secs", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2291 { &hf_zbee_zcl_attr_csecs
,
2292 { "Centiseconds", "zbee_zcl.attr.csecs", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
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,
2326 { &hf_zbee_zcl_attr_start
,
2327 { "Start Attribute", "zbee_zcl.attr.start", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2330 { &hf_zbee_zcl_attr_maxnum
,
2331 { "Maxiumum Number", "zbee_zcl.attr.maxnum", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2334 { &hf_zbee_zcl_attr_str_len
,
2335 { "Length", "zbee_zcl.attr.str.len", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2338 { &hf_zbee_zcl_attr_str
,
2339 { "String", "zbee_zcl.attr.str", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2342 { &hf_zbee_zcl_attr_ostr
,
2343 { "Octet String", "zbee_zcl.attr.ostr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
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,
2351 { &hf_zbee_zcl_attr_array_elements_num
,
2352 { "Elements Number", "zbee_zcl.attr.array.elements_num", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
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:------------------------------------------------------
2388 * proto_reg_handoff_zbee_zcl
2390 * Finds the dissectors used in this module.
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:------------------------------------------------------
2421 * zbee_zcl_init_cluster
2423 * Register the specific cluster.
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
2432 *---------------------------------------------------------------
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
;
2453 /*FUNCTION:------------------------------------------------------
2455 * zbee_zcl_get_cluster_desc
2457 * Retrieves the registered specific cluster descriptor.
2459 * cluster_id - cluster id
2461 * zbee_zcl_cluster_desc - cluster descriptor pointer
2462 *---------------------------------------------------------------
2464 zbee_zcl_cluster_desc
2465 *zbee_zcl_get_cluster_desc(guint16 cluster_id
)
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
;