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
18 #define WS_LOG_DOMAIN "Z21"
20 #include <epan/packet.h>
21 #include <epan/expert.h>
22 #include <epan/prefs.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 */
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 */
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
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" },
392 static const value_string z21_loco_mode_vals
[] = {
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" },
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" },
420 static const value_string z21_loco_func_vals
[] = {
424 { 3, "Not allowed" },
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" },
436 static const value_string z21_pom_operation_vals
[] = {
437 { 0x39, "Read byte" }, /* 111001 */
438 { 0x3a, "Write bit" }, /* 111010 */
439 { 0x3b, "Write byte" }, /* 111011 */
443 static const value_string z21_zlink_message_type_vals
[] = {
444 { 0x06, "ZLINK_MSG_TYPE_HW_INFO" },
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" };
454 update_command_field(proto_item
*ti
, unsigned command
)
459 else if (command
<= 0xffff)
461 else if (command
<= 0xffffff)
463 proto_item_append_text(ti
, ": %s (0x%0*x)",
464 val_to_str_const(command
, z21_command_vals
, "unknown"),
469 /* Code to actually dissect the packets */
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
;
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
,
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
,
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
,
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
,
525 static int * const speed_bits
[] = {
526 &hf_z21_loco_direction
,
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
,
536 static int * const loco_info_bits2
[] = {
537 &hf_z21_loco_info_direction
,
538 &hf_z21_loco_info_speed
,
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
,
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
,
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
,
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
,
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
,
590 static int * const loco_func_bits
[] = {
591 &hf_z21_loco_func_switch_type
,
592 &hf_z21_loco_func_index
,
595 static int * const turnout_state_bits
[] = {
596 &hf_z21_turnout_state
,
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
,
605 static int * const cv_bits
[] = {
606 &hf_z21_cv_bit_value
,
607 &hf_z21_cv_bit_position
,
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
,
619 /* Check that the packet is long enough for it to belong to us. */
620 if (tvb_reported_length(tvb
) < Z21_MIN_LENGTH
)
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
);
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 */
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
);
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
;
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
;
692 command_ti
= proto_tree_add_uint(z21_tree
, hf_z21_command
,
693 tvb
, offset
, 4, x_bus_command
);
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
);
708 calculated_checksum
^= (unsigned)status
;
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
);
723 calculated_checksum
^= address_bytes
>> 8;
724 calculated_checksum
^= address_bytes
& 0xFF;
725 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Loco=%d (%d SS)",
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
);
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");
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);
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
);
751 calculated_checksum
^= address_bytes
>> 8;
752 calculated_checksum
^= address_bytes
& 0xFF;
753 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Loco=%d", addr
);
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
);
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
);
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
);
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
,
782 proto_tree_add_bitmask_list_ret_uint64(z21_tree
, tvb
, offset
, 1,
783 loco_info_bits3
, ENC_NA
, &temp_uint64
);
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
);
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
);
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
);
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
);
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! */
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
);
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
);
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
);
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
);
841 case Z21_LAN_X_SET_LOCO_BINARY_STATE
:
842 col_append_str(pinfo
->cinfo
, COL_INFO
, ", TO BE COMPLETED");
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
);
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
);
856 calculated_checksum
^= temp_uint64
;
857 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Function=%" PRIu64
", State=%s",
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",
862 val_to_str_const((uint32_t)temp_uint64
>> 6, z21_loco_func_vals
, "unknown"));
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
);
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
);
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
);
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
);
884 calculated_checksum
^= temp_uint64
;
885 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Address=%d, State=%s",
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",
890 val_to_str_const((uint32_t)temp_uint64
& 0x03, z21_turnout_state_vals
, "unknown"));
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
);
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
);
904 calculated_checksum
^= temp_uint64
;
905 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Address=%d, %s, Output=%s",
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",
911 tfs_get_string((bool)(temp_uint64
& 0x08), &tfs_turnout_command
),
912 tfs_get_string((bool)(temp_uint64
& 0x01), &tfs_turnout_output
));
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
);
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
);
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
);
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);
935 calculated_checksum
^= temp_uint
>> 8;
936 proto_tree_add_uint(z21_tree
, hf_z21_accessory_status
,
937 tvb
, offset
, 1, temp_uint
& 0xff);
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);
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
);
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
);
956 calculated_checksum
^= temp_uint
;
957 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Address=%d, State=%d",
959 proto_item_append_text(z21_tree
, ", Address: %d, State: %d",
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;
968 proto_tree_add_uint(z21_tree
, hf_z21_cv_address
,
969 tvb
, offset
, 2, cv_addr
);
971 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", CV%d", cv_addr
);
972 proto_item_append_text(z21_tree
, ", CV%d", cv_addr
);
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;
980 proto_tree_add_uint(z21_tree
, hf_z21_cv_address
,
981 tvb
, offset
, 2, cv_addr
);
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
);
987 calculated_checksum
^= temp_uint
;
988 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", CV%d, Value=%d",
990 proto_item_append_text(z21_tree
, ", CV%d, Value: %d",
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;
999 proto_tree_add_uint(z21_tree
, hf_z21_cv_address
,
1000 tvb
, offset
, 2, cv_addr
);
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
);
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
);
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
);
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
);
1028 proto_tree_add_item_ret_uint(z21_tree
, hf_z21_cv_value
,
1029 tvb
, offset
, 1, ENC_NA
, &temp_uint
);
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
);
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
);
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
);
1053 proto_tree_add_bitmask_list_ret_uint64(z21_tree
, tvb
, offset
, 1,
1054 cv_bits
, ENC_NA
, &temp_uint64
);
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);
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
);
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
);
1078 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Loco=%d, CV%d",
1080 proto_item_append_text(z21_tree
, ", Loco: %d, CV%d",
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 ***");
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
);
1093 calculated_checksum
^= temp_uint
;
1094 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Register%d",
1096 proto_item_append_text(z21_tree
, ", Register%d",
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);
1104 calculated_checksum
^= temp_uint
>> 8;
1105 proto_tree_add_uint(z21_tree
, hf_z21_register_value
,
1106 tvb
, offset
, 1, temp_uint
& 0xff);
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);
1114 case Z21_LAN_X_MM_WRITE_BYTE
:
1115 /* Skip one zero byte */
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);
1121 calculated_checksum
^= temp_uint
>> 8;
1122 proto_tree_add_uint(z21_tree
, hf_z21_register_value
,
1123 tvb
, offset
, 1, temp_uint
& 0xff);
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);
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
);
1138 calculated_checksum
^= version
>> 8;
1139 calculated_checksum
^= version
& 0xFF;
1140 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Version=%s",
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
);
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
);
1160 command_ti
= proto_tree_add_uint(z21_tree
, hf_z21_command
,
1161 tvb
, offset
, 2, command
);
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"));
1169 case Z21_LAN_GET_SERIAL_NUMBER
:
1172 proto_tree_add_item_ret_uint(z21_tree
, hf_z21_serial_number
,
1173 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &serial
);
1175 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Serial number: %d",
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
);
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
);
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
);
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
);
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
);
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
);
1216 proto_tree_add_bitmask(z21_tree
, tvb
, offset
, hf_z21_central_state
,
1217 ett_z21
, state_bits_byte1
, ENC_NA
);
1219 proto_tree_add_bitmask(z21_tree
, tvb
, offset
, hf_z21_central_state_ex
,
1220 ett_z21
, state_bits_byte2
, ENC_NA
);
1222 proto_tree_add_item(z21_tree
, hf_z21_systemstate_reserved
,
1223 tvb
, offset
, 1, ENC_NA
);
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)");
1232 proto_tree_add_bitmask(z21_tree
, tvb
, offset
, hf_z21_capabilities
,
1233 ett_z21
, capability_bits
, ENC_NA
);
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
);
1241 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Group=%d", temp_uint
);
1242 proto_item_append_text(z21_tree
, ", Group: %d", temp_uint
);
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
);
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
);
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
);
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
);
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
);
1268 proto_tree_add_item(z21_tree
, hf_z21_railcom_error_counter
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1270 proto_tree_add_item(z21_tree
, hf_z21_railcom_reserved1
, tvb
, offset
, 1, ENC_NA
);
1272 proto_tree_add_item(z21_tree
, hf_z21_railcom_options
, tvb
, offset
, 1, ENC_NA
);
1274 proto_tree_add_item(z21_tree
, hf_z21_railcom_speed
, tvb
, offset
, 1, ENC_NA
);
1276 proto_tree_add_item(z21_tree
, hf_z21_railcom_qos
, tvb
, offset
, 1, ENC_NA
);
1278 proto_tree_add_item(z21_tree
, hf_z21_railcom_reserved2
, tvb
, offset
, 1, ENC_NA
);
1281 case Z21_LAN_RAILCOM_GETDATA
:
1282 proto_tree_add_item(z21_tree
, hf_z21_railcom_type
, tvb
, offset
, 1, ENC_NA
);
1284 proto_tree_add_item(z21_tree
, hf_z21_loco_address
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
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;
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
);
1298 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Loco=%d", temp_uint
);
1299 proto_item_append_text(z21_tree
, ", Loco: %d", temp_uint
);
1301 /* Response from Z21 */
1302 proto_tree_add_item(z21_tree
, hf_z21_loconet_result
, tvb
, offset
, 1, ENC_NA
);
1306 case Z21_LAN_LOCONET_DETECTOR
:
1307 proto_tree_add_item(z21_tree
, hf_z21_loconet_type
, tvb
, offset
, 1, ENC_NA
);
1310 /* This is request */
1311 proto_tree_add_item(z21_tree
, hf_z21_loconet_report_address
,
1312 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1317 proto_tree_add_item(z21_tree
, hf_z21_loconet_feedback_address
,
1318 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1320 proto_tree_add_item(z21_tree
, hf_z21_loconet_info
,
1321 tvb
, offset
, datalen
-7, ENC_NA
);
1322 offset
+= datalen
-7;
1325 case Z21_LAN_CAN_DETECTOR
:
1327 /* This is request */
1328 proto_tree_add_item(z21_tree
, hf_z21_can_type
, tvb
, offset
, 1, ENC_NA
);
1330 proto_tree_add_item_ret_uint(z21_tree
, hf_z21_can_network_id
,
1331 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &temp_uint
);
1333 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", NetworkID=%d", temp_uint
);
1334 proto_item_append_text(z21_tree
, ", NetworkID: %d", temp_uint
);
1338 proto_tree_add_item_ret_uint(z21_tree
, hf_z21_can_network_id
,
1339 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &temp_uint
);
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
);
1346 proto_tree_add_item(z21_tree
, hf_z21_can_port
, tvb
, offset
, 1, ENC_NA
);
1348 proto_tree_add_item(z21_tree
, hf_z21_can_type
, tvb
, offset
, 1, ENC_NA
);
1350 proto_tree_add_item(z21_tree
, hf_z21_can_value1
,
1351 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1353 proto_tree_add_item(z21_tree
, hf_z21_can_value2
,
1354 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
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
);
1363 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", NetworkID=%d", temp_uint
);
1364 proto_item_append_text(z21_tree
, ", NetworkID: %d", temp_uint
);
1366 proto_tree_add_item(z21_tree
, hf_z21_can_booster_name
,
1367 tvb
, offset
, 16, ENC_ISO_8859_1
);
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
);
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
);
1380 proto_tree_add_bitmask(z21_tree
, tvb
, offset
,
1381 hf_z21_can_booster_state
, ett_z21
, booster_state_bits
, ENC_LITTLE_ENDIAN
);
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
);
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
);
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
);
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
);
1401 case Z21_LAN_ZLINK_GET_HWINFO
:
1402 proto_tree_add_item(z21_tree
, hf_z21_zlink_message_type
, tvb
, offset
, 1, ENC_NA
);
1405 proto_tree_add_item(z21_tree
, hf_z21_zlink_hwid
,
1406 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1408 proto_tree_add_item(z21_tree
, hf_z21_zlink_fw_major
, tvb
, offset
, 1, ENC_NA
);
1410 proto_tree_add_item(z21_tree
, hf_z21_zlink_fw_minor
, tvb
, offset
, 1, ENC_NA
);
1412 proto_tree_add_item(z21_tree
, hf_z21_zlink_fw_build
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1414 proto_tree_add_item(z21_tree
, hf_z21_zlink_mac
, tvb
, offset
, 18, ENC_ASCII
);
1416 proto_tree_add_item(z21_tree
, hf_z21_zlink_name
, tvb
, offset
, 33, ENC_ISO_8859_1
);
1418 proto_tree_add_item(z21_tree
, hf_z21_zlink_reserved
, tvb
, offset
, 1, ENC_NA
);
1422 case Z21_LAN_BOOSTER_GET_DESCRIPTION
:
1423 case Z21_LAN_BOOSTER_SET_DESCRIPTION
:
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, "");
1432 proto_tree_add_string(z21_tree
, hf_z21_booster_name
, tvb
, offset
, 32, buf
);
1437 case Z21_LAN_BOOSTER_SYSTEMSTATE_GETDATA
:
1438 case Z21_LAN_DECODER_SYSTEMSTATE_GETDATA
:
1440 case Z21_LAN_DECODER_GET_DESCRIPTION
:
1441 case Z21_LAN_DECODER_SET_DESCRIPTION
:
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, "");
1450 proto_tree_add_string(z21_tree
, hf_z21_decoder_name
, tvb
, offset
, 32, buf
);
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
);
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
);
1464 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", State=%d", temp_uint
);
1465 proto_item_append_text(z21_tree
, ", State: %d", temp_uint
);
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
);
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;
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
);
1486 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Loco=%d", addr
);
1488 unsigned mode
= tvb_get_uint8(tvb
, offset
);
1489 proto_tree_add_uint(z21_tree
, hf_z21_loco_mode
, tvb
, offset
, 1, mode
);
1491 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Mode: %d", mode
);
1494 case Z21_LAN_GET_BROADCASTFLAGS
:
1495 case Z21_LAN_SET_BROADCASTFLAGS
:
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
);
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
);
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
);
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
;
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
);
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
) {
1538 int pdu_len
= get_z21_pdu_len(pinfo
, tvb
, offset
, data
);
1539 if (pdu_len
< Z21_MIN_LENGTH
|| pdu_len
> remaining_length
) {
1542 uint16_t command
= tvb_get_uint16(tvb
, offset
+ 2, ENC_BIG_ENDIAN
);
1543 if (!try_val_to_str(command
, z21_command_vals
)) {
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.
1562 proto_register_z21(void)
1564 expert_module_t
*expert_z21
;
1566 static hf_register_info hf
[] = {
1568 { "Data length", "z21.datalen",
1569 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1573 { "Command", "z21.command",
1574 FT_UINT32
, BASE_HEX
|BASE_NO_DISPLAY_VALUE
, VALS(z21_command_vals
), 0x0,
1578 { "X-BUS", "z21.xbus",
1579 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1582 { &hf_z21_serial_number
,
1583 { "Serial number", "z21.serialnumber",
1584 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1588 { "Checksum", "z21.checksum",
1589 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1592 { &hf_z21_main_current
,
1593 { "Main track current", "z21.maincurrent",
1594 FT_INT16
, BASE_DEC
, NULL
, 0x0,
1597 { &hf_z21_prog_current
,
1598 { "Programming track current", "z21.progcurrent",
1599 FT_INT16
, BASE_DEC
, NULL
, 0x0,
1602 { &hf_z21_filtered_main_current
,
1603 { "Filtered main track current", "z21.filteredmaincurrent",
1604 FT_INT16
, BASE_DEC
, NULL
, 0x0,
1607 { &hf_z21_temperature
,
1608 { "Command station temperature", "z21.temperature",
1609 FT_INT16
, BASE_DEC
, NULL
, 0x0,
1612 { &hf_z21_supply_voltage
,
1613 { "Supply voltage", "z21.supplyvoltage",
1614 FT_FLOAT
, BASE_DEC
, NULL
, 0x0,
1617 { &hf_z21_track_voltage
,
1618 { "Track voltage", "z21.trackvoltage",
1619 FT_FLOAT
, BASE_DEC
, NULL
, 0x0,
1622 { &hf_z21_broadcast_flags
,
1623 { "Broadcast flags", "z21.broadcastflags",
1624 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1627 { &hf_z21_central_state
,
1628 { "Central state, first byte", "z21.centralstate1",
1629 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1632 { &hf_z21_central_state_ex
,
1633 { "Central state, second byte", "z21.centralstate2",
1634 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1637 { &hf_z21_systemstate_reserved
,
1638 { "Reserved", "z21.systemstatereserved",
1639 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1642 { &hf_z21_capabilities
,
1643 { "Capabilities", "z21.capabilities",
1644 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1648 { "Status", "z21.status",
1649 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
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,
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,
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,
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,
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,
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,
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,
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,
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,
1697 { &hf_z21_broadcast_flags_railcom
,
1698 { "Changes of RailCom data", "z21.broadcastflags.railcom",
1699 FT_BOOLEAN
, 32, TFS(&tfs_enabled_disabled
), 0x00040000,
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,
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,
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,
1717 { &hf_z21_state_emergency_stop
,
1718 { "Emergency stop", "z21.state.emergencystop",
1719 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x01,
1722 { &hf_z21_state_track_voltage_off
,
1723 { "Track voltage off", "z21.state.trackvoltageoff",
1724 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x02,
1727 { &hf_z21_state_short_circuit
,
1728 { "Short circuit", "z21.state.shortcircuit",
1729 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x04,
1732 { &hf_z21_state_programming_mode
,
1733 { "Programming mode", "z21.state.programmingmode",
1734 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x20,
1737 { &hf_z21_state_high_temperature
,
1738 { "High temperature", "z21.state.hightemperature",
1739 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x01,
1742 { &hf_z21_state_power_lost
,
1743 { "Power lost", "z21.state.powerlost",
1744 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x02,
1747 { &hf_z21_state_short_circuit_external
,
1748 { "External short circuit", "z21.state.externalshortcircuit",
1749 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x04,
1752 { &hf_z21_state_short_circuit_internal
,
1753 { "Internal short circuit", "z21.state.internalshortcircuit",
1754 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x08,
1757 { &hf_z21_state_rcn_213
,
1758 { "RCN-213 turnout addressing", "z21.state.rcn213addressing",
1759 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x20,
1762 { &hf_z21_capability_dcc
,
1763 { "DCC capability", "z21.capability.dcc",
1764 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x01,
1767 { &hf_z21_capability_mm
,
1768 { "MM capability", "z21.capability.mm",
1769 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x02,
1772 { &hf_z21_capability_reserved
,
1773 { "Reserved capability", "z21.capability.reserved",
1774 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x04,
1777 { &hf_z21_capability_railcom
,
1778 { "RailCom capability", "z21.capability.railcom",
1779 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x08,
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,
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,
1792 { &hf_z21_capability_detector_cmds
,
1793 { "Accepts LAN commands for detectors", "z21.capability.detectorcmds",
1794 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x40,
1797 { &hf_z21_capability_needs_unlock_code
,
1798 { "Needs unlock code", "z21.capability.needsunlockcode",
1799 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x80,
1802 { &hf_z21_loco_mode
,
1803 { "Locomotive mode", "z21.locomode",
1804 FT_UINT8
, BASE_DEC
, VALS(z21_loco_mode_vals
), 0x0,
1807 { &hf_z21_loco_address
,
1808 { "Locomotive address", "z21.locoaddress",
1809 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1812 { &hf_z21_loco_direction_and_speed
,
1813 { "Locomotive direction and speed", "z21.locodirectionandspeed",
1814 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1817 { &hf_z21_loco_direction
,
1818 { "Locomotive direction", "z21.locodirection",
1819 FT_BOOLEAN
, 8, TFS(&tfs_forward_reverse
), 0x80,
1822 { &hf_z21_loco_speed
,
1823 { "Locomotive speed", "z21.locospeed",
1824 FT_UINT8
, BASE_HEX
, NULL
, 0x7F,
1827 { &hf_z21_loco_info_mm
,
1828 { "Locomotive is MM (MƤrklin-Motorola)", "z21.locomm",
1829 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x10,
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,
1842 { &hf_z21_loco_info_direction
,
1843 { "Locomotive direction", "z21.locoinfodirection",
1844 FT_BOOLEAN
, 8, TFS(&tfs_forward_reverse
), 0x80,
1847 { &hf_z21_loco_info_speed
,
1848 { "Locomotive speed", "z21.locoinfospeed",
1849 FT_UINT8
, BASE_HEX
, NULL
, 0x7f,
1852 { &hf_z21_loco_info_double_traction
,
1853 { "Double traction", "z21.locoinfodoubletraction",
1854 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x40,
1857 { &hf_z21_loco_info_smartsearch
,
1858 { "Smartsearch", "z21.locoinfosmartsearch",
1859 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x20,
1862 { &hf_z21_loco_info_f0
,
1863 { "Function F0 (lights)", "z21.locoinfof0",
1864 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x10,
1867 { &hf_z21_loco_info_f4
,
1868 { "Function F4", "z21.locoinfof4",
1869 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x08,
1872 { &hf_z21_loco_info_f3
,
1873 { "Function F3", "z21.locoinfof3",
1874 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x04,
1877 { &hf_z21_loco_info_f2
,
1878 { "Function F2", "z21.locoinfof2",
1879 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x02,
1882 { &hf_z21_loco_info_f1
,
1883 { "Function F1", "z21.locoinfof1",
1884 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x01,
1887 { &hf_z21_loco_info_f12
,
1888 { "Function F12", "z21.locoinfof12",
1889 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x80,
1892 { &hf_z21_loco_info_f11
,
1893 { "Function F11", "z21.locoinfof11",
1894 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x40,
1897 { &hf_z21_loco_info_f10
,
1898 { "Function F10", "z21.locoinfof10",
1899 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x20,
1902 { &hf_z21_loco_info_f9
,
1903 { "Function F9", "z21.locoinfof9",
1904 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x10,
1907 { &hf_z21_loco_info_f8
,
1908 { "Function F8", "z21.locoinfof8",
1909 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x08,
1912 { &hf_z21_loco_info_f7
,
1913 { "Function F7", "z21.locoinfof7",
1914 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x04,
1917 { &hf_z21_loco_info_f6
,
1918 { "Function F6", "z21.locoinfof6",
1919 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x02,
1922 { &hf_z21_loco_info_f5
,
1923 { "Function F5", "z21.locoinfof5",
1924 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x01,
1927 { &hf_z21_loco_info_f20
,
1928 { "Function F20", "z21.locoinfof20",
1929 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x80,
1932 { &hf_z21_loco_info_f19
,
1933 { "Function F19", "z21.locoinfof19",
1934 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x40,
1937 { &hf_z21_loco_info_f18
,
1938 { "Function F18", "z21.locoinfof18",
1939 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x20,
1942 { &hf_z21_loco_info_f17
,
1943 { "Function F17", "z21.locoinfof17",
1944 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x10,
1947 { &hf_z21_loco_info_f16
,
1948 { "Function F16", "z21.locoinfof16",
1949 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x08,
1952 { &hf_z21_loco_info_f15
,
1953 { "Function F15", "z21.locoinfof15",
1954 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x04,
1957 { &hf_z21_loco_info_f14
,
1958 { "Function F14", "z21.locoinfof14",
1959 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x02,
1962 { &hf_z21_loco_info_f13
,
1963 { "Function F13", "z21.locoinfof13",
1964 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x01,
1967 { &hf_z21_loco_info_f28
,
1968 { "Function F28", "z21.locoinfof28",
1969 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x80,
1972 { &hf_z21_loco_info_f27
,
1973 { "Function F27", "z21.locoinfof27",
1974 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x40,
1977 { &hf_z21_loco_info_f26
,
1978 { "Function F26", "z21.locoinfof26",
1979 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x20,
1982 { &hf_z21_loco_info_f25
,
1983 { "Function F25", "z21.locoinfof25",
1984 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x10,
1987 { &hf_z21_loco_info_f24
,
1988 { "Function F24", "z21.locoinfof24",
1989 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x08,
1992 { &hf_z21_loco_info_f23
,
1993 { "Function F23", "z21.locoinfof23",
1994 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x04,
1997 { &hf_z21_loco_info_f22
,
1998 { "Function F22", "z21.locoinfof22",
1999 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x02,
2002 { &hf_z21_loco_info_f21
,
2003 { "Function F21", "z21.locoinfof21",
2004 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x01,
2007 { &hf_z21_loco_info_f31
,
2008 { "Function F31", "z21.locoinfof31",
2009 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x04,
2012 { &hf_z21_loco_info_f30
,
2013 { "Function F30", "z21.locoinfof30",
2014 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x02,
2017 { &hf_z21_loco_info_f29
,
2018 { "Function F29", "z21.locoinfof29",
2019 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x01,
2022 { &hf_z21_loco_info_extensions
,
2023 { "Extensions", "z21.locoinfoextensions",
2024 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2027 { &hf_z21_speed_steps
,
2028 { "Speed steps", "z21.speedsteps",
2029 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2033 { "Hardware type", "z21.hwtype",
2034 FT_UINT32
, BASE_HEX
, VALS(z21_hw_type_vals
), 0x0,
2037 { &hf_z21_firmware_version
,
2038 { "Firmware version", "z21.firmwareversion",
2039 FT_STRING
, BASE_NONE
, NULL
, 0x0,
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,
2047 { &hf_z21_loco_func_index
,
2048 { "Locomotive function index", "z21.locofunctionindex",
2049 FT_UINT8
, BASE_DEC
, NULL
, 0x3f,
2052 { &hf_z21_function_address
,
2053 { "Function address", "z21.functionaddress",
2054 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2057 { &hf_z21_turnout_state
,
2058 { "Turnout state", "z21.turnoutstate",
2059 FT_UINT8
, BASE_DEC
, VALS(z21_turnout_state_vals
), 0x03,
2062 { &hf_z21_turnout_queue_bit
,
2063 { "Queue the turnout command", "z21.turnoutqueue",
2064 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), 0x20,
2067 { &hf_z21_turnout_activate_bit
,
2068 { "Turnout command", "z21.turnoutcommand",
2069 FT_BOOLEAN
, 8, TFS(&tfs_turnout_command
), 0x08,
2072 { &hf_z21_turnout_output_bit
,
2073 { "Select turnout output", "z21.turnoutoutput",
2074 FT_BOOLEAN
, 8, TFS(&tfs_turnout_output
), 0x01,
2077 { &hf_z21_accessory_address
,
2078 { "Accessory address", "z21.accessoryaddress",
2079 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2082 { &hf_z21_accessory_state
,
2083 { "Accessory state", "z21.accessorystate",
2084 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2087 { &hf_z21_accessory_status
,
2088 { "Accessory status", "z21.accessorystatus",
2089 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2092 { &hf_z21_cv_address
,
2093 { "CV address", "z21.cvaddress",
2094 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2098 { "CV value", "z21.cvvalue",
2099 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2103 { "Register", "z21.register",
2104 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2107 { &hf_z21_register_value
,
2108 { "Register value", "z21.registervalue",
2109 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2112 { &hf_z21_pom_operation
,
2113 { "POM operation", "z21.pomoperation",
2114 FT_UINT16
, BASE_HEX
, VALS(z21_pom_operation_vals
), 0x0,
2117 { &hf_z21_cv_bit_position
,
2118 { "CV bit position", "z21.cvbitposition",
2119 FT_UINT8
, BASE_DEC
, NULL
, 0x07,
2122 { &hf_z21_cv_bit_value
,
2123 { "CV bit value", "z21.cvbitvalue",
2124 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x08,
2127 { &hf_z21_rmbus_group
,
2128 { "R-BUS group index", "z21.rbusgroup",
2129 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2132 { &hf_z21_rmbus_feedbacks
,
2133 { "R-BUS feedbacks", "z21.rbusfeedbacks",
2134 FT_BYTES
, BASE_NONE
|SEP_SPACE
, NULL
, 0x0,
2137 { &hf_z21_rmbus_address
,
2138 { "R-BUS feedback module address", "z21.rbusaddress",
2139 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2142 { &hf_z21_railcom_receive_counter
,
2143 { "RailCom receive counter", "z21.railcomreceives",
2144 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2147 { &hf_z21_railcom_error_counter
,
2148 { "RailCom error counter", "z21.railcomerrors",
2149 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2152 { &hf_z21_railcom_reserved1
,
2153 { "RailCom reserved 1", "z21.railcomreserved1",
2154 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2157 { &hf_z21_railcom_reserved2
,
2158 { "RailCom reserved 2", "z21.railcomreserved2",
2159 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2162 { &hf_z21_railcom_options
,
2163 { "RailCom options", "z21.railcomoptions",
2164 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2167 { &hf_z21_railcom_speed
,
2168 { "RailCom speed", "z21.railcomspeed",
2169 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2172 { &hf_z21_railcom_qos
,
2173 { "RailCom QoS", "z21.railcomqos",
2174 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2177 { &hf_z21_railcom_type
,
2178 { "RailCom type", "z21.railcomtype",
2179 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2182 { &hf_z21_loconet_message
,
2183 { "LocoNet message", "z21.loconetmessage",
2184 FT_BYTES
, BASE_NONE
|SEP_SPACE
, NULL
, 0x0,
2187 { &hf_z21_loconet_result
,
2188 { "LocoNet result", "z21.loconetresult",
2189 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2192 { &hf_z21_loconet_type
,
2193 { "LocoNet type", "z21.loconettype",
2194 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2197 { &hf_z21_loconet_report_address
,
2198 { "LocoNet report address", "z21.loconetreportaddress",
2199 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2202 { &hf_z21_loconet_feedback_address
,
2203 { "LocoNet feedback address", "z21.loconetfeedbackaddress",
2204 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2207 { &hf_z21_loconet_info
,
2208 { "LocoNet info", "z21.loconetinfo",
2209 FT_BYTES
, BASE_NONE
|SEP_SPACE
, NULL
, 0x0,
2213 { "CAN type", "z21.cantype",
2214 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2217 { &hf_z21_can_network_id
,
2218 { "CAN network ID", "z21.cannetworkid",
2219 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2222 { &hf_z21_can_module_address
,
2223 { "CAN module address", "z21.canmoduleaddress",
2224 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2228 { "CAN input port (pin)", "z21.canport",
2229 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2232 { &hf_z21_can_value1
,
2233 { "CAN value 1", "z21.canvalue1",
2234 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2237 { &hf_z21_can_value2
,
2238 { "CAN value 2", "z21.canvalue2",
2239 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2242 { &hf_z21_can_booster_name
,
2243 { "CAN booster name", "z21.canboostername",
2244 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2247 { &hf_z21_can_booster_output_port
,
2248 { "CAN booster output port", "z21.canboosteroutputport",
2249 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2252 { &hf_z21_can_booster_state
,
2253 { "CAN booster state", "z21.canboosterstate",
2254 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2257 { &hf_z21_can_booster_state_bg_active
,
2258 { "CAN booster brake generator active", "z21.canboosterbrakegenerator",
2259 FT_BOOLEAN
, 16, NULL
, 0x0001,
2262 { &hf_z21_can_booster_state_short_circuit
,
2263 { "CAN booster short circuit", "z21.canboostershortcircuit",
2264 FT_BOOLEAN
, 16, NULL
, 0x0020,
2267 { &hf_z21_can_booster_state_track_voltage_off
,
2268 { "CAN booster track voltage off", "z21.canboostertrackvoltageoff",
2269 FT_BOOLEAN
, 16, NULL
, 0x0080,
2272 { &hf_z21_can_booster_state_railcom_active
,
2273 { "CAN booster RailCom cutout active", "z21.canboosterrailcomactive",
2274 FT_BOOLEAN
, 16, NULL
, 0x0800,
2277 { &hf_z21_can_booster_state_output_disabled
,
2278 { "CAN booster output disabled", "z21.canboosteroutputdisabled",
2279 FT_BOOLEAN
, 16, NULL
, 0x0100,
2282 { &hf_z21_can_booster_vcc
,
2283 { "CAN booster VCC voltage", "z21.canboostervoltage",
2284 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2287 { &hf_z21_can_booster_current
,
2288 { "CAN booster current", "z21.canboostercurrent",
2289 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2292 { &hf_z21_can_booster_power
,
2293 { "CAN booster power", "z21.canboosterpower",
2294 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2297 { &hf_z21_zlink_message_type
,
2298 { "zLink message type", "z21.zlinkmessagetype",
2299 FT_UINT8
, BASE_HEX
, VALS(z21_zlink_message_type_vals
), 0x0,
2302 { &hf_z21_zlink_hwid
,
2303 { "zLink hardware ID", "z21.zlinkhwid",
2304 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2307 { &hf_z21_zlink_fw_major
,
2308 { "zLink firmware major version", "z21.zlinkmajorversion",
2309 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2312 { &hf_z21_zlink_fw_minor
,
2313 { "zLink firmware minor version", "z21.zlinkminorversion",
2314 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2317 { &hf_z21_zlink_fw_build
,
2318 { "zLink firmware build version", "z21.zlinkbuildversion",
2319 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2322 { &hf_z21_zlink_mac
,
2323 { "zLink MAC address", "z21.zlinkmac",
2324 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2327 { &hf_z21_zlink_name
,
2328 { "zLink name", "z21.zlinkname",
2329 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2332 { &hf_z21_zlink_reserved
,
2333 { "zLink reserved", "z21.zlinkreserved",
2334 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2337 { &hf_z21_booster_name
,
2338 { "Booster name", "z21.boostername",
2339 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2342 { &hf_z21_booster_port
,
2343 { "Booster port", "z21.boosterport",
2344 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2347 { &hf_z21_booster_port_state
,
2348 { "Booster port state", "z21.boosterportstate",
2349 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2352 { &hf_z21_booster_state_data
,
2353 { "Booster state data", "z21.boosterstatedata",
2354 FT_BYTES
, BASE_NONE
|SEP_SPACE
, NULL
, 0x0,
2357 { &hf_z21_decoder_name
,
2358 { "Decoder name", "z21.decodername",
2359 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
2362 { &hf_z21_decoder_state_data
,
2363 { "Decoder state data", "z21.decoderstatedata",
2364 FT_BYTES
, BASE_NONE
|SEP_SPACE
, NULL
, 0x0,
2368 { "Undecoded data", "z21.data",
2369 FT_BYTES
, BASE_NONE
|SEP_SPACE
, NULL
, 0x0,
2374 /* Setup protocol subtree array */
2375 static int *ett
[] = {
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
);
2411 proto_reg_handoff_z21(void)
2413 static bool initialized
= false;
2416 dissector_add_uint_range_with_preference("udp.port", Z21_UDP_PORTS
, z21_handle
);
2419 udp_port_range
= prefs_get_range_value("Z21", "udp.port");