Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-mdb.c
Warning:line 1221, column 5
Value stored to 'offset' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-mdb.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-06-08-100342-3529-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-mdb.c
1/*
2 * packet-mdb.c
3 * Routines for MDB dissection
4 * Copyright 2023 Martin Kaiser for PayTec AG (www.paytec.ch)
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13/*
14 * The MDB (Multi-Drop Bus) protocol is used inside a vending machine. MDB
15 * defines the communication between the main control board (VMC = Vending
16 * Machine Controller) and peripheral components, e.g. a payment terminal
17 * or a bill validator.
18 *
19 * The VMC acts as bus master and sends a request to one peripheral at a time.
20 * A peripheral may send data only in response to such a request.
21 *
22 * The MDB specification is maintained by the National Automatic Merchandising
23 * Association (NAMA). As of August 2023, the current version of the MDB
24 * specification is 4.3. It is available from
25 * https://namanow.org/nama-releases-mdb-version-4-3/
26 *
27 * The pcap input format for this dissector is documented at
28 * https://www.kaiser.cx/pcap-mdb.html
29 */
30
31#include "config.h"
32#include <epan/expert.h>
33#include <epan/packet.h>
34#include <epan/conversation.h>
35#include <epan/tfs.h>
36#include <wsutil/array.h>
37#include <wiretap/wtap.h>
38
39void proto_reg_handoff_mdb(void);
40void proto_register_mdb(void);
41
42static int proto_mdb;
43
44static int ett_mdb;
45static int ett_mdb_hdr;
46static int ett_mdb_cl;
47static int ett_mdb_cgw;
48static int ett_mdb_bv;
49
50static int hf_mdb_hdr_ver;
51static int hf_mdb_event;
52static int hf_mdb_addr;
53static int hf_mdb_cmd;
54static int hf_mdb_cl_setup_sub;
55static int hf_mdb_cl_feat_lvl;
56static int hf_mdb_cl_cols;
57static int hf_mdb_cl_rows;
58static int hf_mdb_cl_disp_info;
59static int hf_mdb_cl_max_price;
60static int hf_mdb_cl_min_price;
61static int hf_mdb_cl_vend_sub;
62static int hf_mdb_cl_item_price;
63static int hf_mdb_cl_item_num;
64static int hf_mdb_cl_reader_sub;
65static int hf_mdb_cl_resp;
66static int hf_mdb_cl_scale;
67static int hf_mdb_cl_dec_pl;
68static int hf_mdb_cl_max_rsp_time;
69static int hf_mdb_cl_vend_amt;
70static int hf_mdb_cl_expns_sub;
71static int hf_mdb_cl_manuf_code;
72static int hf_mdb_cl_ser_num;
73static int hf_mdb_cl_mod_num;
74static int hf_mdb_cl_opt_feat;
75static int hf_mdb_cgw_feat_lvl;
76static int hf_mdb_cgw_scale;
77static int hf_mdb_cgw_dec_pl;
78static int hf_mdb_cgw_resp;
79static int hf_mdb_cgw_max_rsp_time;
80static int hf_mdb_cgw_report_sub;
81static int hf_mdb_cgw_dts_evt_code;
82static int hf_mdb_cgw_duration;
83static int hf_mdb_cgw_activity;
84static int hf_mdb_cgw_expns_sub;
85static int hf_mdb_cgw_opt_feat;
86static int hf_mdb_cgw_manuf_code;
87static int hf_mdb_cgw_ser_num;
88static int hf_mdb_cgw_mod_num;
89static int hf_mdb_bv_setup_bill_val_feature;
90static int hf_mdb_bv_setup_ctry_currency_code;
91static int hf_mdb_bv_setup_bill_scal_fac;
92static int hf_mdb_bv_setup_dec_places;
93static int hf_mdb_bv_setup_bill_stacker_cap;
94static int hf_mdb_bv_setup_bill_sec_lvls;
95static int hf_mdb_bv_setup_escrow;
96static int hf_mdb_bv_setup_bill_type_cred;
97static int hf_mdb_bv_bill_enable;
98static int hf_mdb_bv_bill_escrow_enable;
99static int hf_mdb_bv_poll_state;
100static int hf_mdb_bv_poll_bill_routing_state;
101static int hf_mdb_bv_poll_bill_type;
102static int hf_mdb_bv_escrow_state;
103static int hf_mdb_bv_stacker;
104static int hf_mdb_bv_exp_cmd;
105static int hf_mdb_bv_exp_opt_feat;
106static int hf_mdb_bv_exp_opt_feat_enable;
107static int hf_mdb_bv_exp_manufact_code;
108static int hf_mdb_bv_exp_serial_num;
109static int hf_mdb_bv_exp_model_tuning_num;
110static int hf_mdb_bv_exp_software_version;
111static int hf_mdb_bv_exp_bill_type_routing;
112static int hf_mdb_bv_exp_manual_dispense_enable;
113static int hf_mdb_bv_exp_bill_recycler_enabled;
114static int hf_mdb_bv_exp_bill_count;
115static int hf_mdb_bv_exp_dispenser_full_state;
116static int hf_mdb_bv_exp_bill_type_dispensed;
117static int hf_mdb_bv_exp_bill_type_number_bills;
118static int hf_mdb_bv_exp_dispense_value_bills;
119static int hf_mdb_bv_exp_payout_state;
120static int hf_mdb_bv_exp_dispenser_payout_activity;
121
122static int hf_mdb_ack;
123static int hf_mdb_data;
124static int hf_mdb_chk;
125static int hf_mdb_chk_status;
126static int hf_mdb_response_in;
127static int hf_mdb_response_to;
128static int hf_mdb_time;
129
130static expert_field ei_mdb_short_packet;
131static expert_field ei_mdb_bad_checksum;
132
133static dissector_handle_t mdb_handle;
134
135/* MDB is a master slave protocol, so per request, there is exactly one response */
136typedef struct {
137 uint32_t req_num, rep_num;
138 nstime_t req_time;
139 uint16_t cmd; // In case of expanse cmd, 2 byte are used
140} mdb_transaction_t;
141
142typedef struct {
143 wmem_tree_t* transactions;
144 uint32_t last_req_packet;
145 uint16_t last_cmd;
146} mdb_conv_info_t;
147
148static mdb_conv_info_t* get_mdb_conv_info(packet_info* pinfo)
149{
150 conversation_t* conversation;
151 mdb_conv_info_t* conv_info;
152
153 conversation = find_or_create_conversation(pinfo);
154 conv_info = (mdb_conv_info_t*)conversation_get_proto_data(conversation, proto_mdb);
155 if (!conv_info) {
156 conv_info = wmem_new0(wmem_file_scope(), mdb_conv_info_t)((mdb_conv_info_t*)wmem_alloc0((wmem_file_scope()), sizeof(mdb_conv_info_t
)))
;
157 conv_info->transactions = wmem_tree_new(wmem_file_scope());
158 conversation_add_proto_data(conversation, proto_mdb, conv_info);
159 }
160 return conv_info;
161}
162
163#define MDB_EVT_DATA_MST_PER0xFF 0xFF
164#define MDB_EVT_DATA_PER_MST0xFE 0xFE
165#define MDB_EVT_BUS_RESET0xFD 0xFD
166
167#define MDB_PSEUDO_HDR_LEN2 2
168
169static bool_Bool is_mdb_reply(uint8_t byte) {
170 return (byte == 0x00 || byte == 0xAA || byte == 0xFF);
171}
172
173static const value_string mdb_event[] = {
174 { MDB_EVT_DATA_MST_PER0xFF, "Data transfer Master -> Peripheral" },
175 { MDB_EVT_DATA_PER_MST0xFE, "Data transfer Peripheral -> Master" },
176 { MDB_EVT_BUS_RESET0xFD, "Bus reset" },
177 { 0, NULL((void*)0) }
178};
179
180#define ADDR_VMC"VMC" "VMC"
181
182#define ADDR_CASHLESS10x10 0x10
183#define ADDR_COMMS_GW0x18 0x18
184#define ADDR_BILL_VALIDATOR0x30 0x30
185
186#define ADDR_MASK0xF8 0xF8
187#define CMD_MASK0x07 0x07
188#define SUB_CMD_OFFSET8 8
189
190static const value_string mdb_addr[] = {
191 { 0x00, "Reserved for VMC" },
192 { 0x08, "Changer" },
193 { ADDR_CASHLESS10x10, "Cashless #1" },
194 { ADDR_COMMS_GW0x18, "Communications Gateway" },
195 { 0x20, "Display" },
196 { 0x28, "Energy Management System" },
197 { ADDR_BILL_VALIDATOR0x30, "Bill Validator" },
198 { 0x38, "Reserved for Future Standard Peripheral" },
199 { 0x40, "Universal Satellite Device #1" },
200 { 0x48, "Universal Satellite Device #2" },
201 { 0x50, "Universal Satellite Device #3" },
202 { 0x58, "Coin Hopper or Tube - Dispenser 1" },
203 { 0x60, "Cashless #2" },
204 { 0x68, "Age Verification Device" },
205 { 0x70, "Coin Hopper or Tube - Dispenser 2" },
206 { 0xF0, "Vending Machine Specific Peripheral #1" },
207 { 0xF8, "Vending Machine Specific Peripheral #2" },
208 { 0, NULL((void*)0) }
209};
210
211static const value_string mdb_ack[] = {
212 { 0x00, "ACK" },
213 { 0xAA, "RET" },
214 { 0xFF, "NAK" },
215 { 0, NULL((void*)0) }
216};
217
218/*
219 * These are just the command bits in the address + command byte. MDB supports
220 * two Cashless peripherals (Cashless #1 and #2) with different addresses,
221 * both use the same commands.
222 */
223#define MDB_CL_CMD_SETUP0x01 0x01
224#define MDB_CL_CMD_VEND0x03 0x03
225#define MDB_CL_CMD_READER0x04 0x04
226#define MDB_CL_CMD_EXPNS0x07 0x07
227
228static const value_string mdb_cl_cmd[] = {
229 { 0x00, "Reset" },
230 { MDB_CL_CMD_SETUP0x01, "Setup" },
231 { 0x02, "Poll" },
232 { MDB_CL_CMD_VEND0x03, "Vend" },
233 { MDB_CL_CMD_READER0x04, "Reader" },
234 { MDB_CL_CMD_EXPNS0x07, "Expansion" },
235 { 0, NULL((void*)0) }
236};
237
238#define MDB_CL_SETUP_CFG_DATA0x00 0x00
239#define MDB_CL_SETUP_MAX_MIN0x01 0x01
240
241static const value_string mdb_cl_setup_sub_cmd[] = {
242 { MDB_CL_SETUP_CFG_DATA0x00, "Config Data" },
243 { MDB_CL_SETUP_MAX_MIN0x01, "Max/Min Prices" },
244 { 0, NULL((void*)0) }
245};
246
247#define MDB_CL_VEND_REQ0x00 0x00
248#define MDB_CL_VEND_SUC0x02 0x02
249
250static const value_string mdb_cl_vend_sub_cmd[] = {
251 { MDB_CL_VEND_REQ0x00, "Vend Request" },
252 { MDB_CL_VEND_SUC0x02, "Vend Success" },
253 { 0x04, "Session Complete" },
254 { 0, NULL((void*)0) }
255};
256
257static const value_string mdb_cl_reader_sub_cmd[] = {
258 { 0x00, "Reader Disable" },
259 { 0x01, "Reader Enable" },
260 { 0, NULL((void*)0) }
261};
262
263#define MDB_CL_EXPNS_REQ_ID0x00 0x00
264#define MDB_CL_EXPNS_OPT_ENA0x04 0x04
265
266static const value_string mdb_cl_expns_sub_cmd[] = {
267 { MDB_CL_EXPNS_REQ_ID0x00, "Request ID" },
268 { MDB_CL_EXPNS_OPT_ENA0x04, "Optional Feature Enabled" },
269 { 0, NULL((void*)0) }
270};
271
272#define MDB_CL_RESP_RD_CFG_DATA0x01 0x01
273#define MDB_CL_RESP_VEND_APRV0x05 0x05
274#define MDB_CL_RESP_PER_ID0x09 0x09
275
276static const value_string mdb_cl_resp[] = {
277 { 0x00, "Just Reset" },
278 { MDB_CL_RESP_RD_CFG_DATA0x01, "Reader Config Data" },
279 { 0x03, "Begin Session" },
280 { MDB_CL_RESP_VEND_APRV0x05, "Vend Approved" },
281 { 0x06, "Vend Denied" },
282 { 0x07, "End Session" },
283 { MDB_CL_RESP_PER_ID0x09, "Peripheral ID" },
284 { 0x0b, "Cmd Out Of Sequence" },
285 { 0, NULL((void*)0) }
286};
287
288/*
289 * For the Communications Gateway, we use the complete address + command byte
290 * as value for the value string. The values here match those in the MDB
291 * specification.
292 *
293 * There's only one Communications Gateway, the address bits are always the
294 * same. (This is different from the Cashless peripherals, see above.)
295 */
296#define MDB_CGW_ADDR_CMD_SETUP0x19 0x19
297#define MDB_CGW_ADDR_CMD_REPORT0x1B 0x1B
298#define MDB_CGW_ADDR_CMD_EXPNS0x1F 0x1F
299
300static const value_string mdb_cgw_addr_cmd[] = {
301 { 0x18, "Reset" },
302 { MDB_CGW_ADDR_CMD_SETUP0x19, "Setup" },
303 { 0x1A, "Poll" },
304 { MDB_CGW_ADDR_CMD_REPORT0x1B, "Report" },
305 { MDB_CGW_ADDR_CMD_EXPNS0x1F, "Expansion" },
306 { 0, NULL((void*)0) }
307};
308
309#define MDB_CGW_REPORT_DTS_EVT0x02 0x02
310
311static const value_string mdb_cgw_report_sub_cmd[] = {
312 { 0x01, "Transaction" },
313 { MDB_CGW_REPORT_DTS_EVT0x02, "DTS Event" },
314 { 0, NULL((void*)0) }
315};
316
317#define MDB_CGW_EXPNS_FEAT_ENA0x01 0x01
318
319static const value_string mdb_cgw_expns_sub_cmd[] = {
320 { 0x00, "Identification" },
321 { MDB_CGW_EXPNS_FEAT_ENA0x01, "Feature enable" },
322 { 0x02, "Time/Date Request" },
323 { 0, NULL((void*)0) }
324};
325
326#define MDB_CGW_RESP_CFG0x01 0x01
327#define MDB_CGW_RESP_PER_ID0x06 0x06
328
329static const value_string mdb_cgw_resp[] = {
330 { 0x00, "Just Reset" },
331 { MDB_CGW_RESP_CFG0x01, "Comms Gateway Config" },
332 { 0x05, "DTS Event Acknowledge" },
333 { MDB_CGW_RESP_PER_ID0x06, "Peripheral ID" },
334 { 0, NULL((void*)0) }
335};
336
337/*
338 * Commands for Bill Validator
339 */
340#define MDB_BV_CMD_SETUP0x01 0x01
341#define MDB_BV_CMD_SECURITY0x02 0x02
342#define MDB_BV_CMD_POLL0x03 0x03
343#define MDB_BV_CMD_BILL_TYPE0x04 0x04
344#define MDB_BV_CMD_ESCROW0x05 0x05
345#define MDB_BV_CMD_STACKER0x06 0x06
346#define MDB_BV_CMD_EXPNS0x07 0x07
347#define MDB_BV_CMD_NONE0xFF 0xFF
348
349static const value_string mdb_bv_cmd[] = {
350 { 0x00, "Reset" },
351 { MDB_BV_CMD_SETUP0x01, "Setup" },
352 { MDB_BV_CMD_SECURITY0x02, "Security" },
353 { MDB_BV_CMD_POLL0x03, "Poll" },
354 { MDB_BV_CMD_BILL_TYPE0x04, "Bill type" },
355 { MDB_BV_CMD_ESCROW0x05, "Escrow" },
356 { MDB_BV_CMD_STACKER0x06, "Stacker" },
357 { MDB_BV_CMD_EXPNS0x07, "Expansion" },
358 { 0, NULL((void*)0) }
359};
360
361#define MDB_BV_LVL1_WITHOUT_OPT_BITS0x00 0x00
362#define MDB_BV_LVL2_FEATURE_ENABLE0x01 0x01
363#define MDB_BV_LVL2_ID_WITH_OPTION_BITS0x02 0x02
364#define MDB_BV_RECYCL_SETUP0x03 0x03
365#define MDB_BV_RECYCL_ENABLE0x04 0x04
366#define MDB_BV_BILL_DISPENSE_STAT0x05 0x05
367#define MDB_BV_DISPENSE_BILL0x06 0x06
368#define MDB_BV_DISPENSE_VAL0x07 0x07
369#define MDB_BV_PAYOUT_STAT0x08 0x08
370#define MDB_BV_PAYOUT_VALUE_POLL0x09 0x09
371#define MDB_BV_PAYOUT_CANCEL0x0A 0x0A
372
373static const value_string mdb_bv_exp_cmd[] = {
374 { MDB_BV_LVL1_WITHOUT_OPT_BITS0x00, "Level1 Identification without option bits" },
375 { MDB_BV_LVL2_FEATURE_ENABLE0x01, "Level2+ Feature Enable" },
376 { MDB_BV_LVL2_ID_WITH_OPTION_BITS0x02, "ID with Option Bits" },
377 { MDB_BV_RECYCL_SETUP0x03, "Recycler Setup" },
378 { MDB_BV_RECYCL_ENABLE0x04, "Recycler Enable" },
379 { MDB_BV_BILL_DISPENSE_STAT0x05, "Bill Dispense Status" },
380 { MDB_BV_DISPENSE_BILL0x06, "Dispense Bill" },
381 { MDB_BV_DISPENSE_VAL0x07, "Dispense Value" },
382 { MDB_BV_PAYOUT_STAT0x08, "Payout Status" },
383 { MDB_BV_PAYOUT_VALUE_POLL0x09, "Payout Value Poll" },
384 { MDB_BV_PAYOUT_CANCEL0x0A, "Payout Cancel" },
385 { 0, NULL((void*)0) }
386};
387
388static const true_false_string mdb_bv_escrow_state = { "Escrow Stack Bill", "Escrow Return Bill" };
389
390// Format: 1yyyxxxx, where yyy = Bill routing, xxxx = Bill type (0 to 15)
391static const value_string mdb_bv_poll_bill_routing_state[] = {
392 { 0x00, "Bill Stacked" },
393 { 0x01, "Escrow Position" },
394 { 0x02, "Bill Returned" },
395 { 0x03, "Bill to Recycler" },
396 { 0x04, "Disabled Bill Rejected" },
397 { 0x05, "Bill to Recycler" },
398 { 0x06, "Manual Dispense" },
399 { 0x07, "Transferred from Recycler to Cashbox" },
400 { 0, NULL((void*)0) }
401};
402
403
404static const value_string mdb_bv_poll_state[] = {
405/* Bill Validator (Only) */
406 { 0x01, "Defective Motor" }, // One of the motors has failed to perform its expected assignment.
407 { 0x02, "Sensor Problem" }, // One of the sensors has failed to provide its response.
408 { 0x03, "Validator Busy" }, // The validator is busy and can not answer a detailed command right now.
409 { 0x04, "ROM Checksum Error" }, // The validators internal checksum does not match the calculated checksum.
410 { 0x05, "Validator Jammed" }, // A bill(s) has jammed in the acceptance path.
411 { 0x06, "Validator was reset" }, // The validator has been reset since the last POLL.
412 { 0x07, "Bill removed" }, // A bill in the escrow position has been removed by an unknown means. A BILL RETURNED message should also be sent.
413 { 0x08, "Cash Box out of position" }, // The validator has detected the cash box to be open or removed.
414 { 0x09, "Validator disabled" }, // The validator has been disabled, by the VMC or because of internal conditions.
415 { 0x0A, "Invalid Escrow request" }, // An ESCROW command was requested for a bill not in the escrow position.
416 { 0x0B, "Bill rejected" }, // A bill was detected, but rejected because it could not be identified.
417 { 0x0C, "Possible Credited Bill Removal" }, // There has been an attempt to remove a credited (stacked) bill.
418 { 0x40, "Disabled validator, number of attempts to input bill" }, // Format: 010xxxxx
419/* Bill Recycler (Only) */
420 { 0x21, "Escrow request" }, // An escrow lever activation has been detected. If a button is present and activated.
421 { 0x22, "Dispenser Payout Busy" }, // The dispenser is busy activating payout devices.
422 { 0x23, "Dispenser Busy" }, // The dispenser is busy and can not answer a detailed command right now
423 { 0x24, "Defective Dispenser Sensor" }, // The dispenser has detected one of the dispenser sensors behaving abnormally
424
425 { 0x26, "Dispenser did not start / motor problem" },
426 { 0x27, "Dispenser Jam" }, // A dispenser payout attempt has resulted in jammed condition.
427 { 0x28, "ROM Checksum Error" }, // The dispensers internal checksum does not match the calculated checksum.
428 // (If separate from validator microprocessor.)
429 { 0x29, "Dispenser Disabled" }, // dispenser disabled because of error or bill in escrow position
430 { 0x2A, "Bill Waiting" }, // waiting for customer removal
431 { 0x2F, "Filled key pressed" }, // The VMC should request a new DISPENSER STATUS
432 { 0, NULL((void*)0) }
433};
434
435static const value_string mdb_bv_exp_bills_recyc_enabled[] = {
436 { 0x00, "Bill type disabled" },
437 { 0x01, "Only High quality bills are used" },
438 { 0x02, "Only High and Medium quality bills are used" },
439 { 0x03, "Use all possible bills" },
440 { 0, NULL((void*)0) }
441};
442
443static void dissect_mdb_ack(tvbuff_t *tvb, int offset,
444 packet_info *pinfo, proto_tree *tree)
445{
446 uint32_t ack;
447
448 proto_tree_add_item_ret_uint(tree, hf_mdb_ack, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &ack);
449 col_set_str(pinfo->cinfo, COL_INFO,
450 val_to_str_const(ack, mdb_ack, "Invalid ack byte"));
451}
452
453static void mdb_set_addrs(uint8_t event, uint8_t addr, packet_info *pinfo)
454{
455 const char *periph = val_to_str(pinfo->pool, addr, mdb_addr, "Unknown (0x%02x)");
456
457 /* pinfo->p2p_dir is from the perspective of the master (VMC) */
458
459 if (event == MDB_EVT_DATA_MST_PER0xFF) {
460 set_address(&pinfo->src, AT_STRINGZ, (int)strlen(ADDR_VMC"VMC")+1, ADDR_VMC"VMC");
461 set_address(&pinfo->dst, AT_STRINGZ, (int)strlen(periph)+1, periph);
462 pinfo->p2p_dir = P2P_DIR_SENT0;
463 }
464 else if (event == MDB_EVT_DATA_PER_MST0xFE) {
465 set_address(&pinfo->src, AT_STRINGZ, (int)strlen(periph)+1, periph);
466 set_address(&pinfo->dst, AT_STRINGZ, (int)strlen(ADDR_VMC"VMC")+1, ADDR_VMC"VMC");
467 pinfo->p2p_dir = P2P_DIR_RECV1;
468 }
469}
470
471static void mdb_add_checksum(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int total_len)
472{
473 if (total_len <= 1) return;
474 uint8_t calculated_checksum = 0;
475
476 for (int i = 0; i < total_len - 1; i++) {
477 uint8_t val = tvb_get_uint8(tvb, offset + i);
478 /* The MDB checksum is a simple sum modulo 256. Using uint8_t
479 * causes an intentional wrap-around that perfectly matches the modulo.
480 */
481 calculated_checksum += val;
482 }
483
484 proto_tree_add_checksum(tree, tvb, offset + total_len - 1, hf_mdb_chk, hf_mdb_chk_status, &ei_mdb_bad_checksum, pinfo, calculated_checksum, ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_VERIFY0x01);
485}
486
487static void dissect_mdb_cl_setup(tvbuff_t *tvb, int offset,
488 packet_info *pinfo, proto_tree *tree)
489{
490 uint32_t sub_cmd, price;
491 const char *s;
492 proto_item *pi;
493
494 proto_tree_add_item_ret_uint(tree, hf_mdb_cl_setup_sub,
495 tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &sub_cmd);
496 s = try_val_to_str(sub_cmd, mdb_cl_setup_sub_cmd);
497 if (s) {
498 col_set_str(pinfo->cinfo, COL_INFO, s);
499 }
500 offset++;
501
502 switch (sub_cmd) {
503 case MDB_CL_SETUP_CFG_DATA0x00:
504 proto_tree_add_item(tree, hf_mdb_cl_feat_lvl, tvb, offset, 1,
505 ENC_BIG_ENDIAN0x00000000);
506 offset++;
507 proto_tree_add_item(tree, hf_mdb_cl_cols, tvb, offset, 1,
508 ENC_BIG_ENDIAN0x00000000);
509 offset++;
510 proto_tree_add_item(tree, hf_mdb_cl_rows, tvb, offset, 1,
511 ENC_BIG_ENDIAN0x00000000);
512 offset++;
513 proto_tree_add_item(tree, hf_mdb_cl_disp_info, tvb, offset, 1,
514 ENC_BIG_ENDIAN0x00000000);
515 break;
516
517 case MDB_CL_SETUP_MAX_MIN0x01:
518 if (tvb_reported_length_remaining(tvb, offset) == 5) {
519 /* This is the "default version" of Max/Min Prices. */
520
521 /* XXX - convert the scaled prices into actual amounts */
522 pi = proto_tree_add_item_ret_uint(tree, hf_mdb_cl_max_price,
523 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &price);
524 if (price == 0xFFFF) {
525 proto_item_append_text(pi, " (unknown)");
526 }
527 offset += 2;
528
529 pi = proto_tree_add_item_ret_uint(tree, hf_mdb_cl_min_price,
530 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &price);
531 if (price == 0x0000) {
532 proto_item_append_text(pi, " (unknown)");
533 }
534 }
535 else if (tvb_reported_length_remaining(tvb, offset) == 11) {
536 /* This is the "expanded currency version" of Max/Min Prices. */
537
538 proto_tree_add_item(tree, hf_mdb_cl_max_price, tvb, offset, 4,
539 ENC_BIG_ENDIAN0x00000000);
540 offset += 4;
541 proto_tree_add_item(tree, hf_mdb_cl_min_price, tvb, offset, 4,
542 ENC_BIG_ENDIAN0x00000000);
543 }
544 /* XXX - expert info for other lengths */
545 break;
546 }
547}
548
549static void dissect_mdb_cl_vend(tvbuff_t *tvb, int offset,
550 packet_info *pinfo, proto_tree *tree)
551{
552 uint32_t sub_cmd, price, item;
553 const char *s;
554
555 proto_tree_add_item_ret_uint(tree, hf_mdb_cl_vend_sub, tvb, offset, 1,
556 ENC_BIG_ENDIAN0x00000000, &sub_cmd);
557 s = try_val_to_str(sub_cmd, mdb_cl_vend_sub_cmd);
558 if (s) {
559 col_set_str(pinfo->cinfo, COL_INFO, s);
560 }
561 offset++;
562
563 switch (sub_cmd) {
564 case MDB_CL_VEND_REQ0x00:
565 if (tvb_reported_length_remaining(tvb, offset) == 5) {
566 proto_tree_add_item_ret_uint(tree, hf_mdb_cl_item_price, tvb,
567 offset, 2, ENC_BIG_ENDIAN0x00000000, &price);
568 offset += 2;
569 proto_tree_add_item_ret_uint(tree, hf_mdb_cl_item_num, tvb,
570 offset, 2, ENC_BIG_ENDIAN0x00000000, &item);
571 col_append_fstr(pinfo->cinfo, COL_INFO, " (item %d, price %d)",
572 item, price);
573 }
574 /* XXX - dissect the longer request in Expanded Currency Mode */
575 break;
576 case MDB_CL_VEND_SUC0x02:
577 proto_tree_add_item(tree, hf_mdb_cl_item_num, tvb, offset, 2,
578 ENC_BIG_ENDIAN0x00000000);
579 break;
580 }
581}
582
583static int
584dissect_mdb_cl_id_fields(tvbuff_t *tvb, int offset, proto_tree *tree)
585{
586 proto_tree_add_item(tree, hf_mdb_cl_manuf_code, tvb, offset, 3, ENC_ASCII0x00000000);
587 offset += 3;
588 proto_tree_add_item(tree, hf_mdb_cl_ser_num, tvb, offset, 12, ENC_ASCII0x00000000);
589 offset += 12;
590 proto_tree_add_item(tree, hf_mdb_cl_mod_num, tvb, offset, 12, ENC_ASCII0x00000000);
591 offset += 12;
592 /* XXX - dissect the Software Version bytes */
593 offset += 2;
594
595 return offset;
596}
597
598static void dissect_mdb_cl_expns(tvbuff_t *tvb, int offset, packet_info *pinfo,
599 proto_tree *tree)
600{
601 uint32_t sub_cmd;
602 const char *s;
603
604 proto_tree_add_item_ret_uint(tree, hf_mdb_cl_expns_sub,
605 tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &sub_cmd);
606 s = try_val_to_str(sub_cmd, mdb_cl_expns_sub_cmd);
607 if (s) {
608 col_set_str(pinfo->cinfo, COL_INFO, s);
609 }
610 offset++;
611
612 switch (sub_cmd) {
613 case MDB_CL_EXPNS_REQ_ID0x00:
614 dissect_mdb_cl_id_fields(tvb, offset, tree);
615 break;
616 case MDB_CL_EXPNS_OPT_ENA0x04:
617 /* XXX - add a bitmask for the Optional Feature Bits */
618 proto_tree_add_item(tree, hf_mdb_cl_opt_feat, tvb, offset, 4,
619 ENC_BIG_ENDIAN0x00000000);
620 break;
621 }
622}
623
624static void dissect_mdb_cl_rd_cfg_data(tvbuff_t *tvb, int offset,
625 packet_info *pinfo _U___attribute__((unused)), proto_tree *tree)
626{
627 proto_tree_add_item(tree, hf_mdb_cl_feat_lvl, tvb, offset, 1,
628 ENC_BIG_ENDIAN0x00000000);
629 offset++;
630 /* XXX - dissect Country/Currency Code */
631 offset += 2;
632 proto_tree_add_item(tree, hf_mdb_cl_scale, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
633 offset++;
634 proto_tree_add_item(tree, hf_mdb_cl_dec_pl, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
635 offset++;
636 proto_tree_add_item(tree, hf_mdb_cl_max_rsp_time, tvb, offset, 1,
637 ENC_TIME_SECS0x00000012 | ENC_BIG_ENDIAN0x00000000);
638}
639
640static void dissect_mdb_mst_per_cl( tvbuff_t *tvb, int offset, int len _U___attribute__((unused)),
641 packet_info *pinfo, proto_tree *tree, proto_item *cmd_it,
642 uint8_t addr_byte, mdb_conv_info_t* conv_info _U___attribute__((unused)))
643{
644 uint8_t cmd = addr_byte & 0x07; /* the 3-bit command */
645 proto_tree *cl_tree;
646 uint32_t sub_cmd;
647 const char *s;
648
649 s = val_to_str_const(cmd, mdb_cl_cmd, "Unknown");
650 proto_item_append_text(cmd_it, " (%s)", s);
651 col_set_str(pinfo->cinfo, COL_INFO, s);
652
653 cl_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_cl,
654 NULL((void*)0), "Cashless");
655
656 s = NULL((void*)0);
657 switch (cmd) {
658 case MDB_CL_CMD_SETUP0x01:
659 dissect_mdb_cl_setup(tvb, offset, pinfo, cl_tree);
660 break;
661 case MDB_CL_CMD_VEND0x03:
662 dissect_mdb_cl_vend(tvb, offset, pinfo, cl_tree);
663 break;
664 case MDB_CL_CMD_READER0x04:
665 proto_tree_add_item_ret_uint(cl_tree, hf_mdb_cl_reader_sub,
666 tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &sub_cmd);
667 s = try_val_to_str(sub_cmd, mdb_cl_reader_sub_cmd);
668 break;
669 case MDB_CL_CMD_EXPNS0x07:
670 dissect_mdb_cl_expns(tvb, offset, pinfo, cl_tree);
671 break;
672 }
673 if (s)
674 col_set_str(pinfo->cinfo, COL_INFO, s);
675}
676
677static void dissect_mdb_per_mst_cl( tvbuff_t *tvb, int offset,
678 int len _U___attribute__((unused)), packet_info *pinfo, proto_tree *tree, mdb_conv_info_t* conv_info _U___attribute__((unused)))
679{
680 proto_tree *cl_tree;
681 uint32_t cl_resp;
682
683 cl_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_cl,
684 NULL((void*)0), "Cashless");
685
686 proto_tree_add_item_ret_uint(cl_tree, hf_mdb_cl_resp, tvb, offset, 1,
687 ENC_BIG_ENDIAN0x00000000, &cl_resp);
688 col_set_str(pinfo->cinfo,
689 COL_INFO, val_to_str_const(cl_resp, mdb_cl_resp, "Unknown"));
690 offset++;
691
692 switch (cl_resp) {
693 case MDB_CL_RESP_RD_CFG_DATA0x01:
694 dissect_mdb_cl_rd_cfg_data(tvb, offset, pinfo, cl_tree);
695 break;
696 case MDB_CL_RESP_VEND_APRV0x05:
697 if (tvb_reported_length_remaining(tvb, offset) == 3) {
698 proto_tree_add_item(cl_tree, hf_mdb_cl_vend_amt, tvb, offset,
699 2, ENC_BIG_ENDIAN0x00000000);
700 }
701 /* XXX - dissect the longer response in Expanded Currency Mode */
702 break;
703 case MDB_CL_RESP_PER_ID0x09:
704 dissect_mdb_cl_id_fields(tvb, offset, tree);
705 /* XXX - check if we have Optional Feature Bits */
706 break;
707 }
708}
709
710static void dissect_mdb_cgw_report(tvbuff_t *tvb, int offset,
711 packet_info *pinfo, proto_tree *tree)
712{
713 uint32_t sub_cmd;
714 const char *s;
715
716 proto_tree_add_item_ret_uint(tree, hf_mdb_cgw_report_sub,
717 tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &sub_cmd);
718 s = try_val_to_str(sub_cmd, mdb_cgw_report_sub_cmd);
719 if (s) {
720 col_set_str(pinfo->cinfo, COL_INFO, s);
721 }
722 offset++;
723
724 switch (sub_cmd) {
725 case MDB_CGW_REPORT_DTS_EVT0x02:
726 proto_tree_add_item(tree, hf_mdb_cgw_dts_evt_code, tvb, offset, 10,
727 ENC_ASCII0x00000000);
728 offset += 10;
729 /* XXX - dissect Date */
730 offset += 4;
731 /* XXX - dissect Time */
732 offset += 2;
733 proto_tree_add_item(tree, hf_mdb_cgw_duration, tvb, offset, 4,
734 ENC_BIG_ENDIAN0x00000000);
735 offset += 4;
736 proto_tree_add_item(tree, hf_mdb_cgw_activity, tvb, offset, 1,
737 ENC_BIG_ENDIAN0x00000000);
738 break;
739 }
740}
741
742static void dissect_mdb_cgw_expns(tvbuff_t *tvb, int offset,
743 packet_info *pinfo, proto_tree *tree)
744{
745 uint32_t sub_cmd;
746 const char *s;
747
748 proto_tree_add_item_ret_uint(tree, hf_mdb_cgw_expns_sub,
749 tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &sub_cmd);
750 s = try_val_to_str(sub_cmd, mdb_cgw_expns_sub_cmd);
751 if (s) {
752 col_set_str(pinfo->cinfo, COL_INFO, s);
753 }
754 offset++;
755
756 switch (sub_cmd) {
757 case MDB_CGW_EXPNS_FEAT_ENA0x01:
758 proto_tree_add_item(tree, hf_mdb_cgw_opt_feat, tvb, offset, 4,
759 ENC_BIG_ENDIAN0x00000000);
760 break;
761 }
762}
763
764static void dissect_mdb_mst_per_cgw( tvbuff_t *tvb, int offset, int len,
765 packet_info *pinfo, proto_tree *tree, proto_item *cmd_it,
766 uint8_t addr_cmd_byte, mdb_conv_info_t* conv_info _U___attribute__((unused)))
767{
768 proto_tree *cgw_tree;
769 const char *s;
770
771 s = val_to_str_const(addr_cmd_byte, mdb_cgw_addr_cmd, "Unknown");
772 proto_item_append_text(cmd_it, " (%s)", s);
773 col_set_str(pinfo->cinfo, COL_INFO, s);
774
775 cgw_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_cgw,
776 NULL((void*)0), "Communications Gateway");
777
778 switch (addr_cmd_byte) {
779 case MDB_CGW_ADDR_CMD_SETUP0x19:
780 proto_tree_add_item(cgw_tree, hf_mdb_cgw_feat_lvl, tvb, offset, 1,
781 ENC_BIG_ENDIAN0x00000000);
782 offset++;
783 proto_tree_add_item(cgw_tree, hf_mdb_cgw_scale, tvb, offset, 1,
784 ENC_BIG_ENDIAN0x00000000);
785 offset++;
786 proto_tree_add_item(cgw_tree, hf_mdb_cgw_dec_pl, tvb, offset, 1,
787 ENC_BIG_ENDIAN0x00000000);
788 break;
789 case MDB_CGW_ADDR_CMD_REPORT0x1B:
790 dissect_mdb_cgw_report(tvb, offset, pinfo, cgw_tree);
791 break;
792 case MDB_CGW_ADDR_CMD_EXPNS0x1F:
793 dissect_mdb_cgw_expns(tvb, offset, pinfo, cgw_tree);
794 break;
795 }
796}
797
798static void dissect_mdb_per_mst_cgw( tvbuff_t *tvb, int offset,
799 int len, packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, mdb_conv_info_t* conv_info _U___attribute__((unused)))
800{
801 proto_tree *cgw_tree;
802 uint32_t cgw_resp;
803
804 cgw_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_cgw,
805 NULL((void*)0), "Communications Gateway");
806
807 proto_tree_add_item_ret_uint(cgw_tree, hf_mdb_cgw_resp, tvb, offset, 1,
808 ENC_BIG_ENDIAN0x00000000, &cgw_resp);
809 col_set_str(pinfo->cinfo,
810 COL_INFO, val_to_str_const(cgw_resp, mdb_cgw_resp, "Unknown"));
811 offset++;
812
813 switch (cgw_resp) {
814 case MDB_CGW_RESP_CFG0x01:
815 proto_tree_add_item(cgw_tree, hf_mdb_cgw_feat_lvl, tvb, offset, 1,
816 ENC_BIG_ENDIAN0x00000000);
817 offset++;
818 proto_tree_add_item(cgw_tree, hf_mdb_cgw_max_rsp_time, tvb, offset,
819 2, ENC_TIME_SECS0x00000012 | ENC_BIG_ENDIAN0x00000000);
820 break;
821 case MDB_CGW_RESP_PER_ID0x06:
822 proto_tree_add_item(tree, hf_mdb_cgw_manuf_code, tvb, offset, 3,
823 ENC_ASCII0x00000000);
824 offset += 3;
825 proto_tree_add_item(tree, hf_mdb_cgw_ser_num, tvb, offset, 12,
826 ENC_ASCII0x00000000);
827 offset += 12;
828 proto_tree_add_item(tree, hf_mdb_cgw_mod_num, tvb, offset, 12,
829 ENC_ASCII0x00000000);
830 offset += 12;
831 /* XXX - dissect the Software Version bytes */
832 offset += 2;
833 proto_tree_add_item(tree, hf_mdb_cgw_opt_feat, tvb, offset, 4,
834 ENC_BIG_ENDIAN0x00000000);
835 break;
836 }
837}
838
839static int dissect_mdb_bv_setup_fields(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
840{
841 wmem_strbuf_t* bill_str = wmem_strbuf_new(pinfo->pool, "");
842
843 proto_tree_add_item(tree, hf_mdb_bv_setup_bill_val_feature, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
844 offset += 1;
845 proto_tree_add_item(tree, hf_mdb_bv_setup_ctry_currency_code, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
846 offset += 2;
847 proto_tree_add_item(tree, hf_mdb_bv_setup_bill_scal_fac, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
848 offset += 2;
849 proto_tree_add_item(tree, hf_mdb_bv_setup_dec_places, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
850 offset += 1;
851 proto_tree_add_item(tree, hf_mdb_bv_setup_bill_stacker_cap, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
852 offset += 2;
853 proto_tree_add_item(tree, hf_mdb_bv_setup_bill_sec_lvls, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
854 offset += 2;
855 proto_tree_add_item(tree, hf_mdb_bv_setup_escrow, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
856 offset += 1;
857
858 uint8_t bill_val;
859 for (int i = 0; i < 16; i++) {
860 bill_val = tvb_get_uint8(tvb, offset + i);
861 // Append each bill value to comma separated string
862 wmem_strbuf_append_printf(bill_str, "%u%s", bill_val, (i < 15) ? "," : "");
863 }
864 // Add the formatted string to the protocol tree
865 proto_tree_add_string_format_value(tree, hf_mdb_bv_setup_bill_type_cred, tvb, offset, 16,
866 bill_str->str, "Bill values: %s", bill_str->str);
867 offset += 16;
868
869 return offset;
870}
871
872static int dissect_mdb_bv_poll_stat_bill_accept(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
873{
874 uint32_t bill_routing;
875
876 proto_tree_add_item_ret_uint(tree, hf_mdb_bv_poll_bill_routing_state, tvb, offset, 1, ENC_NA0x00000000, &bill_routing);
877 proto_tree_add_item(tree, hf_mdb_bv_poll_bill_type, tvb, offset, 1, ENC_NA0x00000000);
878
879 col_add_str(pinfo->cinfo, COL_INFO,
880 val_to_str(pinfo->pool, bill_routing, mdb_bv_poll_bill_routing_state, "Unknown Bill Routing: 0x%x"));
881
882 offset += 1;
883
884 return offset;
885}
886
887static int dissect_mdb_bv_poll_fields(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
888{
889 uint8_t cmd = tvb_get_uint8(tvb, offset);
890
891 if (cmd & 0x80)
892 {
893 // Bills Accepted response
894 dissect_mdb_bv_poll_stat_bill_accept(tvb, offset, pinfo, tree);
895 offset += 1;
896 }
897 else if (cmd > 0x1A)
898 {
899 // File transport layer response
900 offset += 1;
901 }
902 else
903 {
904 proto_tree_add_item(tree, hf_mdb_bv_poll_state, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
905 col_add_str(pinfo->cinfo, COL_INFO,
906 val_to_str(pinfo->pool, cmd, mdb_bv_poll_state, "Unknown Poll Response 0x%x"));
907 offset += 1;
908 }
909
910 return offset;
911}
912
913static int dissect_mdb_bv_bill_type(tvbuff_t *tvb, int offset, proto_tree *tree)
914{
915 proto_tree_add_item(tree, hf_mdb_bv_bill_enable, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
916 offset += 2;
917 proto_tree_add_item(tree, hf_mdb_bv_bill_escrow_enable, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
918 offset += 2;
919
920 return offset;
921}
922
923static int dissect_mdb_bv_escrow(tvbuff_t *tvb, int offset, proto_tree *tree)
924{
925 proto_tree_add_item(tree, hf_mdb_bv_escrow_state, tvb, offset, 1, ENC_NA0x00000000);
926 offset += 1;
927
928 return offset;
929}
930
931static int dissect_mdb_bv_stacker(tvbuff_t *tvb, int offset, proto_tree *tree)
932{
933 proto_tree_add_item(tree, hf_mdb_bv_stacker, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
934 offset += 2;
935
936 return offset;
937}
938
939static int dissect_mdb_bv_exp_id_opt_fields(tvbuff_t *tvb, int offset,
940proto_tree *tree, bool_Bool opt_features)
941{
942 proto_tree_add_item(tree, hf_mdb_bv_exp_manufact_code, tvb, offset, 3, ENC_ASCII0x00000000);
943 offset += 3;
944 proto_tree_add_item(tree, hf_mdb_bv_exp_serial_num, tvb, offset, 12, ENC_ASCII0x00000000);
945 offset += 12;
946 proto_tree_add_item(tree, hf_mdb_bv_exp_model_tuning_num, tvb, offset, 12, ENC_ASCII0x00000000);
947 offset += 12;
948 proto_tree_add_item(tree, hf_mdb_bv_exp_software_version, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
949 offset += 2;
950 // Only for cmd 37 02
951 if (opt_features) {
952 proto_tree_add_item(tree, hf_mdb_bv_exp_opt_feat, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
953 offset += 4;
954 }
955
956 return offset;
957}
958
959static int dissect_mdb_bv_exp_recycler_setup(tvbuff_t *tvb, int offset, proto_tree *tree)
960{
961 proto_tree_add_item(tree, hf_mdb_bv_exp_manual_dispense_enable, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
962 offset += 2;
963
964 return offset;
965}
966
967static int dissect_mdb_bv_exp_recycler_enable(tvbuff_t *tvb, int offset, proto_tree *tree)
968{
969 proto_tree_add_item(tree, hf_mdb_bv_exp_bill_type_routing, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
970 offset += 2;
971
972 for (int i = 0; i < 16; i++) {
973 proto_tree_add_item(tree, hf_mdb_bv_exp_bill_recycler_enabled, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
974 offset += 1;
975 }
976
977 return offset;
978}
979
980static int dissect_mdb_bv_exp_dispense_status(tvbuff_t *tvb, int offset, proto_tree *tree)
981{
982 proto_tree_add_item(tree, hf_mdb_bv_exp_dispenser_full_state, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
983 offset += 2;
984 for (int i = 0; i < 32; i++) {
985 proto_tree_add_item(tree, hf_mdb_bv_exp_bill_count, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
986 offset += 1;
987 }
988
989 return offset;
990}
991
992static int dissect_mdb_bv_exp_dispense_bill(tvbuff_t *tvb, int offset, proto_tree *tree)
993{
994 proto_tree_add_item(tree, hf_mdb_bv_exp_bill_type_dispensed, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
995 offset += 1;
996 proto_tree_add_item(tree, hf_mdb_bv_exp_bill_type_number_bills, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
997 offset += 2;
998
999 return offset;
1000}
1001
1002static int dissect_mdb_bv_exp_dispense_value_bill(tvbuff_t *tvb, int offset, proto_tree *tree)
1003{
1004 proto_tree_add_item(tree, hf_mdb_bv_exp_dispense_value_bills, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
1005 offset += 2;
1006
1007 return offset;
1008}
1009
1010static int dissect_mdb_bv_exp_payout_status(tvbuff_t *tvb, int offset, proto_tree *tree)
1011{
1012 for (int i = 0; i < 16; i++) {
1013 proto_tree_add_item(tree, hf_mdb_bv_exp_payout_state, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
1014 offset += 2;
1015 }
1016
1017 return offset;
1018}
1019
1020static int dissect_mdb_bv_exp_payout_value_poll(tvbuff_t *tvb, int offset, proto_tree *tree)
1021{
1022 proto_tree_add_item(tree, hf_mdb_bv_exp_dispenser_payout_activity, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
1023 offset += 2;
1024
1025 return offset;
1026}
1027
1028static void dissect_mdb_bv_expns_mst_per(tvbuff_t *tvb, int offset, packet_info *pinfo,
1029 proto_tree *tree)
1030{
1031 const char *s;
1032 uint32_t sub_cmd = tvb_get_uint8(tvb, offset);
1033
1034 s = try_val_to_str(sub_cmd, mdb_bv_exp_cmd);
1035 if (s) {
1036 col_set_str(pinfo->cinfo, COL_INFO, s);
1037 }
1038
1039 switch (sub_cmd) {
1040 case MDB_BV_LVL2_FEATURE_ENABLE0x01:
1041 proto_tree_add_item(tree, hf_mdb_bv_exp_opt_feat_enable, tvb, offset, 4,
1042 ENC_BIG_ENDIAN0x00000000);
1043 break;
1044 case MDB_BV_RECYCL_ENABLE0x04:
1045 dissect_mdb_bv_exp_recycler_enable(tvb, offset, tree);
1046 break;
1047 case MDB_BV_DISPENSE_BILL0x06:
1048 dissect_mdb_bv_exp_dispense_bill(tvb, offset, tree);
1049 break;
1050 case MDB_BV_DISPENSE_VAL0x07:
1051 dissect_mdb_bv_exp_dispense_value_bill(tvb, offset, tree);
1052 break;
1053 case MDB_BV_PAYOUT_CANCEL0x0A:
1054 // Nothing to dissect
1055 break;
1056 }
1057}
1058
1059static void dissect_mdb_bv_expns_per_mst(tvbuff_t *tvb, int offset, proto_tree *tree, uint16_t cmd)
1060{
1061 uint8_t sub_cmd = cmd >> SUB_CMD_OFFSET8;
1062
1063 switch (sub_cmd) {
1064 case MDB_BV_LVL1_WITHOUT_OPT_BITS0x00:
1065 dissect_mdb_bv_exp_id_opt_fields(tvb, offset, tree, false0);
1066 break;
1067 case MDB_BV_LVL2_ID_WITH_OPTION_BITS0x02:
1068 dissect_mdb_bv_exp_id_opt_fields(tvb, offset, tree, true1);
1069 break;
1070 case MDB_BV_RECYCL_SETUP0x03:
1071 dissect_mdb_bv_exp_recycler_setup(tvb, offset, tree);
1072 break;
1073 case MDB_BV_BILL_DISPENSE_STAT0x05:
1074 dissect_mdb_bv_exp_dispense_status(tvb, offset, tree);
1075 break;
1076 case MDB_BV_PAYOUT_STAT0x08:
1077 dissect_mdb_bv_exp_payout_status(tvb, offset, tree);
1078 break;
1079 case MDB_BV_PAYOUT_VALUE_POLL0x09:
1080 dissect_mdb_bv_exp_payout_value_poll(tvb, offset, tree);
1081 break;
1082 // FTL Expansion commands not implemented yet
1083 }
1084}
1085
1086static void dissect_mdb_mst_per_bv( tvbuff_t *tvb, int offset, int len,
1087 packet_info *pinfo, proto_tree *tree, proto_item *cmd_it,
1088 uint8_t addr_cmd_byte, mdb_conv_info_t* conv_info)
1089{
1090 uint8_t cmd = CMD_MASK0x07 & addr_cmd_byte; /* the 3-bit command */
1091 proto_tree *bv_tree;
1092 mdb_transaction_t* transaction;
1093 uint8_t sub_cmd = 0;
1094 const char *s;
1095
1096 s = val_to_str(pinfo->pool, cmd, mdb_bv_cmd, "Unknown Command: 0x%x");
1097 proto_item_append_text(cmd_it, " (%s)", s);
1098 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (Request)", s);
1099
1100 bv_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_bv,
1101 NULL((void*)0), "Bill Validator");
1102
1103 switch (cmd) {
1104 case MDB_BV_CMD_SETUP0x01:
1105 break;
1106 case MDB_BV_CMD_SECURITY0x02:
1107 break;
1108 case MDB_BV_CMD_BILL_TYPE0x04:
1109 dissect_mdb_bv_bill_type(tvb, offset, bv_tree);
1110 break;
1111 case MDB_BV_CMD_ESCROW0x05:
1112 dissect_mdb_bv_escrow(tvb, offset, bv_tree);
1113 break;
1114 case MDB_BV_CMD_STACKER0x06:
1115 break;
1116 case MDB_BV_CMD_EXPNS0x07:
1117 sub_cmd = tvb_get_uint8(tvb, offset);
1118 dissect_mdb_bv_expns_mst_per(tvb, offset, pinfo, bv_tree);
1119 break;
1120 }
1121
1122 if (!pinfo->fd->visited)
1123 {
1124 //Create the request information
1125 transaction = wmem_new0(wmem_file_scope(), mdb_transaction_t)((mdb_transaction_t*)wmem_alloc0((wmem_file_scope()), sizeof(
mdb_transaction_t)))
;
1126 transaction->req_num = pinfo->num;
1127 transaction->req_time = pinfo->abs_ts;
1128
1129 // If not MDB_BV_CMD_EXPNS, then sub_cmd is just 0
1130 transaction->cmd = (cmd | (sub_cmd << SUB_CMD_OFFSET8));
1131 wmem_tree_insert32(conv_info->transactions, pinfo->num, (void*)transaction);
1132 conv_info->last_cmd = transaction->cmd;
1133 conv_info->last_req_packet = pinfo->num;
1134 }
1135 else
1136 {
1137 transaction = (mdb_transaction_t*)wmem_tree_lookup32_le(conv_info->transactions, pinfo->num);
1138 }
1139
1140 if ((transaction != NULL((void*)0)) && (transaction->rep_num))
1141 {
1142 proto_item* it = proto_tree_add_uint(tree, hf_mdb_response_in, NULL((void*)0), 0, 0, transaction->rep_num);
1143 proto_item_set_generated(it);
1144
1145 }
1146}
1147
1148
1149static void dissect_mdb_mst_per(tvbuff_t *tvb, int offset, packet_info *pinfo,
1150 proto_tree *tree)
1151{
1152 uint8_t addr_byte, addr;
1153 int mst_per_len;
1154 unsigned data_len;
1155 proto_item *cmd_it;
1156
1157 mst_per_len = tvb_reported_length_remaining(tvb, offset);
1158 if (mst_per_len <= 0) {
1159 expert_add_info(pinfo, tree, &ei_mdb_short_packet);
1160 return;
1161 }
1162
1163 if (mst_per_len == 1) {
1164 dissect_mdb_ack(tvb, offset, pinfo, tree);
1165 return;
1166 }
1167
1168 /*
1169 * Our packet has one address byte, an optional data block and one
1170 * checksum byte.
1171 */
1172
1173 data_len = mst_per_len - 2;
1174 int start_offset = offset;
1175
1176 /*
1177 * The address byte is 5-bit address | 3-bit command.
1178 *
1179 * The specification uses 8-bit addresses which are the address byte
1180 * with the three lowest bits set to 0.
1181 *
1182 * The commands are defined as the complete address byte (i.e. they
1183 * include the address part). This does not make much sense: Cashless #1
1184 * and #2 have different addresses but exactly the same 3-bit commands.
1185 *
1186 * In this dissector, we try to use the same values as the specification.
1187 */
1188 addr_byte = tvb_get_uint8(tvb, offset);
1189 addr = addr_byte & ADDR_MASK0xF8;
1190 proto_tree_add_uint_bits_format_value(tree, hf_mdb_addr,
1191 tvb, 8*offset, 5, addr, ENC_BIG_ENDIAN0x00000000, "0x%02x", addr);
1192 cmd_it = proto_tree_add_uint(tree, hf_mdb_cmd, tvb, offset, 1, addr_byte & CMD_MASK0x07);
1193 mdb_set_addrs(MDB_EVT_DATA_MST_PER0xFF, addr, pinfo);
1194 mdb_conv_info_t* conv_info = get_mdb_conv_info(pinfo);
1195 offset++;
1196
1197 /*
1198 * We call the peripheral functions even if data_len == 0 so they can fix
1199 * up the command with peripheral-specific info.
1200 */
1201 switch (addr) {
1202 case ADDR_CASHLESS10x10:
1203 dissect_mdb_mst_per_cl(tvb, offset, data_len, pinfo, tree,
1204 cmd_it, addr_byte, conv_info);
1205 break;
1206 case ADDR_COMMS_GW0x18:
1207 dissect_mdb_mst_per_cgw(tvb, offset, data_len, pinfo, tree,
1208 cmd_it, addr_byte, conv_info);
1209 break;
1210 case ADDR_BILL_VALIDATOR0x30:
1211 dissect_mdb_mst_per_bv(tvb, offset, data_len, pinfo, tree,
1212 cmd_it, addr_byte, conv_info);
1213 break;
1214 default:
1215 if (data_len > 0) {
1216 proto_tree_add_item(tree, hf_mdb_data,
1217 tvb, offset, data_len, ENC_NA0x00000000);
1218 }
1219 break;
1220 }
1221 offset += data_len;
Value stored to 'offset' is never read
1222
1223 /* Verify the checksum */
1224 mdb_add_checksum(tvb, pinfo, tree, start_offset, data_len + 2);
1225}
1226
1227static void dissect_mdb_per_mst_bv( tvbuff_t *tvb, int offset,
1228 int len, packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, mdb_conv_info_t* conv_info)
1229{
1230 proto_tree *bv_tree;
1231 mdb_transaction_t* transaction;
1232
1233 if (!pinfo->fd->visited)
1234 {
1235 transaction = (mdb_transaction_t*)wmem_tree_lookup32_le(conv_info->transactions, conv_info->last_req_packet);
1236 if (transaction)
1237 {
1238 transaction->rep_num = pinfo->num;
1239 }
1240 else
1241 {
1242 transaction = wmem_new0(wmem_file_scope(), mdb_transaction_t)((mdb_transaction_t*)wmem_alloc0((wmem_file_scope()), sizeof(
mdb_transaction_t)))
;
1243 transaction->rep_num = pinfo->num;
1244 }
1245 wmem_tree_insert32(conv_info->transactions, pinfo->num, (void*)transaction);
1246 }
1247 else
1248 {
1249 transaction = (mdb_transaction_t*)wmem_tree_lookup32_le(conv_info->transactions, pinfo->num);
1250 }
1251
1252 //Sanity check
1253 if (transaction == NULL((void*)0))
1254 return;
1255
1256 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (Response)",
1257 val_to_str(pinfo->pool, transaction->cmd & CMD_MASK0x07, mdb_bv_cmd, "Unknown Command: 0x%x"));
1258
1259 switch (transaction->cmd & CMD_MASK0x07) {
1260 case MDB_BV_CMD_SETUP0x01:
1261 bv_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_bv, NULL((void*)0), "Setup Response");
1262 dissect_mdb_bv_setup_fields(tvb, offset, pinfo, bv_tree);
1263 break;
1264 case MDB_BV_CMD_SECURITY0x02:
1265 /* bv_tree = */ proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_bv, NULL((void*)0), "Security Response");
1266 break;
1267 case MDB_BV_CMD_POLL0x03:
1268 bv_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_bv, NULL((void*)0), "Poll Response");
1269 dissect_mdb_bv_poll_fields(tvb, offset, pinfo, bv_tree);
1270 break;
1271 case MDB_BV_CMD_BILL_TYPE0x04:
1272 break;
1273 case MDB_BV_CMD_ESCROW0x05:
1274 break;
1275 case MDB_BV_CMD_STACKER0x06:
1276 bv_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_bv, NULL((void*)0), "Stacker Response");
1277 dissect_mdb_bv_stacker(tvb, offset, bv_tree);
1278 break;
1279 case MDB_BV_CMD_EXPNS0x07:
1280 bv_tree = proto_tree_add_subtree(tree, tvb, offset, len, ett_mdb_bv, NULL((void*)0), "Expansion Feature Response");
1281 dissect_mdb_bv_expns_per_mst(tvb, offset, bv_tree, transaction->cmd);
1282 break;
1283 }
1284
1285 // This is a reply
1286 if (transaction->req_num)
1287 {
1288 proto_item* it;
1289 nstime_t ns;
1290
1291 it = proto_tree_add_uint(tree, hf_mdb_response_to, NULL((void*)0), 0, 0, transaction->req_num);
1292 proto_item_set_generated(it);
1293
1294 nstime_delta(&ns, &pinfo->abs_ts, &transaction->req_time);
1295 it = proto_tree_add_time(tree, hf_mdb_time, NULL((void*)0), 0, 0, &ns);
1296 proto_item_set_generated(it);
1297 }
1298
1299}
1300
1301/*
1302 * Peripheral-to-Master messages can be simple control replies (ACK, NAK, RET)
1303 * that do not include a checksum. Master-to-Peripheral commands always
1304 * require a checksum, which is why this check is only needed for
1305 * Peripheral-to-Master events.
1306 */
1307static void dissect_mdb_per_mst(tvbuff_t *tvb, int offset, packet_info *pinfo,
1308 proto_tree *tree, uint8_t addr)
1309{
1310 int per_mst_len;
1311 unsigned data_len;
1312
1313 /*
1314 * A packet from peripheral to master is either a single ACK/NAK byte or
1315 * a non-empty data block followed by one checksum byte.
1316 */
1317
1318 per_mst_len = tvb_reported_length_remaining(tvb, offset);
1319 if (per_mst_len <= 0) {
1320 expert_add_info(pinfo, tree, &ei_mdb_short_packet);
1321 return;
1322 }
1323
1324 if (per_mst_len == 1) {
1325 dissect_mdb_ack(tvb, offset, pinfo, tree);
1326 return;
1327 }
1328
1329 col_set_str(pinfo->cinfo,
1330 COL_INFO, val_to_str_const(addr, mdb_addr, "Unknown"));
1331
1332 mdb_conv_info_t* conv_info = get_mdb_conv_info(pinfo);
1333
1334 data_len = per_mst_len - 1;
1335 int start_offset = offset;
1336
1337 /*
1338 * Peripheral-to-Master messages can be simple control replies (ACK, NAK, RET)
1339 * that do not include a checksum.
1340 */
1341 bool_Bool checksum_needed = true1;
1342 if (data_len == 1 && is_mdb_reply(tvb_get_uint8(tvb, offset))) {
1343 checksum_needed = false0;
1344 }
1345
1346
1347 switch (addr) {
1348 case ADDR_CASHLESS10x10:
1349 dissect_mdb_per_mst_cl(tvb, offset, data_len, pinfo, tree, conv_info);
1350 break;
1351 case ADDR_COMMS_GW0x18:
1352 dissect_mdb_per_mst_cgw(tvb, offset, data_len, pinfo, tree, conv_info);
1353 break;
1354 case ADDR_BILL_VALIDATOR0x30:
1355 dissect_mdb_per_mst_bv(tvb, offset, data_len, pinfo, tree, conv_info);
1356 break;
1357 default:
1358 proto_tree_add_item(tree, hf_mdb_data, tvb, offset, data_len, ENC_NA0x00000000);
1359 break;
1360 }
1361 offset += data_len;
1362
1363 if (checksum_needed) {
1364 mdb_add_checksum(tvb, pinfo, tree, start_offset, data_len + 1);
1365 }
1366}
1367
1368static int dissect_mdb(tvbuff_t *tvb,
1369 packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
1370{
1371 int offset = 0, offset_ver, offset_evt;
1372 uint8_t version, event, addr;
1373 proto_tree *mdb_tree, *hdr_tree;
1374 proto_item *tree_ti, *hdr_ti;
1375
1376 /* We need at least the shortest possible pseudo header. */
1377 if (tvb_captured_length(tvb) < 3)
1378 return 0;
1379
1380 offset_ver = offset;
1381 version = tvb_get_uint8(tvb, offset++);
1382 if (version != 0)
1383 return 0;
1384
1385 offset_evt = offset;
1386 event = tvb_get_uint8(tvb, offset++);
1387 if (!try_val_to_str(event, mdb_event))
1388 return 0;
1389
1390 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDB");
1391 col_clear(pinfo->cinfo, COL_INFO);
1392
1393 tree_ti = proto_tree_add_item(tree, proto_mdb, tvb, 0, -1, ENC_NA0x00000000);
1394 mdb_tree = proto_item_add_subtree(tree_ti, ett_mdb);
1395
1396 hdr_tree = proto_tree_add_subtree(mdb_tree, tvb, 0, -1, ett_mdb_hdr,
1397 &hdr_ti, "Pseudo header");
1398
1399 proto_tree_add_item(hdr_tree, hf_mdb_hdr_ver,
1400 tvb, offset_ver, 1, ENC_BIG_ENDIAN0x00000000);
1401 proto_tree_add_item(hdr_tree, hf_mdb_event,
1402 tvb, offset_evt, 1, ENC_BIG_ENDIAN0x00000000);
1403
1404 /* Packets from peripheral to master always have an address byte in their
1405 pseudo header. */
1406 if (event == MDB_EVT_DATA_PER_MST0xFE) {
1407 /* See the comment in dissect_mdb_mst_per about MDB addresses. */
1408 addr = tvb_get_uint8(tvb, offset) & ADDR_MASK0xF8;
1409 proto_tree_add_uint_bits_format_value(hdr_tree, hf_mdb_addr,
1410 tvb, 8*offset, 5, addr, ENC_BIG_ENDIAN0x00000000, "0x%02x", addr);
1411 offset++;
1412 mdb_set_addrs(event, addr, pinfo);
1413 }
1414
1415 /* We're now at the end of the pseudo header. */
1416 proto_item_set_len(hdr_ti, offset);
1417
1418 if (event == MDB_EVT_BUS_RESET0xFD)
1419 return offset;
1420
1421 if (event == MDB_EVT_DATA_MST_PER0xFF)
1422 dissect_mdb_mst_per(tvb, offset, pinfo, mdb_tree);
1423 else if (event == MDB_EVT_DATA_PER_MST0xFE)
1424 dissect_mdb_per_mst(tvb, offset, pinfo, mdb_tree, addr);
1425
1426 return tvb_reported_length(tvb);
1427}
1428
1429void proto_register_mdb(void)
1430{
1431 expert_module_t* expert_mdb;
1432
1433 static int *ett[] = {
1434 &ett_mdb,
1435 &ett_mdb_hdr,
1436 &ett_mdb_cl,
1437 &ett_mdb_cgw,
1438 &ett_mdb_bv
1439 };
1440
1441 static hf_register_info hf[] = {
1442 { &hf_mdb_hdr_ver,
1443 { "Version", "mdb.hdr_ver",
1444 FT_UINT8, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1445 },
1446 { &hf_mdb_event,
1447 { "Event", "mdb.event",
1448 FT_UINT8, BASE_HEX, VALS(mdb_event)((0 ? (const struct _value_string*)0 : ((mdb_event)))), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1449 },
1450 { &hf_mdb_addr,
1451 { "Address", "mdb.addr",
1452 FT_UINT8, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1453 },
1454 { &hf_mdb_cmd,
1455 { "Command", "mdb.cmd",
1456 FT_UINT8, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1457 },
1458 { &hf_mdb_cl_setup_sub,
1459 { "Sub-command", "mdb.cashless.setup_sub_cmd",
1460 FT_UINT8, BASE_HEX, VALS(mdb_cl_setup_sub_cmd)((0 ? (const struct _value_string*)0 : ((mdb_cl_setup_sub_cmd
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1461 },
1462 { &hf_mdb_cl_feat_lvl,
1463 { "Feature level", "mdb.cashless.feature_level",
1464 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1465 },
1466 { &hf_mdb_cl_cols,
1467 { "Columns on display", "mdb.cashless.columns",
1468 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1469 },
1470 { &hf_mdb_cl_rows,
1471 { "Rows on display", "mdb.cashless.rows",
1472 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1473 },
1474 { &hf_mdb_cl_disp_info,
1475 { "Display information", "mdb.cashless.disp_info",
1476 FT_UINT8, BASE_HEX, NULL((void*)0), 0x07, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1477 },
1478 { &hf_mdb_cl_max_price,
1479 { "Maximum price", "mdb.cashless.max_price",
1480 FT_UINT32, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1481 },
1482 { &hf_mdb_cl_min_price,
1483 { "Minimum price", "mdb.cashless.min_price",
1484 FT_UINT32, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1485 },
1486 { &hf_mdb_cl_vend_sub,
1487 { "Sub-command", "mdb.cashless.vend_sub_cmd",
1488 FT_UINT8, BASE_HEX, VALS(mdb_cl_vend_sub_cmd)((0 ? (const struct _value_string*)0 : ((mdb_cl_vend_sub_cmd)
)))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1489 },
1490 { &hf_mdb_cl_item_price,
1491 { "Item Price", "mdb.cashless.item_price",
1492 FT_UINT32, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1493 },
1494 { &hf_mdb_cl_item_num,
1495 { "Item Number", "mdb.cashless.item_number",
1496 FT_UINT32, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1497 },
1498 { &hf_mdb_cl_reader_sub,
1499 { "Sub-command", "mdb.cashless.reader_sub_cmd",
1500 FT_UINT8, BASE_HEX, VALS(mdb_cl_reader_sub_cmd)((0 ? (const struct _value_string*)0 : ((mdb_cl_reader_sub_cmd
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1501 },
1502 { &hf_mdb_cl_resp,
1503 { "Response", "mdb.cashless.resp",
1504 FT_UINT8, BASE_HEX, VALS(mdb_cl_resp)((0 ? (const struct _value_string*)0 : ((mdb_cl_resp)))), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1505 },
1506 { &hf_mdb_cl_scale,
1507 { "Scale factor", "mdb.cashless.scale_factor",
1508 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1509 },
1510 { &hf_mdb_cl_dec_pl,
1511 { "Decimal places", "mdb.cashless.decimal_places",
1512 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1513 },
1514 { &hf_mdb_cl_max_rsp_time,
1515 { "Application maximum response time", "mdb.cashless.max_rsp_time",
1516 FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1517 },
1518 { &hf_mdb_cl_vend_amt,
1519 { "Vend Amount", "mdb.cashless.vend_amount",
1520 FT_UINT32, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1521 },
1522 { &hf_mdb_cl_expns_sub,
1523 { "Sub-command", "mdb.cashless.expansion_sub_cmd",
1524 FT_UINT8, BASE_HEX, VALS(mdb_cl_expns_sub_cmd)((0 ? (const struct _value_string*)0 : ((mdb_cl_expns_sub_cmd
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1525 },
1526 { &hf_mdb_cl_manuf_code,
1527 { "Manufacturer Code", "mdb.cashless.manuf_code",
1528 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1529 },
1530 { &hf_mdb_cl_ser_num,
1531 { "Serial Number", "mdb.cashless.serial_number",
1532 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1533 },
1534 { &hf_mdb_cl_mod_num,
1535 { "Model Number", "mdb.cashless.model_number",
1536 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1537 },
1538 { &hf_mdb_cl_opt_feat,
1539 { "Optional Feature Bits", "mdb.cashless.opt_feature_bits",
1540 FT_UINT32, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1541 },
1542 { &hf_mdb_cgw_feat_lvl,
1543 { "Feature level", "mdb.comms_gw.feature_level",
1544 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1545 },
1546 { &hf_mdb_cgw_scale,
1547 { "Scale factor", "mdb.comms_gw.scale_factor",
1548 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1549 },
1550 { &hf_mdb_cgw_dec_pl,
1551 { "Decimal places", "mdb.comms_gw.decimal_places",
1552 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1553 },
1554 { &hf_mdb_cgw_resp,
1555 { "Response", "mdb.comms_gw.resp",
1556 FT_UINT8, BASE_HEX, VALS(mdb_cgw_resp)((0 ? (const struct _value_string*)0 : ((mdb_cgw_resp)))), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1557 },
1558 { &hf_mdb_cgw_max_rsp_time,
1559 { "Application maximum response time", "mdb.comms_gw.max_rsp_time",
1560 FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1561 },
1562 { &hf_mdb_cgw_report_sub,
1563 { "Sub-command", "mdb.comms_gw.report_sub_cmd", FT_UINT8,
1564 BASE_HEX, VALS(mdb_cgw_report_sub_cmd)((0 ? (const struct _value_string*)0 : ((mdb_cgw_report_sub_cmd
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1565 },
1566 { &hf_mdb_cgw_dts_evt_code,
1567 { "DTS Event Code", "mdb.comms_gw.dts_event_code",
1568 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1569 },
1570 { &hf_mdb_cgw_duration,
1571 { "Duration", "mdb.comms_gw.duration",
1572 FT_UINT32, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1573 },
1574 { &hf_mdb_cgw_activity,
1575 { "Activity", "mdb.comms_gw.activity",
1576 FT_BOOLEAN, 8, TFS(&tfs_active_inactive)((0 ? (const struct true_false_string*)0 : ((&tfs_active_inactive
))))
, 0x1, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1577 },
1578 { &hf_mdb_cgw_expns_sub,
1579 { "Sub-command", "mdb.comms_gw.expansion_sub_cmd", FT_UINT8,
1580 BASE_HEX, VALS(mdb_cgw_expns_sub_cmd)((0 ? (const struct _value_string*)0 : ((mdb_cgw_expns_sub_cmd
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1581 },
1582 { &hf_mdb_cgw_opt_feat,
1583 { "Optional Feature Bits", "mdb.comms_gw.opt_feature_bits",
1584 FT_UINT32, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1585 },
1586 { &hf_mdb_cgw_manuf_code,
1587 { "Manufacturer Code", "mdb.comms_gw.manuf_code",
1588 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1589 },
1590 { &hf_mdb_cgw_ser_num,
1591 { "Serial Number", "mdb.comms_gw.serial_number",
1592 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1593 },
1594 { &hf_mdb_cgw_mod_num,
1595 { "Model Number", "mdb.comms_gw.model_number",
1596 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1597 },
1598 { &hf_mdb_bv_setup_bill_val_feature,
1599 { "Bill Validator Feature Level", "mdb.bv.setup.feature_level",
1600 FT_UINT8, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1601 },
1602 { &hf_mdb_bv_setup_ctry_currency_code,
1603 { "Country/Currency Code", "mdb.bv.setup.ctry_currency",
1604 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1605 },
1606 { &hf_mdb_bv_setup_bill_scal_fac,
1607 { "Bill scaling factor", "mdb.bv.setup.bill_scale_factor",
1608 FT_UINT16, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1609 },
1610 { &hf_mdb_bv_setup_dec_places,
1611 { "Decimal Places", "mdb.bv.setup.dec_places",
1612 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1613 },
1614 { &hf_mdb_bv_setup_bill_stacker_cap,
1615 { "Stacker Capacity", "mdb.bv.setup.stacker_cap",
1616 FT_UINT16, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1617 },
1618 { &hf_mdb_bv_setup_bill_sec_lvls,
1619 { "Security Levels", "mdb.bv.setup.sec_levels",
1620 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1621 },
1622 { &hf_mdb_bv_setup_escrow,
1623 { "Escrow capability", "mdb.bv.setup.escrow",
1624 FT_UINT8, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1625 },
1626 { &hf_mdb_bv_setup_bill_type_cred,
1627 { "Bill Type Credit", "mdb.bv.setup.bill_type_credit",
1628 FT_STRING, BASE_NONE, NULL((void*)0), 0, "Bill values per channel", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1629 },
1630 { &hf_mdb_bv_bill_enable,
1631 { "Bill Enable State", "mdb.bv.bill_type.enable",
1632 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1633 },
1634 { &hf_mdb_bv_bill_escrow_enable,
1635 { "Bill Escrow Enable State", "mdb.bv.bill_type.escrow_enable",
1636 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1637 },
1638 { &hf_mdb_bv_poll_bill_routing_state,
1639 { "Escrow", "mdb.bv.poll.routing_state",
1640 FT_UINT8, BASE_HEX, VALS(mdb_bv_poll_bill_routing_state)((0 ? (const struct _value_string*)0 : ((mdb_bv_poll_bill_routing_state
))))
, 0x70, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1641 },
1642 { &hf_mdb_bv_poll_bill_type,
1643 { "Bill Type", "mdb.bv.poll.bill_type",
1644 FT_UINT8, BASE_HEX, NULL((void*)0), 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1645 },
1646 { &hf_mdb_bv_poll_state,
1647 { "Bill Accept State", "mdb.bv.poll.state",
1648 FT_UINT8, BASE_HEX, VALS(mdb_bv_poll_state)((0 ? (const struct _value_string*)0 : ((mdb_bv_poll_state)))
)
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1649 },
1650 { &hf_mdb_bv_escrow_state,
1651 { "Escrow", "mdb.bv.escrow.state",
1652 FT_BOOLEAN, 8, TFS(&mdb_bv_escrow_state)((0 ? (const struct true_false_string*)0 : ((&mdb_bv_escrow_state
))))
, 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1653 },
1654 { &hf_mdb_bv_stacker,
1655 { "Stacker Full", "mdb.bv.stacker.full_state",
1656 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1657 },
1658 { &hf_mdb_bv_exp_cmd,
1659 { "Expansion Command", "mdb.bv.exp.cmd", FT_UINT8,
1660 BASE_HEX, VALS(mdb_bv_exp_cmd)((0 ? (const struct _value_string*)0 : ((mdb_bv_exp_cmd)))), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1661 },
1662 // EXPANSION cmd: Level 1/2 Identification with/Without Option bits
1663 { &hf_mdb_bv_exp_opt_feat,
1664 { "Bill Type Routing", "mdb.bv.exp.bill_type_routing",
1665 FT_UINT32, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1666 },
1667 { &hf_mdb_bv_exp_manufact_code,
1668 { "Manufacturer Code", "mdb.bv.expns.manufact_code",
1669 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1670 },
1671 { &hf_mdb_bv_exp_serial_num,
1672 { "Serial Number", "mdb.bv.expns.serial_num",
1673 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1674 },
1675 { &hf_mdb_bv_exp_model_tuning_num,
1676 { "Model/Tuning number", "mdb.bv.expns.model_tuning_num",
1677 FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1678 },
1679 { &hf_mdb_bv_exp_software_version,
1680 { "Software version", "mdb.bv.expns.software_version",
1681 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1682 },
1683 // EXPANSION cmd: Lvl2 Feature enable
1684 { &hf_mdb_bv_exp_opt_feat_enable,
1685 { "Level 2+ Feature enable", "mdb.bv.exp.opt_feat",
1686 FT_UINT32, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1687 },
1688 // EXPANSION cmd: Recycler Setup
1689 { &hf_mdb_bv_exp_bill_type_routing,
1690 { "Bill Type Routing", "mdb.bv.exp.bill_type_routing",
1691 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1692 },
1693 // EXPANSION cmd: Recycler Enable
1694 { &hf_mdb_bv_exp_manual_dispense_enable,
1695 { "Manual Dispense Enable", "mdb.bv.exp.manual_dispense_enable",
1696 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1697 },
1698 { &hf_mdb_bv_exp_bill_recycler_enabled,
1699 { "Bill Recycler Enabled", "mdb.bv.exp.bill_recycler_enabled",
1700 FT_UINT8, BASE_HEX, VALS(mdb_bv_exp_bills_recyc_enabled)((0 ? (const struct _value_string*)0 : ((mdb_bv_exp_bills_recyc_enabled
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1701 },
1702 // EXPANSION cmd: Bill Dispense Status
1703 { &hf_mdb_bv_exp_dispenser_full_state,
1704 { "Dispenser Full Status", "mdb.bv.exp.dispenser_full_state",
1705 FT_UINT16, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1706 },
1707 { &hf_mdb_bv_exp_bill_count,
1708 { "Bill count", "mdb.bv.exp.bill_count",
1709 FT_UINT8, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1710 },
1711 // EXPANSION cmd: Dispense Bill
1712 { &hf_mdb_bv_exp_bill_type_dispensed,
1713 { "Bill type to be dispensed", "mdb.bv.exp.bill_type_disp",
1714 FT_UINT8, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1715 },
1716 { &hf_mdb_bv_exp_bill_type_number_bills,
1717 { "Bills type number of bills", "mdb.bv.exp.bill_type_num_bills",
1718 FT_UINT16, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1719 },
1720 // EXPANSION cmd: Dispense Value
1721 { &hf_mdb_bv_exp_dispense_value_bills,
1722 { "Bill value to be paid out", "mdb.bv.exp.dispense_value_bills",
1723 FT_UINT16, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1724 },
1725 // EXPANSION cmd: Payout Status
1726 { &hf_mdb_bv_exp_payout_state,
1727 { "Number of bills paid out", "mdb.bv.exp.payout_state_num_bills",
1728 FT_UINT16, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1729 },
1730 // EXPANSION cmd: Payout Value Poll
1731 { &hf_mdb_bv_exp_dispenser_payout_activity,
1732 { "Dispenser Payout Activity", "mdb.bv.exp.payout_value_activity",
1733 FT_UINT16, BASE_DEC, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1734 },
1735 // EXPANSION cmd: Payout Cancel
1736 // No data
1737 // EXPANSION cmd: FTL REQ to RCV
1738 // EXPANSION cmd: FTL Send Block
1739 // EXPANSION cmd: FTL OK to Send
1740 // EXPANSION cmd: FTL REQ to Send
1741 // EXPANSION cmd: Diagnostics
1742 { &hf_mdb_ack,
1743 { "Ack byte", "mdb.ack",
1744 FT_UINT8, BASE_HEX, VALS(mdb_ack)((0 ? (const struct _value_string*)0 : ((mdb_ack)))), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1745 },
1746 { &hf_mdb_data,
1747 { "Data", "mdb.data",
1748 FT_BYTES, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1749 },
1750 { &hf_mdb_chk,
1751 { "Checksum", "mdb.chk",
1752 FT_UINT8, BASE_HEX, NULL((void*)0), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1753 },
1754 { &hf_mdb_chk_status,
1755 { "Checksum Status", "mdb.chk.status",
1756 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals)((0 ? (const struct _value_string*)0 : ((proto_checksum_vals)
)))
, 0x0,
1757 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1758 },
1759 { &hf_mdb_response_in,
1760 { "Response In", "mdb.response_in",
1761 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE)((gpointer) (glong) (FT_FRAMENUM_RESPONSE)), 0x0,
1762 "The response to this request is in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1763 },
1764 { &hf_mdb_response_to,
1765 { "Request In", "mdb.response_to",
1766 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0x0,
1767 "This is a response to the request in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1768 },
1769 { &hf_mdb_time,
1770 { "Time", "mdb.time",
1771 FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,
1772 "The time between the Call and the Reply", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1773 }
1774 };
1775
1776 static ei_register_info ei[] = {
1777 { &ei_mdb_short_packet,
1778 { "mdb.short_packet", PI_PROTOCOL0x09000000, PI_ERROR0x00800000,
1779 "MDB packet without payload", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
1780 { &ei_mdb_bad_checksum,
1781 { "mdb.bad_checksum", PI_CHECKSUM0x01000000, PI_ERROR0x00800000,
1782 "Bad checksum", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}}
1783 };
1784
1785 proto_mdb = proto_register_protocol("Multi-Drop Bus", "MDB", "mdb");
1786 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1787 proto_register_field_array(proto_mdb, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1788 expert_mdb = expert_register_protocol(proto_mdb);
1789 expert_register_field_array(expert_mdb, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1790 mdb_handle = register_dissector("mdb", dissect_mdb, proto_mdb);
1791}
1792
1793void proto_reg_handoff_mdb(void)
1794{
1795 dissector_add_uint("wtap_encap", WTAP_ENCAP_MDB223, mdb_handle);
1796}
1797
1798/*
1799 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1800 *
1801 * Local variables:
1802 * c-basic-offset: 4
1803 * tab-width: 8
1804 * indent-tabs-mode: nil
1805 * End:
1806 *
1807 * vi: set shiftwidth=4 tabstop=8 expandtab:
1808 * :indentSize=4:tabSize=8:noTabs=true:
1809 */