Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-z21.c
Line
Count
Source
1
/* packet-z21.c
2
 * Routines for Z21 LAN protocol dissection
3
 * Copyright 2023, Markku Leiniƶ <markku.leinio@gmail.com>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/*
13
 * Z21 LAN protocol specification can be found at:
14
 * https://www.z21.eu/en/downloads/manuals
15
 */
16
17
#include "config.h"
18
#define WS_LOG_DOMAIN "Z21"
19
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"
26
27
void proto_register_z21(void);
28
void proto_reg_handoff_z21(void);
29
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;
193
194
static dissector_handle_t z21_handle;
195
196
/* Not IANA registered */
197
14
#define Z21_UDP_PORTS "21105,21106"
198
static range_t *udp_port_range;
199
200
/* Initialize the subtree pointers */
201
static int ett_z21;
202
203
/* Initialize expert fields */
204
static expert_field ei_z21_invalid_checksum;
205
206
26
#define Z21_MIN_LENGTH 4
207
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
0
#define Z21_LAN_GET_SERIAL_NUMBER               0x1000
213
0
#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
0
#define Z21_LAN_X_BC                            0x4000
219
0
#define Z21_LAN_SET_BROADCASTFLAGS              0x5000
220
0
#define Z21_LAN_GET_BROADCASTFLAGS              0x5100
221
0
#define Z21_LAN_GET_LOCOMODE                    0x6000
222
0
#define Z21_LAN_SET_LOCOMODE                    0x6100
223
0
#define Z21_LAN_RMBUS_DATACHANGED               0x8000
224
0
#define Z21_LAN_RMBUS_GETDATA                   0x8100
225
0
#define Z21_LAN_RMBUS_PROGRAMMODULE             0x8200
226
0
#define Z21_LAN_SYSTEMSTATE_DATACHANGED         0x8400
227
#define Z21_LAN_SYSTEMSTATE_GETDATA             0x8500
228
0
#define Z21_LAN_RAILCOM_DATACHANGED             0x8800
229
0
#define Z21_LAN_RAILCOM_GETDATA                 0x8900
230
0
#define Z21_LAN_LOCONET_Z21_RX                  0xA000
231
0
#define Z21_LAN_LOCONET_Z21_TX                  0xA100
232
0
#define Z21_LAN_LOCONET_FROM_LAN                0xA200
233
0
#define Z21_LAN_LOCONET_DISPATCH_ADDR           0xA300
234
0
#define Z21_LAN_LOCONET_DETECTOR                0xA400
235
0
#define Z21_LAN_BOOSTER_SET_POWER               0xB200
236
0
#define Z21_LAN_BOOSTER_GET_DESCRIPTION         0xB800
237
0
#define Z21_LAN_BOOSTER_SET_DESCRIPTION         0xB900
238
0
#define Z21_LAN_BOOSTER_SYSTEMSTATE_DATACHANGED 0xBA00
239
0
#define Z21_LAN_BOOSTER_SYSTEMSTATE_GETDATA     0xBB00
240
0
#define Z21_LAN_CAN_DETECTOR                    0xC400
241
0
#define Z21_LAN_CAN_DEVICE_GET_DESCRIPTION      0xC800
242
0
#define Z21_LAN_CAN_DEVICE_SET_DESCRIPTION      0xC900
243
0
#define Z21_LAN_CAN_BOOSTER_SYSTEMSTATE_CHGD    0xCA00
244
0
#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
0
#define Z21_LAN_DECODER_GET_DESCRIPTION         0xD800
250
0
#define Z21_LAN_DECODER_SET_DESCRIPTION         0xD900
251
0
#define Z21_LAN_DECODER_SYSTEMSTATE_DATACHANGED 0xDA00
252
0
#define Z21_LAN_DECODER_SYSTEMSTATE_GETDATA     0xDB00
253
0
#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
0
#define Z21_LAN_X_DCC_READ_REGISTER             0x40002211
261
0
#define Z21_LAN_X_CV_READ                       0x40002311
262
0
#define Z21_LAN_X_DCC_WRITE_REGISTER            0x40002312
263
0
#define Z21_LAN_X_CV_WRITE                      0x40002412
264
0
#define Z21_LAN_X_MM_WRITE_BYTE                 0x400024FF
265
0
#define Z21_LAN_X_GET_TURNOUT_INFO              0x400043
266
0
#define Z21_LAN_X_TURNOUT_INFO                  0x40FF43    /* To be set manually */
267
0
#define Z21_LAN_X_GET_EXT_ACCESSORY_INFO        0x400044
268
0
#define Z21_LAN_X_EXT_ACCESSORY_INFO            0x40FF44    /* To be set manually */
269
0
#define Z21_LAN_X_SET_TURNOUT                   0x400053
270
0
#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
0
#define Z21_LAN_X_STATUS_CHANGED                0x40006222
279
0
#define Z21_LAN_X_CV_RESULT                     0x40006414
280
0
#define Z21_LAN_X_SET_STOP                      0x400080
281
#define Z21_LAN_X_BC_STOPPED                    0x40008100
282
0
#define Z21_LAN_X_SET_LOCO_E_STOP               0x400092
283
0
#define Z21_LAN_X_PURGE_LOCO                    0x4000E344
284
0
#define Z21_LAN_X_GET_LOCO_INFO                 0x4000E3F0
285
0
#define Z21_LAN_X_SET_LOCO_DRIVE_DCC14          0x4000E410
286
0
#define Z21_LAN_X_SET_LOCO_DRIVE_DCC28          0x4000E412
287
0
#define Z21_LAN_X_SET_LOCO_DRIVE_DCC128         0x4000E413
288
0
#define Z21_LAN_X_SET_LOCO_FUNCTION             0x4000E4F8
289
0
#define Z21_LAN_X_SET_LOCO_BINARY_STATE         0x4000E55F
290
0
#define Z21_LAN_X_CV_POM_COMMANDS               0x4000E630
291
0
#define Z21_LAN_X_CV_POM_WRITE_BYTE             0x40FFE630      /* To be set manually */
292
0
#define Z21_LAN_X_CV_POM_WRITE_BIT              0x40FEE630      /* To be set manually */
293
0
#define Z21_LAN_X_CV_POM_READ_BYTE              0x40FDE630      /* To be set manually */
294
0
#define Z21_LAN_X_CV_POM_ACCESSORY_COMMANDS     0x4000E631
295
0
#define Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BYTE   0x40FFE631      /* To be set manually */
296
0
#define Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BIT    0x40FEE631      /* To be set manually */
297
0
#define Z21_LAN_X_CV_POM_ACCESSORY_READ_BYTE    0x40FDE631      /* To be set manually */
298
0
#define Z21_LAN_X_LOCO_INFO                     0x4000EF
299
#define Z21_LAN_X_GET_FIRMWARE_VERSION_REQUEST  0x4000F10A
300
0
#define Z21_LAN_X_GET_FIRMWARE_VERSION_REPLY    0x4000F30A
301
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.
304
 */
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 },
390
};
391
392
static const value_string z21_loco_mode_vals[] = {
393
    { 0, "DCC Format" },
394
    { 1, "MM Format" },
395
    { 0, NULL },
396
};
397
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 },
411
};
412
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 },
418
};
419
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 },
426
};
427
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 },
434
};
435
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 },
441
};
442
443
static const value_string z21_zlink_message_type_vals[] = {
444
    { 0x06, "ZLINK_MSG_TYPE_HW_INFO" },
445
    { 0, NULL },
446
};
447
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" };
451
452
453
static void
454
update_command_field(proto_item *ti, unsigned command)
455
0
{
456
0
    int width = 8;
457
0
    if (command <= 0xff)
458
0
        width = 2;
459
0
    else if (command <= 0xffff)
460
0
        width = 4;
461
0
    else if (command <= 0xffffff)
462
0
        width = 6;
463
0
    proto_item_append_text(ti, ": %s (0x%0*x)",
464
0
        val_to_str_const(command, z21_command_vals, "unknown"),
465
0
        width, command);
466
0
}
467
468
469
/* Code to actually dissect the packets */
470
471
static int
472
dissect_z21_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
473
0
{
474
0
    proto_item *ti, *temp_ti, *command_ti;
475
0
    proto_tree *z21_tree;
476
0
    unsigned offset = 0, datalen, command;
477
0
    unsigned checksum, calculated_checksum, one_byte, version, temp_uint;
478
0
    unsigned address_bytes, addr, speed_steps = 0, cv_addr;
479
0
    uint64_t status, direction_and_speed, temp_uint64;
480
0
    int32_t main_current, temp_int32;
481
0
    char *buffer;
482
0
    float temp_float;
483
0
    static int * const broadcast_flags_bits[] = {
484
0
        &hf_z21_broadcast_flags_loconet_detector,
485
0
        &hf_z21_broadcast_flags_loconet_switching,
486
0
        &hf_z21_broadcast_flags_loconet_driving,
487
0
        &hf_z21_broadcast_flags_loconet,
488
0
        &hf_z21_broadcast_flags_can_detector,
489
0
        &hf_z21_broadcast_flags_railcom,
490
0
        &hf_z21_broadcast_flags_can_booster,
491
0
        &hf_z21_broadcast_flags_driving_switching_ex,
492
0
        &hf_z21_broadcast_flags_system_status,
493
0
        &hf_z21_broadcast_flags_fast_clock,
494
0
        &hf_z21_broadcast_flags_railcom_subscribed,
495
0
        &hf_z21_broadcast_flags_rmbus,
496
0
        &hf_z21_broadcast_flags_driving_switching,
497
0
        NULL
498
0
    };
499
0
    static int * const state_bits_byte1[] = {
500
0
        &hf_z21_state_programming_mode,
501
0
        &hf_z21_state_short_circuit,
502
0
        &hf_z21_state_track_voltage_off,
503
0
        &hf_z21_state_emergency_stop,
504
0
        NULL
505
0
    };
506
0
    static int * const state_bits_byte2[] = {
507
0
        &hf_z21_state_rcn_213,
508
0
        &hf_z21_state_short_circuit_internal,
509
0
        &hf_z21_state_short_circuit_external,
510
0
        &hf_z21_state_power_lost,
511
0
        &hf_z21_state_high_temperature,
512
0
        NULL
513
0
    };
514
0
    static int * const capability_bits[] = {
515
0
        &hf_z21_capability_needs_unlock_code,
516
0
        &hf_z21_capability_detector_cmds,
517
0
        &hf_z21_capability_accessory_cmds,
518
0
        &hf_z21_capability_loco_cmds,
519
0
        &hf_z21_capability_railcom,
520
0
        &hf_z21_capability_reserved,
521
0
        &hf_z21_capability_mm,
522
0
        &hf_z21_capability_dcc,
523
0
        NULL
524
0
    };
525
0
    static int * const speed_bits[] = {
526
0
        &hf_z21_loco_direction,
527
0
        &hf_z21_loco_speed,
528
0
        NULL
529
0
    };
530
0
    static int * const loco_info_bits1[] = {
531
0
        &hf_z21_loco_info_mm,
532
0
        &hf_z21_loco_info_busy,
533
0
        &hf_z21_loco_info_speed_steps,
534
0
        NULL
535
0
    };
536
0
    static int * const loco_info_bits2[] = {
537
0
        &hf_z21_loco_info_direction,
538
0
        &hf_z21_loco_info_speed,
539
0
        NULL
540
0
    };
541
0
    static int * const loco_info_bits3[] = {
542
0
        &hf_z21_loco_info_double_traction,
543
0
        &hf_z21_loco_info_smartsearch,
544
0
        &hf_z21_loco_info_f0,
545
0
        &hf_z21_loco_info_f4,
546
0
        &hf_z21_loco_info_f3,
547
0
        &hf_z21_loco_info_f2,
548
0
        &hf_z21_loco_info_f1,
549
0
        NULL
550
0
    };
551
0
    static int * const loco_info_bits4[] = {
552
0
        &hf_z21_loco_info_f12,
553
0
        &hf_z21_loco_info_f11,
554
0
        &hf_z21_loco_info_f10,
555
0
        &hf_z21_loco_info_f9,
556
0
        &hf_z21_loco_info_f8,
557
0
        &hf_z21_loco_info_f7,
558
0
        &hf_z21_loco_info_f6,
559
0
        &hf_z21_loco_info_f5,
560
0
        NULL
561
0
    };
562
0
    static int * const loco_info_bits5[] = {
563
0
        &hf_z21_loco_info_f20,
564
0
        &hf_z21_loco_info_f19,
565
0
        &hf_z21_loco_info_f18,
566
0
        &hf_z21_loco_info_f17,
567
0
        &hf_z21_loco_info_f16,
568
0
        &hf_z21_loco_info_f15,
569
0
        &hf_z21_loco_info_f14,
570
0
        &hf_z21_loco_info_f13,
571
0
        NULL
572
0
    };
573
0
    static int * const loco_info_bits6[] = {
574
0
        &hf_z21_loco_info_f28,
575
0
        &hf_z21_loco_info_f27,
576
0
        &hf_z21_loco_info_f26,
577
0
        &hf_z21_loco_info_f25,
578
0
        &hf_z21_loco_info_f24,
579
0
        &hf_z21_loco_info_f23,
580
0
        &hf_z21_loco_info_f22,
581
0
        &hf_z21_loco_info_f21,
582
0
        NULL
583
0
    };
584
0
    static int * const loco_info_bits7[] = {
585
0
        &hf_z21_loco_info_f31,
586
0
        &hf_z21_loco_info_f30,
587
0
        &hf_z21_loco_info_f29,
588
0
        NULL
589
0
    };
590
0
    static int * const loco_func_bits[] = {
591
0
        &hf_z21_loco_func_switch_type,
592
0
        &hf_z21_loco_func_index,
593
0
        NULL
594
0
    };
595
0
    static int * const turnout_state_bits[] = {
596
0
        &hf_z21_turnout_state,
597
0
        NULL
598
0
    };
599
0
    static int * const turnout_set_bits[] = {
600
0
        &hf_z21_turnout_queue_bit,
601
0
        &hf_z21_turnout_activate_bit,
602
0
        &hf_z21_turnout_output_bit,
603
0
        NULL
604
0
    };
605
0
    static int * const cv_bits[] = {
606
0
        &hf_z21_cv_bit_value,
607
0
        &hf_z21_cv_bit_position,
608
0
        NULL
609
0
    };
610
0
    static int * const booster_state_bits[] = {
611
0
        &hf_z21_can_booster_state_railcom_active,
612
0
        &hf_z21_can_booster_state_output_disabled,
613
0
        &hf_z21_can_booster_state_track_voltage_off,
614
0
        &hf_z21_can_booster_state_short_circuit,
615
0
        &hf_z21_can_booster_state_bg_active,
616
0
        NULL
617
0
    };
618
619
    /* Check that the packet is long enough for it to belong to us. */
620
0
    if (tvb_reported_length(tvb) < Z21_MIN_LENGTH)
621
0
        return 0;
622
623
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Z21");
624
625
0
    ti = proto_tree_add_item(tree, proto_z21, tvb, 0, -1, ENC_NA);
626
0
    z21_tree = proto_item_add_subtree(ti, ett_z21);
627
0
    proto_tree_add_item_ret_uint(z21_tree, hf_z21_datalen,
628
0
        tvb, offset, 2, ENC_LITTLE_ENDIAN, &datalen);
629
0
    offset += 2;
630
0
    command = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
631
0
    if (command == Z21_LAN_X_BC) {
632
0
        proto_tree_add_boolean(z21_tree, hf_z21_x_bus, tvb, offset, 2, true);
633
        /* Note that we do not increment the offset yet */
634
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.
644
         */
645
0
        temp_uint = 0x40000000 + tvb_get_uint16(tvb, offset+2, ENC_BIG_ENDIAN);
646
0
        unsigned x_bus_command = temp_uint >> 8;
647
        /* Check for all the "one-byte" commands */
648
0
        if (x_bus_command == Z21_LAN_X_SET_STOP ||
649
0
            x_bus_command == Z21_LAN_X_SET_LOCO_E_STOP ||
650
0
            x_bus_command == Z21_LAN_X_GET_EXT_ACCESSORY_INFO ||
651
0
            x_bus_command == Z21_LAN_X_SET_EXT_ACCESSORY ||
652
0
            x_bus_command == Z21_LAN_X_GET_TURNOUT_INFO ||
653
0
            x_bus_command == Z21_LAN_X_SET_TURNOUT ||
654
0
            x_bus_command == Z21_LAN_X_LOCO_INFO) {
655
            /* Initialize the checksum without the 0x4000 prefix */
656
0
            calculated_checksum = x_bus_command & 0xff;
657
            /* Check for these that are actually another command */
658
0
            if (x_bus_command == Z21_LAN_X_GET_TURNOUT_INFO && datalen == 9) {
659
0
                x_bus_command = Z21_LAN_X_TURNOUT_INFO;
660
0
            } else if (x_bus_command == Z21_LAN_X_GET_EXT_ACCESSORY_INFO && datalen == 10) {
661
0
                x_bus_command = Z21_LAN_X_EXT_ACCESSORY_INFO;
662
0
            }
663
0
            command_ti = proto_tree_add_uint(z21_tree, hf_z21_command, tvb, offset, 3, x_bus_command);
664
0
            offset += 3;
665
0
        }
666
0
        else {
667
            /* First assume "two-byte command", then check for exceptions */
668
0
            x_bus_command = temp_uint;
669
0
            if (x_bus_command == Z21_LAN_X_CV_POM_COMMANDS ||
670
0
                x_bus_command == Z21_LAN_X_CV_POM_ACCESSORY_COMMANDS) {
671
                /* Read DB3 from data, get the two interesting bits */
672
0
                temp_uint = tvb_get_uint8(tvb, offset + 6) >> 2 & 0x3;
673
0
                switch (x_bus_command) {
674
0
                case Z21_LAN_X_CV_POM_COMMANDS:
675
0
                    if (temp_uint == 0x1)
676
0
                        x_bus_command = Z21_LAN_X_CV_POM_READ_BYTE;
677
0
                    else if (temp_uint == 0x2)
678
0
                        x_bus_command = Z21_LAN_X_CV_POM_WRITE_BIT;
679
0
                    else if (temp_uint == 0x3)
680
0
                        x_bus_command = Z21_LAN_X_CV_POM_WRITE_BYTE;
681
0
                    break;
682
0
                case Z21_LAN_X_CV_POM_ACCESSORY_COMMANDS:
683
0
                    if (temp_uint == 0x1)
684
0
                        x_bus_command = Z21_LAN_X_CV_POM_ACCESSORY_READ_BYTE;
685
0
                    else if (temp_uint == 0x2)
686
0
                        x_bus_command = Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BIT;
687
0
                    else if (temp_uint == 0x3)
688
0
                        x_bus_command = Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BYTE;
689
0
                    break;
690
0
                }
691
0
            }
692
0
            command_ti = proto_tree_add_uint(z21_tree, hf_z21_command,
693
0
                tvb, offset, 4, x_bus_command);
694
0
            offset += 4;
695
            /* Initialize the checksum with the two LSBs */
696
0
            calculated_checksum = ((x_bus_command & 0xff00) >> 8) ^ (x_bus_command & 0x00ff);
697
0
        }
698
0
        update_command_field(command_ti, x_bus_command);
699
0
        col_add_fstr(pinfo->cinfo, COL_INFO, "Command=%s",
700
0
            val_to_str_const(x_bus_command, z21_command_vals, "unknown"));
701
0
        proto_item_append_text(z21_tree, ", Command: %s",
702
0
            val_to_str_const(x_bus_command, z21_command_vals, "unknown"));
703
0
        switch (x_bus_command) {
704
0
        case Z21_LAN_X_STATUS_CHANGED:
705
0
            proto_tree_add_bitmask_ret_uint64(z21_tree, tvb, offset, hf_z21_status,
706
0
                ett_z21, state_bits_byte1, ENC_NA, &status);
707
0
            offset += 1;
708
0
            calculated_checksum ^= (unsigned)status;
709
0
            break;
710
0
        case Z21_LAN_X_SET_LOCO_DRIVE_DCC14:
711
0
        case Z21_LAN_X_SET_LOCO_DRIVE_DCC28:
712
0
        case Z21_LAN_X_SET_LOCO_DRIVE_DCC128:
713
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
714
0
            addr = address_bytes & 0x3FFF;
715
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
716
0
            switch (x_bus_command) {
717
0
            case Z21_LAN_X_SET_LOCO_DRIVE_DCC14: speed_steps = 14; break;
718
0
            case Z21_LAN_X_SET_LOCO_DRIVE_DCC28: speed_steps = 28; break;
719
0
            case Z21_LAN_X_SET_LOCO_DRIVE_DCC128: speed_steps = 128; break;
720
0
            }
721
0
            proto_tree_add_uint(z21_tree, hf_z21_speed_steps, tvb, offset-1, 1, speed_steps);
722
0
            offset += 2;
723
0
            calculated_checksum ^= address_bytes >> 8;
724
0
            calculated_checksum ^= address_bytes & 0xFF;
725
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d (%d SS)",
726
0
                addr, speed_steps);
727
0
            temp_ti = proto_tree_add_bitmask_ret_uint64(z21_tree, tvb, offset, hf_z21_loco_direction_and_speed,
728
0
                ett_z21, speed_bits, ENC_NA, &direction_and_speed);
729
0
            offset += 1;
730
0
            calculated_checksum ^= (unsigned)direction_and_speed;
731
0
            if (direction_and_speed & 0x80) {
732
0
                proto_item_set_text(temp_ti,
733
0
                    "Locomotive direction and speed: Forward, 0x%02" PRIx64,
734
0
                    direction_and_speed & 0x7F);
735
0
                col_append_str(pinfo->cinfo, COL_INFO, ", Forward");
736
0
            }
737
0
            else {
738
0
                proto_item_set_text(temp_ti,
739
0
                    "Locomotive direction and speed: Reverse, 0x%02" PRIx64,
740
0
                    direction_and_speed & 0x7F);
741
0
                col_append_str(pinfo->cinfo, COL_INFO, ", Reverse");
742
0
            }
743
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Speed=0x%02" PRIx64,
744
0
                direction_and_speed & 0x7F);
745
0
            break;
746
0
        case Z21_LAN_X_GET_LOCO_INFO:
747
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
748
0
            addr = address_bytes & 0x3FFF;
749
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
750
0
            offset += 2;
751
0
            calculated_checksum ^= address_bytes >> 8;
752
0
            calculated_checksum ^= address_bytes & 0xFF;
753
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
754
0
            break;
755
0
        case Z21_LAN_X_LOCO_INFO:
756
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
757
0
            addr = address_bytes & 0x3FFF;
758
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
759
0
            offset += 2;
760
0
            calculated_checksum ^= address_bytes >> 8;
761
0
            calculated_checksum ^= address_bytes & 0xFF;
762
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
763
0
            proto_item_append_text(z21_tree, ", Loco: %d", addr);
764
765
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
766
0
                loco_info_bits1, ENC_NA, &temp_uint64);
767
0
            offset += 1;
768
0
            calculated_checksum ^= temp_uint64;
769
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
770
0
                val_to_str_const((uint32_t)temp_uint64 & 0x07,
771
0
                    z21_loco_info_speed_steps_vals, "unknown"));
772
773
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
774
0
                loco_info_bits2, ENC_NA, &temp_uint64);
775
0
            offset += 1;
776
0
            calculated_checksum ^= temp_uint64;
777
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
778
0
                tfs_get_string((bool)(temp_uint64 >> 7), &tfs_forward_reverse));
779
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Speed=0x%02" PRIx64,
780
0
                temp_uint64 & 0x7f);
781
782
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
783
0
                loco_info_bits3, ENC_NA, &temp_uint64);
784
0
            offset += 1;
785
0
            calculated_checksum ^= temp_uint64;
786
0
            if (temp_uint64 & 0x40) {
787
0
                col_append_str(pinfo->cinfo, COL_INFO, ", in double traction");
788
0
            }
789
790
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
791
0
                loco_info_bits4, ENC_NA, &temp_uint64);
792
0
            offset += 1;
793
0
            calculated_checksum ^= temp_uint64;
794
795
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
796
0
                loco_info_bits5, ENC_NA, &temp_uint64);
797
0
            offset += 1;
798
0
            calculated_checksum ^= temp_uint64;
799
800
            /* The following bytes are not always there it seems */
801
0
            if (offset < datalen-1) {
802
0
                proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
803
0
                    loco_info_bits6, ENC_NA, &temp_uint64);
804
0
                offset += 1;
805
0
                calculated_checksum ^= temp_uint64;
806
0
            }
807
0
            if (offset < datalen-1) {
808
0
                proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
809
0
                    loco_info_bits7, ENC_NA, &temp_uint64);
810
0
                offset += 1;
811
0
                calculated_checksum ^= temp_uint64;
812
0
            }
813
            /* If still something, dissect as bytes */
814
0
            if (offset < datalen-1) {
815
0
                proto_tree_add_item(z21_tree, hf_z21_loco_info_extensions,
816
0
                    tvb, offset, datalen-1-offset, ENC_NA);
817
                /* Note: Do not increment offset because the checksum
818
                 * will be calculated below! */
819
0
            }
820
0
            break;
821
0
        case Z21_LAN_X_PURGE_LOCO:
822
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
823
0
            addr = address_bytes & 0x3FFF;
824
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
825
0
            offset += 2;
826
0
            calculated_checksum ^= address_bytes >> 8;
827
0
            calculated_checksum ^= address_bytes & 0xFF;
828
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
829
0
            proto_item_append_text(z21_tree, ", Loco: %d", addr);
830
0
            break;
831
0
        case Z21_LAN_X_SET_LOCO_E_STOP:
832
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
833
0
            addr = address_bytes & 0x3FFF;
834
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
835
0
            offset += 2;
836
0
            calculated_checksum ^= address_bytes >> 8;
837
0
            calculated_checksum ^= address_bytes & 0xFF;
838
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
839
0
            proto_item_append_text(z21_tree, ", Loco: %d", addr);
840
0
            break;
841
0
        case Z21_LAN_X_SET_LOCO_BINARY_STATE:
842
0
            col_append_str(pinfo->cinfo, COL_INFO, ", TO BE COMPLETED");
843
0
            break;
844
0
        case Z21_LAN_X_SET_LOCO_FUNCTION:
845
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
846
0
            addr = address_bytes & 0x3FFF;
847
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
848
0
            offset += 2;
849
0
            calculated_checksum ^= address_bytes >> 8;
850
0
            calculated_checksum ^= address_bytes & 0xFF;
851
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
852
0
            proto_item_append_text(z21_tree, ", Loco: %d", addr);
853
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
854
0
                loco_func_bits, ENC_NA, &temp_uint64);
855
0
            offset += 1;
856
0
            calculated_checksum ^= temp_uint64;
857
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Function=%" PRIu64 ", State=%s",
858
0
                temp_uint64 & 0x3f,
859
0
                val_to_str_const((uint32_t)temp_uint64 >> 6, z21_loco_func_vals, "unknown"));
860
0
            proto_item_append_text(z21_tree, ", Function: %" PRIu64 ", State: %s",
861
0
                temp_uint64 & 0x3f,
862
0
                val_to_str_const((uint32_t)temp_uint64 >> 6, z21_loco_func_vals, "unknown"));
863
0
            break;
864
0
        case Z21_LAN_X_GET_TURNOUT_INFO:
865
0
            addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
866
0
            proto_tree_add_uint(z21_tree, hf_z21_function_address,
867
0
                tvb, offset, 2, addr);
868
0
            offset += 2;
869
0
            calculated_checksum ^= addr >> 8;
870
0
            calculated_checksum ^= addr & 0xFF;
871
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Function=%d", addr);
872
0
            proto_item_append_text(z21_tree, ", Function: %d", addr);
873
0
            break;
874
0
        case Z21_LAN_X_TURNOUT_INFO:
875
0
            addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
876
0
            proto_tree_add_uint(z21_tree, hf_z21_function_address,
877
0
                tvb, offset, 2, addr);
878
0
            offset += 2;
879
0
            calculated_checksum ^= addr >> 8;
880
0
            calculated_checksum ^= addr & 0xFF;
881
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
882
0
                turnout_state_bits, ENC_NA, &temp_uint64);
883
0
            offset += 1;
884
0
            calculated_checksum ^= temp_uint64;
885
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d, State=%s",
886
0
                addr,
887
0
                val_to_str_const((uint32_t)temp_uint64 & 0x03, z21_turnout_state_vals, "unknown"));
888
0
            proto_item_append_text(z21_tree, ", Address: %d, State: %s",
889
0
                addr,
890
0
                val_to_str_const((uint32_t)temp_uint64 & 0x03, z21_turnout_state_vals, "unknown"));
891
0
            break;
892
0
        case Z21_LAN_X_SET_TURNOUT:
893
0
            addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
894
0
            proto_tree_add_uint(z21_tree, hf_z21_function_address,
895
0
                tvb, offset, 2, addr);
896
0
            offset += 2;
897
0
            calculated_checksum ^= addr >> 8;
898
0
            calculated_checksum ^= addr & 0xFF;
899
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d", addr);
900
0
            proto_item_append_text(z21_tree, ", Address: %d", addr);
901
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
902
0
                turnout_set_bits, ENC_NA, &temp_uint64);
903
0
            offset += 1;
904
0
            calculated_checksum ^= temp_uint64;
905
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d, %s, Output=%s",
906
0
                addr,
907
0
                tfs_get_string((bool)(temp_uint64 & 0x08), &tfs_turnout_command),
908
0
                tfs_get_string((bool)(temp_uint64 & 0x01), &tfs_turnout_output));
909
0
            proto_item_append_text(z21_tree, ", Address: %d, %s, Output: %s",
910
0
                addr,
911
0
                tfs_get_string((bool)(temp_uint64 & 0x08), &tfs_turnout_command),
912
0
                tfs_get_string((bool)(temp_uint64 & 0x01), &tfs_turnout_output));
913
0
            break;
914
0
        case Z21_LAN_X_GET_EXT_ACCESSORY_INFO:
915
0
            addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
916
0
            proto_tree_add_uint(z21_tree, hf_z21_accessory_address,
917
0
                tvb, offset, 2, addr);
918
0
            offset += 2;
919
0
            calculated_checksum ^= addr >> 8;
920
0
            calculated_checksum ^= addr & 0xFF;
921
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d", addr);
922
0
            proto_item_append_text(z21_tree, ", Address: %d", addr);
923
0
            break;
924
0
        case Z21_LAN_X_EXT_ACCESSORY_INFO:
925
0
            addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
926
0
            proto_tree_add_uint(z21_tree, hf_z21_accessory_address,
927
0
                tvb, offset, 2, addr);
928
0
            offset += 2;
929
0
            calculated_checksum ^= addr >> 8;
930
0
            calculated_checksum ^= addr & 0xFF;
931
0
            temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
932
0
            proto_tree_add_uint(z21_tree, hf_z21_accessory_state,
933
0
                tvb, offset, 1, temp_uint >> 8);
934
0
            offset += 1;
935
0
            calculated_checksum ^= temp_uint >> 8;
936
0
            proto_tree_add_uint(z21_tree, hf_z21_accessory_status,
937
0
                tvb, offset, 1, temp_uint & 0xff);
938
0
            offset += 1;
939
0
            calculated_checksum ^= temp_uint & 0xff;
940
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d, State=%d, Status=0x%02x",
941
0
                addr, temp_uint >> 8, temp_uint & 0xff);
942
0
            proto_item_append_text(z21_tree, ", Address: %d, State: %d, Status: 0x%02x",
943
0
                addr, temp_uint >> 8, temp_uint & 0xff);
944
0
            break;
945
0
        case Z21_LAN_X_SET_EXT_ACCESSORY:
946
0
            addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
947
0
            proto_tree_add_uint(z21_tree, hf_z21_accessory_address,
948
0
                tvb, offset, 2, addr);
949
0
            offset += 2;
950
0
            calculated_checksum ^= addr >> 8;
951
0
            calculated_checksum ^= addr & 0xFF;
952
0
            temp_uint = tvb_get_uint8(tvb, offset);
953
0
            proto_tree_add_uint(z21_tree, hf_z21_accessory_state,
954
0
                tvb, offset, 1, temp_uint);
955
0
            offset += 1;
956
0
            calculated_checksum ^= temp_uint;
957
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d, State=%d",
958
0
                addr, temp_uint);
959
0
            proto_item_append_text(z21_tree, ", Address: %d, State: %d",
960
0
                addr, temp_uint);
961
0
            break;
962
0
        case Z21_LAN_X_CV_READ:
963
0
            cv_addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
964
            /* CV addresses are 1-based, update checksum first */
965
0
            calculated_checksum ^= cv_addr >> 8;
966
0
            calculated_checksum ^= cv_addr & 0xFF;
967
0
            cv_addr += 1;
968
0
            proto_tree_add_uint(z21_tree, hf_z21_cv_address,
969
0
                tvb, offset, 2, cv_addr);
970
0
            offset += 2;
971
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", CV%d", cv_addr);
972
0
            proto_item_append_text(z21_tree, ", CV%d", cv_addr);
973
0
            break;
974
0
        case Z21_LAN_X_CV_WRITE:
975
0
            cv_addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
976
            /* CV addresses are 1-based, update checksum first */
977
0
            calculated_checksum ^= cv_addr >> 8;
978
0
            calculated_checksum ^= cv_addr & 0xFF;
979
0
            cv_addr += 1;
980
0
            proto_tree_add_uint(z21_tree, hf_z21_cv_address,
981
0
                tvb, offset, 2, cv_addr);
982
0
            offset += 2;
983
0
            temp_uint = tvb_get_uint8(tvb, offset);
984
0
            proto_tree_add_uint(z21_tree, hf_z21_cv_value,
985
0
                tvb, offset, 1, temp_uint);
986
0
            offset += 1;
987
0
            calculated_checksum ^= temp_uint;
988
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", CV%d, Value=%d",
989
0
                cv_addr, temp_uint);
990
0
            proto_item_append_text(z21_tree, ", CV%d, Value: %d",
991
0
                cv_addr, temp_uint);
992
0
            break;
993
0
        case Z21_LAN_X_CV_RESULT:
994
0
            cv_addr = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
995
            /* CV addresses are 1-based, update checksum first */
996
0
            calculated_checksum ^= cv_addr >> 8;
997
0
            calculated_checksum ^= cv_addr & 0xFF;
998
0
            cv_addr += 1;
999
0
            proto_tree_add_uint(z21_tree, hf_z21_cv_address,
1000
0
                tvb, offset, 2, cv_addr);
1001
0
            offset += 2;
1002
0
            temp_uint = tvb_get_uint8(tvb, offset);
1003
0
            proto_tree_add_uint(z21_tree, hf_z21_cv_value,
1004
0
                tvb, offset, 1, temp_uint);
1005
0
            offset += 1;
1006
0
            calculated_checksum ^= temp_uint;
1007
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", CV%d, Value=%d",
1008
0
                cv_addr, temp_uint);
1009
0
            proto_item_append_text(z21_tree, ", CV%d, Value: %d",
1010
0
                cv_addr, temp_uint);
1011
0
            break;
1012
0
        case Z21_LAN_X_CV_POM_WRITE_BYTE:
1013
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1014
0
            addr = address_bytes & 0x3FFF;
1015
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
1016
0
            offset += 2;
1017
0
            calculated_checksum ^= address_bytes >> 8;
1018
0
            calculated_checksum ^= address_bytes & 0xFF;
1019
0
            temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1020
0
            calculated_checksum ^= temp_uint >> 8;
1021
0
            calculated_checksum ^= temp_uint & 0xff;
1022
0
            proto_tree_add_uint(z21_tree, hf_z21_pom_operation,
1023
0
                tvb, offset, 1, temp_uint >> 2);
1024
0
            cv_addr = (temp_uint & 0x03ff) + 1;
1025
0
            proto_tree_add_uint(z21_tree, hf_z21_cv_address,
1026
0
                tvb, offset, 2, cv_addr);
1027
0
            offset += 2;
1028
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_cv_value,
1029
0
                tvb, offset, 1, ENC_NA, &temp_uint);
1030
0
            offset += 1;
1031
0
            calculated_checksum ^= temp_uint;
1032
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d, CV%d, Value=%d",
1033
0
                addr, cv_addr, temp_uint);
1034
0
            proto_item_append_text(z21_tree, ", Loco: %d, CV%d, Value: %d",
1035
0
                addr, cv_addr, temp_uint);
1036
0
            break;
1037
0
        case Z21_LAN_X_CV_POM_WRITE_BIT:
1038
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1039
0
            addr = address_bytes & 0x3FFF;
1040
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
1041
0
            offset += 2;
1042
0
            calculated_checksum ^= address_bytes >> 8;
1043
0
            calculated_checksum ^= address_bytes & 0xFF;
1044
0
            temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1045
0
            calculated_checksum ^= temp_uint >> 8;
1046
0
            calculated_checksum ^= temp_uint & 0xff;
1047
0
            proto_tree_add_uint(z21_tree, hf_z21_pom_operation,
1048
0
                tvb, offset, 1, temp_uint >> 2);
1049
0
            cv_addr = (temp_uint & 0x03ff) + 1;
1050
0
            proto_tree_add_uint(z21_tree, hf_z21_cv_address,
1051
0
                tvb, offset, 2, cv_addr);
1052
0
            offset += 2;
1053
0
            proto_tree_add_bitmask_list_ret_uint64(z21_tree, tvb, offset, 1,
1054
0
                cv_bits, ENC_NA, &temp_uint64);
1055
0
            offset += 1;
1056
0
            calculated_checksum ^= (unsigned)temp_uint64;
1057
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d, CV%d, Bit position=%" PRIu64 ", Value=%" PRIu64,
1058
0
                addr, cv_addr, temp_uint64 & 0x07, temp_uint64 >> 3 & 0x01);
1059
0
            proto_item_append_text(z21_tree, ", Loco: %d, CV%d, Bit position: %" PRIu64 ", Value: %" PRIu64,
1060
0
                addr, cv_addr, temp_uint64 & 0x07, temp_uint64 >> 3 & 0x01);
1061
0
            break;
1062
0
        case Z21_LAN_X_CV_POM_READ_BYTE:
1063
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1064
0
            addr = address_bytes & 0x3FFF;
1065
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
1066
0
            offset += 2;
1067
0
            calculated_checksum ^= address_bytes >> 8;
1068
0
            calculated_checksum ^= address_bytes & 0xFF;
1069
0
            temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1070
0
            calculated_checksum ^= temp_uint >> 8;
1071
0
            calculated_checksum ^= temp_uint & 0xff;
1072
0
            proto_tree_add_uint(z21_tree, hf_z21_pom_operation,
1073
0
                tvb, offset, 1, temp_uint >> 2);
1074
0
            cv_addr = (temp_uint & 0x03ff) + 1;
1075
0
            proto_tree_add_uint(z21_tree, hf_z21_cv_address,
1076
0
                tvb, offset, 2, cv_addr);
1077
0
            offset += 2;
1078
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d, CV%d",
1079
0
                addr, cv_addr);
1080
0
            proto_item_append_text(z21_tree, ", Loco: %d, CV%d",
1081
0
                addr, cv_addr);
1082
0
            break;
1083
0
        case Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BYTE:
1084
0
        case Z21_LAN_X_CV_POM_ACCESSORY_WRITE_BIT:
1085
0
        case Z21_LAN_X_CV_POM_ACCESSORY_READ_BYTE:
1086
0
            col_append_str(pinfo->cinfo, COL_INFO, ", *** TO BE COMPLETED ***");
1087
0
            break;
1088
0
        case Z21_LAN_X_DCC_READ_REGISTER:
1089
0
            temp_uint = tvb_get_uint8(tvb, offset);
1090
0
            proto_tree_add_uint(z21_tree, hf_z21_register,
1091
0
                tvb, offset, 1, temp_uint);
1092
0
            offset += 1;
1093
0
            calculated_checksum ^= temp_uint;
1094
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Register%d",
1095
0
                temp_uint);
1096
0
            proto_item_append_text(z21_tree, ", Register%d",
1097
0
                temp_uint);
1098
0
            break;
1099
0
        case Z21_LAN_X_DCC_WRITE_REGISTER:
1100
0
            temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1101
0
            proto_tree_add_uint(z21_tree, hf_z21_register,
1102
0
                tvb, offset, 1, temp_uint >> 8);
1103
0
            offset += 1;
1104
0
            calculated_checksum ^= temp_uint >> 8;
1105
0
            proto_tree_add_uint(z21_tree, hf_z21_register_value,
1106
0
                tvb, offset, 1, temp_uint & 0xff);
1107
0
            offset += 1;
1108
0
            calculated_checksum ^= temp_uint & 0xff;
1109
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Register%d, Value=%d",
1110
0
                temp_uint >> 8, temp_uint & 0xff);
1111
0
            proto_item_append_text(z21_tree, ", Register%d, Value: %d",
1112
0
                temp_uint >> 8, temp_uint & 0xff);
1113
0
            break;
1114
0
        case Z21_LAN_X_MM_WRITE_BYTE:
1115
            /* Skip one zero byte */
1116
0
            offset += 1;
1117
0
            temp_uint = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1118
0
            proto_tree_add_uint(z21_tree, hf_z21_register,
1119
0
                tvb, offset, 1, temp_uint >> 8);
1120
0
            offset += 1;
1121
0
            calculated_checksum ^= temp_uint >> 8;
1122
0
            proto_tree_add_uint(z21_tree, hf_z21_register_value,
1123
0
                tvb, offset, 1, temp_uint & 0xff);
1124
0
            offset += 1;
1125
0
            calculated_checksum ^= temp_uint & 0xff;
1126
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Register%d, Value=%d",
1127
0
                temp_uint >> 8, temp_uint & 0xff);
1128
0
            proto_item_append_text(z21_tree, ", Register%d, Value: %d",
1129
0
                temp_uint >> 8, temp_uint & 0xff);
1130
0
            break;
1131
0
        case Z21_LAN_X_GET_FIRMWARE_VERSION_REPLY:
1132
0
            version = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1133
0
            buffer = wmem_strdup_printf(pinfo->pool, "%x.%02x",
1134
0
                version >> 8, version & 0xff);
1135
0
            proto_tree_add_string(z21_tree, hf_z21_firmware_version,
1136
0
                tvb, offset, 2, buffer);
1137
0
            offset += 2;
1138
0
            calculated_checksum ^= version >> 8;
1139
0
            calculated_checksum ^= version & 0xFF;
1140
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Version=%s",
1141
0
                buffer);
1142
0
        }
1143
1144
        /* Calculate checksum for the rest of the bytes (if any) for now */
1145
0
        while (offset < datalen-1) {
1146
0
            one_byte = tvb_get_uint8(tvb, offset);
1147
0
            offset += 1;
1148
0
            calculated_checksum ^= one_byte;
1149
0
        }
1150
        /* No more data in the X-BUS command, read the checksum */
1151
0
        temp_ti = proto_tree_add_item_ret_uint(z21_tree, hf_z21_checksum,
1152
0
            tvb, offset, 1, ENC_NA, &checksum);
1153
0
        if (checksum != calculated_checksum) {
1154
0
            expert_add_info_format(pinfo, temp_ti, &ei_z21_invalid_checksum,
1155
0
                "Invalid checksum, calculated: 0x%02x", calculated_checksum);
1156
0
        }
1157
0
    }
1158
0
    else {
1159
        /* Not X-BUS */
1160
0
        command_ti = proto_tree_add_uint(z21_tree, hf_z21_command,
1161
0
            tvb, offset, 2, command);
1162
0
        offset += 2;
1163
0
        update_command_field(command_ti, command);
1164
0
        col_add_fstr(pinfo->cinfo, COL_INFO, "Command=%s",
1165
0
            val_to_str_const(command, z21_command_vals, "unknown"));
1166
0
        proto_item_append_text(z21_tree, ", Command: %s",
1167
0
            val_to_str_const(command, z21_command_vals, "unknown"));
1168
0
        switch (command) {
1169
0
        case Z21_LAN_GET_SERIAL_NUMBER:
1170
0
            if (datalen == 8) {
1171
0
                unsigned serial;
1172
0
                proto_tree_add_item_ret_uint(z21_tree, hf_z21_serial_number,
1173
0
                    tvb, offset, 4, ENC_LITTLE_ENDIAN, &serial);
1174
0
                offset += 4;
1175
0
                col_append_fstr(pinfo->cinfo, COL_INFO, ", Serial number: %d",
1176
0
                    serial);
1177
0
            }
1178
0
            break;
1179
0
        case Z21_LAN_SYSTEMSTATE_DATACHANGED:
1180
0
            main_current = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1181
0
            proto_tree_add_int_format_value(z21_tree, hf_z21_main_current,
1182
0
                tvb, offset, 2, main_current, "%d mA", main_current);
1183
0
            offset += 2;
1184
1185
0
            temp_int32 = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1186
0
            proto_tree_add_int_format_value(z21_tree, hf_z21_prog_current,
1187
0
                tvb, offset, 2, temp_int32, "%d mA", temp_int32);
1188
0
            offset += 2;
1189
1190
0
            temp_int32 = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1191
0
            proto_tree_add_int_format_value(z21_tree, hf_z21_filtered_main_current,
1192
0
                tvb, offset, 2, temp_int32, "%d mA", temp_int32);
1193
0
            offset += 2;
1194
1195
0
            temp_int32 = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1196
0
            proto_tree_add_int_format_value(z21_tree, hf_z21_temperature,
1197
0
                tvb, offset, 2, temp_int32, "%d°C", temp_int32);
1198
0
            offset += 2;
1199
0
            col_append_fstr(pinfo->cinfo, COL_INFO,
1200
0
                ", Temperature=%d°C", temp_int32);
1201
1202
0
            temp_uint = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
1203
0
            temp_float = (float)temp_uint / 1000;
1204
0
            proto_tree_add_float_format_value(z21_tree, hf_z21_supply_voltage,
1205
0
                tvb, offset, 2, temp_float, "%.3f V", temp_float);
1206
0
            offset += 2;
1207
0
            col_append_fstr(pinfo->cinfo, COL_INFO,
1208
0
                ", Track=%.3f V/%d mA", temp_float, main_current);
1209
1210
0
            temp_uint = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
1211
0
            temp_float = (float)temp_uint / 1000;
1212
0
            proto_tree_add_float_format_value(z21_tree, hf_z21_track_voltage,
1213
0
                tvb, offset, 2, temp_float, "%.3f V", temp_float);
1214
0
            offset += 2;
1215
1216
0
            proto_tree_add_bitmask(z21_tree, tvb, offset, hf_z21_central_state,
1217
0
                ett_z21, state_bits_byte1, ENC_NA);
1218
0
            offset += 1;
1219
0
            proto_tree_add_bitmask(z21_tree, tvb, offset, hf_z21_central_state_ex,
1220
0
                ett_z21, state_bits_byte2, ENC_NA);
1221
0
            offset += 1;
1222
0
            proto_tree_add_item(z21_tree, hf_z21_systemstate_reserved,
1223
0
                tvb, offset, 1, ENC_NA);
1224
0
            offset += 1;
1225
0
            temp_uint = tvb_get_uint8(tvb, offset);
1226
0
            if (temp_uint == 0) {
1227
                /* Don't interpret the flags */
1228
0
                proto_tree_add_uint_format_value(z21_tree, hf_z21_capabilities,
1229
0
                tvb, offset, 1, 0, "0x00 (Capability flags not supported)");
1230
0
            }
1231
0
            else {
1232
0
                proto_tree_add_bitmask(z21_tree, tvb, offset, hf_z21_capabilities,
1233
0
                    ett_z21, capability_bits, ENC_NA);
1234
0
            }
1235
0
            offset += 1;
1236
0
            break;
1237
0
        case Z21_LAN_RMBUS_GETDATA:
1238
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_rmbus_group,
1239
0
                tvb, offset, 1, ENC_NA, &temp_uint);
1240
0
            offset += 1;
1241
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Group=%d", temp_uint);
1242
0
            proto_item_append_text(z21_tree, ", Group: %d", temp_uint);
1243
0
            break;
1244
0
        case Z21_LAN_RMBUS_DATACHANGED:
1245
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_rmbus_group,
1246
0
                tvb, offset, 1, ENC_NA, &temp_uint);
1247
0
            offset += 1;
1248
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Group=%d", temp_uint);
1249
0
            proto_item_append_text(z21_tree, ", Group: %d", temp_uint);
1250
0
            proto_tree_add_item(z21_tree, hf_z21_rmbus_feedbacks, tvb, offset, 10, ENC_NA);
1251
0
            offset += 10;
1252
0
            break;
1253
0
        case Z21_LAN_RMBUS_PROGRAMMODULE:
1254
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_rmbus_address,
1255
0
                tvb, offset, 1, ENC_NA, &temp_uint);
1256
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Address=%d", temp_uint);
1257
0
            proto_item_append_text(z21_tree, ", Address: %d", temp_uint);
1258
0
            offset += 1;
1259
0
            break;
1260
0
        case Z21_LAN_RAILCOM_DATACHANGED:
1261
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_loco_address,
1262
0
                tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1263
0
            offset += 2;
1264
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", temp_uint);
1265
0
            proto_item_append_text(z21_tree, ", Loco: %d", temp_uint);
1266
0
            proto_tree_add_item(z21_tree, hf_z21_railcom_receive_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1267
0
            offset += 4;
1268
0
            proto_tree_add_item(z21_tree, hf_z21_railcom_error_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1269
0
            offset += 2;
1270
0
            proto_tree_add_item(z21_tree, hf_z21_railcom_reserved1, tvb, offset, 1, ENC_NA);
1271
0
            offset += 1;
1272
0
            proto_tree_add_item(z21_tree, hf_z21_railcom_options, tvb, offset, 1, ENC_NA);
1273
0
            offset += 1;
1274
0
            proto_tree_add_item(z21_tree, hf_z21_railcom_speed, tvb, offset, 1, ENC_NA);
1275
0
            offset += 1;
1276
0
            proto_tree_add_item(z21_tree, hf_z21_railcom_qos, tvb, offset, 1, ENC_NA);
1277
0
            offset += 1;
1278
0
            proto_tree_add_item(z21_tree, hf_z21_railcom_reserved2, tvb, offset, 1, ENC_NA);
1279
0
            offset += 1;
1280
0
            break;
1281
0
        case Z21_LAN_RAILCOM_GETDATA:
1282
0
            proto_tree_add_item(z21_tree, hf_z21_railcom_type, tvb, offset, 1, ENC_NA);
1283
0
            offset += 1;
1284
0
            proto_tree_add_item(z21_tree, hf_z21_loco_address, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1285
0
            offset += 2;
1286
0
            break;
1287
0
        case Z21_LAN_LOCONET_FROM_LAN:
1288
0
        case Z21_LAN_LOCONET_Z21_RX:
1289
0
        case Z21_LAN_LOCONET_Z21_TX:
1290
0
            proto_tree_add_item(z21_tree, hf_z21_loconet_message,
1291
0
                tvb, offset, datalen-4, ENC_NA);
1292
0
            offset += datalen-4;
1293
0
            break;
1294
0
        case Z21_LAN_LOCONET_DISPATCH_ADDR:
1295
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_loco_address,
1296
0
                tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1297
0
            offset += 2;
1298
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", temp_uint);
1299
0
            proto_item_append_text(z21_tree, ", Loco: %d", temp_uint);
1300
0
            if (datalen > 6) {
1301
                /* Response from Z21 */
1302
0
                proto_tree_add_item(z21_tree, hf_z21_loconet_result, tvb, offset, 1, ENC_NA);
1303
0
                offset += 1;
1304
0
            }
1305
0
            break;
1306
0
        case Z21_LAN_LOCONET_DETECTOR:
1307
0
            proto_tree_add_item(z21_tree, hf_z21_loconet_type, tvb, offset, 1, ENC_NA);
1308
0
            offset += 1;
1309
0
            if (datalen == 7) {
1310
                /* This is request */
1311
0
                proto_tree_add_item(z21_tree, hf_z21_loconet_report_address,
1312
0
                    tvb, offset, 2, ENC_LITTLE_ENDIAN);
1313
0
                offset += 2;
1314
0
            }
1315
0
            else {
1316
                /* This is reply */
1317
0
                proto_tree_add_item(z21_tree, hf_z21_loconet_feedback_address,
1318
0
                    tvb, offset, 2, ENC_LITTLE_ENDIAN);
1319
0
                offset += 2;
1320
0
                proto_tree_add_item(z21_tree, hf_z21_loconet_info,
1321
0
                    tvb, offset, datalen-7, ENC_NA);
1322
0
                offset += datalen-7;
1323
0
            }
1324
0
            break;
1325
0
        case Z21_LAN_CAN_DETECTOR:
1326
0
            if (datalen == 7) {
1327
                /* This is request */
1328
0
                proto_tree_add_item(z21_tree, hf_z21_can_type, tvb, offset, 1, ENC_NA);
1329
0
                offset += 1;
1330
0
                proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1331
0
                    tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1332
0
                offset += 2;
1333
0
                col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1334
0
                proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1335
0
            }
1336
0
            else {
1337
                /* This is reply */
1338
0
                proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1339
0
                    tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1340
0
                offset += 2;
1341
0
                col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1342
0
                proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1343
0
                proto_tree_add_item(z21_tree, hf_z21_can_module_address,
1344
0
                    tvb, offset, 2, ENC_LITTLE_ENDIAN);
1345
0
                offset += 2;
1346
0
                proto_tree_add_item(z21_tree, hf_z21_can_port, tvb, offset, 1, ENC_NA);
1347
0
                offset += 1;
1348
0
                proto_tree_add_item(z21_tree, hf_z21_can_type, tvb, offset, 1, ENC_NA);
1349
0
                offset += 1;
1350
0
                proto_tree_add_item(z21_tree, hf_z21_can_value1,
1351
0
                    tvb, offset, 2, ENC_LITTLE_ENDIAN);
1352
0
                offset += 2;
1353
0
                proto_tree_add_item(z21_tree, hf_z21_can_value2,
1354
0
                    tvb, offset, 2, ENC_LITTLE_ENDIAN);
1355
0
                offset += 2;
1356
0
            }
1357
0
            break;
1358
0
        case Z21_LAN_CAN_DEVICE_GET_DESCRIPTION:
1359
0
        case Z21_LAN_CAN_DEVICE_SET_DESCRIPTION:
1360
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1361
0
                tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1362
0
            offset += 2;
1363
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1364
0
            proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1365
0
            if (datalen > 6) {
1366
0
                proto_tree_add_item(z21_tree, hf_z21_can_booster_name,
1367
0
                    tvb, offset, 16, ENC_ISO_8859_1);
1368
0
                offset += 16;
1369
0
            }
1370
0
            break;
1371
0
        case Z21_LAN_CAN_BOOSTER_SYSTEMSTATE_CHGD:
1372
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1373
0
                tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1374
0
            offset += 2;
1375
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1376
0
            proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1377
0
            proto_tree_add_item(z21_tree, hf_z21_can_booster_output_port,
1378
0
                tvb, offset, 2, ENC_LITTLE_ENDIAN);
1379
0
            offset += 2;
1380
0
            proto_tree_add_bitmask(z21_tree, tvb, offset,
1381
0
                hf_z21_can_booster_state, ett_z21, booster_state_bits, ENC_LITTLE_ENDIAN);
1382
0
            offset += 2;
1383
0
            temp_uint = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1384
0
            proto_tree_add_uint_format_value(z21_tree, hf_z21_can_booster_vcc,
1385
0
                tvb, offset, 2, temp_uint, "%d mV", temp_uint);
1386
0
            offset += 2;
1387
0
            temp_uint = tvb_get_int16(tvb, offset, ENC_LITTLE_ENDIAN);
1388
0
            proto_tree_add_uint_format_value(z21_tree, hf_z21_can_booster_current,
1389
0
                tvb, offset, 2, temp_uint, "%d mA", temp_uint);
1390
0
            offset += 2;
1391
0
            break;
1392
0
        case Z21_LAN_CAN_BOOSTER_SET_TRACKPOWER:
1393
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_can_network_id,
1394
0
                tvb, offset, 2, ENC_LITTLE_ENDIAN, &temp_uint);
1395
0
            offset += 2;
1396
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", NetworkID=%d", temp_uint);
1397
0
            proto_item_append_text(z21_tree, ", NetworkID: %d", temp_uint);
1398
0
            proto_tree_add_item(z21_tree, hf_z21_can_booster_power, tvb, offset, 1, ENC_NA);
1399
0
            offset += 1;
1400
0
            break;
1401
0
        case Z21_LAN_ZLINK_GET_HWINFO:
1402
0
            proto_tree_add_item(z21_tree, hf_z21_zlink_message_type, tvb, offset, 1, ENC_NA);
1403
0
            offset += 1;
1404
0
            if (datalen > 5) {
1405
0
                proto_tree_add_item(z21_tree, hf_z21_zlink_hwid,
1406
0
                    tvb, offset, 2, ENC_LITTLE_ENDIAN);
1407
0
                offset += 2;
1408
0
                proto_tree_add_item(z21_tree, hf_z21_zlink_fw_major, tvb, offset, 1, ENC_NA);
1409
0
                offset += 1;
1410
0
                proto_tree_add_item(z21_tree, hf_z21_zlink_fw_minor, tvb, offset, 1, ENC_NA);
1411
0
                offset += 1;
1412
0
                proto_tree_add_item(z21_tree, hf_z21_zlink_fw_build, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1413
0
                offset += 2;
1414
0
                proto_tree_add_item(z21_tree, hf_z21_zlink_mac, tvb, offset, 18, ENC_ASCII);
1415
0
                offset += 18;
1416
0
                proto_tree_add_item(z21_tree, hf_z21_zlink_name, tvb, offset, 33, ENC_ISO_8859_1);
1417
0
                offset += 18;
1418
0
                proto_tree_add_item(z21_tree, hf_z21_zlink_reserved, tvb, offset, 1, ENC_NA);
1419
0
                offset += 1;
1420
0
            }
1421
0
            break;
1422
0
        case Z21_LAN_BOOSTER_GET_DESCRIPTION:
1423
0
        case Z21_LAN_BOOSTER_SET_DESCRIPTION:
1424
0
            if (datalen > 4) {
1425
                /* SET_DESCRIPTION or reply to GET_DESCRIPTION */
1426
0
                uint8_t *buf = tvb_get_stringz_enc(pinfo->pool, tvb, offset, NULL, ENC_ISO_8859_1);
1427
0
                if (buf[0] == 0xff) {
1428
                    /* Interpreted as an empty name */
1429
0
                    proto_tree_add_string(z21_tree, hf_z21_booster_name, tvb, offset, 32, "");
1430
0
                }
1431
0
                else {
1432
0
                    proto_tree_add_string(z21_tree, hf_z21_booster_name, tvb, offset, 32, (char*)buf);
1433
0
                }
1434
0
                offset += 32;
1435
0
            }
1436
0
            break;
1437
0
        case Z21_LAN_BOOSTER_SYSTEMSTATE_GETDATA:
1438
0
        case Z21_LAN_DECODER_SYSTEMSTATE_GETDATA:
1439
0
            break;
1440
0
        case Z21_LAN_DECODER_GET_DESCRIPTION:
1441
0
        case Z21_LAN_DECODER_SET_DESCRIPTION:
1442
0
            if (datalen > 4) {
1443
                /* SET_DESCRIPTION or reply to GET_DESCRIPTION */
1444
0
                uint8_t *buf = tvb_get_stringz_enc(pinfo->pool, tvb, offset, NULL, ENC_ISO_8859_1);
1445
0
                if (buf[0] == 0xff) {
1446
                    /* Interpreted as an empty name */
1447
0
                    proto_tree_add_string(z21_tree, hf_z21_decoder_name, tvb, offset, 32, "");
1448
0
                }
1449
0
                else {
1450
0
                    proto_tree_add_string(z21_tree, hf_z21_decoder_name, tvb, offset, 32, (char*)buf);
1451
0
                }
1452
0
                offset += 32;
1453
0
            }
1454
0
            break;
1455
0
        case Z21_LAN_BOOSTER_SET_POWER:
1456
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_booster_port,
1457
0
                tvb, offset, 1, ENC_NA, &temp_uint);
1458
0
            offset += 1;
1459
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Port=%d", temp_uint);
1460
0
            proto_item_append_text(z21_tree, ", Port: %d", temp_uint);
1461
0
            proto_tree_add_item_ret_uint(z21_tree, hf_z21_booster_port_state,
1462
0
                tvb, offset, 1, ENC_NA, &temp_uint);
1463
0
            offset += 1;
1464
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", State=%d", temp_uint);
1465
0
            proto_item_append_text(z21_tree, ", State: %d", temp_uint);
1466
0
            break;
1467
0
        case Z21_LAN_BOOSTER_SYSTEMSTATE_DATACHANGED:
1468
            /* To be expanded later... */
1469
0
            proto_tree_add_item(z21_tree, hf_z21_booster_state_data,
1470
0
                tvb, offset, 24, ENC_NA);
1471
0
            offset += 24;
1472
0
            break;
1473
0
        case Z21_LAN_DECODER_SYSTEMSTATE_DATACHANGED:
1474
            /* To be expanded later... */
1475
            /* Data is variable length */
1476
0
            proto_tree_add_item(z21_tree, hf_z21_decoder_state_data,
1477
0
                tvb, offset, datalen-4, ENC_NA);
1478
0
            offset += datalen-4;
1479
0
            break;
1480
0
        case Z21_LAN_GET_LOCOMODE:
1481
0
        case Z21_LAN_SET_LOCOMODE:
1482
0
            address_bytes = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1483
0
            addr = address_bytes & 0x3FFF;
1484
0
            proto_tree_add_uint(z21_tree, hf_z21_loco_address, tvb, offset, 2, addr);
1485
0
            offset += 2;
1486
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Loco=%d", addr);
1487
0
            if (datalen > 6) {
1488
0
                unsigned mode = tvb_get_uint8(tvb, offset);
1489
0
                proto_tree_add_uint(z21_tree, hf_z21_loco_mode, tvb, offset, 1, mode);
1490
0
                offset += 1;
1491
0
                col_append_fstr(pinfo->cinfo, COL_INFO, ", Mode: %d", mode);
1492
0
            }
1493
0
            break;
1494
0
        case Z21_LAN_GET_BROADCASTFLAGS:
1495
0
        case Z21_LAN_SET_BROADCASTFLAGS:
1496
0
            if (datalen == 8) {
1497
0
                proto_tree_add_bitmask_with_flags(z21_tree, tvb, offset, hf_z21_broadcast_flags,
1498
0
                    ett_z21, broadcast_flags_bits, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
1499
0
                offset += 4;
1500
0
            }
1501
0
            break;
1502
0
        case Z21_LAN_GET_HWINFO:
1503
0
            if (datalen == 12) {
1504
0
                unsigned hwtype = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN);
1505
0
                proto_tree_add_uint(z21_tree, hf_z21_hw_type, tvb, offset, 1, hwtype);
1506
0
                offset += 4;
1507
0
                version = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN);
1508
0
                buffer = wmem_strdup_printf(pinfo->pool, "%x.%02x",
1509
0
                    version >> 8, version & 0xff);
1510
0
                proto_tree_add_string(z21_tree, hf_z21_firmware_version,
1511
0
                    tvb, offset, 2, buffer);
1512
0
                offset += 4;
1513
0
            }
1514
0
            break;
1515
0
        }
1516
0
        if (offset < datalen) {
1517
            /* Just dump all the rest, if any */
1518
0
            proto_tree_add_item(z21_tree, hf_z21_data, tvb, offset, datalen-offset, ENC_NA);
1519
0
            offset += datalen-offset;
1520
0
        }
1521
0
    }
1522
0
    return offset;
1523
0
}
1524
1525
static unsigned
1526
get_z21_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1527
6
{
1528
6
    return tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
1529
6
}
1530
1531
static bool
1532
check_z21_header(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1533
7
{
1534
7
    int remaining_length = tvb_reported_length_remaining(tvb, offset);
1535
7
    if (remaining_length < Z21_MIN_LENGTH) {
1536
1
        return false;
1537
1
    }
1538
6
    int pdu_len = get_z21_pdu_len(pinfo, tvb, offset, data);
1539
6
    if (pdu_len < Z21_MIN_LENGTH || pdu_len > remaining_length) {
1540
6
        return false;
1541
6
    }
1542
0
    uint16_t command = tvb_get_uint16(tvb, offset + 2, ENC_BIG_ENDIAN);
1543
0
    if (!try_val_to_str(command, z21_command_vals)) {
1544
0
        return false;
1545
0
    }
1546
0
    return true;
1547
0
}
1548
1549
static int
1550
dissect_z21(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1551
7
{
1552
7
    return udp_dissect_pdus(tvb, pinfo, tree, Z21_MIN_LENGTH,
1553
7
        check_z21_header, get_z21_pdu_len, dissect_z21_pdu, data);
1554
7
}
1555
1556
/* Register the protocol with Wireshark.
1557
 *
1558
 * This format is required because a script is used to build the C function that
1559
 * calls all the protocol registration.
1560
 */
1561
void
1562
proto_register_z21(void)
1563
14
{
1564
14
    expert_module_t *expert_z21;
1565
1566
14
    static hf_register_info hf[] = {
1567
14
        { &hf_z21_datalen,
1568
14
          { "Data length", "z21.datalen",
1569
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
1570
14
            NULL, HFILL }
1571
14
        },
1572
14
        { &hf_z21_command,
1573
14
          { "Command", "z21.command",
1574
14
            FT_UINT32, BASE_HEX|BASE_NO_DISPLAY_VALUE, VALS(z21_command_vals), 0x0,
1575
14
            NULL, HFILL }
1576
14
        },
1577
14
        { &hf_z21_x_bus,
1578
14
          { "X-BUS", "z21.xbus",
1579
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1580
14
            NULL, HFILL }
1581
14
        },
1582
14
        { &hf_z21_serial_number,
1583
14
          { "Serial number", "z21.serialnumber",
1584
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1585
14
            NULL, HFILL }
1586
14
        },
1587
14
        { &hf_z21_checksum,
1588
14
          { "Checksum", "z21.checksum",
1589
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1590
14
            NULL, HFILL }
1591
14
        },
1592
14
        { &hf_z21_main_current,
1593
14
          { "Main track current", "z21.maincurrent",
1594
14
            FT_INT16, BASE_DEC, NULL, 0x0,
1595
14
            NULL, HFILL }
1596
14
        },
1597
14
        { &hf_z21_prog_current,
1598
14
          { "Programming track current", "z21.progcurrent",
1599
14
            FT_INT16, BASE_DEC, NULL, 0x0,
1600
14
            NULL, HFILL }
1601
14
        },
1602
14
        { &hf_z21_filtered_main_current,
1603
14
          { "Filtered main track current", "z21.filteredmaincurrent",
1604
14
            FT_INT16, BASE_DEC, NULL, 0x0,
1605
14
            NULL, HFILL }
1606
14
        },
1607
14
        { &hf_z21_temperature,
1608
14
          { "Command station temperature", "z21.temperature",
1609
14
            FT_INT16, BASE_DEC, NULL, 0x0,
1610
14
            NULL, HFILL }
1611
14
        },
1612
14
        { &hf_z21_supply_voltage,
1613
14
          { "Supply voltage", "z21.supplyvoltage",
1614
14
            FT_FLOAT, BASE_DEC, NULL, 0x0,
1615
14
            NULL, HFILL }
1616
14
        },
1617
14
        { &hf_z21_track_voltage,
1618
14
          { "Track voltage", "z21.trackvoltage",
1619
14
            FT_FLOAT, BASE_DEC, NULL, 0x0,
1620
14
            NULL, HFILL }
1621
14
        },
1622
14
        { &hf_z21_broadcast_flags,
1623
14
          { "Broadcast flags", "z21.broadcastflags",
1624
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
1625
14
            NULL, HFILL }
1626
14
        },
1627
14
        { &hf_z21_central_state,
1628
14
          { "Central state, first byte", "z21.centralstate1",
1629
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1630
14
            NULL, HFILL }
1631
14
        },
1632
14
        { &hf_z21_central_state_ex,
1633
14
          { "Central state, second byte", "z21.centralstate2",
1634
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1635
14
            NULL, HFILL }
1636
14
        },
1637
14
        { &hf_z21_systemstate_reserved,
1638
14
          { "Reserved", "z21.systemstatereserved",
1639
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1640
14
            NULL, HFILL }
1641
14
        },
1642
14
        { &hf_z21_capabilities,
1643
14
          { "Capabilities", "z21.capabilities",
1644
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1645
14
            NULL, HFILL }
1646
14
        },
1647
14
        { &hf_z21_status,
1648
14
          { "Status", "z21.status",
1649
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1650
14
            NULL, HFILL }
1651
14
        },
1652
14
        { &hf_z21_broadcast_flags_driving_switching,
1653
14
          { "Broadcasts messages concerning driving and switching", "z21.broadcastflags.driving_switching",
1654
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000001,
1655
14
            NULL, HFILL }
1656
14
        },
1657
14
        { &hf_z21_broadcast_flags_rmbus,
1658
14
          { "Changes of the feedback devices on the R-Bus", "z21.broadcastflags.rmbus",
1659
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000002,
1660
14
            NULL, HFILL }
1661
14
        },
1662
14
        { &hf_z21_broadcast_flags_railcom_subscribed,
1663
14
          { "Changes of RailCom data of subscribed locomotives", "z21.broadcastflags.railcom_subscribed",
1664
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000004,
1665
14
            NULL, HFILL }
1666
14
        },
1667
14
        { &hf_z21_broadcast_flags_system_status,
1668
14
          { "Changes of the Z21 system status", "z21.broadcastflags.system_status",
1669
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000100,
1670
14
            NULL, HFILL }
1671
14
        },
1672
14
        { &hf_z21_broadcast_flags_driving_switching_ex,
1673
14
          { "Extends flag 0x00000001, LAN_X_LOCO_INFO is sent for all modified locomotives", "z21.broadcastflags.driving_switching_ex",
1674
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00010000,
1675
14
            NULL, HFILL }
1676
14
        },
1677
14
        { &hf_z21_broadcast_flags_loconet,
1678
14
          { "Forward messages from LocoNet without locos and switches", "z21.broadcastflags.loconet",
1679
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x01000000,
1680
14
            NULL, HFILL }
1681
14
        },
1682
14
        { &hf_z21_broadcast_flags_loconet_driving,
1683
14
          { "Forward locomotive-specific LocoNet", "z21.broadcastflags.loconet_driving",
1684
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x02000000,
1685
14
            NULL, HFILL }
1686
14
        },
1687
14
        { &hf_z21_broadcast_flags_loconet_switching,
1688
14
          { "Forward switch-specific LocoNet", "z21.broadcastflags.loconet_switching",
1689
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x04000000,
1690
14
            NULL, HFILL }
1691
14
        },
1692
14
        { &hf_z21_broadcast_flags_loconet_detector,
1693
14
          { "Changes of LocoNet track occupancy detectors", "z21.broadcastflags.emergencystop",
1694
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x08000000,
1695
14
            NULL, HFILL }
1696
14
        },
1697
14
        { &hf_z21_broadcast_flags_railcom,
1698
14
          { "Changes of RailCom data", "z21.broadcastflags.railcom",
1699
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00040000,
1700
14
            NULL, HFILL }
1701
14
        },
1702
14
        { &hf_z21_broadcast_flags_can_detector,
1703
14
          { "Changes of CAN-Bus track occupancy detectors", "z21.broadcastflags.can_detector",
1704
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00080000,
1705
14
            NULL, HFILL }
1706
14
        },
1707
14
        { &hf_z21_broadcast_flags_can_booster,
1708
14
          { "Forward CAN-Bus booster status messages", "z21.broadcastflags.can_booster",
1709
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00020000,
1710
14
            NULL, HFILL }
1711
14
        },
1712
14
        { &hf_z21_broadcast_flags_fast_clock,
1713
14
          { "Fast clock time messages", "z21.broadcastflags.fast_clock",
1714
14
            FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000010,
1715
14
            NULL, HFILL }
1716
14
        },
1717
14
        { &hf_z21_state_emergency_stop,
1718
14
          { "Emergency stop", "z21.state.emergencystop",
1719
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1720
14
            NULL, HFILL }
1721
14
        },
1722
14
        { &hf_z21_state_track_voltage_off,
1723
14
          { "Track voltage off", "z21.state.trackvoltageoff",
1724
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1725
14
            NULL, HFILL }
1726
14
        },
1727
14
        { &hf_z21_state_short_circuit,
1728
14
          { "Short circuit", "z21.state.shortcircuit",
1729
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1730
14
            NULL, HFILL }
1731
14
        },
1732
14
        { &hf_z21_state_programming_mode,
1733
14
          { "Programming mode", "z21.state.programmingmode",
1734
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1735
14
            NULL, HFILL }
1736
14
        },
1737
14
        { &hf_z21_state_high_temperature,
1738
14
          { "High temperature", "z21.state.hightemperature",
1739
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1740
14
            NULL, HFILL }
1741
14
        },
1742
14
        { &hf_z21_state_power_lost,
1743
14
          { "Power lost", "z21.state.powerlost",
1744
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1745
14
            NULL, HFILL }
1746
14
        },
1747
14
        { &hf_z21_state_short_circuit_external,
1748
14
          { "External short circuit", "z21.state.externalshortcircuit",
1749
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1750
14
            NULL, HFILL }
1751
14
        },
1752
14
        { &hf_z21_state_short_circuit_internal,
1753
14
          { "Internal short circuit", "z21.state.internalshortcircuit",
1754
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1755
14
            NULL, HFILL }
1756
14
        },
1757
14
        { &hf_z21_state_rcn_213,
1758
14
          { "RCN-213 turnout addressing", "z21.state.rcn213addressing",
1759
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1760
14
            NULL, HFILL }
1761
14
        },
1762
14
        { &hf_z21_capability_dcc,
1763
14
          { "DCC capability", "z21.capability.dcc",
1764
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1765
14
            NULL, HFILL }
1766
14
        },
1767
14
        { &hf_z21_capability_mm,
1768
14
          { "MM capability", "z21.capability.mm",
1769
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1770
14
            NULL, HFILL }
1771
14
        },
1772
14
        { &hf_z21_capability_reserved,
1773
14
          { "Reserved capability", "z21.capability.reserved",
1774
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1775
14
            NULL, HFILL }
1776
14
        },
1777
14
        { &hf_z21_capability_railcom,
1778
14
          { "RailCom capability", "z21.capability.railcom",
1779
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1780
14
            NULL, HFILL }
1781
14
        },
1782
14
        { &hf_z21_capability_loco_cmds,
1783
14
          { "Accepts LAN commands for locomotive decoders", "z21.capability.lococmds",
1784
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1785
14
            NULL, HFILL }
1786
14
        },
1787
14
        { &hf_z21_capability_accessory_cmds,
1788
14
          { "Accepts LAN commands for accessory decoders", "z21.capability.accessorycmds",
1789
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1790
14
            NULL, HFILL }
1791
14
        },
1792
14
        { &hf_z21_capability_detector_cmds,
1793
14
          { "Accepts LAN commands for detectors", "z21.capability.detectorcmds",
1794
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1795
14
            NULL, HFILL }
1796
14
        },
1797
14
        { &hf_z21_capability_needs_unlock_code,
1798
14
          { "Needs unlock code", "z21.capability.needsunlockcode",
1799
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
1800
14
            NULL, HFILL }
1801
14
        },
1802
14
        { &hf_z21_loco_mode,
1803
14
          { "Locomotive mode", "z21.locomode",
1804
14
            FT_UINT8, BASE_DEC, VALS(z21_loco_mode_vals), 0x0,
1805
14
            NULL, HFILL }
1806
14
        },
1807
14
        { &hf_z21_loco_address,
1808
14
          { "Locomotive address", "z21.locoaddress",
1809
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
1810
14
            NULL, HFILL }
1811
14
        },
1812
14
        { &hf_z21_loco_direction_and_speed,
1813
14
          { "Locomotive direction and speed", "z21.locodirectionandspeed",
1814
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1815
14
            NULL, HFILL }
1816
14
        },
1817
14
        { &hf_z21_loco_direction,
1818
14
          { "Locomotive direction", "z21.locodirection",
1819
14
            FT_BOOLEAN, 8, TFS(&tfs_forward_reverse), 0x80,
1820
14
            NULL, HFILL }
1821
14
        },
1822
14
        { &hf_z21_loco_speed,
1823
14
          { "Locomotive speed", "z21.locospeed",
1824
14
            FT_UINT8, BASE_HEX, NULL, 0x7F,
1825
14
            NULL, HFILL }
1826
14
        },
1827
14
        { &hf_z21_loco_info_mm,
1828
14
          { "Locomotive is MM (MƤrklin-Motorola)", "z21.locomm",
1829
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1830
14
            NULL, HFILL }
1831
14
        },
1832
14
        { &hf_z21_loco_info_busy,
1833
14
          { "Locomotive is busy", "z21.locoinfobusy",
1834
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1835
14
            "Locomotive is controlled by another X-BUS handset controller", HFILL }
1836
14
        },
1837
14
        { &hf_z21_loco_info_speed_steps,
1838
14
          { "Locomotive speed steps", "z21.locoinfospeedsteps",
1839
14
            FT_UINT8, BASE_DEC, VALS(z21_loco_info_speed_steps_vals), 0x07,
1840
14
            NULL, HFILL }
1841
14
        },
1842
14
        { &hf_z21_loco_info_direction,
1843
14
          { "Locomotive direction", "z21.locoinfodirection",
1844
14
            FT_BOOLEAN, 8, TFS(&tfs_forward_reverse), 0x80,
1845
14
            NULL, HFILL }
1846
14
        },
1847
14
        { &hf_z21_loco_info_speed,
1848
14
          { "Locomotive speed", "z21.locoinfospeed",
1849
14
            FT_UINT8, BASE_HEX, NULL, 0x7f,
1850
14
            NULL, HFILL }
1851
14
        },
1852
14
        { &hf_z21_loco_info_double_traction,
1853
14
          { "Double traction", "z21.locoinfodoubletraction",
1854
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1855
14
            NULL, HFILL }
1856
14
        },
1857
14
        { &hf_z21_loco_info_smartsearch,
1858
14
          { "Smartsearch", "z21.locoinfosmartsearch",
1859
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1860
14
            NULL, HFILL }
1861
14
        },
1862
14
        { &hf_z21_loco_info_f0,
1863
14
          { "Function F0 (lights)", "z21.locoinfof0",
1864
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1865
14
            NULL, HFILL }
1866
14
        },
1867
14
        { &hf_z21_loco_info_f4,
1868
14
          { "Function F4", "z21.locoinfof4",
1869
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1870
14
            NULL, HFILL }
1871
14
        },
1872
14
        { &hf_z21_loco_info_f3,
1873
14
          { "Function F3", "z21.locoinfof3",
1874
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1875
14
            NULL, HFILL }
1876
14
        },
1877
14
        { &hf_z21_loco_info_f2,
1878
14
          { "Function F2", "z21.locoinfof2",
1879
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1880
14
            NULL, HFILL }
1881
14
        },
1882
14
        { &hf_z21_loco_info_f1,
1883
14
          { "Function F1", "z21.locoinfof1",
1884
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1885
14
            NULL, HFILL }
1886
14
        },
1887
14
        { &hf_z21_loco_info_f12,
1888
14
          { "Function F12", "z21.locoinfof12",
1889
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
1890
14
            NULL, HFILL }
1891
14
        },
1892
14
        { &hf_z21_loco_info_f11,
1893
14
          { "Function F11", "z21.locoinfof11",
1894
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1895
14
            NULL, HFILL }
1896
14
        },
1897
14
        { &hf_z21_loco_info_f10,
1898
14
          { "Function F10", "z21.locoinfof10",
1899
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1900
14
            NULL, HFILL }
1901
14
        },
1902
14
        { &hf_z21_loco_info_f9,
1903
14
          { "Function F9", "z21.locoinfof9",
1904
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1905
14
            NULL, HFILL }
1906
14
        },
1907
14
        { &hf_z21_loco_info_f8,
1908
14
          { "Function F8", "z21.locoinfof8",
1909
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1910
14
            NULL, HFILL }
1911
14
        },
1912
14
        { &hf_z21_loco_info_f7,
1913
14
          { "Function F7", "z21.locoinfof7",
1914
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1915
14
            NULL, HFILL }
1916
14
        },
1917
14
        { &hf_z21_loco_info_f6,
1918
14
          { "Function F6", "z21.locoinfof6",
1919
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1920
14
            NULL, HFILL }
1921
14
        },
1922
14
        { &hf_z21_loco_info_f5,
1923
14
          { "Function F5", "z21.locoinfof5",
1924
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1925
14
            NULL, HFILL }
1926
14
        },
1927
14
        { &hf_z21_loco_info_f20,
1928
14
          { "Function F20", "z21.locoinfof20",
1929
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
1930
14
            NULL, HFILL }
1931
14
        },
1932
14
        { &hf_z21_loco_info_f19,
1933
14
          { "Function F19", "z21.locoinfof19",
1934
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1935
14
            NULL, HFILL }
1936
14
        },
1937
14
        { &hf_z21_loco_info_f18,
1938
14
          { "Function F18", "z21.locoinfof18",
1939
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1940
14
            NULL, HFILL }
1941
14
        },
1942
14
        { &hf_z21_loco_info_f17,
1943
14
          { "Function F17", "z21.locoinfof17",
1944
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1945
14
            NULL, HFILL }
1946
14
        },
1947
14
        { &hf_z21_loco_info_f16,
1948
14
          { "Function F16", "z21.locoinfof16",
1949
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1950
14
            NULL, HFILL }
1951
14
        },
1952
14
        { &hf_z21_loco_info_f15,
1953
14
          { "Function F15", "z21.locoinfof15",
1954
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1955
14
            NULL, HFILL }
1956
14
        },
1957
14
        { &hf_z21_loco_info_f14,
1958
14
          { "Function F14", "z21.locoinfof14",
1959
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1960
14
            NULL, HFILL }
1961
14
        },
1962
14
        { &hf_z21_loco_info_f13,
1963
14
          { "Function F13", "z21.locoinfof13",
1964
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1965
14
            NULL, HFILL }
1966
14
        },
1967
14
        { &hf_z21_loco_info_f28,
1968
14
          { "Function F28", "z21.locoinfof28",
1969
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
1970
14
            NULL, HFILL }
1971
14
        },
1972
14
        { &hf_z21_loco_info_f27,
1973
14
          { "Function F27", "z21.locoinfof27",
1974
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
1975
14
            NULL, HFILL }
1976
14
        },
1977
14
        { &hf_z21_loco_info_f26,
1978
14
          { "Function F26", "z21.locoinfof26",
1979
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
1980
14
            NULL, HFILL }
1981
14
        },
1982
14
        { &hf_z21_loco_info_f25,
1983
14
          { "Function F25", "z21.locoinfof25",
1984
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
1985
14
            NULL, HFILL }
1986
14
        },
1987
14
        { &hf_z21_loco_info_f24,
1988
14
          { "Function F24", "z21.locoinfof24",
1989
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
1990
14
            NULL, HFILL }
1991
14
        },
1992
14
        { &hf_z21_loco_info_f23,
1993
14
          { "Function F23", "z21.locoinfof23",
1994
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
1995
14
            NULL, HFILL }
1996
14
        },
1997
14
        { &hf_z21_loco_info_f22,
1998
14
          { "Function F22", "z21.locoinfof22",
1999
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
2000
14
            NULL, HFILL }
2001
14
        },
2002
14
        { &hf_z21_loco_info_f21,
2003
14
          { "Function F21", "z21.locoinfof21",
2004
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
2005
14
            NULL, HFILL }
2006
14
        },
2007
14
        { &hf_z21_loco_info_f31,
2008
14
          { "Function F31", "z21.locoinfof31",
2009
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
2010
14
            NULL, HFILL }
2011
14
        },
2012
14
        { &hf_z21_loco_info_f30,
2013
14
          { "Function F30", "z21.locoinfof30",
2014
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
2015
14
            NULL, HFILL }
2016
14
        },
2017
14
        { &hf_z21_loco_info_f29,
2018
14
          { "Function F29", "z21.locoinfof29",
2019
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
2020
14
            NULL, HFILL }
2021
14
        },
2022
14
        { &hf_z21_loco_info_extensions,
2023
14
          { "Extensions", "z21.locoinfoextensions",
2024
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
2025
14
            NULL, HFILL }
2026
14
        },
2027
14
        { &hf_z21_speed_steps,
2028
14
          { "Speed steps", "z21.speedsteps",
2029
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2030
14
            NULL, HFILL }
2031
14
        },
2032
14
        { &hf_z21_hw_type,
2033
14
          { "Hardware type", "z21.hwtype",
2034
14
            FT_UINT32, BASE_HEX, VALS(z21_hw_type_vals), 0x0,
2035
14
            NULL, HFILL }
2036
14
        },
2037
14
        { &hf_z21_firmware_version,
2038
14
          { "Firmware version", "z21.firmwareversion",
2039
14
            FT_STRING, BASE_NONE, NULL, 0x0,
2040
14
            NULL, HFILL }
2041
14
        },
2042
14
        { &hf_z21_loco_func_switch_type,
2043
14
          { "Locomotive function switch type", "z21.locofunctionswitchtype",
2044
14
            FT_UINT8, BASE_DEC, VALS(z21_loco_func_vals), 0xc0,
2045
14
            NULL, HFILL }
2046
14
        },
2047
14
        { &hf_z21_loco_func_index,
2048
14
          { "Locomotive function index", "z21.locofunctionindex",
2049
14
            FT_UINT8, BASE_DEC, NULL, 0x3f,
2050
14
            NULL, HFILL }
2051
14
        },
2052
14
        { &hf_z21_function_address,
2053
14
          { "Function address", "z21.functionaddress",
2054
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2055
14
            NULL, HFILL }
2056
14
        },
2057
14
        { &hf_z21_turnout_state,
2058
14
          { "Turnout state", "z21.turnoutstate",
2059
14
            FT_UINT8, BASE_DEC, VALS(z21_turnout_state_vals), 0x03,
2060
14
            NULL, HFILL }
2061
14
        },
2062
14
        { &hf_z21_turnout_queue_bit,
2063
14
          { "Queue the turnout command", "z21.turnoutqueue",
2064
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
2065
14
            NULL, HFILL }
2066
14
        },
2067
14
        { &hf_z21_turnout_activate_bit,
2068
14
          { "Turnout command", "z21.turnoutcommand",
2069
14
            FT_BOOLEAN, 8, TFS(&tfs_turnout_command), 0x08,
2070
14
            NULL, HFILL }
2071
14
        },
2072
14
        { &hf_z21_turnout_output_bit,
2073
14
          { "Select turnout output", "z21.turnoutoutput",
2074
14
            FT_BOOLEAN, 8, TFS(&tfs_turnout_output), 0x01,
2075
14
            NULL, HFILL }
2076
14
        },
2077
14
        { &hf_z21_accessory_address,
2078
14
          { "Accessory address", "z21.accessoryaddress",
2079
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2080
14
            NULL, HFILL }
2081
14
        },
2082
14
        { &hf_z21_accessory_state,
2083
14
          { "Accessory state", "z21.accessorystate",
2084
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2085
14
            NULL, HFILL }
2086
14
        },
2087
14
        { &hf_z21_accessory_status,
2088
14
          { "Accessory status", "z21.accessorystatus",
2089
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2090
14
            NULL, HFILL }
2091
14
        },
2092
14
        { &hf_z21_cv_address,
2093
14
          { "CV address", "z21.cvaddress",
2094
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2095
14
            NULL, HFILL }
2096
14
        },
2097
14
        { &hf_z21_cv_value,
2098
14
          { "CV value", "z21.cvvalue",
2099
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2100
14
            NULL, HFILL }
2101
14
        },
2102
14
        { &hf_z21_register,
2103
14
          { "Register", "z21.register",
2104
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2105
14
            NULL, HFILL }
2106
14
        },
2107
14
        { &hf_z21_register_value,
2108
14
          { "Register value", "z21.registervalue",
2109
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2110
14
            NULL, HFILL }
2111
14
        },
2112
14
        { &hf_z21_pom_operation,
2113
14
          { "POM operation", "z21.pomoperation",
2114
14
            FT_UINT16, BASE_HEX, VALS(z21_pom_operation_vals), 0x0,
2115
14
            NULL, HFILL }
2116
14
        },
2117
14
        { &hf_z21_cv_bit_position,
2118
14
          { "CV bit position", "z21.cvbitposition",
2119
14
            FT_UINT8, BASE_DEC, NULL, 0x07,
2120
14
            NULL, HFILL }
2121
14
        },
2122
14
        { &hf_z21_cv_bit_value,
2123
14
          { "CV bit value", "z21.cvbitvalue",
2124
14
            FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x08,
2125
14
            NULL, HFILL }
2126
14
        },
2127
14
        { &hf_z21_rmbus_group,
2128
14
          { "R-BUS group index", "z21.rbusgroup",
2129
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2130
14
            NULL, HFILL }
2131
14
        },
2132
14
        { &hf_z21_rmbus_feedbacks,
2133
14
          { "R-BUS feedbacks", "z21.rbusfeedbacks",
2134
14
            FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2135
14
            NULL, HFILL }
2136
14
        },
2137
14
        { &hf_z21_rmbus_address,
2138
14
          { "R-BUS feedback module address", "z21.rbusaddress",
2139
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2140
14
            NULL, HFILL }
2141
14
        },
2142
14
        { &hf_z21_railcom_receive_counter,
2143
14
          { "RailCom receive counter", "z21.railcomreceives",
2144
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
2145
14
            NULL, HFILL }
2146
14
        },
2147
14
        { &hf_z21_railcom_error_counter,
2148
14
          { "RailCom error counter", "z21.railcomerrors",
2149
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2150
14
            NULL, HFILL }
2151
14
        },
2152
14
        { &hf_z21_railcom_reserved1,
2153
14
          { "RailCom reserved 1", "z21.railcomreserved1",
2154
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2155
14
            NULL, HFILL }
2156
14
        },
2157
14
        { &hf_z21_railcom_reserved2,
2158
14
          { "RailCom reserved 2", "z21.railcomreserved2",
2159
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2160
14
            NULL, HFILL }
2161
14
        },
2162
14
        { &hf_z21_railcom_options,
2163
14
          { "RailCom options", "z21.railcomoptions",
2164
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2165
14
            NULL, HFILL }
2166
14
        },
2167
14
        { &hf_z21_railcom_speed,
2168
14
          { "RailCom speed", "z21.railcomspeed",
2169
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2170
14
            NULL, HFILL }
2171
14
        },
2172
14
        { &hf_z21_railcom_qos,
2173
14
          { "RailCom QoS", "z21.railcomqos",
2174
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2175
14
            NULL, HFILL }
2176
14
        },
2177
14
        { &hf_z21_railcom_type,
2178
14
          { "RailCom type", "z21.railcomtype",
2179
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2180
14
            NULL, HFILL }
2181
14
        },
2182
14
        { &hf_z21_loconet_message,
2183
14
          { "LocoNet message", "z21.loconetmessage",
2184
14
            FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2185
14
            NULL, HFILL }
2186
14
        },
2187
14
        { &hf_z21_loconet_result,
2188
14
          { "LocoNet result", "z21.loconetresult",
2189
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2190
14
            NULL, HFILL }
2191
14
        },
2192
14
        { &hf_z21_loconet_type,
2193
14
          { "LocoNet type", "z21.loconettype",
2194
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2195
14
            NULL, HFILL }
2196
14
        },
2197
14
        { &hf_z21_loconet_report_address,
2198
14
          { "LocoNet report address", "z21.loconetreportaddress",
2199
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2200
14
            NULL, HFILL }
2201
14
        },
2202
14
        { &hf_z21_loconet_feedback_address,
2203
14
          { "LocoNet feedback address", "z21.loconetfeedbackaddress",
2204
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2205
14
            NULL, HFILL }
2206
14
        },
2207
14
        { &hf_z21_loconet_info,
2208
14
          { "LocoNet info", "z21.loconetinfo",
2209
14
            FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2210
14
            NULL, HFILL }
2211
14
        },
2212
14
        { &hf_z21_can_type,
2213
14
          { "CAN type", "z21.cantype",
2214
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2215
14
            NULL, HFILL }
2216
14
        },
2217
14
        { &hf_z21_can_network_id,
2218
14
          { "CAN network ID", "z21.cannetworkid",
2219
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
2220
14
            NULL, HFILL }
2221
14
        },
2222
14
        { &hf_z21_can_module_address,
2223
14
          { "CAN module address", "z21.canmoduleaddress",
2224
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
2225
14
            NULL, HFILL }
2226
14
        },
2227
14
        { &hf_z21_can_port,
2228
14
          { "CAN input port (pin)", "z21.canport",
2229
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2230
14
            NULL, HFILL }
2231
14
        },
2232
14
        { &hf_z21_can_value1,
2233
14
          { "CAN value 1", "z21.canvalue1",
2234
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
2235
14
            NULL, HFILL }
2236
14
        },
2237
14
        { &hf_z21_can_value2,
2238
14
          { "CAN value 2", "z21.canvalue2",
2239
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
2240
14
            NULL, HFILL }
2241
14
        },
2242
14
        { &hf_z21_can_booster_name,
2243
14
          { "CAN booster name", "z21.canboostername",
2244
14
            FT_STRINGZ, BASE_NONE, NULL, 0x0,
2245
14
            NULL, HFILL }
2246
14
        },
2247
14
        { &hf_z21_can_booster_output_port,
2248
14
          { "CAN booster output port", "z21.canboosteroutputport",
2249
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2250
14
            NULL, HFILL }
2251
14
        },
2252
14
        { &hf_z21_can_booster_state,
2253
14
          { "CAN booster state", "z21.canboosterstate",
2254
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
2255
14
            NULL, HFILL }
2256
14
        },
2257
14
        { &hf_z21_can_booster_state_bg_active,
2258
14
          { "CAN booster brake generator active", "z21.canboosterbrakegenerator",
2259
14
            FT_BOOLEAN, 16, NULL, 0x0001,
2260
14
            NULL, HFILL }
2261
14
        },
2262
14
        { &hf_z21_can_booster_state_short_circuit,
2263
14
          { "CAN booster short circuit", "z21.canboostershortcircuit",
2264
14
            FT_BOOLEAN, 16, NULL, 0x0020,
2265
14
            NULL, HFILL }
2266
14
        },
2267
14
        { &hf_z21_can_booster_state_track_voltage_off,
2268
14
          { "CAN booster track voltage off", "z21.canboostertrackvoltageoff",
2269
14
            FT_BOOLEAN, 16, NULL, 0x0080,
2270
14
            NULL, HFILL }
2271
14
        },
2272
14
        { &hf_z21_can_booster_state_railcom_active,
2273
14
          { "CAN booster RailCom cutout active", "z21.canboosterrailcomactive",
2274
14
            FT_BOOLEAN, 16, NULL, 0x0800,
2275
14
            NULL, HFILL }
2276
14
        },
2277
14
        { &hf_z21_can_booster_state_output_disabled,
2278
14
          { "CAN booster output disabled", "z21.canboosteroutputdisabled",
2279
14
            FT_BOOLEAN, 16, NULL, 0x0100,
2280
14
            NULL, HFILL }
2281
14
        },
2282
14
        { &hf_z21_can_booster_vcc,
2283
14
          { "CAN booster VCC voltage", "z21.canboostervoltage",
2284
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2285
14
            NULL, HFILL }
2286
14
        },
2287
14
        { &hf_z21_can_booster_current,
2288
14
          { "CAN booster current", "z21.canboostercurrent",
2289
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2290
14
            NULL, HFILL }
2291
14
        },
2292
14
        { &hf_z21_can_booster_power,
2293
14
          { "CAN booster power", "z21.canboosterpower",
2294
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2295
14
            NULL, HFILL }
2296
14
        },
2297
14
        { &hf_z21_zlink_message_type,
2298
14
          { "zLink message type", "z21.zlinkmessagetype",
2299
14
            FT_UINT8, BASE_HEX, VALS(z21_zlink_message_type_vals), 0x0,
2300
14
            NULL, HFILL }
2301
14
        },
2302
14
        { &hf_z21_zlink_hwid,
2303
14
          { "zLink hardware ID", "z21.zlinkhwid",
2304
14
            FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2305
14
            NULL, HFILL }
2306
14
        },
2307
14
        { &hf_z21_zlink_fw_major,
2308
14
          { "zLink firmware major version", "z21.zlinkmajorversion",
2309
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2310
14
            NULL, HFILL }
2311
14
        },
2312
14
        { &hf_z21_zlink_fw_minor,
2313
14
          { "zLink firmware minor version", "z21.zlinkminorversion",
2314
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
2315
14
            NULL, HFILL }
2316
14
        },
2317
14
        { &hf_z21_zlink_fw_build,
2318
14
          { "zLink firmware build version", "z21.zlinkbuildversion",
2319
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
2320
14
            NULL, HFILL }
2321
14
        },
2322
14
        { &hf_z21_zlink_mac,
2323
14
          { "zLink MAC address", "z21.zlinkmac",
2324
14
            FT_STRINGZ, BASE_NONE, NULL, 0x0,
2325
14
            NULL, HFILL }
2326
14
        },
2327
14
        { &hf_z21_zlink_name,
2328
14
          { "zLink name", "z21.zlinkname",
2329
14
            FT_STRINGZ, BASE_NONE, NULL, 0x0,
2330
14
            NULL, HFILL }
2331
14
        },
2332
14
        { &hf_z21_zlink_reserved,
2333
14
          { "zLink reserved", "z21.zlinkreserved",
2334
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2335
14
            NULL, HFILL }
2336
14
        },
2337
14
        { &hf_z21_booster_name,
2338
14
          { "Booster name", "z21.boostername",
2339
14
            FT_STRINGZ, BASE_NONE, NULL, 0x0,
2340
14
            NULL, HFILL }
2341
14
        },
2342
14
        { &hf_z21_booster_port,
2343
14
          { "Booster port", "z21.boosterport",
2344
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2345
14
            NULL, HFILL }
2346
14
        },
2347
14
        { &hf_z21_booster_port_state,
2348
14
          { "Booster port state", "z21.boosterportstate",
2349
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
2350
14
            NULL, HFILL }
2351
14
        },
2352
14
        { &hf_z21_booster_state_data,
2353
14
          { "Booster state data", "z21.boosterstatedata",
2354
14
            FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2355
14
            NULL, HFILL }
2356
14
        },
2357
14
        { &hf_z21_decoder_name,
2358
14
          { "Decoder name", "z21.decodername",
2359
14
            FT_STRINGZ, BASE_NONE, NULL, 0x0,
2360
14
            NULL, HFILL }
2361
14
        },
2362
14
        { &hf_z21_decoder_state_data,
2363
14
          { "Decoder state data", "z21.decoderstatedata",
2364
14
            FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2365
14
            NULL, HFILL }
2366
14
        },
2367
14
        { &hf_z21_data,
2368
14
          { "Undecoded data", "z21.data",
2369
14
            FT_BYTES, BASE_NONE|SEP_SPACE, NULL, 0x0,
2370
14
            NULL, HFILL }
2371
14
        },
2372
14
    };
2373
2374
    /* Setup protocol subtree array */
2375
14
    static int *ett[] = {
2376
14
        &ett_z21,
2377
14
    };
2378
2379
    /* Setup protocol expert items */
2380
14
    static ei_register_info ei[] = {
2381
14
        { &ei_z21_invalid_checksum,
2382
14
            { "z21.invalidchecksum", PI_CHECKSUM, PI_WARN,
2383
14
            "Invalid XOR checksum", EXPFILL }
2384
14
        },
2385
14
    };
2386
2387
    /* Register the protocol name and description */
2388
14
    proto_z21 = proto_register_protocol("Z21 LAN Protocol", "Z21", "z21");
2389
2390
    /* Required function calls to register the header fields and subtrees */
2391
14
    proto_register_field_array(proto_z21, hf, array_length(hf));
2392
14
    proto_register_subtree_array(ett, array_length(ett));
2393
2394
    /* Required function calls to register expert items */
2395
14
    expert_z21 = expert_register_protocol(proto_z21);
2396
14
    expert_register_field_array(expert_z21, ei, array_length(ei));
2397
2398
14
    z21_handle = register_dissector("z21", dissect_z21, proto_z21);
2399
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.
2406
     */
2407
14
    prefs_register_protocol(proto_z21, proto_reg_handoff_z21);
2408
14
}
2409
2410
void
2411
proto_reg_handoff_z21(void)
2412
14
{
2413
14
    static bool initialized = false;
2414
2415
14
    if (!initialized) {
2416
14
        dissector_add_uint_range_with_preference("udp.port", Z21_UDP_PORTS, z21_handle);
2417
        initialized = true;
2418
14
    }
2419
14
    udp_port_range = prefs_get_range_value("Z21", "udp.port");
2420
14
}