epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-z21.c
blobd8e3f71ee755d90392656d6de3448d49881c73bf
1 /* packet-z21.c
2 * Routines for Z21 LAN protocol dissection
3 * Copyright 2023, Markku Leiniƶ <markku.leinio@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * Z21 LAN protocol specification can be found at:
14 * https://www.z21.eu/en/downloads/manuals
17 #include "config.h"
18 #define WS_LOG_DOMAIN "Z21"
20 #include <epan/packet.h>
21 #include <epan/expert.h>
22 #include <epan/prefs.h>
23 #include <epan/tfs.h>
24 #include <wsutil/array.h>
25 #include "packet-udp.h"
27 void proto_register_z21(void);
28 void proto_reg_handoff_z21(void);
30 /* Initialize the protocol and registered fields */
31 static int proto_z21;
32 static int hf_z21_datalen;
33 static int hf_z21_command;
34 static int hf_z21_x_bus;
35 static int hf_z21_serial_number;
36 static int hf_z21_checksum;
37 static int hf_z21_main_current;
38 static int hf_z21_prog_current;
39 static int hf_z21_filtered_main_current;
40 static int hf_z21_temperature;
41 static int hf_z21_supply_voltage;
42 static int hf_z21_track_voltage;
43 static int hf_z21_broadcast_flags;
44 static int hf_z21_central_state;
45 static int hf_z21_central_state_ex;
46 static int hf_z21_systemstate_reserved;
47 static int hf_z21_capabilities;
48 static int hf_z21_status;
49 static int hf_z21_loco_mode;
50 static int hf_z21_loco_address;
51 static int hf_z21_loco_direction_and_speed;
52 static int hf_z21_loco_direction;
53 static int hf_z21_loco_speed;
54 static int hf_z21_loco_info_mm;
55 static int hf_z21_loco_info_busy;
56 static int hf_z21_loco_info_speed_steps;
57 static int hf_z21_loco_info_direction;
58 static int hf_z21_loco_info_speed;
59 static int hf_z21_loco_info_double_traction;
60 static int hf_z21_loco_info_smartsearch;
61 static int hf_z21_loco_info_f0;
62 static int hf_z21_loco_info_f1;
63 static int hf_z21_loco_info_f2;
64 static int hf_z21_loco_info_f3;
65 static int hf_z21_loco_info_f4;
66 static int hf_z21_loco_info_f5;
67 static int hf_z21_loco_info_f6;
68 static int hf_z21_loco_info_f7;
69 static int hf_z21_loco_info_f8;
70 static int hf_z21_loco_info_f9;
71 static int hf_z21_loco_info_f10;
72 static int hf_z21_loco_info_f11;
73 static int hf_z21_loco_info_f12;
74 static int hf_z21_loco_info_f13;
75 static int hf_z21_loco_info_f14;
76 static int hf_z21_loco_info_f15;
77 static int hf_z21_loco_info_f16;
78 static int hf_z21_loco_info_f17;
79 static int hf_z21_loco_info_f18;
80 static int hf_z21_loco_info_f19;
81 static int hf_z21_loco_info_f20;
82 static int hf_z21_loco_info_f21;
83 static int hf_z21_loco_info_f22;
84 static int hf_z21_loco_info_f23;
85 static int hf_z21_loco_info_f24;
86 static int hf_z21_loco_info_f25;
87 static int hf_z21_loco_info_f26;
88 static int hf_z21_loco_info_f27;
89 static int hf_z21_loco_info_f28;
90 static int hf_z21_loco_info_f29;
91 static int hf_z21_loco_info_f30;
92 static int hf_z21_loco_info_f31;
93 static int hf_z21_loco_info_extensions;
94 static int hf_z21_loco_func_switch_type;
95 static int hf_z21_loco_func_index;
96 static int hf_z21_speed_steps;
97 static int hf_z21_hw_type;
98 static int hf_z21_firmware_version;
99 static int hf_z21_broadcast_flags_driving_switching;
100 static int hf_z21_broadcast_flags_rmbus;
101 static int hf_z21_broadcast_flags_railcom_subscribed;
102 static int hf_z21_broadcast_flags_system_status;
103 static int hf_z21_broadcast_flags_driving_switching_ex;
104 static int hf_z21_broadcast_flags_loconet;
105 static int hf_z21_broadcast_flags_loconet_driving;
106 static int hf_z21_broadcast_flags_loconet_switching;
107 static int hf_z21_broadcast_flags_loconet_detector;
108 static int hf_z21_broadcast_flags_railcom;
109 static int hf_z21_broadcast_flags_can_detector;
110 static int hf_z21_broadcast_flags_can_booster;
111 static int hf_z21_broadcast_flags_fast_clock;
112 static int hf_z21_state_emergency_stop;
113 static int hf_z21_state_track_voltage_off;
114 static int hf_z21_state_short_circuit;
115 static int hf_z21_state_programming_mode;
116 static int hf_z21_state_high_temperature;
117 static int hf_z21_state_power_lost;
118 static int hf_z21_state_short_circuit_external;
119 static int hf_z21_state_short_circuit_internal;
120 static int hf_z21_state_rcn_213;
121 static int hf_z21_capability_dcc;
122 static int hf_z21_capability_mm;
123 static int hf_z21_capability_reserved;
124 static int hf_z21_capability_railcom;
125 static int hf_z21_capability_loco_cmds;
126 static int hf_z21_capability_accessory_cmds;
127 static int hf_z21_capability_detector_cmds;
128 static int hf_z21_capability_needs_unlock_code;
129 static int hf_z21_function_address;
130 static int hf_z21_turnout_state;
131 static int hf_z21_turnout_activate_bit;
132 static int hf_z21_turnout_output_bit;
133 static int hf_z21_turnout_queue_bit;
134 static int hf_z21_accessory_address;
135 static int hf_z21_accessory_state;
136 static int hf_z21_accessory_status;
137 static int hf_z21_cv_address;
138 static int hf_z21_cv_value;
139 static int hf_z21_register;
140 static int hf_z21_register_value;
141 static int hf_z21_pom_operation;
142 static int hf_z21_cv_bit_position;
143 static int hf_z21_cv_bit_value;
144 static int hf_z21_rmbus_group;
145 static int hf_z21_rmbus_feedbacks;
146 static int hf_z21_rmbus_address;
147 static int hf_z21_railcom_receive_counter;
148 static int hf_z21_railcom_error_counter;
149 static int hf_z21_railcom_reserved1;
150 static int hf_z21_railcom_options;
151 static int hf_z21_railcom_speed;
152 static int hf_z21_railcom_qos;
153 static int hf_z21_railcom_reserved2;
154 static int hf_z21_railcom_type;
155 static int hf_z21_loconet_message;
156 static int hf_z21_loconet_result;
157 static int hf_z21_loconet_type;
158 static int hf_z21_loconet_report_address;
159 static int hf_z21_loconet_feedback_address;
160 static int hf_z21_loconet_info;
161 static int hf_z21_can_type;
162 static int hf_z21_can_network_id;
163 static int hf_z21_can_module_address;
164 static int hf_z21_can_port;
165 static int hf_z21_can_value1;
166 static int hf_z21_can_value2;
167 static int hf_z21_can_booster_name;
168 static int hf_z21_can_booster_output_port;
169 static int hf_z21_can_booster_state;
170 static int hf_z21_can_booster_state_bg_active;
171 static int hf_z21_can_booster_state_short_circuit;
172 static int hf_z21_can_booster_state_track_voltage_off;
173 static int hf_z21_can_booster_state_railcom_active;
174 static int hf_z21_can_booster_state_output_disabled;
175 static int hf_z21_can_booster_vcc;
176 static int hf_z21_can_booster_current;
177 static int hf_z21_can_booster_power;
178 static int hf_z21_zlink_message_type;
179 static int hf_z21_zlink_hwid;
180 static int hf_z21_zlink_fw_major;
181 static int hf_z21_zlink_fw_minor;
182 static int hf_z21_zlink_fw_build;
183 static int hf_z21_zlink_mac;
184 static int hf_z21_zlink_name;
185 static int hf_z21_zlink_reserved;
186 static int hf_z21_booster_name;
187 static int hf_z21_booster_port;
188 static int hf_z21_booster_port_state;
189 static int hf_z21_booster_state_data;
190 static int hf_z21_decoder_name;
191 static int hf_z21_decoder_state_data;
192 static int hf_z21_data;
194 static dissector_handle_t z21_handle;
196 /* Not IANA registered */
197 #define Z21_UDP_PORTS "21105,21106"
198 static range_t *udp_port_range;
200 /* Initialize the subtree pointers */
201 static int ett_z21;
203 /* Initialize expert fields */
204 static expert_field ei_z21_invalid_checksum;
206 #define Z21_MIN_LENGTH 4
208 /* All commands are here defined as big-endian even though the
209 * specifications are all little-endian. That's fine as we are
210 * not comparing the values numerically, just matching them
211 * in the packets. */
212 #define Z21_LAN_GET_SERIAL_NUMBER 0x1000
213 #define Z21_LAN_GET_HWINFO 0x1A00
214 #define Z21_LAN_LOGOFF 0x3000
215 /* Responses and requests based on the X-BUS protocol are transmitted
216 * with the Z21-LAN-Header 0x40 and the specific command is indicated
217 * with additional bytes inside the data field. */
218 #define Z21_LAN_X_BC 0x4000
219 #define Z21_LAN_SET_BROADCASTFLAGS 0x5000
220 #define Z21_LAN_GET_BROADCASTFLAGS 0x5100
221 #define Z21_LAN_GET_LOCOMODE 0x6000
222 #define Z21_LAN_SET_LOCOMODE 0x6100
223 #define Z21_LAN_RMBUS_DATACHANGED 0x8000
224 #define Z21_LAN_RMBUS_GETDATA 0x8100
225 #define Z21_LAN_RMBUS_PROGRAMMODULE 0x8200
226 #define Z21_LAN_SYSTEMSTATE_DATACHANGED 0x8400
227 #define Z21_LAN_SYSTEMSTATE_GETDATA 0x8500
228 #define Z21_LAN_RAILCOM_DATACHANGED 0x8800
229 #define Z21_LAN_RAILCOM_GETDATA 0x8900
230 #define Z21_LAN_LOCONET_Z21_RX 0xA000
231 #define Z21_LAN_LOCONET_Z21_TX 0xA100
232 #define Z21_LAN_LOCONET_FROM_LAN 0xA200
233 #define Z21_LAN_LOCONET_DISPATCH_ADDR 0xA300
234 #define Z21_LAN_LOCONET_DETECTOR 0xA400
235 #define Z21_LAN_BOOSTER_SET_POWER 0xB200
236 #define Z21_LAN_BOOSTER_GET_DESCRIPTION 0xB800
237 #define Z21_LAN_BOOSTER_SET_DESCRIPTION 0xB900
238 #define Z21_LAN_BOOSTER_SYSTEMSTATE_DATACHANGED 0xBA00
239 #define Z21_LAN_BOOSTER_SYSTEMSTATE_GETDATA 0xBB00
240 #define Z21_LAN_CAN_DETECTOR 0xC400
241 #define Z21_LAN_CAN_DEVICE_GET_DESCRIPTION 0xC800
242 #define Z21_LAN_CAN_DEVICE_SET_DESCRIPTION 0xC900
243 #define Z21_LAN_CAN_BOOSTER_SYSTEMSTATE_CHGD 0xCA00
244 #define Z21_LAN_CAN_BOOSTER_SET_TRACKPOWER 0xCB00
245 #define Z21_LAN_FAST_CLOCK_CONTROL 0xCC00
246 #define Z21_LAN_FAST_CLOCK_DATA 0xCD00
247 #define Z21_LAN_FAST_CLOCK_SETTINGS_GET 0xCE00
248 #define Z21_LAN_FAST_CLOCK_SETTINGS_SET 0xCF00
249 #define Z21_LAN_DECODER_GET_DESCRIPTION 0xD800
250 #define Z21_LAN_DECODER_SET_DESCRIPTION 0xD900
251 #define Z21_LAN_DECODER_SYSTEMSTATE_DATACHANGED 0xDA00
252 #define Z21_LAN_DECODER_SYSTEMSTATE_GETDATA 0xDB00
253 #define Z21_LAN_ZLINK_GET_HWINFO 0xE800
254 /* X-BUS commands are listed as 32-bit big-endian */
255 #define Z21_LAN_X_GET_VERSION_REQUEST 0x40002121
256 #define Z21_LAN_X_GET_VERSION_REPLY 0x40006321
257 #define Z21_LAN_X_GET_STATUS_REQUEST 0x40002124
258 #define Z21_LAN_X_SET_TRACK_POWER_OFF 0x40002180
259 #define Z21_LAN_X_SET_TRACK_POWER_ON 0x40002181
260 #define Z21_LAN_X_DCC_READ_REGISTER 0x40002211
261 #define Z21_LAN_X_CV_READ 0x40002311
262 #define Z21_LAN_X_DCC_WRITE_REGISTER 0x40002312
263 #define Z21_LAN_X_CV_WRITE 0x40002412
264 #define Z21_LAN_X_MM_WRITE_BYTE 0x400024FF
265 #define Z21_LAN_X_GET_TURNOUT_INFO 0x400043
266 #define Z21_LAN_X_TURNOUT_INFO 0x40FF43 /* To be set manually */
267 #define Z21_LAN_X_GET_EXT_ACCESSORY_INFO 0x400044
268 #define Z21_LAN_X_EXT_ACCESSORY_INFO 0x40FF44 /* To be set manually */
269 #define Z21_LAN_X_SET_TURNOUT 0x400053
270 #define Z21_LAN_X_SET_EXT_ACCESSORY 0x400054
271 #define Z21_LAN_X_BC_TRACK_POWER_OFF 0x40006100
272 #define Z21_LAN_X_BC_TRACK_POWER_ON 0x40006101
273 #define Z21_LAN_X_BC_PROGRAMMING_MODE 0x40006102
274 #define Z21_LAN_X_BC_TRACK_SHORT_CIRCUIT 0x40006108
275 #define Z21_LAN_X_CV_NACK_SC 0x40006112
276 #define Z21_LAN_X_CV_NACK 0x40006113
277 #define Z21_LAN_X_UNKNOWN_COMMAND 0x40006182
278 #define Z21_LAN_X_STATUS_CHANGED 0x40006222
279 #define Z21_LAN_X_CV_RESULT 0x40006414
280 #define Z21_LAN_X_SET_STOP 0x400080
281 #define Z21_LAN_X_BC_STOPPED 0x40008100
282 #define Z21_LAN_X_SET_LOCO_E_STOP 0x400092
283 #define Z21_LAN_X_PURGE_LOCO 0x4000E344
284 #define Z21_LAN_X_GET_LOCO_INFO 0x4000E3F0
285 #define Z21_LAN_X_SET_LOCO_DRIVE_DCC14 0x4000E410
286 #define Z21_LAN_X_SET_LOCO_DRIVE_DCC28 0x4000E412
287 #define Z21_LAN_X_SET_LOCO_DRIVE_DCC128 0x4000E413
288 #define Z21_LAN_X_SET_LOCO_FUNCTION 0x4000E4F8
289 #define Z21_LAN_X_SET_LOCO_BINARY_STATE 0x4000E55F
290 #define Z21_LAN_X_CV_POM_COMMANDS 0x4000E630
291 #define Z21_LAN_X_CV_POM_WRITE_BYTE 0x40FFE630 /* To be set manually */
292 #define Z21_LAN_X_CV_POM_WRITE_BIT 0x40FEE630 /* To be set manually */
293 #define Z21_LAN_X_CV_POM_READ_BYTE 0x40FDE630 /* To be set manually */
294 #define Z21_LAN_X_CV_POM_ACCESSORY_COMMANDS 0x4000E631
295 #define Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BYTE 0x40FFE631 /* To be set manually */
296 #define Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BIT 0x40FEE631 /* To be set manually */
297 #define Z21_LAN_X_CV_POM_ACCESSORY_READ_BYTE 0x40FDE631 /* To be set manually */
298 #define Z21_LAN_X_LOCO_INFO 0x4000EF
299 #define Z21_LAN_X_GET_FIRMWARE_VERSION_REQUEST 0x4000F10A
300 #define Z21_LAN_X_GET_FIRMWARE_VERSION_REPLY 0x4000F30A
302 /* This should be put in numerical order, not alphabetical order,
303 * if it is ever converted to a value_string_ext, to allow binary search.
305 static const value_string z21_command_vals[] = {
306 { Z21_LAN_CAN_BOOSTER_SET_TRACKPOWER, "LAN_CAN_BOOSTER_SET_TRACKPOWER" },
307 { Z21_LAN_CAN_BOOSTER_SYSTEMSTATE_CHGD, "LAN_CAN_BOOSTER_SYSTEMSTATE_CHGD" },
308 { Z21_LAN_CAN_DETECTOR, "LAN_CAN_DETECTOR" },
309 { Z21_LAN_CAN_DEVICE_GET_DESCRIPTION, "LAN_CAN_DEVICE_GET_DESCRIPTION" },
310 { Z21_LAN_CAN_DEVICE_SET_DESCRIPTION, "LAN_CAN_DEVICE_SET_DESCRIPTION" },
311 { Z21_LAN_BOOSTER_GET_DESCRIPTION, "LAN_BOOSTER_GET_DESCRIPTION" },
312 { Z21_LAN_BOOSTER_SET_DESCRIPTION, "LAN_BOOSTER_SET_DESCRIPTION" },
313 { Z21_LAN_BOOSTER_SET_POWER, "LAN_BOOSTER_SET_POWER" },
314 { Z21_LAN_BOOSTER_SYSTEMSTATE_DATACHANGED, "LAN_BOOSTER_SYSTEMSTATE_DATACHANGED" },
315 { Z21_LAN_BOOSTER_SYSTEMSTATE_GETDATA, "LAN_BOOSTER_SYSTEMSTATE_GETDATA" },
316 { Z21_LAN_DECODER_GET_DESCRIPTION, "LAN_DECODER_GET_DESCRIPTION" },
317 { Z21_LAN_DECODER_SET_DESCRIPTION, "LAN_DECODER_SET_DESCRIPTION" },
318 { Z21_LAN_DECODER_SYSTEMSTATE_DATACHANGED, "LAN_DECODER_SYSTEMSTATE_DATACHANGED" },
319 { Z21_LAN_DECODER_SYSTEMSTATE_GETDATA, "LAN_DECODER_SYSTEMSTATE_GETDATA" },
320 { Z21_LAN_FAST_CLOCK_CONTROL, "LAN_FAST_CLOCK_CONTROL" },
321 { Z21_LAN_FAST_CLOCK_DATA, "LAN_FAST_CLOCK_DATA" },
322 { Z21_LAN_FAST_CLOCK_SETTINGS_GET, "LAN_FAST_CLOCK_SETTINGS_GET" },
323 { Z21_LAN_FAST_CLOCK_SETTINGS_SET, "LAN_FAST_CLOCK_SETTINGS_SET" },
324 { Z21_LAN_GET_BROADCASTFLAGS, "LAN_GET_BROADCASTFLAGS" },
325 { Z21_LAN_GET_HWINFO, "LAN_GET_HWINFO" },
326 { Z21_LAN_GET_LOCOMODE, "LAN_GET_LOCOMODE" },
327 { Z21_LAN_GET_SERIAL_NUMBER, "LAN_GET_SERIAL_NUMBER" },
328 { Z21_LAN_LOCONET_DETECTOR, "LAN_LOCONET_DETECTOR" },
329 { Z21_LAN_LOCONET_DISPATCH_ADDR, "LAN_LOCONET_DISPATCH_ADDR" },
330 { Z21_LAN_LOCONET_FROM_LAN, "LAN_LOCONET_FROM_LAN" },
331 { Z21_LAN_LOCONET_Z21_RX, "LAN_LOCONET_Z21_RX" },
332 { Z21_LAN_LOCONET_Z21_TX, "LAN_LOCONET_Z21_TX" },
333 { Z21_LAN_LOGOFF, "LAN_LOGOFF" },
334 { Z21_LAN_RAILCOM_GETDATA, "LAN_RAILCOM_GETDATA" },
335 { Z21_LAN_RAILCOM_DATACHANGED, "LAN_RAILCOM_DATACHANGED" },
336 { Z21_LAN_RMBUS_DATACHANGED, "LAN_RMBUS_DATACHANGED" },
337 { Z21_LAN_RMBUS_GETDATA, "LAN_RMBUS_GETDATA" },
338 { Z21_LAN_RMBUS_PROGRAMMODULE, "LAN_RMBUS_PROGRAMMODULE" },
339 { Z21_LAN_SET_BROADCASTFLAGS, "LAN_SET_BROADCASTFLAGS" },
340 { Z21_LAN_SET_LOCOMODE, "LAN_SET_LOCOMODE" },
341 { Z21_LAN_SYSTEMSTATE_DATACHANGED, "LAN_SYSTEMSTATE_DATACHANGED" },
342 { Z21_LAN_SYSTEMSTATE_GETDATA, "LAN_SYSTEMSTATE_GETDATA" },
343 { Z21_LAN_X_BC, "LAN_X_xxx" }, /* Unspecified X-Bus command */
344 { Z21_LAN_X_BC_PROGRAMMING_MODE, "LAN_X_BC_PROGRAMMING_MODE" },
345 { Z21_LAN_X_BC_STOPPED, "LAN_X_BC_STOPPED" },
346 { Z21_LAN_X_BC_TRACK_POWER_OFF, "LAN_X_BC_TRACK_POWER_OFF" },
347 { Z21_LAN_X_BC_TRACK_POWER_ON, "LAN_X_BC_TRACK_POWER_ON" },
348 { Z21_LAN_X_BC_TRACK_SHORT_CIRCUIT, "LAN_X_BC_TRACK_SHORT_CIRCUIT" },
349 { Z21_LAN_X_CV_NACK, "LAN_X_CV_NACK" },
350 { Z21_LAN_X_CV_NACK_SC, "LAN_X_CV_NACK_SC" },
351 { Z21_LAN_X_CV_POM_ACCESSORY_READ_BYTE, "LAN_X_CV_POM_ACCESSORY_READ_BYTE" },
352 { Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BIT, "LAN_X_CV_POM_ACCESSORY_WRITE_BIT" },
353 { Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BYTE, "LAN_X_CV_POM_ACCESSORY_WRITE_BYTE" },
354 { Z21_LAN_X_CV_POM_READ_BYTE, "LAN_X_CV_POM_READ_BYTE" },
355 { Z21_LAN_X_CV_POM_WRITE_BIT, "LAN_X_CV_POM_WRITE_BIT" },
356 { Z21_LAN_X_CV_POM_WRITE_BYTE, "LAN_X_CV_POM_WRITE_BYTE" },
357 { Z21_LAN_X_CV_READ, "LAN_X_CV_READ" },
358 { Z21_LAN_X_CV_RESULT, "LAN_X_CV_RESULT" },
359 { Z21_LAN_X_CV_WRITE, "LAN_X_CV_WRITE" },
360 { Z21_LAN_X_DCC_READ_REGISTER, "LAN_X_DCC_READ_REGISTER" },
361 { Z21_LAN_X_DCC_WRITE_REGISTER, "LAN_X_DCC_WRITE_REGISTER" },
362 { Z21_LAN_X_EXT_ACCESSORY_INFO, "LAN_X_EXT_ACCESSORY_INFO" },
363 { Z21_LAN_X_GET_EXT_ACCESSORY_INFO, "LAN_X_GET_EXT_ACCESSORY_INFO" },
364 { Z21_LAN_X_GET_FIRMWARE_VERSION_REQUEST, "LAN_X_GET_FIRMWARE_VERSION" },
365 { Z21_LAN_X_GET_FIRMWARE_VERSION_REPLY, "LAN_X_GET_FIRMWARE_VERSION" },
366 { Z21_LAN_X_GET_LOCO_INFO, "LAN_X_GET_LOCO_INFO" },
367 { Z21_LAN_X_GET_TURNOUT_INFO, "LAN_X_GET_TURNOUT_INFO" },
368 { Z21_LAN_X_GET_VERSION_REQUEST, "LAN_X_GET_VERSION" },
369 { Z21_LAN_X_GET_VERSION_REPLY, "LAN_X_GET_VERSION" },
370 { Z21_LAN_X_GET_STATUS_REQUEST, "LAN_X_GET_STATUS" },
371 { Z21_LAN_X_LOCO_INFO, "LAN_X_LOCO_INFO" },
372 { Z21_LAN_X_MM_WRITE_BYTE, "LAN_X_MM_WRITE_BYTE" },
373 { Z21_LAN_X_PURGE_LOCO, "LAN_X_PURGE_LOCO" },
374 { Z21_LAN_X_SET_EXT_ACCESSORY, "LAN_X_SET_EXT_ACCESSORY" },
375 { Z21_LAN_X_SET_LOCO_BINARY_STATE, "LAN_X_SET_LOCO_BINARY_STATE" },
376 { Z21_LAN_X_SET_LOCO_DRIVE_DCC14, "LAN_X_SET_LOCO_DRIVE" },
377 { Z21_LAN_X_SET_LOCO_DRIVE_DCC28, "LAN_X_SET_LOCO_DRIVE" },
378 { Z21_LAN_X_SET_LOCO_DRIVE_DCC128, "LAN_X_SET_LOCO_DRIVE" },
379 { Z21_LAN_X_SET_LOCO_E_STOP, "LAN_X_SET_LOCO_E_STOP" },
380 { Z21_LAN_X_SET_LOCO_FUNCTION, "LAN_X_SET_LOCO_FUNCTION" },
381 { Z21_LAN_X_SET_STOP, "LAN_X_SET_STOP" },
382 { Z21_LAN_X_SET_TRACK_POWER_OFF, "LAN_X_SET_TRACK_POWER_OFF" },
383 { Z21_LAN_X_SET_TRACK_POWER_ON, "LAN_X_SET_TRACK_POWER_ON" },
384 { Z21_LAN_X_SET_TURNOUT, "LAN_X_SET_TURNOUT" },
385 { Z21_LAN_X_STATUS_CHANGED, "LAN_X_STATUS_CHANGED" },
386 { Z21_LAN_X_TURNOUT_INFO, "LAN_X_TURNOUT_INFO" },
387 { Z21_LAN_X_UNKNOWN_COMMAND, "LAN_X_UNKNOWN_COMMAND" },
388 { Z21_LAN_ZLINK_GET_HWINFO, "LAN_ZLINK_GET_HWINFO" },
389 { 0, NULL },
392 static const value_string z21_loco_mode_vals[] = {
393 { 0, "DCC Format" },
394 { 1, "MM Format" },
395 { 0, NULL },
398 static const value_string z21_hw_type_vals[] = {
399 { 0x00000200, "Z21a" },
400 { 0x00000201, "Z21b" },
401 { 0x00000202, "SmartRail" },
402 { 0x00000203, "z21small" },
403 { 0x00000204, "z21start" },
404 { 0x00000205, "Z21 Single Booster" },
405 { 0x00000206, "Z21 Dual Booster" },
406 { 0x00000211, "Z21 XL Series" },
407 { 0x00000212, "Z21 XL Booster" },
408 { 0x00000301, "Z21 Switch Decoder" },
409 { 0x00000302, "Z21 Signal Decoder" },
410 { 0, NULL },
413 static const value_string z21_loco_info_speed_steps_vals[] = {
414 { 0, "14 speed steps" },
415 { 2, "28 speed steps" },
416 { 4, "128 speed steps" },
417 { 0, NULL },
420 static const value_string z21_loco_func_vals[] = {
421 { 0, "Off" },
422 { 1, "On" },
423 { 2, "Toggle" },
424 { 3, "Not allowed" },
425 { 0, NULL },
428 static const value_string z21_turnout_state_vals[] = {
429 { 0, "Not switched yet" },
430 { 1, "Turnout is in position \"P=0\"" },
431 { 2, "Turnout is in position \"P=1\"" },
432 { 3, "Invalid combination" },
433 { 0, NULL },
436 static const value_string z21_pom_operation_vals[] = {
437 { 0x39, "Read byte" }, /* 111001 */
438 { 0x3a, "Write bit" }, /* 111010 */
439 { 0x3b, "Write byte" }, /* 111011 */
440 { 0, NULL },
443 static const value_string z21_zlink_message_type_vals[] = {
444 { 0x06, "ZLINK_MSG_TYPE_HW_INFO" },
445 { 0, NULL },
448 static const true_false_string tfs_forward_reverse = { "Forward", "Reverse" };
449 static const true_false_string tfs_turnout_command = { "Activate", "Deactivate" };
450 static const true_false_string tfs_turnout_output = { "Output 2", "Output 1" };
453 static void
454 update_command_field(proto_item *ti, unsigned command)
456 int width = 8;
457 if (command <= 0xff)
458 width = 2;
459 else if (command <= 0xffff)
460 width = 4;
461 else if (command <= 0xffffff)
462 width = 6;
463 proto_item_append_text(ti, ": %s (0x%0*x)",
464 val_to_str_const(command, z21_command_vals, "unknown"),
465 width, command);
469 /* Code to actually dissect the packets */
471 static int
472 dissect_z21_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
474 proto_item *ti, *temp_ti, *command_ti;
475 proto_tree *z21_tree;
476 unsigned offset = 0, datalen, command;
477 unsigned checksum, calculated_checksum, one_byte, version, temp_uint;
478 unsigned address_bytes, addr, speed_steps = 0, cv_addr;
479 uint64_t status, direction_and_speed, temp_uint64;
480 int32_t main_current, temp_int32;
481 char *buffer;
482 float temp_float;
483 static int * const broadcast_flags_bits[] = {
484 &hf_z21_broadcast_flags_loconet_detector,
485 &hf_z21_broadcast_flags_loconet_switching,
486 &hf_z21_broadcast_flags_loconet_driving,
487 &hf_z21_broadcast_flags_loconet,
488 &hf_z21_broadcast_flags_can_detector,
489 &hf_z21_broadcast_flags_railcom,
490 &hf_z21_broadcast_flags_can_booster,
491 &hf_z21_broadcast_flags_driving_switching_ex,
492 &hf_z21_broadcast_flags_system_status,
493 &hf_z21_broadcast_flags_fast_clock,
494 &hf_z21_broadcast_flags_railcom_subscribed,
495 &hf_z21_broadcast_flags_rmbus,
496 &hf_z21_broadcast_flags_driving_switching,
497 NULL
499 static int * const state_bits_byte1[] = {
500 &hf_z21_state_programming_mode,
501 &hf_z21_state_short_circuit,
502 &hf_z21_state_track_voltage_off,
503 &hf_z21_state_emergency_stop,
504 NULL
506 static int * const state_bits_byte2[] = {
507 &hf_z21_state_rcn_213,
508 &hf_z21_state_short_circuit_internal,
509 &hf_z21_state_short_circuit_external,
510 &hf_z21_state_power_lost,
511 &hf_z21_state_high_temperature,
512 NULL
514 static int * const capability_bits[] = {
515 &hf_z21_capability_needs_unlock_code,
516 &hf_z21_capability_detector_cmds,
517 &hf_z21_capability_accessory_cmds,
518 &hf_z21_capability_loco_cmds,
519 &hf_z21_capability_railcom,
520 &hf_z21_capability_reserved,
521 &hf_z21_capability_mm,
522 &hf_z21_capability_dcc,
523 NULL
525 static int * const speed_bits[] = {
526 &hf_z21_loco_direction,
527 &hf_z21_loco_speed,
528 NULL
530 static int * const loco_info_bits1[] = {
531 &hf_z21_loco_info_mm,
532 &hf_z21_loco_info_busy,
533 &hf_z21_loco_info_speed_steps,
534 NULL
536 static int * const loco_info_bits2[] = {
537 &hf_z21_loco_info_direction,
538 &hf_z21_loco_info_speed,
539 NULL
541 static int * const loco_info_bits3[] = {
542 &hf_z21_loco_info_double_traction,
543 &hf_z21_loco_info_smartsearch,
544 &hf_z21_loco_info_f0,
545 &hf_z21_loco_info_f4,
546 &hf_z21_loco_info_f3,
547 &hf_z21_loco_info_f2,
548 &hf_z21_loco_info_f1,
549 NULL
551 static int * const loco_info_bits4[] = {
552 &hf_z21_loco_info_f12,
553 &hf_z21_loco_info_f11,
554 &hf_z21_loco_info_f10,
555 &hf_z21_loco_info_f9,
556 &hf_z21_loco_info_f8,
557 &hf_z21_loco_info_f7,
558 &hf_z21_loco_info_f6,
559 &hf_z21_loco_info_f5,
560 NULL
562 static int * const loco_info_bits5[] = {
563 &hf_z21_loco_info_f20,
564 &hf_z21_loco_info_f19,
565 &hf_z21_loco_info_f18,
566 &hf_z21_loco_info_f17,
567 &hf_z21_loco_info_f16,
568 &hf_z21_loco_info_f15,
569 &hf_z21_loco_info_f14,
570 &hf_z21_loco_info_f13,
571 NULL
573 static int * const loco_info_bits6[] = {
574 &hf_z21_loco_info_f28,
575 &hf_z21_loco_info_f27,
576 &hf_z21_loco_info_f26,
577 &hf_z21_loco_info_f25,
578 &hf_z21_loco_info_f24,
579 &hf_z21_loco_info_f23,
580 &hf_z21_loco_info_f22,
581 &hf_z21_loco_info_f21,
582 NULL
584 static int * const loco_info_bits7[] = {
585 &hf_z21_loco_info_f31,
586 &hf_z21_loco_info_f30,
587 &hf_z21_loco_info_f29,
588 NULL
590 static int * const loco_func_bits[] = {
591 &hf_z21_loco_func_switch_type,
592 &hf_z21_loco_func_index,
593 NULL
595 static int * const turnout_state_bits[] = {
596 &hf_z21_turnout_state,
597 NULL
599 static int * const turnout_set_bits[] = {
600 &hf_z21_turnout_queue_bit,
601 &hf_z21_turnout_activate_bit,
602 &hf_z21_turnout_output_bit,
603 NULL
605 static int * const cv_bits[] = {
606 &hf_z21_cv_bit_value,
607 &hf_z21_cv_bit_position,
608 NULL
610 static int * const booster_state_bits[] = {
611 &hf_z21_can_booster_state_railcom_active,
612 &hf_z21_can_booster_state_output_disabled,
613 &hf_z21_can_booster_state_track_voltage_off,
614 &hf_z21_can_booster_state_short_circuit,
615 &hf_z21_can_booster_state_bg_active,
616 NULL
619 /* Check that the packet is long enough for it to belong to us. */
620 if (tvb_reported_length(tvb) < Z21_MIN_LENGTH)
621 return 0;
623 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Z21");
625 ti = proto_tree_add_item(tree, proto_z21, tvb, 0, -1, ENC_NA);
626 z21_tree = proto_item_add_subtree(ti, ett_z21);
627 proto_tree_add_item_ret_uint(z21_tree, hf_z21_datalen,
628 tvb, offset, 2, ENC_LITTLE_ENDIAN, &datalen);
629 offset += 2;
630 command = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
631 if (command == Z21_LAN_X_BC) {
632 proto_tree_add_boolean(z21_tree, hf_z21_x_bus, tvb, offset, 2, true);
633 /* Note that we do not increment the offset yet */
635 /* Strategy:
636 * 1. Read two bytes of the data (as big-endian)
637 * 2. Prepend it with 0x4000 (the header bytes for X-BUS)
638 * 3. If the three MSBs are one of the "one-byte commands",
639 * set x_bus_command accordingly and run with that
640 * 4. Otherwise run with "two-byte commands"...
641 * 5. ... except that there are some commands that need more data to
642 * determine the exact command (as their two "command bytes" are the
643 * same), so check for those and set x_bus_command manually for them.
645 temp_uint = 0x40000000 + tvb_get_uint16(tvb, offset+2, ENC_BIG_ENDIAN);
646 unsigned x_bus_command = temp_uint >> 8;
647 /* Check for all the "one-byte" commands */
648 if (x_bus_command == Z21_LAN_X_SET_STOP ||
649 x_bus_command == Z21_LAN_X_SET_LOCO_E_STOP ||
650 x_bus_command == Z21_LAN_X_GET_EXT_ACCESSORY_INFO ||
651 x_bus_command == Z21_LAN_X_SET_EXT_ACCESSORY ||
652 x_bus_command == Z21_LAN_X_GET_TURNOUT_INFO ||
653 x_bus_command == Z21_LAN_X_SET_TURNOUT ||
654 x_bus_command == Z21_LAN_X_LOCO_INFO) {
655 /* Initialize the checksum without the 0x4000 prefix */
656 calculated_checksum = x_bus_command & 0xff;
657 /* Check for these that are actually another command */
658 if (x_bus_command == Z21_LAN_X_GET_TURNOUT_INFO && datalen == 9) {
659 x_bus_command = Z21_LAN_X_TURNOUT_INFO;
660 } else if (x_bus_command == Z21_LAN_X_GET_EXT_ACCESSORY_INFO && datalen == 10) {
661 x_bus_command = Z21_LAN_X_EXT_ACCESSORY_INFO;
663 command_ti = proto_tree_add_uint(z21_tree, hf_z21_command, tvb, offset, 3, x_bus_command);
664 offset += 3;
666 else {
667 /* First assume "two-byte command", then check for exceptions */
668 x_bus_command = temp_uint;
669 if (x_bus_command == Z21_LAN_X_CV_POM_COMMANDS ||
670 x_bus_command == Z21_LAN_X_CV_POM_ACCESSORY_COMMANDS) {
671 /* Read DB3 from data, get the two interesting bits */
672 temp_uint = tvb_get_uint8(tvb, offset + 6) >> 2 & 0x3;
673 switch (x_bus_command) {
674 case Z21_LAN_X_CV_POM_COMMANDS:
675 if (temp_uint == 0x1)
676 x_bus_command = Z21_LAN_X_CV_POM_READ_BYTE;
677 else if (temp_uint == 0x2)
678 x_bus_command = Z21_LAN_X_CV_POM_WRITE_BIT;
679 else if (temp_uint == 0x3)
680 x_bus_command = Z21_LAN_X_CV_POM_WRITE_BYTE;
681 break;
682 case Z21_LAN_X_CV_POM_ACCESSORY_COMMANDS:
683 if (temp_uint == 0x1)
684 x_bus_command = Z21_LAN_X_CV_POM_ACCESSORY_READ_BYTE;
685 else if (temp_uint == 0x2)
686 x_bus_command = Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BIT;
687 else if (temp_uint == 0x3)
688 x_bus_command = Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BYTE;
689 break;
692 command_ti = proto_tree_add_uint(z21_tree, hf_z21_command,
693 tvb, offset, 4, x_bus_command);
694 offset += 4;
695 /* Initialize the checksum with the two LSBs */
696 calculated_checksum = ((x_bus_command & 0xff00) >> 8) ^ (x_bus_command & 0x00ff);
698 update_command_field(command_ti, x_bus_command);
699 col_add_fstr(pinfo->cinfo, COL_INFO, "Command=%s",
700 val_to_str_const(x_bus_command, z21_command_vals, "unknown"));
701 proto_item_append_text(z21_tree, ", Command: %s",
702 val_to_str_const(x_bus_command, z21_command_vals, "unknown"));
703 switch (x_bus_command) {
704 case Z21_LAN_X_STATUS_CHANGED:
705 proto_tree_add_bitmask_ret_uint64(z21_tree, tvb, offset, hf_z21_status,
706 ett_z21, state_bits_byte1, ENC_NA, &status);
707 offset += 1;
708 calculated_checksum ^= (unsigned)status;
709 break;
710 case Z21_LAN_X_SET_LOCO_DRIVE_DCC14:
711 case Z21_LAN_X_SET_LOCO_DRIVE_DCC28:
712 case Z21_LAN_X_SET_LOCO_DRIVE_DCC128:
713 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
714 addr = address_bytes & 0x3FFF;
715 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
716 switch (x_bus_command) {
717 case Z21_LAN_X_SET_LOCO_DRIVE_DCC14: speed_steps = 14; break;
718 case Z21_LAN_X_SET_LOCO_DRIVE_DCC28: speed_steps = 28; break;
719 case Z21_LAN_X_SET_LOCO_DRIVE_DCC128: speed_steps = 128; break;
721 proto_tree_add_uint(z21_tree, hf_z21_speed_steps, tvb, offset-1, 1, speed_steps);
722 offset += 2;
723 calculated_checksum ^= address_bytes >> 8;
724 calculated_checksum ^= address_bytes & 0xFF;
725 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d (%d SS)",
726 addr, speed_steps);
727 temp_ti = proto_tree_add_bitmask_ret_uint64(z21_tree, tvb, offset, hf_z21_loco_direction_and_speed,
728 ett_z21, speed_bits, ENC_NA, &direction_and_speed);
729 offset += 1;
730 calculated_checksum ^= (unsigned)direction_and_speed;
731 if (direction_and_speed & 0x80) {
732 proto_item_set_text(temp_ti,
733 "Locomotive direction and speed: Forward, 0x%02" PRIx64,
734 direction_and_speed & 0x7F);
735 col_append_str(pinfo->cinfo, COL_INFO, ", Forward");
737 else {
738 proto_item_set_text(temp_ti,
739 "Locomotive direction and speed: Reverse, 0x%02" PRIx64,
740 direction_and_speed & 0x7F);
741 col_append_str(pinfo->cinfo, COL_INFO, ", Reverse");
743 col_append_fstr(pinfo->cinfo, COL_INFO, ", Speed=0x%02" PRIx64,
744 direction_and_speed & 0x7F);
745 break;
746 case Z21_LAN_X_GET_LOCO_INFO:
747 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
748 addr = address_bytes & 0x3FFF;
749 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
750 offset += 2;
751 calculated_checksum ^= address_bytes >> 8;
752 calculated_checksum ^= address_bytes & 0xFF;
753 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
754 break;
755 case Z21_LAN_X_LOCO_INFO:
756 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
757 addr = address_bytes & 0x3FFF;
758 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
759 offset += 2;
760 calculated_checksum ^= address_bytes >> 8;
761 calculated_checksum ^= address_bytes & 0xFF;
762 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
763 proto_item_append_text(z21_tree, ", Loco: %d", addr);
765 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
766 loco_info_bits1, ENC_NA, &temp_uint64);
767 offset += 1;
768 calculated_checksum ^= temp_uint64;
769 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
770 val_to_str_const((uint32_t)temp_uint64 & 0x07,
771 z21_loco_info_speed_steps_vals, "unknown"));
773 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
774 loco_info_bits2, ENC_NA, &temp_uint64);
775 offset += 1;
776 calculated_checksum ^= temp_uint64;
777 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
778 tfs_get_string((bool)(temp_uint64 >> 7), &tfs_forward_reverse));
779 col_append_fstr(pinfo->cinfo, COL_INFO, ", Speed=0x%02" PRIx64,
780 temp_uint64 & 0x7f);
782 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
783 loco_info_bits3, ENC_NA, &temp_uint64);
784 offset += 1;
785 calculated_checksum ^= temp_uint64;
786 if (temp_uint64 & 0x40) {
787 col_append_str(pinfo->cinfo, COL_INFO, ", in double traction");
790 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
791 loco_info_bits4, ENC_NA, &temp_uint64);
792 offset += 1;
793 calculated_checksum ^= temp_uint64;
795 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
796 loco_info_bits5, ENC_NA, &temp_uint64);
797 offset += 1;
798 calculated_checksum ^= temp_uint64;
800 /* The following bytes are not always there it seems */
801 if (offset < datalen-1) {
802 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
803 loco_info_bits6, ENC_NA, &temp_uint64);
804 offset += 1;
805 calculated_checksum ^= temp_uint64;
807 if (offset < datalen-1) {
808 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
809 loco_info_bits7, ENC_NA, &temp_uint64);
810 offset += 1;
811 calculated_checksum ^= temp_uint64;
813 /* If still something, dissect as bytes */
814 if (offset < datalen-1) {
815 proto_tree_add_item(z21_tree, hf_z21_loco_info_extensions,
816 tvb, offset, datalen-1-offset, ENC_NA);
817 /* Note: Do not increment offset because the checksum
818 * will be calculated below! */
820 break;
821 case Z21_LAN_X_PURGE_LOCO:
822 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
823 addr = address_bytes & 0x3FFF;
824 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
825 offset += 2;
826 calculated_checksum ^= address_bytes >> 8;
827 calculated_checksum ^= address_bytes & 0xFF;
828 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
829 proto_item_append_text(z21_tree, ", Loco: %d", addr);
830 break;
831 case Z21_LAN_X_SET_LOCO_E_STOP:
832 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
833 addr = address_bytes & 0x3FFF;
834 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
835 offset += 2;
836 calculated_checksum ^= address_bytes >> 8;
837 calculated_checksum ^= address_bytes & 0xFF;
838 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
839 proto_item_append_text(z21_tree, ", Loco: %d", addr);
840 break;
841 case Z21_LAN_X_SET_LOCO_BINARY_STATE:
842 col_append_str(pinfo->cinfo, COL_INFO, ", TO BE COMPLETED");
843 break;
844 case Z21_LAN_X_SET_LOCO_FUNCTION:
845 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
846 addr = address_bytes & 0x3FFF;
847 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
848 offset += 2;
849 calculated_checksum ^= address_bytes >> 8;
850 calculated_checksum ^= address_bytes & 0xFF;
851 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
852 proto_item_append_text(z21_tree, ", Loco: %d", addr);
853 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
854 loco_func_bits, ENC_NA, &temp_uint64);
855 offset += 1;
856 calculated_checksum ^= temp_uint64;
857 col_append_fstr(pinfo->cinfo, COL_INFO, ", Function=%" PRIu64 ", State=%s",
858 temp_uint64 & 0x3f,
859 val_to_str_const((uint32_t)temp_uint64 >> 6, z21_loco_func_vals, "unknown"));
860 proto_item_append_text(z21_tree, ", Function: %" PRIu64 ", State: %s",
861 temp_uint64 & 0x3f,
862 val_to_str_const((uint32_t)temp_uint64 >> 6, z21_loco_func_vals, "unknown"));
863 break;
864 case Z21_LAN_X_GET_TURNOUT_INFO:
865 addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
866 proto_tree_add_uint(z21_tree, hf_z21_function_address,
867 tvb, offset, 2, addr);
868 offset += 2;
869 calculated_checksum ^= addr >> 8;
870 calculated_checksum ^= addr & 0xFF;
871 col_append_fstr(pinfo->cinfo, COL_INFO, ", Function=%d", addr);
872 proto_item_append_text(z21_tree, ", Function: %d", addr);
873 break;
874 case Z21_LAN_X_TURNOUT_INFO:
875 addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
876 proto_tree_add_uint(z21_tree, hf_z21_function_address,
877 tvb, offset, 2, addr);
878 offset += 2;
879 calculated_checksum ^= addr >> 8;
880 calculated_checksum ^= addr & 0xFF;
881 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
882 turnout_state_bits, ENC_NA, &temp_uint64);
883 offset += 1;
884 calculated_checksum ^= temp_uint64;
885 col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d, State=%s",
886 addr,
887 val_to_str_const((uint32_t)temp_uint64 & 0x03, z21_turnout_state_vals, "unknown"));
888 proto_item_append_text(z21_tree, ", Address: %d, State: %s",
889 addr,
890 val_to_str_const((uint32_t)temp_uint64 & 0x03, z21_turnout_state_vals, "unknown"));
891 break;
892 case Z21_LAN_X_SET_TURNOUT:
893 addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
894 proto_tree_add_uint(z21_tree, hf_z21_function_address,
895 tvb, offset, 2, addr);
896 offset += 2;
897 calculated_checksum ^= addr >> 8;
898 calculated_checksum ^= addr & 0xFF;
899 col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d", addr);
900 proto_item_append_text(z21_tree, ", Address: %d", addr);
901 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
902 turnout_set_bits, ENC_NA, &temp_uint64);
903 offset += 1;
904 calculated_checksum ^= temp_uint64;
905 col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d, %s, Output=%s",
906 addr,
907 tfs_get_string((bool)(temp_uint64 & 0x08), &tfs_turnout_command),
908 tfs_get_string((bool)(temp_uint64 & 0x01), &tfs_turnout_output));
909 proto_item_append_text(z21_tree, ", Address: %d, %s, Output: %s",
910 addr,
911 tfs_get_string((bool)(temp_uint64 & 0x08), &tfs_turnout_command),
912 tfs_get_string((bool)(temp_uint64 & 0x01), &tfs_turnout_output));
913 break;
914 case Z21_LAN_X_GET_EXT_ACCESSORY_INFO:
915 addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
916 proto_tree_add_uint(z21_tree, hf_z21_accessory_address,
917 tvb, offset, 2, addr);
918 offset += 2;
919 calculated_checksum ^= addr >> 8;
920 calculated_checksum ^= addr & 0xFF;
921 col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d", addr);
922 proto_item_append_text(z21_tree, ", Address: %d", addr);
923 break;
924 case Z21_LAN_X_EXT_ACCESSORY_INFO:
925 addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
926 proto_tree_add_uint(z21_tree, hf_z21_accessory_address,
927 tvb, offset, 2, addr);
928 offset += 2;
929 calculated_checksum ^= addr >> 8;
930 calculated_checksum ^= addr & 0xFF;
931 temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
932 proto_tree_add_uint(z21_tree, hf_z21_accessory_state,
933 tvb, offset, 1, temp_uint >> 8);
934 offset += 1;
935 calculated_checksum ^= temp_uint >> 8;
936 proto_tree_add_uint(z21_tree, hf_z21_accessory_status,
937 tvb, offset, 1, temp_uint & 0xff);
938 offset += 1;
939 calculated_checksum ^= temp_uint & 0xff;
940 col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d, State=%d, Status=0x%02x",
941 addr, temp_uint >> 8, temp_uint & 0xff);
942 proto_item_append_text(z21_tree, ", Address: %d, State: %d, Status: 0x%02x",
943 addr, temp_uint >> 8, temp_uint & 0xff);
944 break;
945 case Z21_LAN_X_SET_EXT_ACCESSORY:
946 addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
947 proto_tree_add_uint(z21_tree, hf_z21_accessory_address,
948 tvb, offset, 2, addr);
949 offset += 2;
950 calculated_checksum ^= addr >> 8;
951 calculated_checksum ^= addr & 0xFF;
952 temp_uint = tvb_get_uint8(tvb, offset);
953 proto_tree_add_uint(z21_tree, hf_z21_accessory_state,
954 tvb, offset, 1, temp_uint);
955 offset += 1;
956 calculated_checksum ^= temp_uint;
957 col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d, State=%d",
958 addr, temp_uint);
959 proto_item_append_text(z21_tree, ", Address: %d, State: %d",
960 addr, temp_uint);
961 break;
962 case Z21_LAN_X_CV_READ:
963 cv_addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
964 /* CV addresses are 1-based, update checksum first */
965 calculated_checksum ^= cv_addr >> 8;
966 calculated_checksum ^= cv_addr & 0xFF;
967 cv_addr += 1;
968 proto_tree_add_uint(z21_tree, hf_z21_cv_address,
969 tvb, offset, 2, cv_addr);
970 offset += 2;
971 col_append_fstr(pinfo->cinfo, COL_INFO, ", CV%d", cv_addr);
972 proto_item_append_text(z21_tree, ", CV%d", cv_addr);
973 break;
974 case Z21_LAN_X_CV_WRITE:
975 cv_addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
976 /* CV addresses are 1-based, update checksum first */
977 calculated_checksum ^= cv_addr >> 8;
978 calculated_checksum ^= cv_addr & 0xFF;
979 cv_addr += 1;
980 proto_tree_add_uint(z21_tree, hf_z21_cv_address,
981 tvb, offset, 2, cv_addr);
982 offset += 2;
983 temp_uint = tvb_get_uint8(tvb, offset);
984 proto_tree_add_uint(z21_tree, hf_z21_cv_value,
985 tvb, offset, 1, temp_uint);
986 offset += 1;
987 calculated_checksum ^= temp_uint;
988 col_append_fstr(pinfo->cinfo, COL_INFO, ", CV%d, Value=%d",
989 cv_addr, temp_uint);
990 proto_item_append_text(z21_tree, ", CV%d, Value: %d",
991 cv_addr, temp_uint);
992 break;
993 case Z21_LAN_X_CV_RESULT:
994 cv_addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
995 /* CV addresses are 1-based, update checksum first */
996 calculated_checksum ^= cv_addr >> 8;
997 calculated_checksum ^= cv_addr & 0xFF;
998 cv_addr += 1;
999 proto_tree_add_uint(z21_tree, hf_z21_cv_address,
1000 tvb, offset, 2, cv_addr);
1001 offset += 2;
1002 temp_uint = tvb_get_uint8(tvb, offset);
1003 proto_tree_add_uint(z21_tree, hf_z21_cv_value,
1004 tvb, offset, 1, temp_uint);
1005 offset += 1;
1006 calculated_checksum ^= temp_uint;
1007 col_append_fstr(pinfo->cinfo, COL_INFO, ", CV%d, Value=%d",
1008 cv_addr, temp_uint);
1009 proto_item_append_text(z21_tree, ", CV%d, Value: %d",
1010 cv_addr, temp_uint);
1011 break;
1012 case Z21_LAN_X_CV_POM_WRITE_BYTE:
1013 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1014 addr = address_bytes & 0x3FFF;
1015 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
1016 offset += 2;
1017 calculated_checksum ^= address_bytes >> 8;
1018 calculated_checksum ^= address_bytes & 0xFF;
1019 temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1020 calculated_checksum ^= temp_uint >> 8;
1021 calculated_checksum ^= temp_uint & 0xff;
1022 proto_tree_add_uint(z21_tree, hf_z21_pom_operation,
1023 tvb, offset, 1, temp_uint >> 2);
1024 cv_addr = (temp_uint & 0x03ff) + 1;
1025 proto_tree_add_uint(z21_tree, hf_z21_cv_address,
1026 tvb, offset, 2, cv_addr);
1027 offset += 2;
1028 proto_tree_add_item_ret_uint(z21_tree, hf_z21_cv_value,
1029 tvb, offset, 1, ENC_NA, &temp_uint);
1030 offset += 1;
1031 calculated_checksum ^= temp_uint;
1032 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d, CV%d, Value=%d",
1033 addr, cv_addr, temp_uint);
1034 proto_item_append_text(z21_tree, ", Loco: %d, CV%d, Value: %d",
1035 addr, cv_addr, temp_uint);
1036 break;
1037 case Z21_LAN_X_CV_POM_WRITE_BIT:
1038 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1039 addr = address_bytes & 0x3FFF;
1040 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
1041 offset += 2;
1042 calculated_checksum ^= address_bytes >> 8;
1043 calculated_checksum ^= address_bytes & 0xFF;
1044 temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1045 calculated_checksum ^= temp_uint >> 8;
1046 calculated_checksum ^= temp_uint & 0xff;
1047 proto_tree_add_uint(z21_tree, hf_z21_pom_operation,
1048 tvb, offset, 1, temp_uint >> 2);
1049 cv_addr = (temp_uint & 0x03ff) + 1;
1050 proto_tree_add_uint(z21_tree, hf_z21_cv_address,
1051 tvb, offset, 2, cv_addr);
1052 offset += 2;
1053 proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
1054 cv_bits, ENC_NA, &temp_uint64);
1055 offset += 1;
1056 calculated_checksum ^= (unsigned)temp_uint64;
1057 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d, CV%d, Bit position=%" PRIu64 ", Value=%" PRIu64,
1058 addr, cv_addr, temp_uint64 & 0x07, temp_uint64 >> 3 & 0x01);
1059 proto_item_append_text(z21_tree, ", Loco: %d, CV%d, Bit position: %" PRIu64 ", Value: %" PRIu64,
1060 addr, cv_addr, temp_uint64 & 0x07, temp_uint64 >> 3 & 0x01);
1061 break;
1062 case Z21_LAN_X_CV_POM_READ_BYTE:
1063 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1064 addr = address_bytes & 0x3FFF;
1065 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
1066 offset += 2;
1067 calculated_checksum ^= address_bytes >> 8;
1068 calculated_checksum ^= address_bytes & 0xFF;
1069 temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1070 calculated_checksum ^= temp_uint >> 8;
1071 calculated_checksum ^= temp_uint & 0xff;
1072 proto_tree_add_uint(z21_tree, hf_z21_pom_operation,
1073 tvb, offset, 1, temp_uint >> 2);
1074 cv_addr = (temp_uint & 0x03ff) + 1;
1075 proto_tree_add_uint(z21_tree, hf_z21_cv_address,
1076 tvb, offset, 2, cv_addr);
1077 offset += 2;
1078 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d, CV%d",
1079 addr, cv_addr);
1080 proto_item_append_text(z21_tree, ", Loco: %d, CV%d",
1081 addr, cv_addr);
1082 break;
1083 case Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BYTE:
1084 case Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BIT:
1085 case Z21_LAN_X_CV_POM_ACCESSORY_READ_BYTE:
1086 col_append_str(pinfo->cinfo, COL_INFO, ", *** TO BE COMPLETED ***");
1087 break;
1088 case Z21_LAN_X_DCC_READ_REGISTER:
1089 temp_uint = tvb_get_uint8(tvb, offset);
1090 proto_tree_add_uint(z21_tree, hf_z21_register,
1091 tvb, offset, 1, temp_uint);
1092 offset += 1;
1093 calculated_checksum ^= temp_uint;
1094 col_append_fstr(pinfo->cinfo, COL_INFO, ", Register%d",
1095 temp_uint);
1096 proto_item_append_text(z21_tree, ", Register%d",
1097 temp_uint);
1098 break;
1099 case Z21_LAN_X_DCC_WRITE_REGISTER:
1100 temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1101 proto_tree_add_uint(z21_tree, hf_z21_register,
1102 tvb, offset, 1, temp_uint >> 8);
1103 offset += 1;
1104 calculated_checksum ^= temp_uint >> 8;
1105 proto_tree_add_uint(z21_tree, hf_z21_register_value,
1106 tvb, offset, 1, temp_uint & 0xff);
1107 offset += 1;
1108 calculated_checksum ^= temp_uint & 0xff;
1109 col_append_fstr(pinfo->cinfo, COL_INFO, ", Register%d, Value=%d",
1110 temp_uint >> 8, temp_uint & 0xff);
1111 proto_item_append_text(z21_tree, ", Register%d, Value: %d",
1112 temp_uint >> 8, temp_uint & 0xff);
1113 break;
1114 case Z21_LAN_X_MM_WRITE_BYTE:
1115 /* Skip one zero byte */
1116 offset += 1;
1117 temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1118 proto_tree_add_uint(z21_tree, hf_z21_register,
1119 tvb, offset, 1, temp_uint >> 8);
1120 offset += 1;
1121 calculated_checksum ^= temp_uint >> 8;
1122 proto_tree_add_uint(z21_tree, hf_z21_register_value,
1123 tvb, offset, 1, temp_uint & 0xff);
1124 offset += 1;
1125 calculated_checksum ^= temp_uint & 0xff;
1126 col_append_fstr(pinfo->cinfo, COL_INFO, ", Register%d, Value=%d",
1127 temp_uint >> 8, temp_uint & 0xff);
1128 proto_item_append_text(z21_tree, ", Register%d, Value: %d",
1129 temp_uint >> 8, temp_uint & 0xff);
1130 break;
1131 case Z21_LAN_X_GET_FIRMWARE_VERSION_REPLY:
1132 version = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1133 buffer = wmem_strdup_printf(pinfo->pool, "%x.%02x",
1134 version >> 8, version & 0xff);
1135 proto_tree_add_string(z21_tree, hf_z21_firmware_version,
1136 tvb, offset, 2, buffer);
1137 offset += 2;
1138 calculated_checksum ^= version >> 8;
1139 calculated_checksum ^= version & 0xFF;
1140 col_append_fstr(pinfo->cinfo, COL_INFO, ", Version=%s",
1141 buffer);
1144 /* Calculate checksum for the rest of the bytes (if any) for now */
1145 while (offset < datalen-1) {
1146 one_byte = tvb_get_uint8(tvb, offset);
1147 offset += 1;
1148 calculated_checksum ^= one_byte;
1150 /* No more data in the X-BUS command, read the checksum */
1151 temp_ti = proto_tree_add_item_ret_uint(z21_tree, hf_z21_checksum,
1152 tvb, offset, 1, ENC_NA, &checksum);
1153 if (checksum != calculated_checksum) {
1154 expert_add_info_format(pinfo, temp_ti, &ei_z21_invalid_checksum,
1155 "Invalid checksum, calculated: 0x%02x", calculated_checksum);
1158 else {
1159 /* Not X-BUS */
1160 command_ti = proto_tree_add_uint(z21_tree, hf_z21_command,
1161 tvb, offset, 2, command);
1162 offset += 2;
1163 update_command_field(command_ti, command);
1164 col_add_fstr(pinfo->cinfo, COL_INFO, "Command=%s",
1165 val_to_str_const(command, z21_command_vals, "unknown"));
1166 proto_item_append_text(z21_tree, ", Command: %s",
1167 val_to_str_const(command, z21_command_vals, "unknown"));
1168 switch (command) {
1169 case Z21_LAN_GET_SERIAL_NUMBER:
1170 if (datalen == 8) {
1171 unsigned serial;
1172 proto_tree_add_item_ret_uint(z21_tree, hf_z21_serial_number,
1173 tvb, offset, 4, ENC_LITTLE_ENDIAN, &serial);
1174 offset += 4;
1175 col_append_fstr(pinfo->cinfo, COL_INFO, ", Serial number: %d",
1176 serial);
1178 break;
1179 case Z21_LAN_SYSTEMSTATE_DATACHANGED:
1180 main_current = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1181 proto_tree_add_int_format_value(z21_tree, hf_z21_main_current,
1182 tvb, offset, 2, main_current, "%d mA", main_current);
1183 offset += 2;
1185 temp_int32 = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1186 proto_tree_add_int_format_value(z21_tree, hf_z21_prog_current,
1187 tvb, offset, 2, temp_int32, "%d mA", temp_int32);
1188 offset += 2;
1190 temp_int32 = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1191 proto_tree_add_int_format_value(z21_tree, hf_z21_filtered_main_current,
1192 tvb, offset, 2, temp_int32, "%d mA", temp_int32);
1193 offset += 2;
1195 temp_int32 = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1196 proto_tree_add_int_format_value(z21_tree, hf_z21_temperature,
1197 tvb, offset, 2, temp_int32, "%dĀ°C", temp_int32);
1198 offset += 2;
1199 col_append_fstr(pinfo->cinfo, COL_INFO,
1200 ", Temperature=%dĀ°C", temp_int32);
1202 temp_uint = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
1203 temp_float = (float)temp_uint / 1000;
1204 proto_tree_add_float_format_value(z21_tree, hf_z21_supply_voltage,
1205 tvb, offset, 2, temp_float, "%.3f V", temp_float);
1206 offset += 2;
1207 col_append_fstr(pinfo->cinfo, COL_INFO,
1208 ", Track=%.3f V/%d mA", temp_float, main_current);
1210 temp_uint = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
1211 temp_float = (float)temp_uint / 1000;
1212 proto_tree_add_float_format_value(z21_tree, hf_z21_track_voltage,
1213 tvb, offset, 2, temp_float, "%.3f V", temp_float);
1214 offset += 2;
1216 proto_tree_add_bitmask(z21_tree, tvb, offset, hf_z21_central_state,
1217 ett_z21, state_bits_byte1, ENC_NA);
1218 offset += 1;
1219 proto_tree_add_bitmask(z21_tree, tvb, offset, hf_z21_central_state_ex,
1220 ett_z21, state_bits_byte2, ENC_NA);
1221 offset += 1;
1222 proto_tree_add_item(z21_tree, hf_z21_systemstate_reserved,
1223 tvb, offset, 1, ENC_NA);
1224 offset += 1;
1225 temp_uint = tvb_get_uint8(tvb, offset);
1226 if (temp_uint == 0) {
1227 /* Don't interpret the flags */
1228 proto_tree_add_uint_format_value(z21_tree, hf_z21_capabilities,
1229 tvb, offset, 1, 0, "0x00 (Capability flags not supported)");
1231 else {
1232 proto_tree_add_bitmask(z21_tree, tvb, offset, hf_z21_capabilities,
1233 ett_z21, capability_bits, ENC_NA);
1235 offset += 1;
1236 break;
1237 case Z21_LAN_RMBUS_GETDATA:
1238 proto_tree_add_item_ret_uint(z21_tree, hf_z21_rmbus_group,
1239 tvb, offset, 1, ENC_NA, &temp_uint);
1240 offset += 1;
1241 col_append_fstr(pinfo->cinfo, COL_INFO, ", Group=%d", temp_uint);
1242 proto_item_append_text(z21_tree, ", Group: %d", temp_uint);
1243 break;
1244 case Z21_LAN_RMBUS_DATACHANGED:
1245 proto_tree_add_item_ret_uint(z21_tree, hf_z21_rmbus_group,
1246 tvb, offset, 1, ENC_NA, &temp_uint);
1247 offset += 1;
1248 col_append_fstr(pinfo->cinfo, COL_INFO, ", Group=%d", temp_uint);
1249 proto_item_append_text(z21_tree, ", Group: %d", temp_uint);
1250 proto_tree_add_item(z21_tree, hf_z21_rmbus_feedbacks, tvb, offset, 10, ENC_NA);
1251 offset += 10;
1252 break;
1253 case Z21_LAN_RMBUS_PROGRAMMODULE:
1254 proto_tree_add_item_ret_uint(z21_tree, hf_z21_rmbus_address,
1255 tvb, offset, 1, ENC_NA, &temp_uint);
1256 col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d", temp_uint);
1257 proto_item_append_text(z21_tree, ", Address: %d", temp_uint);
1258 offset += 1;
1259 break;
1260 case Z21_LAN_RAILCOM_DATACHANGED:
1261 proto_tree_add_item_ret_uint(z21_tree, hf_z21_loco_address,
1262 tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1263 offset += 2;
1264 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", temp_uint);
1265 proto_item_append_text(z21_tree, ", Loco: %d", temp_uint);
1266 proto_tree_add_item(z21_tree, hf_z21_railcom_receive_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1267 offset += 4;
1268 proto_tree_add_item(z21_tree, hf_z21_railcom_error_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1269 offset += 2;
1270 proto_tree_add_item(z21_tree, hf_z21_railcom_reserved1, tvb, offset, 1, ENC_NA);
1271 offset += 1;
1272 proto_tree_add_item(z21_tree, hf_z21_railcom_options, tvb, offset, 1, ENC_NA);
1273 offset += 1;
1274 proto_tree_add_item(z21_tree, hf_z21_railcom_speed, tvb, offset, 1, ENC_NA);
1275 offset += 1;
1276 proto_tree_add_item(z21_tree, hf_z21_railcom_qos, tvb, offset, 1, ENC_NA);
1277 offset += 1;
1278 proto_tree_add_item(z21_tree, hf_z21_railcom_reserved2, tvb, offset, 1, ENC_NA);
1279 offset += 1;
1280 break;
1281 case Z21_LAN_RAILCOM_GETDATA:
1282 proto_tree_add_item(z21_tree, hf_z21_railcom_type, tvb, offset, 1, ENC_NA);
1283 offset += 1;
1284 proto_tree_add_item(z21_tree, hf_z21_loco_address, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1285 offset += 2;
1286 break;
1287 case Z21_LAN_LOCONET_FROM_LAN:
1288 case Z21_LAN_LOCONET_Z21_RX:
1289 case Z21_LAN_LOCONET_Z21_TX:
1290 proto_tree_add_item(z21_tree, hf_z21_loconet_message,
1291 tvb, offset, datalen-4, ENC_NA);
1292 offset += datalen-4;
1293 break;
1294 case Z21_LAN_LOCONET_DISPATCH_ADDR:
1295 proto_tree_add_item_ret_uint(z21_tree, hf_z21_loco_address,
1296 tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1297 offset += 2;
1298 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", temp_uint);
1299 proto_item_append_text(z21_tree, ", Loco: %d", temp_uint);
1300 if (datalen > 6) {
1301 /* Response from Z21 */
1302 proto_tree_add_item(z21_tree, hf_z21_loconet_result, tvb, offset, 1, ENC_NA);
1303 offset += 1;
1305 break;
1306 case Z21_LAN_LOCONET_DETECTOR:
1307 proto_tree_add_item(z21_tree, hf_z21_loconet_type, tvb, offset, 1, ENC_NA);
1308 offset += 1;
1309 if (datalen == 7) {
1310 /* This is request */
1311 proto_tree_add_item(z21_tree, hf_z21_loconet_report_address,
1312 tvb, offset, 2, ENC_LITTLE_ENDIAN);
1313 offset += 2;
1315 else {
1316 /* This is reply */
1317 proto_tree_add_item(z21_tree, hf_z21_loconet_feedback_address,
1318 tvb, offset, 2, ENC_LITTLE_ENDIAN);
1319 offset += 2;
1320 proto_tree_add_item(z21_tree, hf_z21_loconet_info,
1321 tvb, offset, datalen-7, ENC_NA);
1322 offset += datalen-7;
1324 break;
1325 case Z21_LAN_CAN_DETECTOR:
1326 if (datalen == 7) {
1327 /* This is request */
1328 proto_tree_add_item(z21_tree, hf_z21_can_type, tvb, offset, 1, ENC_NA);
1329 offset += 1;
1330 proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1331 tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1332 offset += 2;
1333 col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1334 proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1336 else {
1337 /* This is reply */
1338 proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1339 tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1340 offset += 2;
1341 col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1342 proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1343 proto_tree_add_item(z21_tree, hf_z21_can_module_address,
1344 tvb, offset, 2, ENC_LITTLE_ENDIAN);
1345 offset += 2;
1346 proto_tree_add_item(z21_tree, hf_z21_can_port, tvb, offset, 1, ENC_NA);
1347 offset += 1;
1348 proto_tree_add_item(z21_tree, hf_z21_can_type, tvb, offset, 1, ENC_NA);
1349 offset += 1;
1350 proto_tree_add_item(z21_tree, hf_z21_can_value1,
1351 tvb, offset, 2, ENC_LITTLE_ENDIAN);
1352 offset += 2;
1353 proto_tree_add_item(z21_tree, hf_z21_can_value2,
1354 tvb, offset, 2, ENC_LITTLE_ENDIAN);
1355 offset += 2;
1357 break;
1358 case Z21_LAN_CAN_DEVICE_GET_DESCRIPTION:
1359 case Z21_LAN_CAN_DEVICE_SET_DESCRIPTION:
1360 proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1361 tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1362 offset += 2;
1363 col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1364 proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1365 if (datalen > 6) {
1366 proto_tree_add_item(z21_tree, hf_z21_can_booster_name,
1367 tvb, offset, 16, ENC_ISO_8859_1);
1368 offset += 16;
1370 break;
1371 case Z21_LAN_CAN_BOOSTER_SYSTEMSTATE_CHGD:
1372 proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1373 tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1374 offset += 2;
1375 col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1376 proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1377 proto_tree_add_item(z21_tree, hf_z21_can_booster_output_port,
1378 tvb, offset, 2, ENC_LITTLE_ENDIAN);
1379 offset += 2;
1380 proto_tree_add_bitmask(z21_tree, tvb, offset,
1381 hf_z21_can_booster_state, ett_z21, booster_state_bits, ENC_LITTLE_ENDIAN);
1382 offset += 2;
1383 temp_uint = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1384 proto_tree_add_uint_format_value(z21_tree, hf_z21_can_booster_vcc,
1385 tvb, offset, 2, temp_uint, "%d mV", temp_uint);
1386 offset += 2;
1387 temp_uint = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1388 proto_tree_add_uint_format_value(z21_tree, hf_z21_can_booster_current,
1389 tvb, offset, 2, temp_uint, "%d mA", temp_uint);
1390 offset += 2;
1391 break;
1392 case Z21_LAN_CAN_BOOSTER_SET_TRACKPOWER:
1393 proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1394 tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1395 offset += 2;
1396 col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1397 proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1398 proto_tree_add_item(z21_tree, hf_z21_can_booster_power, tvb, offset, 1, ENC_NA);
1399 offset += 1;
1400 break;
1401 case Z21_LAN_ZLINK_GET_HWINFO:
1402 proto_tree_add_item(z21_tree, hf_z21_zlink_message_type, tvb, offset, 1, ENC_NA);
1403 offset += 1;
1404 if (datalen > 5) {
1405 proto_tree_add_item(z21_tree, hf_z21_zlink_hwid,
1406 tvb, offset, 2, ENC_LITTLE_ENDIAN);
1407 offset += 2;
1408 proto_tree_add_item(z21_tree, hf_z21_zlink_fw_major, tvb, offset, 1, ENC_NA);
1409 offset += 1;
1410 proto_tree_add_item(z21_tree, hf_z21_zlink_fw_minor, tvb, offset, 1, ENC_NA);
1411 offset += 1;
1412 proto_tree_add_item(z21_tree, hf_z21_zlink_fw_build, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1413 offset += 2;
1414 proto_tree_add_item(z21_tree, hf_z21_zlink_mac, tvb, offset, 18, ENC_ASCII);
1415 offset += 18;
1416 proto_tree_add_item(z21_tree, hf_z21_zlink_name, tvb, offset, 33, ENC_ISO_8859_1);
1417 offset += 18;
1418 proto_tree_add_item(z21_tree, hf_z21_zlink_reserved, tvb, offset, 1, ENC_NA);
1419 offset += 1;
1421 break;
1422 case Z21_LAN_BOOSTER_GET_DESCRIPTION:
1423 case Z21_LAN_BOOSTER_SET_DESCRIPTION:
1424 if (datalen > 4) {
1425 /* SET_DESCRIPTION or reply to GET_DESCRIPTION */
1426 uint8_t *buf = tvb_get_stringz_enc(pinfo->pool, tvb, offset, NULL, ENC_ISO_8859_1);
1427 if (buf[0] == 0xff) {
1428 /* Interpreted as an empty name */
1429 proto_tree_add_string(z21_tree, hf_z21_booster_name, tvb, offset, 32, "");
1431 else {
1432 proto_tree_add_string(z21_tree, hf_z21_booster_name, tvb, offset, 32, buf);
1434 offset += 32;
1436 break;
1437 case Z21_LAN_BOOSTER_SYSTEMSTATE_GETDATA:
1438 case Z21_LAN_DECODER_SYSTEMSTATE_GETDATA:
1439 break;
1440 case Z21_LAN_DECODER_GET_DESCRIPTION:
1441 case Z21_LAN_DECODER_SET_DESCRIPTION:
1442 if (datalen > 4) {
1443 /* SET_DESCRIPTION or reply to GET_DESCRIPTION */
1444 uint8_t *buf = tvb_get_stringz_enc(pinfo->pool, tvb, offset, NULL, ENC_ISO_8859_1);
1445 if (buf[0] == 0xff) {
1446 /* Interpreted as an empty name */
1447 proto_tree_add_string(z21_tree, hf_z21_decoder_name, tvb, offset, 32, "");
1449 else {
1450 proto_tree_add_string(z21_tree, hf_z21_decoder_name, tvb, offset, 32, buf);
1452 offset += 32;
1454 break;
1455 case Z21_LAN_BOOSTER_SET_POWER:
1456 proto_tree_add_item_ret_uint(z21_tree, hf_z21_booster_port,
1457 tvb, offset, 1, ENC_NA, &temp_uint);
1458 offset += 1;
1459 col_append_fstr(pinfo->cinfo, COL_INFO, ", Port=%d", temp_uint);
1460 proto_item_append_text(z21_tree, ", Port: %d", temp_uint);
1461 proto_tree_add_item_ret_uint(z21_tree, hf_z21_booster_port_state,
1462 tvb, offset, 1, ENC_NA, &temp_uint);
1463 offset += 1;
1464 col_append_fstr(pinfo->cinfo, COL_INFO, ", State=%d", temp_uint);
1465 proto_item_append_text(z21_tree, ", State: %d", temp_uint);
1466 break;
1467 case Z21_LAN_BOOSTER_SYSTEMSTATE_DATACHANGED:
1468 /* To be expanded later... */
1469 proto_tree_add_item(z21_tree, hf_z21_booster_state_data,
1470 tvb, offset, 24, ENC_NA);
1471 offset += 24;
1472 break;
1473 case Z21_LAN_DECODER_SYSTEMSTATE_DATACHANGED:
1474 /* To be expanded later... */
1475 /* Data is variable length */
1476 proto_tree_add_item(z21_tree, hf_z21_decoder_state_data,
1477 tvb, offset, datalen-4, ENC_NA);
1478 offset += datalen-4;
1479 break;
1480 case Z21_LAN_GET_LOCOMODE:
1481 case Z21_LAN_SET_LOCOMODE:
1482 address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1483 addr = address_bytes & 0x3FFF;
1484 proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
1485 offset += 2;
1486 col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
1487 if (datalen > 6) {
1488 unsigned mode = tvb_get_uint8(tvb, offset);
1489 proto_tree_add_uint(z21_tree, hf_z21_loco_mode, tvb, offset, 1, mode);
1490 offset += 1;
1491 col_append_fstr(pinfo->cinfo, COL_INFO, ", Mode: %d", mode);
1493 break;
1494 case Z21_LAN_GET_BROADCASTFLAGS:
1495 case Z21_LAN_SET_BROADCASTFLAGS:
1496 if (datalen == 8) {
1497 proto_tree_add_bitmask_with_flags(z21_tree, tvb, offset, hf_z21_broadcast_flags,
1498 ett_z21, broadcast_flags_bits, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
1499 offset += 4;
1501 break;
1502 case Z21_LAN_GET_HWINFO:
1503 if (datalen == 12) {
1504 unsigned hwtype = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN);
1505 proto_tree_add_uint(z21_tree, hf_z21_hw_type, tvb, offset, 1, hwtype);
1506 offset += 4;
1507 version = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN);
1508 buffer = wmem_strdup_printf(pinfo->pool, "%x.%02x",
1509 version >> 8, version & 0xff);
1510 proto_tree_add_string(z21_tree, hf_z21_firmware_version,
1511 tvb, offset, 2, buffer);
1512 offset += 4;
1514 break;
1516 if (offset < datalen) {
1517 /* Just dump all the rest, if any */
1518 proto_tree_add_item(z21_tree, hf_z21_data, tvb, offset, datalen-offset, ENC_NA);
1519 offset += datalen-offset;
1522 return offset;
1525 static unsigned
1526 get_z21_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1528 return tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
1531 static bool
1532 check_z21_header(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1534 int remaining_length = tvb_reported_length_remaining(tvb, offset);
1535 if (remaining_length < Z21_MIN_LENGTH) {
1536 return false;
1538 int pdu_len = get_z21_pdu_len(pinfo, tvb, offset, data);
1539 if (pdu_len < Z21_MIN_LENGTH || pdu_len > remaining_length) {
1540 return false;
1542 uint16_t command = tvb_get_uint16(tvb, offset + 2, ENC_BIG_ENDIAN);
1543 if (!try_val_to_str(command, z21_command_vals)) {
1544 return false;
1546 return true;
1549 static int
1550 dissect_z21(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1552 return udp_dissect_pdus(tvb, pinfo, tree, Z21_MIN_LENGTH,
1553 check_z21_header, get_z21_pdu_len, dissect_z21_pdu, data);
1556 /* Register the protocol with Wireshark.
1558 * This format is required because a script is used to build the C function that
1559 * calls all the protocol registration.
1561 void
1562 proto_register_z21(void)
1564 expert_module_t *expert_z21;
1566 static hf_register_info hf[] = {
1567 { &hf_z21_datalen,
1568 { "Data length", "z21.datalen",
1569 FT_UINT16, BASE_DEC, NULL, 0x0,
1570 NULL, HFILL }
1572 { &hf_z21_command,
1573 { "Command", "z21.command",
1574 FT_UINT32, BASE_HEX|BASE_NO_DISPLAY_VALUE, VALS(z21_command_vals), 0x0,
1575 NULL, HFILL }
1577 { &hf_z21_x_bus,
1578 { "X-BUS", "z21.xbus",
1579 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1580 NULL, HFILL }
1582 { &hf_z21_serial_number,
1583 { "Serial number", "z21.serialnumber",
1584 FT_UINT32, BASE_DEC, NULL, 0x0,
1585 NULL, HFILL }
1587 { &hf_z21_checksum,
1588 { "Checksum", "z21.checksum",
1589 FT_UINT8, BASE_HEX, NULL, 0x0,
1590 NULL, HFILL }
1592 { &hf_z21_main_current,
1593 { "Main track current", "z21.maincurrent",
1594 FT_INT16, BASE_DEC, NULL, 0x0,
1595 NULL, HFILL }
1597 { &hf_z21_prog_current,
1598 { "Programming track current", "z21.progcurrent",
1599 FT_INT16, BASE_DEC, NULL, 0x0,
1600 NULL, HFILL }
1602 { &hf_z21_filtered_main_current,
1603 { "Filtered main track current", "z21.filteredmaincurrent",
1604 FT_INT16, BASE_DEC, NULL, 0x0,
1605 NULL, HFILL }
1607 { &hf_z21_temperature,
1608 { "Command station temperature", "z21.temperature",
1609 FT_INT16, BASE_DEC, NULL, 0x0,
1610 NULL, HFILL }
1612 { &hf_z21_supply_voltage,
1613 { "Supply voltage", "z21.supplyvoltage",
1614 FT_FLOAT, BASE_DEC, NULL, 0x0,
1615 NULL, HFILL }
1617 { &hf_z21_track_voltage,
1618 { "Track voltage", "z21.trackvoltage",
1619 FT_FLOAT, BASE_DEC, NULL, 0x0,
1620 NULL, HFILL }
1622 { &hf_z21_broadcast_flags,
1623 { "Broadcast flags", "z21.broadcastflags",
1624 FT_UINT32, BASE_HEX, NULL, 0x0,
1625 NULL, HFILL }
1627 { &hf_z21_central_state,
1628 { "Central state, first byte", "z21.centralstate1",
1629 FT_UINT8, BASE_HEX, NULL, 0x0,
1630 NULL, HFILL }
1632 { &hf_z21_central_state_ex,
1633 { "Central state, second byte", "z21.centralstate2",
1634 FT_UINT8, BASE_HEX, NULL, 0x0,
1635 NULL, HFILL }
1637 { &hf_z21_systemstate_reserved,
1638 { "Reserved", "z21.systemstatereserved",
1639 FT_UINT8, BASE_HEX, NULL, 0x0,
1640 NULL, HFILL }
1642 { &hf_z21_capabilities,
1643 { "Capabilities", "z21.capabilities",
1644 FT_UINT8, BASE_HEX, NULL, 0x0,
1645 NULL, HFILL }
1647 { &hf_z21_status,
1648 { "Status", "z21.status",
1649 FT_UINT8, BASE_HEX, NULL, 0x0,
1650 NULL, HFILL }
1652 { &hf_z21_broadcast_flags_driving_switching,
1653 { "Broadcasts messages concerning driving and switching", "z21.broadcastflags.driving_switching",
1654 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000001,
1655 NULL, HFILL }
1657 { &hf_z21_broadcast_flags_rmbus,
1658 { "Changes of the feedback devices on the R-Bus", "z21.broadcastflags.rmbus",
1659 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000002,
1660 NULL, HFILL }
1662 { &hf_z21_broadcast_flags_railcom_subscribed,
1663 { "Changes of RailCom data of subscribed locomotives", "z21.broadcastflags.railcom_subscribed",
1664 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000004,
1665 NULL, HFILL }
1667 { &hf_z21_broadcast_flags_system_status,
1668 { "Changes of the Z21 system status", "z21.broadcastflags.system_status",
1669 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000100,
1670 NULL, HFILL }
1672 { &hf_z21_broadcast_flags_driving_switching_ex,
1673 { "Extends flag 0x00000001, LAN_X_LOCO_INFO is sent for all modified locomotives", "z21.broadcastflags.driving_switching_ex",
1674 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00010000,
1675 NULL, HFILL }
1677 { &hf_z21_broadcast_flags_loconet,
1678 { "Forward messages from LocoNet without locos and switches", "z21.broadcastflags.loconet",
1679 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x01000000,
1680 NULL, HFILL }
1682 { &hf_z21_broadcast_flags_loconet_driving,
1683 { "Forward locomotive-specific LocoNet", "z21.broadcastflags.loconet_driving",
1684 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x02000000,
1685 NULL, HFILL }
1687 { &hf_z21_broadcast_flags_loconet_switching,
1688 { "Forward switch-specific LocoNet", "z21.broadcastflags.loconet_switching",
1689 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x04000000,
1690 NULL, HFILL }
1692 { &hf_z21_broadcast_flags_loconet_detector,
1693 { "Changes of LocoNet track occupancy detectors", "z21.broadcastflags.emergencystop",
1694 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x08000000,
1695 NULL, HFILL }
1697 { &hf_z21_broadcast_flags_railcom,
1698 { "Changes of RailCom data", "z21.broadcastflags.railcom",
1699 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00040000,
1700 NULL, HFILL }
1702 { &hf_z21_broadcast_flags_can_detector,
1703 { "Changes of CAN-Bus track occupancy detectors", "z21.broadcastflags.can_detector",
1704 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00080000,
1705 NULL, HFILL }
1707 { &hf_z21_broadcast_flags_can_booster,
1708 { "Forward CAN-Bus booster status messages", "z21.broadcastflags.can_booster",
1709 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00020000,
1710 NULL, HFILL }
1712 { &hf_z21_broadcast_flags_fast_clock,
1713 { "Fast clock time messages", "z21.broadcastflags.fast_clock",
1714 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000010,
1715 NULL, HFILL }
1717 { &hf_z21_state_emergency_stop,
1718 { "Emergency stop", "z21.state.emergencystop",
1719 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1720 NULL, HFILL }
1722 { &hf_z21_state_track_voltage_off,
1723 { "Track voltage off", "z21.state.trackvoltageoff",
1724 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1725 NULL, HFILL }
1727 { &hf_z21_state_short_circuit,
1728 { "Short circuit", "z21.state.shortcircuit",
1729 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1730 NULL, HFILL }
1732 { &hf_z21_state_programming_mode,
1733 { "Programming mode", "z21.state.programmingmode",
1734 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1735 NULL, HFILL }
1737 { &hf_z21_state_high_temperature,
1738 { "High temperature", "z21.state.hightemperature",
1739 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1740 NULL, HFILL }
1742 { &hf_z21_state_power_lost,
1743 { "Power lost", "z21.state.powerlost",
1744 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1745 NULL, HFILL }
1747 { &hf_z21_state_short_circuit_external,
1748 { "External short circuit", "z21.state.externalshortcircuit",
1749 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1750 NULL, HFILL }
1752 { &hf_z21_state_short_circuit_internal,
1753 { "Internal short circuit", "z21.state.internalshortcircuit",
1754 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1755 NULL, HFILL }
1757 { &hf_z21_state_rcn_213,
1758 { "RCN-213 turnout addressing", "z21.state.rcn213addressing",
1759 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1760 NULL, HFILL }
1762 { &hf_z21_capability_dcc,
1763 { "DCC capability", "z21.capability.dcc",
1764 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1765 NULL, HFILL }
1767 { &hf_z21_capability_mm,
1768 { "MM capability", "z21.capability.mm",
1769 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1770 NULL, HFILL }
1772 { &hf_z21_capability_reserved,
1773 { "Reserved capability", "z21.capability.reserved",
1774 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1775 NULL, HFILL }
1777 { &hf_z21_capability_railcom,
1778 { "RailCom capability", "z21.capability.railcom",
1779 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1780 NULL, HFILL }
1782 { &hf_z21_capability_loco_cmds,
1783 { "Accepts LAN commands for locomotive decoders", "z21.capability.lococmds",
1784 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1785 NULL, HFILL }
1787 { &hf_z21_capability_accessory_cmds,
1788 { "Accepts LAN commands for accessory decoders", "z21.capability.accessorycmds",
1789 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1790 NULL, HFILL }
1792 { &hf_z21_capability_detector_cmds,
1793 { "Accepts LAN commands for detectors", "z21.capability.detectorcmds",
1794 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1795 NULL, HFILL }
1797 { &hf_z21_capability_needs_unlock_code,
1798 { "Needs unlock code", "z21.capability.needsunlockcode",
1799 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
1800 NULL, HFILL }
1802 { &hf_z21_loco_mode,
1803 { "Locomotive mode", "z21.locomode",
1804 FT_UINT8, BASE_DEC, VALS(z21_loco_mode_vals), 0x0,
1805 NULL, HFILL }
1807 { &hf_z21_loco_address,
1808 { "Locomotive address", "z21.locoaddress",
1809 FT_UINT16, BASE_DEC, NULL, 0x0,
1810 NULL, HFILL }
1812 { &hf_z21_loco_direction_and_speed,
1813 { "Locomotive direction and speed", "z21.locodirectionandspeed",
1814 FT_UINT8, BASE_HEX, NULL, 0x0,
1815 NULL, HFILL }
1817 { &hf_z21_loco_direction,
1818 { "Locomotive direction", "z21.locodirection",
1819 FT_BOOLEAN, 8, TFS(&tfs_forward_reverse), 0x80,
1820 NULL, HFILL }
1822 { &hf_z21_loco_speed,
1823 { "Locomotive speed", "z21.locospeed",
1824 FT_UINT8, BASE_HEX, NULL, 0x7F,
1825 NULL, HFILL }
1827 { &hf_z21_loco_info_mm,
1828 { "Locomotive is MM (MƤrklin-Motorola)", "z21.locomm",
1829 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1830 NULL, HFILL }
1832 { &hf_z21_loco_info_busy,
1833 { "Locomotive is busy", "z21.locoinfobusy",
1834 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1835 "Locomotive is controlled by another X-BUS handset controller", HFILL }
1837 { &hf_z21_loco_info_speed_steps,
1838 { "Locomotive speed steps", "z21.locoinfospeedsteps",
1839 FT_UINT8, BASE_DEC, VALS(z21_loco_info_speed_steps_vals), 0x07,
1840 NULL, HFILL }
1842 { &hf_z21_loco_info_direction,
1843 { "Locomotive direction", "z21.locoinfodirection",
1844 FT_BOOLEAN, 8, TFS(&tfs_forward_reverse), 0x80,
1845 NULL, HFILL }
1847 { &hf_z21_loco_info_speed,
1848 { "Locomotive speed", "z21.locoinfospeed",
1849 FT_UINT8, BASE_HEX, NULL, 0x7f,
1850 NULL, HFILL }
1852 { &hf_z21_loco_info_double_traction,
1853 { "Double traction", "z21.locoinfodoubletraction",
1854 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1855 NULL, HFILL }
1857 { &hf_z21_loco_info_smartsearch,
1858 { "Smartsearch", "z21.locoinfosmartsearch",
1859 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1860 NULL, HFILL }
1862 { &hf_z21_loco_info_f0,
1863 { "Function F0 (lights)", "z21.locoinfof0",
1864 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1865 NULL, HFILL }
1867 { &hf_z21_loco_info_f4,
1868 { "Function F4", "z21.locoinfof4",
1869 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1870 NULL, HFILL }
1872 { &hf_z21_loco_info_f3,
1873 { "Function F3", "z21.locoinfof3",
1874 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1875 NULL, HFILL }
1877 { &hf_z21_loco_info_f2,
1878 { "Function F2", "z21.locoinfof2",
1879 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1880 NULL, HFILL }
1882 { &hf_z21_loco_info_f1,
1883 { "Function F1", "z21.locoinfof1",
1884 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1885 NULL, HFILL }
1887 { &hf_z21_loco_info_f12,
1888 { "Function F12", "z21.locoinfof12",
1889 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
1890 NULL, HFILL }
1892 { &hf_z21_loco_info_f11,
1893 { "Function F11", "z21.locoinfof11",
1894 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1895 NULL, HFILL }
1897 { &hf_z21_loco_info_f10,
1898 { "Function F10", "z21.locoinfof10",
1899 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1900 NULL, HFILL }
1902 { &hf_z21_loco_info_f9,
1903 { "Function F9", "z21.locoinfof9",
1904 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1905 NULL, HFILL }
1907 { &hf_z21_loco_info_f8,
1908 { "Function F8", "z21.locoinfof8",
1909 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1910 NULL, HFILL }
1912 { &hf_z21_loco_info_f7,
1913 { "Function F7", "z21.locoinfof7",
1914 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1915 NULL, HFILL }
1917 { &hf_z21_loco_info_f6,
1918 { "Function F6", "z21.locoinfof6",
1919 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1920 NULL, HFILL }
1922 { &hf_z21_loco_info_f5,
1923 { "Function F5", "z21.locoinfof5",
1924 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1925 NULL, HFILL }
1927 { &hf_z21_loco_info_f20,
1928 { "Function F20", "z21.locoinfof20",
1929 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
1930 NULL, HFILL }
1932 { &hf_z21_loco_info_f19,
1933 { "Function F19", "z21.locoinfof19",
1934 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1935 NULL, HFILL }
1937 { &hf_z21_loco_info_f18,
1938 { "Function F18", "z21.locoinfof18",
1939 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1940 NULL, HFILL }
1942 { &hf_z21_loco_info_f17,
1943 { "Function F17", "z21.locoinfof17",
1944 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1945 NULL, HFILL }
1947 { &hf_z21_loco_info_f16,
1948 { "Function F16", "z21.locoinfof16",
1949 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1950 NULL, HFILL }
1952 { &hf_z21_loco_info_f15,
1953 { "Function F15", "z21.locoinfof15",
1954 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1955 NULL, HFILL }
1957 { &hf_z21_loco_info_f14,
1958 { "Function F14", "z21.locoinfof14",
1959 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1960 NULL, HFILL }
1962 { &hf_z21_loco_info_f13,
1963 { "Function F13", "z21.locoinfof13",
1964 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1965 NULL, HFILL }
1967 { &hf_z21_loco_info_f28,
1968 { "Function F28", "z21.locoinfof28",
1969 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
1970 NULL, HFILL }
1972 { &hf_z21_loco_info_f27,
1973 { "Function F27", "z21.locoinfof27",
1974 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1975 NULL, HFILL }
1977 { &hf_z21_loco_info_f26,
1978 { "Function F26", "z21.locoinfof26",
1979 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1980 NULL, HFILL }
1982 { &hf_z21_loco_info_f25,
1983 { "Function F25", "z21.locoinfof25",
1984 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1985 NULL, HFILL }
1987 { &hf_z21_loco_info_f24,
1988 { "Function F24", "z21.locoinfof24",
1989 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1990 NULL, HFILL }
1992 { &hf_z21_loco_info_f23,
1993 { "Function F23", "z21.locoinfof23",
1994 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1995 NULL, HFILL }
1997 { &hf_z21_loco_info_f22,
1998 { "Function F22", "z21.locoinfof22",
1999 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
2000 NULL, HFILL }
2002 { &hf_z21_loco_info_f21,
2003 { "Function F21", "z21.locoinfof21",
2004 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
2005 NULL, HFILL }
2007 { &hf_z21_loco_info_f31,
2008 { "Function F31", "z21.locoinfof31",
2009 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
2010 NULL, HFILL }
2012 { &hf_z21_loco_info_f30,
2013 { "Function F30", "z21.locoinfof30",
2014 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
2015 NULL, HFILL }
2017 { &hf_z21_loco_info_f29,
2018 { "Function F29", "z21.locoinfof29",
2019 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
2020 NULL, HFILL }
2022 { &hf_z21_loco_info_extensions,
2023 { "Extensions", "z21.locoinfoextensions",
2024 FT_BYTES, BASE_NONE, NULL, 0x0,
2025 NULL, HFILL }
2027 { &hf_z21_speed_steps,
2028 { "Speed steps", "z21.speedsteps",
2029 FT_UINT8, BASE_DEC, NULL, 0x0,
2030 NULL, HFILL }
2032 { &hf_z21_hw_type,
2033 { "Hardware type", "z21.hwtype",
2034 FT_UINT32, BASE_HEX, VALS(z21_hw_type_vals), 0x0,
2035 NULL, HFILL }
2037 { &hf_z21_firmware_version,
2038 { "Firmware version", "z21.firmwareversion",
2039 FT_STRING, BASE_NONE, NULL, 0x0,
2040 NULL, HFILL }
2042 { &hf_z21_loco_func_switch_type,
2043 { "Locomotive function switch type", "z21.locofunctionswitchtype",
2044 FT_UINT8, BASE_DEC, VALS(z21_loco_func_vals), 0xc0,
2045 NULL, HFILL }
2047 { &hf_z21_loco_func_index,
2048 { "Locomotive function index", "z21.locofunctionindex",
2049 FT_UINT8, BASE_DEC, NULL, 0x3f,
2050 NULL, HFILL }
2052 { &hf_z21_function_address,
2053 { "Function address", "z21.functionaddress",
2054 FT_UINT16, BASE_DEC, NULL, 0x0,
2055 NULL, HFILL }
2057 { &hf_z21_turnout_state,
2058 { "Turnout state", "z21.turnoutstate",
2059 FT_UINT8, BASE_DEC, VALS(z21_turnout_state_vals), 0x03,
2060 NULL, HFILL }
2062 { &hf_z21_turnout_queue_bit,
2063 { "Queue the turnout command", "z21.turnoutqueue",
2064 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
2065 NULL, HFILL }
2067 { &hf_z21_turnout_activate_bit,
2068 { "Turnout command", "z21.turnoutcommand",
2069 FT_BOOLEAN, 8, TFS(&tfs_turnout_command), 0x08,
2070 NULL, HFILL }
2072 { &hf_z21_turnout_output_bit,
2073 { "Select turnout output", "z21.turnoutoutput",
2074 FT_BOOLEAN, 8, TFS(&tfs_turnout_output), 0x01,
2075 NULL, HFILL }
2077 { &hf_z21_accessory_address,
2078 { "Accessory address", "z21.accessoryaddress",
2079 FT_UINT16, BASE_DEC, NULL, 0x0,
2080 NULL, HFILL }
2082 { &hf_z21_accessory_state,
2083 { "Accessory state", "z21.accessorystate",
2084 FT_UINT8, BASE_DEC, NULL, 0x0,
2085 NULL, HFILL }
2087 { &hf_z21_accessory_status,
2088 { "Accessory status", "z21.accessorystatus",
2089 FT_UINT8, BASE_HEX, NULL, 0x0,
2090 NULL, HFILL }
2092 { &hf_z21_cv_address,
2093 { "CV address", "z21.cvaddress",
2094 FT_UINT16, BASE_DEC, NULL, 0x0,
2095 NULL, HFILL }
2097 { &hf_z21_cv_value,
2098 { "CV value", "z21.cvvalue",
2099 FT_UINT8, BASE_DEC, NULL, 0x0,
2100 NULL, HFILL }
2102 { &hf_z21_register,
2103 { "Register", "z21.register",
2104 FT_UINT8, BASE_DEC, NULL, 0x0,
2105 NULL, HFILL }
2107 { &hf_z21_register_value,
2108 { "Register value", "z21.registervalue",
2109 FT_UINT8, BASE_DEC, NULL, 0x0,
2110 NULL, HFILL }
2112 { &hf_z21_pom_operation,
2113 { "POM operation", "z21.pomoperation",
2114 FT_UINT16, BASE_HEX, VALS(z21_pom_operation_vals), 0x0,
2115 NULL, HFILL }
2117 { &hf_z21_cv_bit_position,
2118 { "CV bit position", "z21.cvbitposition",
2119 FT_UINT8, BASE_DEC, NULL, 0x07,
2120 NULL, HFILL }
2122 { &hf_z21_cv_bit_value,
2123 { "CV bit value", "z21.cvbitvalue",
2124 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x08,
2125 NULL, HFILL }
2127 { &hf_z21_rmbus_group,
2128 { "R-BUS group index", "z21.rbusgroup",
2129 FT_UINT8, BASE_DEC, NULL, 0x0,
2130 NULL, HFILL }
2132 { &hf_z21_rmbus_feedbacks,
2133 { "R-BUS feedbacks", "z21.rbusfeedbacks",
2134 FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2135 NULL, HFILL }
2137 { &hf_z21_rmbus_address,
2138 { "R-BUS feedback module address", "z21.rbusaddress",
2139 FT_UINT8, BASE_DEC, NULL, 0x0,
2140 NULL, HFILL }
2142 { &hf_z21_railcom_receive_counter,
2143 { "RailCom receive counter", "z21.railcomreceives",
2144 FT_UINT32, BASE_DEC, NULL, 0x0,
2145 NULL, HFILL }
2147 { &hf_z21_railcom_error_counter,
2148 { "RailCom error counter", "z21.railcomerrors",
2149 FT_UINT16, BASE_DEC, NULL, 0x0,
2150 NULL, HFILL }
2152 { &hf_z21_railcom_reserved1,
2153 { "RailCom reserved 1", "z21.railcomreserved1",
2154 FT_UINT8, BASE_HEX, NULL, 0x0,
2155 NULL, HFILL }
2157 { &hf_z21_railcom_reserved2,
2158 { "RailCom reserved 2", "z21.railcomreserved2",
2159 FT_UINT8, BASE_HEX, NULL, 0x0,
2160 NULL, HFILL }
2162 { &hf_z21_railcom_options,
2163 { "RailCom options", "z21.railcomoptions",
2164 FT_UINT8, BASE_HEX, NULL, 0x0,
2165 NULL, HFILL }
2167 { &hf_z21_railcom_speed,
2168 { "RailCom speed", "z21.railcomspeed",
2169 FT_UINT8, BASE_HEX, NULL, 0x0,
2170 NULL, HFILL }
2172 { &hf_z21_railcom_qos,
2173 { "RailCom QoS", "z21.railcomqos",
2174 FT_UINT8, BASE_HEX, NULL, 0x0,
2175 NULL, HFILL }
2177 { &hf_z21_railcom_type,
2178 { "RailCom type", "z21.railcomtype",
2179 FT_UINT8, BASE_HEX, NULL, 0x0,
2180 NULL, HFILL }
2182 { &hf_z21_loconet_message,
2183 { "LocoNet message", "z21.loconetmessage",
2184 FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2185 NULL, HFILL }
2187 { &hf_z21_loconet_result,
2188 { "LocoNet result", "z21.loconetresult",
2189 FT_UINT8, BASE_HEX, NULL, 0x0,
2190 NULL, HFILL }
2192 { &hf_z21_loconet_type,
2193 { "LocoNet type", "z21.loconettype",
2194 FT_UINT8, BASE_HEX, NULL, 0x0,
2195 NULL, HFILL }
2197 { &hf_z21_loconet_report_address,
2198 { "LocoNet report address", "z21.loconetreportaddress",
2199 FT_UINT16, BASE_DEC, NULL, 0x0,
2200 NULL, HFILL }
2202 { &hf_z21_loconet_feedback_address,
2203 { "LocoNet feedback address", "z21.loconetfeedbackaddress",
2204 FT_UINT16, BASE_DEC, NULL, 0x0,
2205 NULL, HFILL }
2207 { &hf_z21_loconet_info,
2208 { "LocoNet info", "z21.loconetinfo",
2209 FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2210 NULL, HFILL }
2212 { &hf_z21_can_type,
2213 { "CAN type", "z21.cantype",
2214 FT_UINT8, BASE_HEX, NULL, 0x0,
2215 NULL, HFILL }
2217 { &hf_z21_can_network_id,
2218 { "CAN network ID", "z21.cannetworkid",
2219 FT_UINT16, BASE_HEX, NULL, 0x0,
2220 NULL, HFILL }
2222 { &hf_z21_can_module_address,
2223 { "CAN module address", "z21.canmoduleaddress",
2224 FT_UINT16, BASE_HEX, NULL, 0x0,
2225 NULL, HFILL }
2227 { &hf_z21_can_port,
2228 { "CAN input port (pin)", "z21.canport",
2229 FT_UINT8, BASE_DEC, NULL, 0x0,
2230 NULL, HFILL }
2232 { &hf_z21_can_value1,
2233 { "CAN value 1", "z21.canvalue1",
2234 FT_UINT16, BASE_HEX, NULL, 0x0,
2235 NULL, HFILL }
2237 { &hf_z21_can_value2,
2238 { "CAN value 2", "z21.canvalue2",
2239 FT_UINT16, BASE_HEX, NULL, 0x0,
2240 NULL, HFILL }
2242 { &hf_z21_can_booster_name,
2243 { "CAN booster name", "z21.canboostername",
2244 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2245 NULL, HFILL }
2247 { &hf_z21_can_booster_output_port,
2248 { "CAN booster output port", "z21.canboosteroutputport",
2249 FT_UINT16, BASE_DEC, NULL, 0x0,
2250 NULL, HFILL }
2252 { &hf_z21_can_booster_state,
2253 { "CAN booster state", "z21.canboosterstate",
2254 FT_UINT16, BASE_HEX, NULL, 0x0,
2255 NULL, HFILL }
2257 { &hf_z21_can_booster_state_bg_active,
2258 { "CAN booster brake generator active", "z21.canboosterbrakegenerator",
2259 FT_BOOLEAN, 16, NULL, 0x0001,
2260 NULL, HFILL }
2262 { &hf_z21_can_booster_state_short_circuit,
2263 { "CAN booster short circuit", "z21.canboostershortcircuit",
2264 FT_BOOLEAN, 16, NULL, 0x0020,
2265 NULL, HFILL }
2267 { &hf_z21_can_booster_state_track_voltage_off,
2268 { "CAN booster track voltage off", "z21.canboostertrackvoltageoff",
2269 FT_BOOLEAN, 16, NULL, 0x0080,
2270 NULL, HFILL }
2272 { &hf_z21_can_booster_state_railcom_active,
2273 { "CAN booster RailCom cutout active", "z21.canboosterrailcomactive",
2274 FT_BOOLEAN, 16, NULL, 0x0800,
2275 NULL, HFILL }
2277 { &hf_z21_can_booster_state_output_disabled,
2278 { "CAN booster output disabled", "z21.canboosteroutputdisabled",
2279 FT_BOOLEAN, 16, NULL, 0x0100,
2280 NULL, HFILL }
2282 { &hf_z21_can_booster_vcc,
2283 { "CAN booster VCC voltage", "z21.canboostervoltage",
2284 FT_UINT16, BASE_DEC, NULL, 0x0,
2285 NULL, HFILL }
2287 { &hf_z21_can_booster_current,
2288 { "CAN booster current", "z21.canboostercurrent",
2289 FT_UINT16, BASE_DEC, NULL, 0x0,
2290 NULL, HFILL }
2292 { &hf_z21_can_booster_power,
2293 { "CAN booster power", "z21.canboosterpower",
2294 FT_UINT16, BASE_HEX, NULL, 0x0,
2295 NULL, HFILL }
2297 { &hf_z21_zlink_message_type,
2298 { "zLink message type", "z21.zlinkmessagetype",
2299 FT_UINT8, BASE_HEX, VALS(z21_zlink_message_type_vals), 0x0,
2300 NULL, HFILL }
2302 { &hf_z21_zlink_hwid,
2303 { "zLink hardware ID", "z21.zlinkhwid",
2304 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2305 NULL, HFILL }
2307 { &hf_z21_zlink_fw_major,
2308 { "zLink firmware major version", "z21.zlinkmajorversion",
2309 FT_UINT8, BASE_DEC, NULL, 0x0,
2310 NULL, HFILL }
2312 { &hf_z21_zlink_fw_minor,
2313 { "zLink firmware minor version", "z21.zlinkminorversion",
2314 FT_UINT8, BASE_DEC, NULL, 0x0,
2315 NULL, HFILL }
2317 { &hf_z21_zlink_fw_build,
2318 { "zLink firmware build version", "z21.zlinkbuildversion",
2319 FT_UINT16, BASE_DEC, NULL, 0x0,
2320 NULL, HFILL }
2322 { &hf_z21_zlink_mac,
2323 { "zLink MAC address", "z21.zlinkmac",
2324 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2325 NULL, HFILL }
2327 { &hf_z21_zlink_name,
2328 { "zLink name", "z21.zlinkname",
2329 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2330 NULL, HFILL }
2332 { &hf_z21_zlink_reserved,
2333 { "zLink reserved", "z21.zlinkreserved",
2334 FT_UINT8, BASE_HEX, NULL, 0x0,
2335 NULL, HFILL }
2337 { &hf_z21_booster_name,
2338 { "Booster name", "z21.boostername",
2339 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2340 NULL, HFILL }
2342 { &hf_z21_booster_port,
2343 { "Booster port", "z21.boosterport",
2344 FT_UINT8, BASE_HEX, NULL, 0x0,
2345 NULL, HFILL }
2347 { &hf_z21_booster_port_state,
2348 { "Booster port state", "z21.boosterportstate",
2349 FT_UINT8, BASE_HEX, NULL, 0x0,
2350 NULL, HFILL }
2352 { &hf_z21_booster_state_data,
2353 { "Booster state data", "z21.boosterstatedata",
2354 FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2355 NULL, HFILL }
2357 { &hf_z21_decoder_name,
2358 { "Decoder name", "z21.decodername",
2359 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2360 NULL, HFILL }
2362 { &hf_z21_decoder_state_data,
2363 { "Decoder state data", "z21.decoderstatedata",
2364 FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2365 NULL, HFILL }
2367 { &hf_z21_data,
2368 { "Undecoded data", "z21.data",
2369 FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2370 NULL, HFILL }
2374 /* Setup protocol subtree array */
2375 static int *ett[] = {
2376 &ett_z21,
2379 /* Setup protocol expert items */
2380 static ei_register_info ei[] = {
2381 { &ei_z21_invalid_checksum,
2382 { "z21.invalidchecksum", PI_CHECKSUM, PI_WARN,
2383 "Invalid XOR checksum", EXPFILL }
2387 /* Register the protocol name and description */
2388 proto_z21 = proto_register_protocol("Z21 LAN Protocol", "Z21", "z21");
2390 /* Required function calls to register the header fields and subtrees */
2391 proto_register_field_array(proto_z21, hf, array_length(hf));
2392 proto_register_subtree_array(ett, array_length(ett));
2394 /* Required function calls to register expert items */
2395 expert_z21 = expert_register_protocol(proto_z21);
2396 expert_register_field_array(expert_z21, ei, array_length(ei));
2398 z21_handle = register_dissector("z21", dissect_z21, proto_z21);
2400 /* Register a preferences module (see section 2.6 of README.dissector
2401 * for more details). Registration of a prefs callback is not required
2402 * if there are no preferences that affect protocol registration (an example
2403 * of a preference that would affect registration is a port preference).
2404 * If the prefs callback is not needed, use NULL instead of
2405 * proto_reg_handoff_z21 in the following.
2407 prefs_register_protocol(proto_z21, proto_reg_handoff_z21);
2410 void
2411 proto_reg_handoff_z21(void)
2413 static bool initialized = false;
2415 if (!initialized) {
2416 dissector_add_uint_range_with_preference("udp.port", Z21_UDP_PORTS, z21_handle);
2417 initialized = true;
2419 udp_port_range = prefs_get_range_value("Z21", "udp.port");