Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-idn.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-idn.c
2
 * Routines for IDN dissection
3
 * By Maxim Kropp <maxim.kropp@hotmail.de>
4
 * Copyright 2017 Maxim Kropp
5
 *
6
 * Supervised by Matthias Frank <matthew@cs.uni-bonn.de>
7
 * Copyright 2017 Matthias Frank, Institute of Computer Science 4, University of Bonn
8
 *
9
 * Stream Specification: https://www.ilda.com/resources/StandardsDocs/ILDA_IDN-Stream_rev001.pdf
10
 * This specification only defines IDN messages, the other packet commands
11
 * are part of the hello specification which is not released yet.
12
 * All ILDA Technical Standards can be found at https://www.ilda.com/technical.htm
13
 *
14
 * Wireshark - Network traffic analyzer
15
 * By Gerald Combs <gerald@wireshark.org>
16
 * Copyright 1998 Gerald Combs
17
 *
18
 * SPDX-License-Identifier: GPL-2.0-or-later
19
 */
20
21
#include <config.h>
22
#include <epan/packet.h>
23
#include <epan/conversation.h>
24
#include <epan/expert.h>
25
26
#include <wsutil/array.h>
27
28
14
#define IDN_PORT 7255
29
30
26
#define MAX_CHANNELS  512
31
#define MAX_BUFFER    2048
32
33
/* Packet Commands */
34
1.00k
#define IDNCMD_VOID             0x00
35
#define IDNCMD_PING_REQUEST         0x08
36
498
#define IDNCMD_PING_RESPONSE        0x09
37
#define IDNCMD_SCAN_REQUEST         0x10
38
1
#define IDNCMD_SCAN_RESPONSE        0x11
39
#define IDNCMD_SERVICEMAP_REQUEST     0x12
40
10
#define IDNCMD_SERVICEMAP_RESPONSE      0x13
41
22
#define IDNCMD_MESSAGE            0x40
42
76
#define IDNCMD_MESSAGE_ACKREQ       0x41
43
186
#define IDNCMD_MESSAGE_CLOSE        0x44
44
231
#define IDNCMD_MESSAGE_ACKREQ_CLOSE     0x45
45
1
#define IDNCMD_MESSAGE_ACK          0x47
46
47
/* Chunk Types */
48
631
#define IDNCT_VOID        0x00
49
4
#define IDNCT_LP_WAVE_SAMPLE  0x01
50
5
#define IDNCT_LP_FRAME_CHUNK  0x02
51
7
#define IDNCT_LP_FRAME_FF   0x03
52
568
#define IDNCT_LP_FRAME_SF   0xC0
53
691
#define IDNCT_OCTET_SEGMENT   0x10
54
98
#define IDNCT_OCTET_STRING    0x11
55
54
#define IDNCT_DIMMER_LEVELS   0x18
56
365
#define IDNCT_AUDIO_WAVE_SAMPLE   0x20
57
58
/* Service Modes (CONT = continuous stream, DISC = discrete stream) */
59
#define IDNSM_VOID        0x00
60
#define IDNSM_LP_GRAPHIC_CONT 0x01
61
#define IDNSM_LP_GRAPHIC_DISC 0x02
62
#define IDNSM_LP_EFFECTS_CONT 0x03
63
#define IDNSM_LP_EFFECTS_DISC 0x04
64
#define IDNSM_DMX512_CONT   0x05
65
#define IDNSM_DMX512_DISC   0x06
66
#define IDNSM_AUDIO_WAVE_SEGMENTS 0x0C
67
68
/* Dictionary Tags */
69
4.28k
#define IDNTAG_PRECISION      0x4010
70
3.96k
#define IDNTAG_WAVELENGTH_PREFIX  0x5C00
71
3.95k
#define IDNTAG_INTENSITY      0x5C10
72
3.95k
#define IDNTAG_BEAM_BRUSH     0x5C20
73
8.55k
#define IDNTAG_BREAK_START      0x1000
74
3.41k
#define IDNTAG_BREAK_END      0x100F
75
8.50k
#define IDNTAG_SPACE_MOD_START    0x1100
76
3.27k
#define IDNTAG_SPACE_MOD_END    0x11FF
77
4.14k
#define IDNTAG_NOP          0x4000
78
8.26k
#define IDNTAG_HINT0        0x4100
79
2.28k
#define IDNTAG_HINT1        0x4101
80
8.16k
#define IDNTAG_COLOR_START      0x5000
81
1.90k
#define IDNTAG_COLOR_END      0x53FF
82
#define IDNTAG_COLOR_RED      0x527E
83
#define IDNTAG_COLOR_GREEN      0x5214
84
#define IDNTAG_COLOR_BLUE     0x51CC
85
#define IDNTAG_OPTIONAL_U1      0x51BD
86
#define IDNTAG_OPTIONAL_U2      0x5241
87
#define IDNTAG_OPTIONAL_U3      0x51E8
88
44
#define IDNTAG_OPTIONAL_U4      0x4201
89
8.25k
#define IDNTAG_COORD_X        0x4200
90
2.16k
#define IDNTAG_COORD_X_END      0x420F
91
8.21k
#define IDNTAG_COORD_Y        0x4210
92
2.14k
#define IDNTAG_COORD_Y_END      0x421F
93
8.19k
#define IDNTAG_COORD_Z        0x4220
94
2.13k
#define IDNTAG_COORD_Z_END      0x422F
95
4.54k
#define IDNTAG_DIMMER_START     0x0040
96
1.71k
#define IDNTAG_DIMMER_END     0x004F
97
98
/* Other */
99
9.10k
#define IDNO_VOID_AREA  0xF
100
101
typedef struct {
102
  bool has_config_header;
103
  bool is_dmx;
104
  uint16_t total_size;
105
  uint8_t channel_id;
106
  uint8_t chunk_type;
107
  gboolean is_audio;
108
} message_info;
109
110
typedef struct {
111
  uint8_t word_count;
112
  uint8_t sdm;
113
  char *dic_precision;
114
  wmem_strbuf_t *sample_column_string;
115
  int sample_size;
116
  int *count;
117
  int *base;
118
  guint8 audio_format;
119
  guint8 audio_channels;
120
} configuration_info;
121
122
void proto_register_idn(void);
123
void proto_reg_handoff_idn(void);
124
125
static dissector_handle_t idn_handle;
126
127
static int proto_idn;
128
129
static int ett_idn;
130
static int ett_idn_header_tree;
131
static int ett_idn_scanreply_header_tree;
132
static int ett_idn_channel_message_header_tree;
133
static int ett_protocol_version;
134
static int ett_unit_id;
135
static int ett_status;
136
static int ett_idn_cnl;
137
static int ett_configuration_header;
138
static int ett_chunk_header_tree;
139
static int ett_chunk_header_flags;
140
static int ett_cfl;
141
static int ett_dic;
142
static int ett_dic_tree;
143
static int ett_data;
144
static int ett_subdata;
145
static int ett_dmx_subtree;
146
static int ett_audio_header;
147
static int ett_audio_samples;
148
149
static expert_field ei_idn_no_config;
150
static expert_field ei_idn_scwc_unknown;
151
static expert_field ei_idn_channels_over;
152
static expert_field ei_idn_scm_mismatch;
153
154
/* IDN-Header */
155
static int hf_idn_command;
156
static int hf_idn_flags;
157
static int hf_idn_sequence;
158
static int hf_idn_total_size;
159
160
/* Scanreply Header */
161
static int hf_idn_struct_size;
162
static int hf_idn_protocol_version;
163
static int hf_idn_protocol_version_major;
164
static int hf_idn_protocol_version_minor;
165
static int hf_idn_status;
166
static int hf_idn_malfn;
167
static int hf_idn_offline;
168
static int hf_idn_xcld;
169
static int hf_idn_ocpd;
170
static int hf_idn_rt;
171
static int hf_idn_reserved8;
172
static int hf_idn_unit_id;
173
static int hf_idn_uid_length;
174
static int hf_idn_uid_category;
175
static int hf_idn_uid;
176
static int hf_idn_name;
177
178
/* Service Map Response */
179
static int hf_idn_entry_size;
180
static int hf_idn_relay_count;
181
static int hf_idn_service_count;
182
static int hf_idn_relay_number;
183
184
/* Channel Message Header */
185
static int hf_idn_cnl;
186
static int hf_idn_most_significant_bit_cnl;
187
static int hf_idn_cclf;
188
static int hf_idn_channel_id;
189
static int hf_idn_chunk_type;
190
static int hf_idn_timestamp;
191
192
/* Configuration Header */
193
static int hf_idn_scwc;
194
static int hf_idn_cfl;
195
static int hf_idn_sdm;
196
static int hf_idn_close;
197
static int hf_idn_routing;
198
static int hf_idn_service_id;
199
static int hf_idn_service_mode;
200
201
/* Chunk Header */
202
static int hf_idn_chunk_header_flags;
203
static int hf_idn_two_bits_reserved_1;
204
static int hf_idn_two_bits_reserved_2;
205
static int hf_idn_three_bits_reserved;
206
static int hf_idn_four_bits_reserved;
207
static int hf_idn_scm;
208
static int hf_idn_once;
209
static int hf_idn_duration;
210
static int hf_idn_chunk_data_sequence;
211
static int hf_idn_offset;
212
static int hf_idn_dlim;
213
static int hf_idn_reserved;
214
215
/* Audio Dictionary Tags */
216
static int hf_idn_audio_dictionary_tag;
217
static int hf_idn_category;
218
static int hf_idn_format;
219
static int hf_idn_subcategory;
220
static int hf_idn_parameter;
221
static int hf_idn_suffix_length;
222
static int hf_idn_layout;
223
static int hf_idn_4bit_channels;
224
static int hf_idn_8bit_channels;
225
226
/* Audio Header */
227
static int hf_idn_audio_flags;
228
static int hf_idn_audio_duration;
229
static int hf_idn_audio_flags_two_bits_reserved;
230
static int hf_idn_audio_flags_four_bits_reserved;
231
static int hf_idn_audio_flags_scm;
232
233
/* Audio Samples */
234
static int hf_idn_audio_sample_format_zero;
235
static int hf_idn_audio_sample_format_one;
236
static int hf_idn_audio_sample_format_two;
237
/* Tags */
238
static int hf_idn_gts;
239
static int hf_idn_gts_void;
240
static int hf_idn_boundary;
241
static int hf_idn_gts_word;
242
static int hf_idn_gts_break;
243
static int hf_idn_gts_space_modifier;
244
static int hf_idn_gts_hint;
245
static int hf_idn_gts_category;
246
static int hf_idn_gts_subcategory;
247
static int hf_idn_gts_identifier;
248
static int hf_idn_gts_parameter;
249
static int hf_idn_gts_glin;
250
static int hf_idn_gts_clin;
251
static int hf_idn_gts_cbal;
252
static int hf_idn_gts_ctim;
253
static int hf_idn_gts_nop;
254
static int hf_idn_gts_precision;
255
static int hf_idn_gts_cscl;
256
static int hf_idn_gts_iscl;
257
static int hf_idn_gts_sht;
258
static int hf_idn_gts_u4;
259
static int hf_idn_gts_x;
260
static int hf_idn_gts_y;
261
static int hf_idn_gts_z;
262
static int hf_idn_gts_color;
263
static int hf_idn_gts_wavelength_prefix;
264
static int hf_idn_gts_intensity;
265
static int hf_idn_gts_beam_brush;
266
static int hf_idn_gts_sample;
267
static int hf_idn_dmx_octet;
268
static int hf_idn_dmx_identifier;
269
static int hf_idn_dmx_parameter;
270
static int hf_idn_dmx_void;
271
static int hf_idn_octet;
272
static int hf_idn_dmx_base;
273
static int hf_idn_dmx_count;
274
static int hf_idn_dmx_dls;
275
static int hf_idn_dmx_unknown;
276
277
/* Acknowledgement */
278
static int hf_idn_result_code;
279
static int hf_idn_event_flags;
280
281
/* Long Bitmasks that need defining */
282
283
284
static const value_string command_code[] = {
285
  { IDNCMD_VOID, "VOID" },
286
  { IDNCMD_PING_REQUEST, "PING_REQUEST" },
287
  { IDNCMD_PING_RESPONSE, "PING_RESPONSE" },
288
  { IDNCMD_SCAN_REQUEST, "SCAN_REQUEST" },
289
  { IDNCMD_SCAN_RESPONSE, "SCAN_RESPONSE" },
290
  { IDNCMD_SERVICEMAP_REQUEST, "SERVICEMAP_REQUEST" },
291
  { IDNCMD_SERVICEMAP_RESPONSE, "SERVICEMAP_RESPONSE" },
292
  { IDNCMD_MESSAGE, "MESSAGE" },
293
  { IDNCMD_MESSAGE_ACKREQ, "MESSAGE_ACKREQ" },
294
  { IDNCMD_MESSAGE_CLOSE, "MESSAGE_CLOSE" },
295
  { IDNCMD_MESSAGE_ACKREQ_CLOSE, "MESSAGE_ACKREQ_CLOSE" },
296
  { IDNCMD_MESSAGE_ACK, "MESSAGE_ACK" },
297
  { 0, NULL}
298
};
299
static const value_string chunk_type[] = {
300
  { IDNCT_VOID, "VOID" },
301
  { IDNCT_LP_WAVE_SAMPLE, "Laser Projector Wave Samples" },
302
  { IDNCT_LP_FRAME_CHUNK, "Laser Projector Frame Samples (entire chunk)" },
303
  { IDNCT_LP_FRAME_FF, "Laser Projector Frame Samples (first fragment)" },
304
  { IDNCT_OCTET_SEGMENT, "Octet Segment" },
305
  { IDNCT_OCTET_STRING, "Octet String" },
306
  { IDNCT_DIMMER_LEVELS, "Dimmer Levels" },
307
  { IDNCT_LP_FRAME_SF, "Laser Projector Frame Samples (sequel fragment)" },
308
  { IDNCT_AUDIO_WAVE_SAMPLE, "Audio Wave Samples"},
309
  { 0, NULL}
310
};
311
static const value_string chunk_type_header[] = {
312
  { IDNCT_LP_WAVE_SAMPLE, "Wave Sample" },
313
  { IDNCT_LP_FRAME_CHUNK, "Frame Sample" },
314
  { IDNCT_LP_FRAME_FF, "Frame Sample" },
315
  { IDNCT_OCTET_SEGMENT, "Octet Segment" },
316
  { IDNCT_OCTET_STRING, "Octet String" },
317
  { IDNCT_DIMMER_LEVELS, "Dimmer Levels" },
318
  { 0, NULL}
319
};
320
static const value_string cfl_string[] = {
321
  { 0x30, "DATA_MATCH" },
322
  { 0x01, "ROUTING" },
323
  { 0x02, "CLOSE" },
324
  { 0, NULL}
325
};
326
static const value_string service_mode_string[] = {
327
  { IDNSM_VOID, "VOID" },
328
  { IDNSM_LP_GRAPHIC_CONT, "Laser Projector Graphic (Continuous)" },
329
  { IDNSM_LP_GRAPHIC_DISC, "Laser Projector Graphic (Discrete)" },
330
  { IDNSM_LP_EFFECTS_CONT, "Laser Projector Effects (Continuous)" },
331
  { IDNSM_LP_EFFECTS_DISC, "Laser Projector Effects (Discrete)" },
332
  { IDNSM_DMX512_CONT, "DMX512 (Continuous)" },
333
  { IDNSM_DMX512_DISC, "DMX512 (Discrete)" },
334
  { IDNSM_AUDIO_WAVE_SEGMENTS, "Audio: Stream of waveform segments"},
335
  { 0, NULL}
336
};
337
static const value_string gts_glin[] = {
338
  { 0, "Projector specific" },
339
  { 1, "Geometrically corrected and linear, aspect ratio 1:1" },
340
  { 2, "Reserved" },
341
  { 3, "No transformation" },
342
  { 0, NULL}
343
};
344
static const value_string gts_clin[] = {
345
  { 0, "Projector specific" },
346
  { 1, "Power linear (half value SHALL be half power)" },
347
  { 2, "Visually linear (half value SHALL be half brightness)" },
348
  { 3, "No transformation" },
349
  { 0, NULL}
350
};
351
static const value_string gts_cbal[] = {
352
  { 0, "Projector specific" },
353
  { 1, "White balanced" },
354
  { 2, "Reserved" },
355
  { 3, "No transformation" },
356
  { 0, NULL}
357
};
358
static const value_string gts_ctim[] = {
359
  { 0, "Projector specific" },
360
  { 1, "Coordinates and colors correlated in time" },
361
  { 2, "Reserved" },
362
  { 3, "No transformation" },
363
  { 0, NULL}
364
};
365
static const value_string idn_color[] = {
366
  { 638, "Red" },
367
  { 532, "Green" },
368
  { 460, "Blue" },
369
  { 445, "Optional(U1), used as deep blue" },
370
  { 577, "Optional(U2), used as yellow" },
371
  { 488, "Optional(U3), used as cyan" },
372
  { 0, NULL}
373
};
374
static const value_string idn_cat_color[] = {
375
  { IDNTAG_OPTIONAL_U1, "U1" },
376
  { IDNTAG_COLOR_BLUE, "B" },
377
  { IDNTAG_OPTIONAL_U3, "U3" },
378
  { IDNTAG_COLOR_GREEN, "G" },
379
  { IDNTAG_OPTIONAL_U2, "U2" },
380
  { IDNTAG_COLOR_RED, "R" },
381
  { 0, NULL}
382
};
383
static const value_string result_code[] = {
384
  { 0x00, "Message successfully received and passed to the IDN session" },
385
  { 0xEB, "Empty (no message) close command without established connection" },
386
  { 0xEC, "All sessions are occupied by clients (new connection refused)" },
387
  { 0xED, "The client group is excluded from streaming" },
388
  { 0xEE, "Invalid payload" },
389
  { 0xEF, "Any other processing error" },
390
  { 0, NULL}
391
};
392
393
static const value_string category[] _U_= {
394
  { 0x0, "Decoder modifiers with suffix" },
395
  { 0x1, "Decoder modifiers with parameter" },
396
  { 0x4, "Sample word descriptors" },
397
  { 0x6, "Common channel layout descriptors" },
398
  { 0x8, "Multichannel layout descriptors" },
399
  { 0, NULL }
400
};
401
402
static const value_string format[] _U_={
403
  { 0x0, "8 Bit signed integer (one octet)" },
404
  { 0x1, "16 Bit signed integer (two octets)" },
405
  { 0x2, "24 Bit signed integer (three octets)" },
406
  { 0, NULL }
407
};
408
409
225
static int get_service_match(uint8_t flags) {
410
225
  return flags >> 4;
411
225
}
412
413
230
static void determine_message_type(packet_info *pinfo, message_info *minfo) {
414
230
  minfo->is_dmx = 0;
415
230
  minfo->is_audio = 0;
416
230
  switch(minfo->chunk_type) {
417
19
    case IDNCT_VOID:
418
19
      col_append_str(pinfo->cinfo, COL_INFO, "-VOID");
419
19
      break;
420
3
    case IDNCT_LP_WAVE_SAMPLE:
421
3
      col_append_str(pinfo->cinfo, COL_INFO, "-WAVE");
422
3
      break;
423
2
    case IDNCT_LP_FRAME_CHUNK:
424
2
      col_append_str(pinfo->cinfo, COL_INFO, "-FRAME");
425
2
      break;
426
2
    case IDNCT_LP_FRAME_FF:
427
2
      col_append_str(pinfo->cinfo, COL_INFO, "-FIRST");
428
2
      break;
429
10
    case IDNCT_DIMMER_LEVELS:
430
10
      col_append_str(pinfo->cinfo, COL_INFO, "-DMX");
431
10
      minfo->is_dmx = 1;
432
10
      break;
433
44
    case IDNCT_OCTET_STRING:
434
44
      col_append_str(pinfo->cinfo, COL_INFO, "-DMX");
435
44
      minfo->is_dmx = 1;
436
44
      break;
437
10
    case IDNCT_OCTET_SEGMENT:
438
10
      col_append_str(pinfo->cinfo, COL_INFO, "-DMX");
439
10
      minfo->is_dmx = 1;
440
10
      break;
441
1
    case IDNCT_LP_FRAME_SF:
442
1
      if(minfo->has_config_header) {
443
0
        col_append_str(pinfo->cinfo, COL_INFO, "-LAST");
444
1
      }else {
445
1
        col_append_str(pinfo->cinfo, COL_INFO, "-SEQ");
446
1
      }
447
1
      break;
448
40
    case IDNCT_AUDIO_WAVE_SAMPLE:
449
40
      col_append_str(pinfo->cinfo, COL_INFO, "-AUDIO");
450
40
      minfo->is_audio = 1;
451
40
      break;
452
99
    default:
453
99
      col_append_str(pinfo->cinfo, COL_INFO, "-UNKNOWN");
454
230
  }
455
230
}
456
457
1
static int dissect_idn_message_acknowledgement(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
458
1
  proto_tree *idn_message_acknowledgement_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_idn_header_tree, NULL, "Message Acknowledgement");
459
1
  proto_tree_add_item(idn_message_acknowledgement_tree, hf_idn_struct_size, tvb, offset, 1, ENC_BIG_ENDIAN);
460
1
  offset += 1;
461
1
  proto_tree_add_item(idn_message_acknowledgement_tree, hf_idn_result_code, tvb, offset, 1, ENC_BIG_ENDIAN);
462
1
  offset += 1;
463
1
  proto_tree_add_item(idn_message_acknowledgement_tree, hf_idn_event_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
464
1
  offset += 2;
465
1
  return offset;
466
1
}
467
468
4
static configuration_info *get_configuration_info(packet_info *pinfo, int channel_id) {
469
4
  configuration_info *config = NULL;
470
471
4
  conversation_element_t *conv_key = wmem_alloc_array(pinfo->pool, conversation_element_t, 6);
472
4
  conv_key[0].type = CE_ADDRESS;
473
4
  conv_key[0].addr_val = pinfo->src;
474
4
  conv_key[1].type = CE_PORT;
475
4
  conv_key[1].port_val = pinfo->srcport;
476
4
  conv_key[2].type = CE_ADDRESS;
477
4
  conv_key[2].addr_val = pinfo->dst;
478
4
  conv_key[3].type = CE_PORT;
479
4
  conv_key[3].port_val = pinfo->destport;
480
4
  conv_key[4].type = CE_UINT;
481
4
  conv_key[4].uint_val = channel_id;
482
4
  conv_key[5].type = CE_CONVERSATION_TYPE;
483
4
  conv_key[5].conversation_type_val = CONVERSATION_IDN;
484
485
4
  conversation_t *conv = find_conversation_full(pinfo->num, conv_key);
486
4
  if(conv) {
487
2
    wmem_tree_t *config_tree = (wmem_tree_t*)conversation_get_proto_data(conv, proto_idn);
488
2
    if (config_tree) {
489
2
      config = (configuration_info *)wmem_tree_lookup32_le(config_tree, pinfo->num);
490
2
    }
491
2
  }
492
493
4
  return config;
494
4
}
495
496
13
static int dissect_idn_dmx_sample_values(tvbuff_t *tvb, packet_info* pinfo, int offset, proto_tree *idn_dmx_subtree, uint16_t data_size, int base) {
497
13
  int i, j;
498
13
  short int rest;
499
13
  wmem_strbuf_t* values;
500
501
83
  for(i=0; i+16<=data_size; i+=16) {
502
70
    values = wmem_strbuf_new(pinfo->pool, "");
503
1.07k
    for(j=1; j<16; j++){
504
1.00k
      wmem_strbuf_append_printf(values, " %3d", tvb_get_uint8(tvb, offset+j));
505
1.00k
    }
506
70
    proto_tree_add_bytes_format(idn_dmx_subtree, hf_idn_gts_sample, tvb, offset, 16, NULL, "%3d: %s", base+i, wmem_strbuf_get_str(values));
507
70
    offset += 16;
508
70
  }
509
13
  rest = data_size - i;
510
13
  if(rest > 0) {
511
6
    values = wmem_strbuf_new(pinfo->pool, "");
512
42
    for(j=0; j<rest; j++){
513
36
      wmem_strbuf_append_printf(values, " %3d", tvb_get_uint8(tvb, offset+j));
514
36
    }
515
6
    proto_tree_add_bytes_format(idn_dmx_subtree, hf_idn_gts_sample, tvb, offset, rest, NULL, "%3d: %s", base+i, wmem_strbuf_get_str(values));
516
6
    offset += rest;
517
6
  }
518
13
  return offset;
519
13
}
520
521
1.21k
static void set_laser_sample_values_string(tvbuff_t *tvb, int offset, configuration_info *config, wmem_strbuf_t* values) {
522
1.21k
  int i;
523
1.21k
  if((config->dic_precision)[2] == 1)
524
0
    wmem_strbuf_append_printf(values, "%5d", tvb_get_uint16(tvb, offset, 2));
525
1.21k
  else
526
1.21k
    wmem_strbuf_append_printf(values, "%5d", tvb_get_uint8(tvb, offset));
527
528
3.95k
  for(i=1; i<config->sample_size; i++){
529
2.74k
    if((config->dic_precision)[i+1] == 1) {
530
      //do nothing
531
2.74k
    }else if((config->dic_precision)[i+2] == 1) {
532
28
      wmem_strbuf_append_printf(values, " %5d", tvb_get_uint16(tvb, offset+i, 2));
533
28
      i++;
534
2.71k
    }else {
535
2.71k
      wmem_strbuf_append_printf(values, " %5d", tvb_get_uint8(tvb, offset+i));
536
2.71k
    }
537
2.74k
  }
538
1.21k
}
539
540
10
static int dissect_idn_octet_segment(tvbuff_t *tvb, packet_info* pinfo, int offset, proto_tree *idn_tree) {
541
10
  int i, j;
542
10
  short int rest;
543
10
  wmem_strbuf_t* values;
544
10
  int data_size = tvb_reported_length_remaining(tvb, offset);
545
10
  proto_tree *idn_samples_tree = proto_tree_add_subtree(idn_tree, tvb, offset, data_size, ett_data, NULL, "Octets");
546
547
86
  for(i=0; i+16<=data_size; i+=16) {
548
76
    values = wmem_strbuf_new(pinfo->pool, "");
549
1.29k
    for(j=0; j<16; j++){
550
1.21k
      wmem_strbuf_append_printf(values, " %3d", tvb_get_int8(tvb, offset+j));
551
1.21k
    }
552
76
    proto_tree_add_bytes_format(idn_samples_tree, hf_idn_gts_sample, tvb, offset, 16, NULL, "%s", wmem_strbuf_get_str(values));
553
76
    offset += 16;
554
76
  }
555
10
  rest = data_size - i;
556
10
  if(rest > 0) {
557
9
    values = wmem_strbuf_new(pinfo->pool, "");
558
99
    for(j=0; j<rest; j++){
559
90
      wmem_strbuf_append_printf(values, " %3d", tvb_get_int8(tvb, offset+j));
560
90
    }
561
9
    proto_tree_add_bytes_format(idn_samples_tree, hf_idn_gts_sample, tvb, offset, rest, NULL, "%s", wmem_strbuf_get_str(values));
562
9
    offset += rest;
563
9
  }
564
10
  return offset;
565
10
}
566
567
27
static int dissect_idn_dmx_data(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *idn_tree, configuration_info *config) {
568
27
  int i;
569
27
  int *count = config->count;
570
27
  int *base = config->base;
571
27
  int base_value;
572
27
  int data_size = tvb_reported_length_remaining(tvb, offset);
573
27
  proto_tree *idn_samples_tree = proto_tree_add_subtree(idn_tree, tvb, offset, data_size, ett_data, NULL, "Channels");
574
27
  proto_tree *idn_dmx_subtree;
575
576
40
  for(i=0; i<config->word_count; i++) {
577
28
    base_value = base[i]-1;
578
28
    if(base_value == -1)
579
14
      break;
580
14
    if(count[i] != -1) {
581
3
      data_size = count[i];
582
3
      if(data_size + base_value > MAX_CHANNELS) {
583
1
        expert_add_info_format(pinfo, idn_samples_tree, &ei_idn_channels_over, "Over %5d Channels", MAX_CHANNELS);
584
1
        return offset;
585
1
      }
586
2
      idn_dmx_subtree = proto_tree_add_subtree_format(idn_samples_tree, tvb, offset, data_size, ett_dmx_subtree, NULL, "Range: %3d - %3d", base[i], base_value+data_size);
587
11
    }else {
588
11
      int base_size = MAX_CHANNELS - base_value;
589
11
      data_size = tvb_reported_length_remaining(tvb, offset);
590
11
      if(data_size > base_size) {
591
5
        data_size = base_size;
592
5
      }
593
11
      if(data_size + base_value > MAX_CHANNELS) {
594
0
        data_size = MAX_CHANNELS - base_value;
595
0
      }
596
11
      idn_dmx_subtree = proto_tree_add_subtree_format(idn_samples_tree, tvb, offset, data_size, ett_dmx_subtree, NULL, "Range: %3d - %3d", base[i], base_value+data_size);
597
11
    }
598
13
    offset = dissect_idn_dmx_sample_values(tvb, pinfo, offset, idn_dmx_subtree, data_size, base_value);
599
13
  }
600
26
  return offset;
601
27
}
602
603
35
static int dissect_idn_laser_data(tvbuff_t *tvb, packet_info* pinfo, int offset, proto_tree *idn_tree, configuration_info *config) {
604
35
  int i;
605
35
  int laser_data_size = tvb_reported_length_remaining(tvb, offset);
606
35
  wmem_strbuf_t* values;
607
608
35
  if (config->sample_size == 0) {
609
    /* TODO: log expert info error? */
610
1
    return 0;
611
1
  }
612
613
34
  int sample_size = laser_data_size/config->sample_size;
614
34
  proto_tree *idn_samples_tree = proto_tree_add_subtree_format(idn_tree, tvb, offset, laser_data_size, ett_data, NULL, "Samples %s", wmem_strbuf_get_str(config->sample_column_string));
615
34
  proto_tree *idn_samples_subtree = NULL;
616
617
1.24k
  for(i=1; i<=sample_size; i++) {
618
1.21k
    if((i-1)%10 == 0 && i+10 > sample_size) {
619
33
      idn_samples_subtree = proto_tree_add_subtree_format(idn_samples_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), ett_subdata, NULL, "Samples %3d - %3d", i, sample_size);
620
1.18k
    }else if((i-1)%10 == 0) {
621
107
      idn_samples_subtree = proto_tree_add_subtree_format(idn_samples_tree, tvb, offset, config->sample_size*10, ett_subdata, NULL, "Samples %3d - %3d", i, i+9);
622
107
    }
623
1.21k
    values = wmem_strbuf_new(pinfo->pool, "");
624
1.21k
    set_laser_sample_values_string(tvb, offset, config, values);
625
1.21k
    proto_tree_add_bytes_format(idn_samples_subtree, hf_idn_gts_sample, tvb, offset, config->sample_size, NULL,  "Sample %3d: %s", i, wmem_strbuf_get_str(values));
626
1.21k
    offset += config->sample_size;
627
1.21k
  }
628
34
  return offset;
629
35
}
630
631
1
static int dissect_idn_dimmer_levels_chunk_header(tvbuff_t *tvb, int offset, proto_tree* chunk_header_tree, proto_tree* flag_tree) {
632
633
1
  proto_tree_add_item(flag_tree, hf_idn_four_bits_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
634
1
  offset += 1;
635
1
  proto_tree_add_item(chunk_header_tree, hf_idn_reserved, tvb, offset, 3, ENC_NA);
636
1
  offset += 3;
637
1
  return offset;
638
1
}
639
640
12
static int dissect_idn_octet_string_chunk_header(tvbuff_t *tvb, int offset, proto_tree* chunk_header_tree, proto_tree* flag_tree) {
641
642
12
  proto_tree_add_item(flag_tree, hf_idn_four_bits_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
643
12
  offset += 1;
644
12
  proto_tree_add_item(chunk_header_tree, hf_idn_reserved, tvb, offset, 3, ENC_NA);
645
12
  offset += 3;
646
12
  return offset;
647
12
}
648
649
3
static int dissect_idn_octet_segment_chunk_header(tvbuff_t *tvb, int offset, proto_tree* chunk_header_tree, proto_tree* flag_tree) {
650
651
3
  proto_tree_add_item(flag_tree, hf_idn_three_bits_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
652
3
  proto_tree_add_item(flag_tree, hf_idn_dlim, tvb, offset, 1, ENC_BIG_ENDIAN);
653
3
  offset += 1;
654
3
  proto_tree_add_item(chunk_header_tree, hf_idn_chunk_data_sequence, tvb, offset, 1, ENC_BIG_ENDIAN);
655
3
  offset += 1;
656
3
  proto_tree_add_item(chunk_header_tree, hf_idn_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
657
3
  offset += 2;
658
3
  return offset;
659
3
}
660
661
2
static int dissect_idn_frame_chunk_header(tvbuff_t *tvb, int offset, proto_tree* chunk_header_tree, proto_tree* flag_tree) {
662
663
2
  proto_tree_add_item(flag_tree, hf_idn_three_bits_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
664
2
  proto_tree_add_item(flag_tree, hf_idn_once, tvb, offset, 1, ENC_BIG_ENDIAN);
665
2
  offset += 1;
666
2
  proto_tree_add_item(chunk_header_tree, hf_idn_duration, tvb, offset, 3, ENC_BIG_ENDIAN);
667
2
  offset += 3;
668
2
  return offset;
669
2
}
670
671
0
static int dissect_idn_wave_chunk_header(tvbuff_t *tvb, int offset, proto_tree* chunk_header_tree, proto_tree* flag_tree) {
672
673
0
  proto_tree_add_item(flag_tree, hf_idn_four_bits_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
674
0
  offset += 1;
675
0
  proto_tree_add_item(chunk_header_tree, hf_idn_duration, tvb, offset, 3, ENC_BIG_ENDIAN);
676
0
  offset += 3;
677
0
  return offset;
678
0
}
679
680
75
static int dissect_idn_chunk_header(tvbuff_t* tvb, packet_info* pinfo, int offset, proto_tree* idn_tree, message_info* minfo, configuration_info* config) {
681
682
75
  proto_tree *chunk_header_tree, *flag_tree;
683
75
  proto_item *flag_item, *scm_item;
684
75
  uint32_t scm;
685
686
75
  switch (minfo->chunk_type) {
687
1
    case IDNCT_LP_WAVE_SAMPLE:
688
2
    case IDNCT_LP_FRAME_CHUNK:
689
3
    case IDNCT_LP_FRAME_FF:
690
13
    case IDNCT_OCTET_SEGMENT:
691
42
    case IDNCT_OCTET_STRING:
692
43
    case IDNCT_DIMMER_LEVELS:
693
43
      chunk_header_tree = proto_tree_add_subtree_format(idn_tree, tvb, offset, 4, ett_chunk_header_tree, NULL, "%s Chunk Header", val_to_str_const(minfo->chunk_type, chunk_type_header, "Unknown"));
694
43
      flag_item = proto_tree_add_item(chunk_header_tree, hf_idn_chunk_header_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
695
43
      flag_tree = proto_item_add_subtree(flag_item, ett_chunk_header_flags);
696
43
      proto_tree_add_item(flag_tree, hf_idn_two_bits_reserved_1, tvb, offset, 1, ENC_BIG_ENDIAN);
697
43
      scm_item = proto_tree_add_item_ret_uint(flag_tree, hf_idn_scm, tvb, offset, 1, ENC_BIG_ENDIAN, &scm);
698
43
      if (config->sdm != scm) {
699
23
        expert_add_info(pinfo, scm_item, &ei_idn_scm_mismatch);
700
23
        return offset;
701
23
      }
702
703
20
      switch (minfo->chunk_type) {
704
0
      case IDNCT_LP_WAVE_SAMPLE:
705
0
        offset = dissect_idn_wave_chunk_header(tvb, offset, chunk_header_tree, flag_tree);
706
0
        break;
707
1
      case IDNCT_LP_FRAME_CHUNK:
708
2
      case IDNCT_LP_FRAME_FF:
709
2
        offset = dissect_idn_frame_chunk_header(tvb, offset, chunk_header_tree, flag_tree);
710
2
        break;
711
3
      case IDNCT_OCTET_SEGMENT:
712
3
        offset = dissect_idn_octet_segment_chunk_header(tvb, offset, chunk_header_tree, flag_tree);
713
3
        break;
714
12
      case IDNCT_OCTET_STRING:
715
12
        offset = dissect_idn_octet_string_chunk_header(tvb, offset, chunk_header_tree, flag_tree);
716
12
        break;
717
1
      case IDNCT_DIMMER_LEVELS:
718
1
        offset = dissect_idn_dimmer_levels_chunk_header(tvb, offset, chunk_header_tree, flag_tree);
719
1
        break;
720
20
      }
721
16
      break;
722
32
    default:
723
32
      return offset;
724
75
  }
725
16
  return offset;
726
75
}
727
728
2.46k
static int dissect_idn_dmx_gts(tvbuff_t *tvb, int offset, proto_tree *gts_tree, const int hf_hdr, int *dictionary_size) {
729
2.46k
  static int * const gts[] = {
730
2.46k
    &hf_idn_dmx_identifier,
731
2.46k
    &hf_idn_dmx_parameter,
732
2.46k
    NULL
733
2.46k
  };
734
2.46k
  proto_tree_add_bitmask(gts_tree, tvb, offset, hf_hdr, ett_dic, gts, ENC_BIG_ENDIAN);
735
2.46k
  offset++;
736
2.46k
  if(dictionary_size)
737
2.25k
    (*dictionary_size)++;
738
739
2.46k
  return offset;
740
2.46k
}
741
742
557
static int dissect_idn_dimmer_level_subset(tvbuff_t *tvb, int offset, proto_tree *gts_tree, configuration_info *config, int i, int *dictionary_size) {
743
557
  uint8_t dls = tvb_get_uint8(tvb, offset);
744
557
  offset = dissect_idn_dmx_gts(tvb, offset, gts_tree, hf_idn_dmx_dls, dictionary_size);
745
746
557
  if(dls & 2) {
747
113
    proto_tree_add_item(gts_tree, hf_idn_dmx_base, tvb, offset, 2, ENC_BIG_ENDIAN);
748
113
    config->base[i-1] = tvb_get_uint16(tvb, offset, 2);
749
113
    offset += 2;
750
113
    (*dictionary_size) += 2;
751
113
    if(dls & 1) {
752
55
      proto_tree_add_item(gts_tree, hf_idn_dmx_count, tvb, offset, 1, ENC_BIG_ENDIAN);
753
55
      config->count[i-1] = tvb_get_uint8(tvb, offset);
754
55
      offset++;
755
55
      (*dictionary_size)++;
756
58
    }else {
757
58
      config->count[i-1] = -1;
758
58
    }
759
113
  }
760
761
557
  return offset;
762
557
}
763
764
54
static int dissect_idn_dmx_dictionary(tvbuff_t *tvb, int offset, proto_tree *idn_tree, configuration_info *config) {
765
54
  int i, j, curr_size;
766
54
  bool words_found = 0;
767
54
  int dictionary_size = 0;
768
54
  uint8_t idepar; /* idetifier + parameter */
769
54
  proto_tree *gts_tree = proto_tree_add_subtree(idn_tree, tvb, offset, -1, ett_dic_tree, NULL, "Dictionary");
770
771
3.64k
  for(i=1; i<=config->word_count; i++) {
772
3.58k
    idepar = tvb_get_uint8(tvb, offset);
773
774
3.58k
    if(idepar <= IDNO_VOID_AREA) {
775
1.31k
      if(idepar == 0) {
776
1.10k
        proto_tree_add_item(gts_tree, hf_idn_dmx_void, tvb, offset, 1, ENC_BIG_ENDIAN);
777
1.10k
        offset += 1;
778
1.10k
        dictionary_size += 1;
779
1.10k
        if(!words_found)
780
1.10k
          i -= 1;
781
1.10k
      }else {
782
207
        offset = dissect_idn_dmx_gts(tvb, offset, gts_tree, hf_idn_dmx_unknown, NULL);
783
1.43k
        for(j=1; j<=idepar; j++) {
784
1.22k
          proto_tree_add_item(gts_tree, hf_idn_octet, tvb, offset, 1, ENC_BIG_ENDIAN);
785
1.22k
          offset += 1;
786
1.22k
          dictionary_size += 1;
787
1.22k
          if(words_found)
788
15
            i += 1;
789
1.22k
        }
790
207
        if(!words_found)
791
196
          i -= 1;
792
207
      }
793
2.27k
    }else if(idepar >= IDNTAG_DIMMER_START && idepar <= IDNTAG_DIMMER_END) {
794
557
      offset = dissect_idn_dimmer_level_subset(tvb, offset, gts_tree, config, i, &dictionary_size);
795
1.71k
    }else {
796
1.71k
      offset = dissect_idn_dmx_gts(tvb, offset, gts_tree, hf_idn_dmx_unknown, &dictionary_size);
797
1.71k
    }
798
799
3.58k
    if(i == config->word_count && !words_found) {
800
32
      curr_size = dictionary_size;
801
78
      while(curr_size%4 != 0 && i > 0) {
802
46
        i -= 1;
803
46
        curr_size += 1;
804
46
      }
805
32
      words_found = 1;
806
32
    }
807
3.58k
  }
808
54
  proto_item_set_len(gts_tree, dictionary_size);
809
810
54
  return offset;
811
54
}
812
813
5.79k
static int dissect_idn_laser_gts(tvbuff_t *tvb, int offset, proto_tree *gts_tree, const int hf_hdr, int *dictionary_size, configuration_info *config, bool is_sample) {
814
5.79k
  static int * const gts[] = {
815
5.79k
    &hf_idn_gts_category,
816
5.79k
    &hf_idn_gts_subcategory,
817
5.79k
    &hf_idn_gts_identifier,
818
5.79k
    &hf_idn_gts_parameter,
819
5.79k
    NULL
820
5.79k
  };
821
822
5.79k
  proto_tree_add_bitmask(gts_tree, tvb, offset, hf_hdr, ett_dic, gts, ENC_BIG_ENDIAN);
823
824
5.79k
  if(dictionary_size)
825
5.78k
    *dictionary_size += 2;
826
5.79k
  if(config && is_sample)
827
4.08k
    config->sample_size++;
828
829
5.79k
  return offset + 2;
830
5.79k
}
831
832
22
static int dissect_idn_x_area(tvbuff_t *tvb, int offset, proto_tree *gts_tree, uint16_t catsub, int *dictionary_size, configuration_info *config) {
833
834
22
  if(catsub == IDNTAG_OPTIONAL_U4) {
835
11
    offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_u4, dictionary_size, config, 1);
836
11
  }else {
837
11
    offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_x, dictionary_size, config, 1);
838
11
  }
839
840
22
  return offset;
841
22
}
842
843
118
static int dissect_idn_laser_dictionary(tvbuff_t *tvb, int offset, proto_tree *idn_tree, configuration_info *config) {
844
118
  int i, j;
845
118
  int dictionary_size = 0;
846
118
  uint16_t catsub; /* category + subcategory */
847
118
  proto_tree *gts_tree = proto_tree_add_subtree(idn_tree, tvb, offset, -1, ett_dic_tree, NULL, "Dictionary");
848
849
  /* Reset the sample column data */
850
118
  config->sample_column_string = wmem_strbuf_new_len(wmem_file_scope(), "", 0);
851
118
  wmem_strbuf_append(config->sample_column_string, "(");
852
5.63k
  for(i=1; i<=config->word_count*2; i++) {
853
5.51k
    catsub = tvb_get_uint16(tvb, offset, 2);
854
855
5.51k
    if(catsub <= IDNO_VOID_AREA) {
856
1.23k
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_void, &dictionary_size, config, 0);
857
1.23k
      if(catsub > 0) {
858
432
        for(j=0; j<catsub; j++) {
859
351
          offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_void, &dictionary_size, config, 0);
860
351
        }
861
81
      }
862
4.28k
    }else if(catsub == IDNTAG_PRECISION) {
863
7
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_precision, &dictionary_size, config, 1);
864
7
      (config->dic_precision)[i] = 1;
865
4.27k
    }else if(catsub >= IDNTAG_BREAK_START && catsub <= IDNTAG_BREAK_END) {
866
22
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_break, &dictionary_size, config, 0);
867
4.25k
    }else if(catsub >= IDNTAG_SPACE_MOD_START && catsub <= IDNTAG_SPACE_MOD_END) {
868
105
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_space_modifier, &dictionary_size, config, 0);
869
4.14k
    }else if(catsub == IDNTAG_NOP) {
870
15
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_nop, &dictionary_size, config, 1);
871
15
      wmem_strbuf_append(config->sample_column_string, " NOP");
872
4.13k
    }else if(catsub >= IDNTAG_HINT0 && catsub <= IDNTAG_HINT1) {
873
6
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_hint, &dictionary_size, config, 1);
874
6
      wmem_strbuf_append(config->sample_column_string, " H");
875
4.12k
    }else if(catsub >= IDNTAG_COORD_X && catsub <= IDNTAG_COORD_X_END) {
876
22
      offset = dissect_idn_x_area(tvb, offset, gts_tree, catsub, &dictionary_size, config);
877
22
      wmem_strbuf_append(config->sample_column_string, (catsub == IDNTAG_OPTIONAL_U4) ? " U4" : " X");
878
4.10k
    }else if(catsub >= IDNTAG_COORD_Y && catsub <= IDNTAG_COORD_Y_END) {
879
9
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_y, &dictionary_size, config, 1);
880
9
      wmem_strbuf_append(config->sample_column_string, " Y");
881
4.09k
    }else if(catsub >= IDNTAG_COORD_Z && catsub <= IDNTAG_COORD_Z_END) {
882
13
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_z, &dictionary_size, config, 1);
883
13
      wmem_strbuf_append(config->sample_column_string, " Z");
884
4.08k
    }else if(catsub >= IDNTAG_COLOR_START && catsub <= IDNTAG_COLOR_END) {
885
115
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_color, &dictionary_size, config, 1);
886
115
      wmem_strbuf_append_printf(config->sample_column_string, " %s", val_to_str_const(catsub, idn_cat_color, "C"));
887
3.96k
    }else if(catsub == IDNTAG_WAVELENGTH_PREFIX) {
888
14
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_wavelength_prefix, &dictionary_size, config, 1);
889
14
      wmem_strbuf_append(config->sample_column_string, " WP");
890
3.95k
    }else if(catsub == IDNTAG_INTENSITY) {
891
1
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_intensity, &dictionary_size, config, 1);
892
1
      wmem_strbuf_append(config->sample_column_string, " I");
893
3.95k
    }else if(catsub == IDNTAG_BEAM_BRUSH) {
894
12
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_beam_brush, &dictionary_size, config, 1);
895
12
      wmem_strbuf_append(config->sample_column_string, " BB");
896
3.94k
    }else {
897
3.94k
      offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts, &dictionary_size, config, 1);
898
3.94k
      wmem_strbuf_append(config->sample_column_string, " U/R");
899
3.94k
    }
900
5.51k
  }
901
118
  proto_item_set_len(gts_tree, dictionary_size);
902
118
  wmem_strbuf_append(config->sample_column_string, " )");
903
904
118
  return offset;
905
118
}
906
907
225
static int dissect_idn_channel_configuration_header(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *idn_tree, int channel_id, configuration_info **config_p) {
908
225
  conversation_t *conv;
909
225
  uint8_t word_count;
910
225
  uint8_t sdm;
911
225
  static int * const channel_and_service_configuration_flags[] = {
912
225
    &hf_idn_two_bits_reserved_1,
913
225
    &hf_idn_sdm,
914
225
    &hf_idn_two_bits_reserved_2,
915
225
    &hf_idn_close,
916
225
    &hf_idn_routing,
917
225
    NULL
918
225
  };
919
920
225
  col_append_str(pinfo->cinfo, COL_INFO, " (Configuration Header)");
921
225
  proto_tree *configuration_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_configuration_header, NULL, "Channel Configuration Header");
922
225
  proto_tree_add_item(configuration_header_tree, hf_idn_scwc, tvb, offset, 1, ENC_BIG_ENDIAN);
923
225
  word_count = tvb_get_uint8(tvb, offset);
924
225
  offset += 1;
925
225
  proto_tree_add_bitmask(configuration_header_tree, tvb, offset, hf_idn_cfl, ett_cfl, channel_and_service_configuration_flags, ENC_BIG_ENDIAN);
926
225
  sdm = get_service_match(tvb_get_uint8(tvb, offset));
927
225
  offset += 1;
928
225
  proto_tree_add_item(configuration_header_tree, hf_idn_service_id, tvb, offset, 1, ENC_BIG_ENDIAN);
929
225
  offset += 1;
930
225
  proto_tree_add_item(configuration_header_tree, hf_idn_service_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
931
225
  offset += 1;
932
933
934
225
  conversation_element_t *conv_key = wmem_alloc_array(pinfo->pool, conversation_element_t, 6);
935
225
  conv_key[0].type = CE_ADDRESS;
936
225
  conv_key[0].addr_val = pinfo->src;
937
225
  conv_key[1].type = CE_PORT;
938
225
  conv_key[1].port_val = pinfo->srcport;
939
225
  conv_key[2].type = CE_ADDRESS;
940
225
  conv_key[2].addr_val = pinfo->dst;
941
225
  conv_key[3].type = CE_PORT;
942
225
  conv_key[3].port_val = pinfo->destport;
943
225
  conv_key[4].type = CE_UINT;
944
225
  conv_key[4].uint_val = channel_id;
945
225
  conv_key[5].type = CE_CONVERSATION_TYPE;
946
225
  conv_key[5].conversation_type_val = CONVERSATION_IDN;
947
948
225
  configuration_info *config;
949
225
  conv = find_conversation_full(pinfo->num, conv_key);
950
225
  if (!(conv && conv->setup_frame == pinfo->num)) {
951
222
    conv = conversation_new_full(pinfo->num, conv_key);
952
222
  }
953
225
  wmem_tree_t *config_tree = (wmem_tree_t*)conversation_get_proto_data(conv, proto_idn);
954
225
  if (!config_tree) {
955
222
    config_tree = wmem_tree_new(wmem_file_scope());
956
222
    conversation_add_proto_data(conv, proto_idn, config_tree);
957
222
  }
958
  /* XXX: It wastes some memory to allocate a new configuration if it
959
   * hasn't changed since the last time it was sent, so we could use
960
   * lookup32_le and see if it's the same as the previous, but that
961
   * requires doing so after parsing the rest of the configuration.
962
   */
963
225
  config = (configuration_info *)wmem_tree_lookup32(config_tree, pinfo->num);
964
225
  if (config) {
965
    /* sample size increments as we parse the dictionary, so reset.
966
    * The other values shouldn't change, though we'll waste time
967
    * overwriting the array with the same values.
968
    */
969
0
    config->sample_size = 0;
970
225
  } else {
971
225
    config = wmem_new0(wmem_file_scope(), configuration_info);
972
225
    config->word_count = word_count;
973
225
    config->sdm = sdm;
974
225
    config->sample_size = 0;
975
225
    config->dic_precision = wmem_alloc0_array(wmem_file_scope(), char, (255*2)+1);
976
225
    config->sample_column_string = wmem_strbuf_new(wmem_file_scope(), "");
977
225
    config->count = wmem_alloc0_array(wmem_file_scope(), int, word_count+1);
978
225
    config->base = wmem_alloc0_array(wmem_file_scope(), int, word_count+1);
979
225
    wmem_tree_insert32(config_tree, pinfo->num, config);
980
225
  }
981
982
225
  *config_p = config;
983
984
225
  return offset;
985
225
}
986
987
225
static int dissect_idn_channel_configuration(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *idn_tree, message_info *minfo, configuration_info **config_p) {
988
225
  offset = dissect_idn_channel_configuration_header(tvb, pinfo, offset, idn_tree, minfo->channel_id, config_p);
989
990
225
  configuration_info *config = *config_p;
991
225
  if(config->word_count > 0) {
992
219
    if(minfo->chunk_type == IDNCT_OCTET_SEGMENT || minfo->chunk_type == IDNCT_AUDIO_WAVE_SAMPLE) {
993
47
      return offset;
994
172
    }else if(minfo->is_dmx) {
995
54
      offset = dissect_idn_dmx_dictionary(tvb, offset, idn_tree, config);
996
118
    }else {
997
118
      offset = dissect_idn_laser_dictionary(tvb, offset, idn_tree, config);
998
118
    }
999
219
  }
1000
1001
178
  return offset;
1002
225
}
1003
1004
231
static int dissect_idn_message_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree, message_info *minfo) {
1005
231
  uint8_t cnl;
1006
231
  static int * const cnl_data[] = {
1007
231
      &hf_idn_most_significant_bit_cnl,
1008
231
      &hf_idn_cclf,
1009
231
      &hf_idn_channel_id,
1010
231
      NULL
1011
231
  };
1012
1013
231
  proto_tree *idn_channel_message_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 8, ett_idn_channel_message_header_tree, NULL, "Channel Message Header");
1014
231
  proto_tree_add_item(idn_channel_message_header_tree, hf_idn_total_size, tvb, offset, 2, ENC_BIG_ENDIAN);
1015
231
  minfo->total_size = tvb_get_uint16(tvb, offset, 2);
1016
231
  offset += 2;
1017
231
  proto_tree_add_bitmask(idn_channel_message_header_tree, tvb, offset, hf_idn_cnl, ett_idn_cnl, cnl_data, ENC_BIG_ENDIAN);
1018
1019
231
  cnl = tvb_get_uint8(tvb, offset);
1020
231
  minfo->has_config_header = cnl & 0x40;
1021
231
  minfo->channel_id = cnl & 0x3f;
1022
1023
231
  offset += 1;
1024
231
  proto_tree_add_item(idn_channel_message_header_tree, hf_idn_chunk_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1025
231
  minfo->chunk_type = tvb_get_uint8(tvb, offset);
1026
231
  offset += 1;
1027
231
  proto_tree_add_item(idn_channel_message_header_tree, hf_idn_timestamp, tvb, offset, 4, ENC_BIG_ENDIAN);
1028
231
  offset += 4;
1029
1030
231
  return offset;
1031
231
}
1032
1033
// static int dissect_idn_audio_category_0(tvbuff_t *tvb _U_, packet_info *pinfo _U_, int offset _U_, proto_tree *idn_tree _U_){
1034
//  static int * const audio_cat_0[] = {
1035
//    &hf_idn_category,
1036
//    &hf_idn_subcategory,
1037
//    &hf_idn_parameter,
1038
//    &hf_idn_suffix_length,
1039
//    NULL
1040
//  };
1041
//  proto_tree_add_bitmask(idn_tree, tvb, offset, hf_idn_audio_dictionary_tag, ett_audio_header, audio_cat_0, ENC_BIG_ENDIAN);
1042
//  return offset;
1043
// }
1044
1045
0
static int dissect_idn_audio_category_8(tvbuff_t *tvb, int offset, proto_tree *idn_tree, configuration_info *cinfo){
1046
1047
0
  static int * const audio_cat_8[] = {
1048
0
    &hf_idn_category,
1049
0
    &hf_idn_format,
1050
0
    &hf_idn_8bit_channels,
1051
0
    NULL
1052
0
  };
1053
0
  guint8 channels = tvb_get_int8(tvb, offset);
1054
0
  cinfo->audio_format = channels & 0x0F;
1055
0
  channels &= 0x00FF;
1056
0
  cinfo->audio_channels = channels;
1057
1058
0
  proto_tree_add_bitmask(idn_tree, tvb, offset, hf_idn_audio_dictionary_tag, ett_audio_header, audio_cat_8, ENC_BIG_ENDIAN);
1059
1060
0
  return offset;
1061
0
}
1062
1063
454
static int dissect_idn_audio_category_6(tvbuff_t *tvb, int offset, proto_tree *idn_tree, configuration_info *cinfo){
1064
  //proto_tree_add_item(idn_tree, hf_idn_category, tvb, offset, 1, ENC_BIG_ENDIAN);
1065
  //offset += 1;
1066
454
  static int * const audio_cat_6[] = {
1067
454
    &hf_idn_category,
1068
454
    &hf_idn_format,
1069
454
    &hf_idn_layout,
1070
454
    &hf_idn_4bit_channels,
1071
454
    NULL
1072
454
  };
1073
454
  guint8 channels = tvb_get_int8(tvb, offset);
1074
454
  guint8 audio_format = channels;
1075
454
  audio_format = audio_format & 0x0F;
1076
454
  cinfo->audio_format = audio_format;
1077
454
  channels &= 0x0F;
1078
454
  cinfo->audio_channels = channels;
1079
1080
454
  proto_tree_add_bitmask(idn_tree, tvb, offset, hf_idn_audio_dictionary_tag, ett_audio_header, audio_cat_6, ENC_BIG_ENDIAN);
1081
454
  return offset;
1082
454
}
1083
1084
39
static int dissect_idn_audio_dictionary(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *idn_tree, configuration_info *config){
1085
39
  gint8 det_category;
1086
39
  gint16 current_tag;
1087
39
  int tag_count = config->word_count;
1088
39
  tag_count *= 2;
1089
39
  proto_item *dictionary_tree = proto_tree_add_subtree(idn_tree, tvb, offset, tag_count, ett_dic_tree, NULL, "Dictionary");
1090
1091
2.02k
  for(int i = 0; i < tag_count; i++){
1092
1.99k
    current_tag = tvb_get_uint16(tvb, offset, 2);
1093
1.99k
    switch (current_tag) {
1094
319
      case 0x0000:
1095
        //add void tag
1096
319
        proto_tree_add_item(dictionary_tree, hf_idn_gts_void, tvb, offset, 2, ENC_BIG_ENDIAN);
1097
319
        offset += 2;
1098
319
        break;
1099
1.66k
      default:
1100
        //determing category
1101
1.66k
        det_category = tvb_get_int8(tvb, offset);
1102
1.66k
        det_category = det_category >> 4;
1103
        //dissect depending on category
1104
1.66k
        switch (det_category) {
1105
454
          case 0x6:
1106
454
            dissect_idn_audio_category_6(tvb, offset, dictionary_tree, config);
1107
454
            break;
1108
0
          case 0x8:
1109
0
            dissect_idn_audio_category_8(tvb, offset, dictionary_tree, config);
1110
0
            break;
1111
1.66k
        }
1112
1.66k
        offset += 2;
1113
1.66k
        break;
1114
1.99k
    }
1115
1.99k
  }
1116
23
  return offset;
1117
39
}
1118
1119
23
static int dissect_idn_audio_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree){
1120
1121
23
  static int * const audio_flags[] = {
1122
23
    &hf_idn_audio_flags_two_bits_reserved,
1123
23
    &hf_idn_audio_flags_scm,
1124
23
    &hf_idn_audio_flags_four_bits_reserved,
1125
23
    NULL
1126
23
  };
1127
1128
23
  proto_item *audio_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_audio_header, NULL, "Audio Header");
1129
1130
23
  proto_tree_add_bitmask(audio_header_tree, tvb, offset, hf_idn_audio_flags, ett_audio_header, audio_flags, ENC_BIG_ENDIAN);
1131
23
  offset +=1;
1132
1133
23
  proto_tree_add_item(audio_header_tree, hf_idn_audio_duration, tvb, offset, 3, ENC_BIG_ENDIAN);
1134
23
  offset+= 3;
1135
1136
23
  return offset;
1137
23
}
1138
1139
7
static int dissect_idn_audio_samples_format_0(tvbuff_t *tvb, int offset, proto_tree *idn_tree){
1140
7
  int max_samples = tvb_reported_length_remaining(tvb, offset);
1141
279
  for(int i = 0; i < max_samples; i++){
1142
272
    proto_tree_add_item(idn_tree, hf_idn_audio_sample_format_zero, tvb, offset, 1, ENC_BIG_ENDIAN);
1143
272
    offset++;
1144
272
  }
1145
7
  return offset;
1146
7
}
1147
1148
8
static int dissect_idn_audio_samples_format_1(tvbuff_t *tvb, int offset, proto_tree *idn_tree){
1149
8
  int max_samples = tvb_reported_length_remaining(tvb, offset);
1150
8
  max_samples /= 2;
1151
339
  for(int i = 0; i < max_samples; i++){
1152
331
    proto_tree_add_item(idn_tree, hf_idn_audio_sample_format_one, tvb, offset, 2, ENC_BIG_ENDIAN);
1153
331
    offset += 2;
1154
331
  }
1155
8
  return offset;
1156
8
}
1157
1158
7
static int dissect_idn_audio_samples_format_2(tvbuff_t *tvb, int offset, proto_tree *idn_tree){
1159
7
  int max_samples = tvb_reported_length_remaining(tvb, offset);
1160
7
  max_samples /= 3;
1161
305
  for(int i = 0; i < max_samples; i++){
1162
298
    proto_tree_add_item( idn_tree, hf_idn_audio_sample_format_two, tvb, offset, 3, ENC_BIG_ENDIAN);
1163
298
    offset += 3;
1164
298
  }
1165
7
  return offset;
1166
7
}
1167
1168
23
static int dissect_idn_audio_samples(tvbuff_t *tvb, int offset, proto_tree *idn_tree, configuration_info  * config){
1169
23
  proto_item *audio_samples_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_audio_samples, NULL, "Audio Samples");
1170
23
  switch (config->audio_format) {
1171
7
    case 0x00:
1172
7
      dissect_idn_audio_samples_format_0(tvb, offset, audio_samples_tree);
1173
7
      break;
1174
8
    case 0x01:
1175
8
      dissect_idn_audio_samples_format_1(tvb, offset, audio_samples_tree);
1176
8
      break;
1177
7
    case 0x02:
1178
7
      dissect_idn_audio_samples_format_2(tvb, offset, audio_samples_tree);
1179
7
      break;
1180
23
  }
1181
23
  return offset;
1182
23
}
1183
1184
39
static int dissect_idn_audio(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *idn_tree, configuration_info  * config){
1185
1186
39
  offset = dissect_idn_audio_dictionary(tvb, pinfo, offset, idn_tree, config);
1187
39
  offset = dissect_idn_audio_header(tvb, offset, idn_tree);
1188
39
  offset = dissect_idn_audio_samples(tvb, offset, idn_tree, config);
1189
39
  return offset;
1190
39
}
1191
1192
231
static int dissect_idn_message(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *idn_tree) {
1193
1194
231
  configuration_info *config = NULL;
1195
231
  message_info minfo;
1196
1197
231
  offset = dissect_idn_message_header(tvb, offset, idn_tree, &minfo);
1198
231
  determine_message_type(pinfo, &minfo);
1199
231
  if(minfo.total_size == 8)
1200
0
    return offset;
1201
1202
231
  if(minfo.has_config_header && minfo.chunk_type != IDNCT_LP_FRAME_SF) {
1203
225
    offset = dissect_idn_channel_configuration(tvb, pinfo, offset, idn_tree, &minfo, &config);
1204
225
  }else if(minfo.chunk_type != IDNCT_VOID) {
1205
4
    config = get_configuration_info(pinfo, minfo.channel_id);
1206
4
  }
1207
1208
231
  if (config == NULL) {
1209
3
    expert_add_info(pinfo, idn_tree, &ei_idn_no_config);
1210
3
    return offset;
1211
3
  }
1212
1213
228
  if (config->word_count == 0 && minfo.chunk_type != IDNCT_OCTET_SEGMENT) {
1214
1
    expert_add_info(pinfo, idn_tree, &ei_idn_scwc_unknown);
1215
1
    return offset;
1216
1
  }
1217
1218
227
  if(minfo.chunk_type != IDNCT_VOID && minfo.chunk_type != IDNCT_LP_FRAME_SF && minfo.chunk_type != IDNCT_AUDIO_WAVE_SAMPLE) {
1219
75
    offset = dissect_idn_chunk_header(tvb, pinfo, offset, idn_tree, &minfo, config);
1220
152
  }else if(minfo.chunk_type == IDNCT_VOID) {
1221
3
    return offset;
1222
3
  }
1223
1224
224
  if(minfo.chunk_type == IDNCT_OCTET_SEGMENT) {
1225
10
    offset = dissect_idn_octet_segment(tvb, pinfo, offset, idn_tree);
1226
214
  }else if(minfo.is_dmx) {
1227
27
    offset = dissect_idn_dmx_data(tvb, pinfo, offset, idn_tree, config);
1228
187
  }else if(minfo.is_audio){
1229
39
    offset = dissect_idn_audio(tvb, pinfo, offset, idn_tree, config);
1230
148
  }else {
1231
148
    offset = dissect_idn_laser_data(tvb, pinfo, offset, idn_tree, config);
1232
148
  }
1233
1234
224
  return offset;
1235
227
}
1236
1237
83
static int dissect_idn_servicemap_entry(tvbuff_t *tvb, packet_info* pinfo, int offset, proto_tree *idn_tree) {
1238
83
  uint8_t service_id = tvb_get_uint8(tvb, offset);
1239
83
  proto_tree *idn_servicemap_entry_tree = NULL;
1240
83
  proto_item *entry_item;
1241
83
  const uint8_t* name;
1242
1243
83
  if(service_id == 0) {
1244
38
    idn_servicemap_entry_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 24, ett_idn_header_tree, &entry_item, "Relay Entry");
1245
45
  }else {
1246
45
    idn_servicemap_entry_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 24, ett_idn_header_tree, &entry_item, "Service Entry");
1247
45
  }
1248
1249
83
  proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_service_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1250
83
  offset += 1;
1251
83
  proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_service_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
1252
83
  offset += 1;
1253
83
  proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1254
83
  offset += 1;
1255
83
  proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_relay_number, tvb, offset, 1, ENC_BIG_ENDIAN);
1256
83
  offset += 1;
1257
83
  proto_tree_add_item_ret_string(idn_servicemap_entry_tree, hf_idn_name, tvb, offset, 20, ENC_ASCII, pinfo->pool, &name);
1258
83
  proto_item_append_text(entry_item, " - %s", name);
1259
83
  offset += 20;
1260
83
  return offset;
1261
83
}
1262
1263
10
static int dissect_idn_servicemap_response_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree, uint8_t *relay_count, uint8_t *service_count) {
1264
10
  proto_tree *idn_servicemap_response_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_idn_header_tree, NULL, "Service Map Response Header");
1265
10
  proto_tree_add_item(idn_servicemap_response_header_tree, hf_idn_struct_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1266
10
  offset += 1;
1267
10
  proto_tree_add_item(idn_servicemap_response_header_tree, hf_idn_entry_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1268
10
  offset += 1;
1269
10
  *relay_count = tvb_get_uint8(tvb, offset);
1270
10
  proto_tree_add_item(idn_servicemap_response_header_tree, hf_idn_relay_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1271
10
  offset += 1;
1272
10
  *service_count = tvb_get_uint8(tvb, offset);
1273
10
  proto_tree_add_item(idn_servicemap_response_header_tree, hf_idn_service_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1274
10
  offset += 1;
1275
10
  return offset;
1276
10
}
1277
1278
10
static int dissect_idn_servicemap_response(tvbuff_t *tvb, packet_info* pinfo, int offset, proto_tree *idn_tree) {
1279
10
  uint8_t relay_count, service_count;
1280
10
  uint16_t map_entries_size;
1281
1282
10
  offset = dissect_idn_servicemap_response_header(tvb, offset, idn_tree, &relay_count, &service_count);
1283
10
  map_entries_size = relay_count + service_count;
1284
10
  proto_tree *idn_servicemap_entries_tree = proto_tree_add_subtree(idn_tree, tvb, offset, map_entries_size*24, ett_idn_header_tree, NULL, "Service Map Entries");
1285
93
  for(int i=0; i<map_entries_size; i++)
1286
83
    offset = dissect_idn_servicemap_entry(tvb, pinfo, offset, idn_servicemap_entries_tree);
1287
1288
10
  return offset;
1289
10
}
1290
1291
1
static int dissect_idn_scan_response(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
1292
1
  static int * const protocol_version[] = {
1293
1
      &hf_idn_protocol_version_major,
1294
1
      &hf_idn_protocol_version_minor,
1295
1
      NULL
1296
1
  };
1297
1
  static int * const status[] = {
1298
1
      &hf_idn_malfn,
1299
1
      &hf_idn_offline,
1300
1
      &hf_idn_xcld,
1301
1
      &hf_idn_ocpd,
1302
1
      &hf_idn_three_bits_reserved,
1303
1
      &hf_idn_rt,
1304
1
      NULL
1305
1
  };
1306
1307
1308
1
  proto_tree *idn_scanreply_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 40, ett_idn_header_tree, NULL, "Scan Response");
1309
1
  proto_tree_add_item(idn_scanreply_header_tree, hf_idn_struct_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1310
1
  offset += 1;
1311
1
  proto_tree_add_bitmask(idn_scanreply_header_tree, tvb, offset, hf_idn_protocol_version, ett_protocol_version, protocol_version, ENC_BIG_ENDIAN);
1312
1
  offset += 1;
1313
1
  proto_tree_add_bitmask(idn_scanreply_header_tree, tvb, offset, hf_idn_status, ett_status, status, ENC_BIG_ENDIAN);
1314
1
  offset += 1;
1315
1
  proto_tree_add_item(idn_scanreply_header_tree, hf_idn_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
1316
1
  offset += 1;
1317
1
  proto_tree *uid_tree = proto_tree_add_subtree(idn_scanreply_header_tree, tvb, offset, 16, ett_unit_id, NULL, "Unit ID");
1318
1
  proto_tree_add_item(uid_tree, hf_idn_uid_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1319
1
  offset += 1;
1320
1
  proto_tree_add_item(uid_tree, hf_idn_uid_category, tvb, offset, 1, ENC_BIG_ENDIAN);
1321
1
  offset += 1;
1322
1
  proto_tree_add_item(uid_tree, hf_idn_unit_id, tvb, offset, 14, ENC_NA);
1323
1
  offset += 14;
1324
1325
1
  proto_tree_add_item(idn_scanreply_header_tree, hf_idn_name, tvb, offset, 20, ENC_ASCII);
1326
1
  offset += 20;
1327
1
  return offset;
1328
1
}
1329
1330
250
static int dissect_idn_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree, uint8_t packet_type) {
1331
250
  int header_len = (packet_type == IDNCMD_VOID || packet_type == IDNCMD_PING_RESPONSE) ? 1 : 4;
1332
250
  proto_tree *idn_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, header_len, ett_idn_header_tree, NULL, "IDN Header");
1333
250
  proto_tree_add_item(idn_header_tree, hf_idn_command, tvb, offset, 1, ENC_BIG_ENDIAN);
1334
250
  offset += 1;
1335
250
  if (packet_type == IDNCMD_VOID || packet_type == IDNCMD_PING_RESPONSE) {
1336
2
    return offset;
1337
2
  }
1338
248
  proto_tree_add_item(idn_header_tree, hf_idn_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1339
248
  offset += 1;
1340
248
  proto_tree_add_item(idn_header_tree, hf_idn_sequence, tvb, offset, 2, ENC_BIG_ENDIAN);
1341
248
  offset += 2;
1342
248
  return offset;
1343
250
}
1344
1345
250
static int dissect_idn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
1346
250
  int offset = 0;
1347
250
  proto_item *ti = proto_tree_add_item(tree, proto_idn, tvb, 0, -1, ENC_NA);
1348
250
  proto_tree *idn_tree = proto_item_add_subtree(ti, ett_idn);
1349
250
  uint8_t packet_type = tvb_get_uint8(tvb, 0);
1350
1351
250
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "IDN");
1352
250
  col_clear(pinfo->cinfo, COL_INFO);
1353
250
  col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type, command_code, "Unknown (0x%02x)"));
1354
1355
250
  offset = dissect_idn_header(tvb, offset, idn_tree, packet_type);
1356
1357
250
  switch (packet_type) {
1358
1
    case IDNCMD_SCAN_RESPONSE:
1359
1
      dissect_idn_scan_response(tvb, offset, idn_tree);
1360
1
      break;
1361
10
    case IDNCMD_SERVICEMAP_RESPONSE:
1362
10
      offset = dissect_idn_servicemap_response(tvb, pinfo, offset, idn_tree);
1363
10
      break;
1364
22
    case IDNCMD_MESSAGE:
1365
76
    case IDNCMD_MESSAGE_ACKREQ:
1366
186
    case IDNCMD_MESSAGE_CLOSE:
1367
231
    case IDNCMD_MESSAGE_ACKREQ_CLOSE:
1368
231
      offset = dissect_idn_message(tvb, pinfo, offset, idn_tree);
1369
231
      break;
1370
1
    case IDNCMD_MESSAGE_ACK:
1371
1
      offset = dissect_idn_message_acknowledgement(tvb, offset, idn_tree);
1372
1
      break;
1373
3
    default:
1374
3
      break;
1375
250
  }
1376
1377
101
  return offset;
1378
250
}
1379
1380
14
void proto_register_idn(void) {
1381
14
  static hf_register_info hf[] = {
1382
14
    { &hf_idn_command,
1383
14
      { "Command code", "idn.command",
1384
14
      FT_UINT8, BASE_HEX,
1385
14
      VALS(command_code), 0x0,
1386
14
      NULL, HFILL }
1387
14
    },
1388
14
    { &hf_idn_flags,
1389
14
      { "Flags", "idn.flags",
1390
14
      FT_UINT8, BASE_HEX,
1391
14
      NULL, 0x0,
1392
14
      NULL, HFILL }
1393
14
    },
1394
14
    { &hf_idn_sequence,
1395
14
      { "Sequence counter", "idn.sequence",
1396
14
      FT_UINT16, BASE_DEC,
1397
14
      NULL, 0x0,
1398
14
      NULL, HFILL }
1399
14
    },
1400
14
    { &hf_idn_total_size,
1401
14
      { "Total Size", "idn.total_size",
1402
14
      FT_UINT16, BASE_DEC,
1403
14
      NULL, 0x0,
1404
14
      NULL, HFILL }
1405
14
    },
1406
14
    { &hf_idn_struct_size,
1407
14
      { "Struct Size", "idn.struct_size",
1408
14
      FT_UINT8, BASE_DEC,
1409
14
      NULL, 0x0,
1410
14
      NULL, HFILL }
1411
14
    },
1412
14
    { &hf_idn_protocol_version,
1413
14
      { "Protocol Version", "idn.protocol_version",
1414
14
      FT_UINT8, BASE_DEC,
1415
14
      NULL, 0x0,
1416
14
      NULL, HFILL }
1417
14
    },
1418
14
    { &hf_idn_protocol_version_major,
1419
14
      { "Major", "idn.protocol_version_major",
1420
14
      FT_UINT8, BASE_DEC,
1421
14
      NULL, 0xF0,
1422
14
      NULL, HFILL }
1423
14
    },
1424
14
    { &hf_idn_protocol_version_minor,
1425
14
      { "Minor", "idn.protocol_version_minor",
1426
14
      FT_UINT8, BASE_DEC,
1427
14
      NULL, 0x0F,
1428
14
      NULL, HFILL }
1429
14
    },
1430
14
    { &hf_idn_status,
1431
14
      { "Status", "idn.status",
1432
14
      FT_UINT8, BASE_HEX,
1433
14
      NULL, 0x0,
1434
14
      NULL, HFILL }
1435
14
    },
1436
14
    { &hf_idn_malfn,
1437
14
      { "Malfunction", "idn.status_malfn",
1438
14
      FT_UINT8, BASE_DEC,
1439
14
      NULL, 0x80,
1440
14
      NULL, HFILL }
1441
14
    },
1442
14
    { &hf_idn_offline,
1443
14
      { "Offline", "idn.offline",
1444
14
      FT_UINT8, BASE_DEC,
1445
14
      NULL, 0x40,
1446
14
      NULL, HFILL }
1447
14
    },
1448
14
    { &hf_idn_xcld,
1449
14
      { "Excluded", "idn.xcld",
1450
14
      FT_UINT8, BASE_DEC,
1451
14
      NULL, 0x20,
1452
14
      NULL, HFILL }
1453
14
    },
1454
14
    { &hf_idn_ocpd,
1455
14
      { "Occupied", "idn.ocpd",
1456
14
      FT_UINT8, BASE_DEC,
1457
14
      NULL, 0x10,
1458
14
      NULL, HFILL }
1459
14
    },
1460
14
    { &hf_idn_rt,
1461
14
      { "Realtime", "idn.rt",
1462
14
      FT_UINT8, BASE_DEC,
1463
14
      NULL, 0x1,
1464
14
      NULL, HFILL }
1465
14
    },
1466
14
    { &hf_idn_reserved8,
1467
14
      { "Reserved", "idn.reserved8",
1468
14
      FT_UINT8, BASE_HEX,
1469
14
      NULL, 0x0,
1470
14
      NULL, HFILL }
1471
14
    },
1472
14
    { &hf_idn_unit_id,
1473
14
      { "Unit ID", "idn.unit_id",
1474
14
      FT_BYTES, SEP_SPACE,
1475
14
      NULL, 0x0,
1476
14
      NULL, HFILL }
1477
14
    },
1478
14
    { &hf_idn_uid_length,
1479
14
      { "Length", "idn.unit_id_length",
1480
14
      FT_UINT8, BASE_HEX,
1481
14
      NULL, 0x0,
1482
14
      NULL, HFILL }
1483
14
    },
1484
14
    { &hf_idn_uid_category,
1485
14
      { "Caregory", "idn.unit_id_category",
1486
14
      FT_UINT8, BASE_HEX,
1487
14
      NULL, 0x0,
1488
14
      NULL, HFILL }
1489
14
    },
1490
14
    { &hf_idn_uid,
1491
14
      { "Unit ID", "idn.unit_id_number",
1492
14
      FT_BYTES, SEP_SPACE,
1493
14
      NULL, 0x0,
1494
14
      NULL, HFILL }
1495
14
    },
1496
14
    { &hf_idn_name,
1497
14
      { "Name", "idn.name",
1498
14
      FT_STRING, BASE_NONE,
1499
14
      NULL, 0x0,
1500
14
      NULL, HFILL }
1501
14
    },
1502
14
    { &hf_idn_entry_size,
1503
14
      { "Entry Size", "idn.entry_size",
1504
14
      FT_UINT8, BASE_DEC,
1505
14
      NULL, 0x0,
1506
14
      NULL, HFILL }
1507
14
    },
1508
14
    { &hf_idn_relay_count,
1509
14
      { "Relay Count", "idn.relay_count",
1510
14
      FT_UINT8, BASE_DEC,
1511
14
      NULL, 0x0,
1512
14
      NULL, HFILL }
1513
14
    },
1514
14
    { &hf_idn_service_count,
1515
14
      { "Service Count", "idn.service_count",
1516
14
      FT_UINT8, BASE_DEC,
1517
14
      NULL, 0x0,
1518
14
      NULL, HFILL }
1519
14
    },
1520
14
    { &hf_idn_cnl,
1521
14
      { "Channel configuration and routing information (CNL)", "idn.cnl",
1522
14
      FT_UINT8, BASE_HEX,
1523
14
      NULL, 0x0,
1524
14
      NULL, HFILL }
1525
14
    },
1526
14
    { &hf_idn_most_significant_bit_cnl,
1527
14
      { "Most significant bit (always 1)", "idn.most_significant_bit_cnl",
1528
14
      FT_UINT8, BASE_DEC,
1529
14
      NULL, 0x80,
1530
14
      NULL, HFILL }
1531
14
    },
1532
14
    { &hf_idn_cclf,
1533
14
      { "Channel Configuration and Last Fragment bit (CCLF)", "idn.cclf",
1534
14
      FT_UINT8, BASE_DEC,
1535
14
      NULL, 0x40,
1536
14
      NULL, HFILL }
1537
14
    },
1538
14
    { &hf_idn_channel_id,
1539
14
      { "Channel ID (opened Channels)", "idn.channel_id",
1540
14
      FT_UINT8, BASE_DEC,
1541
14
      NULL, 0x3F,
1542
14
      NULL, HFILL }
1543
14
    },
1544
14
    { &hf_idn_chunk_type,
1545
14
      { "Chunk Type", "idn.chunk_type",
1546
14
      FT_UINT8, BASE_HEX,
1547
14
      VALS(chunk_type), 0x0,
1548
14
      NULL, HFILL }
1549
14
    },
1550
14
    { &hf_idn_timestamp,
1551
14
      { "Timestamp", "idn.timestamp",
1552
14
      FT_UINT32, BASE_DEC,
1553
14
      NULL, 0x0,
1554
14
      NULL, HFILL }
1555
14
    },
1556
14
    { &hf_idn_scwc,
1557
14
      { "Service Configuration Word Count (SCWC)", "idn.scwc",
1558
14
      FT_UINT8, BASE_DEC,
1559
14
      NULL, 0x0,
1560
14
      NULL, HFILL }
1561
14
    },
1562
14
    { &hf_idn_cfl,
1563
14
      { "Channel and service configuration Flags (CFL)", "idn.cfl",
1564
14
      FT_UINT8, BASE_HEX,
1565
14
      VALS(cfl_string), 0x0,
1566
14
      NULL, HFILL }
1567
14
    },
1568
14
    { &hf_idn_sdm,
1569
14
      { "Service Data Match (SDM)", "idn.sdm",
1570
14
      FT_UINT8, BASE_DEC,
1571
14
      NULL, 0x30,
1572
14
      NULL, HFILL }
1573
14
    },
1574
14
    { &hf_idn_close,
1575
14
      { "Close", "idn.close",
1576
14
      FT_UINT8, BASE_DEC,
1577
14
      NULL, 0x2,
1578
14
      NULL, HFILL }
1579
14
    },
1580
14
    { &hf_idn_routing,
1581
14
      { "Routing", "idn.routing",
1582
14
      FT_UINT8, BASE_DEC,
1583
14
      NULL, 0x1,
1584
14
      NULL, HFILL }
1585
14
    },
1586
14
    { &hf_idn_service_id,
1587
14
      { "Service ID", "idn.service_id",
1588
14
      FT_UINT8, BASE_HEX,
1589
14
      NULL, 0x0,
1590
14
      NULL, HFILL }
1591
14
    },
1592
14
    { &hf_idn_relay_number,
1593
14
      { "Relay Number", "idn.relay_number",
1594
14
      FT_UINT8, BASE_HEX,
1595
14
      NULL, 0x0,
1596
14
      NULL, HFILL }
1597
14
    },
1598
14
    { &hf_idn_service_mode,
1599
14
      { "Service Mode", "idn.service_mode",
1600
14
      FT_UINT8, BASE_HEX,
1601
14
      VALS(service_mode_string), 0x0,
1602
14
      NULL, HFILL }
1603
14
    },
1604
14
    { &hf_idn_chunk_header_flags,
1605
14
      { "Chunk Header Flags", "idn.chunk_header_flags",
1606
14
      FT_UINT8, BASE_HEX,
1607
14
      NULL, 0x0,
1608
14
      NULL, HFILL }
1609
14
    },
1610
14
    { &hf_idn_two_bits_reserved_1,
1611
14
      { "Reserved", "idn.zero_zero",
1612
14
      FT_UINT8, BASE_DEC,
1613
14
      NULL, 0xC0,
1614
14
      NULL, HFILL }
1615
14
    },
1616
14
    { &hf_idn_two_bits_reserved_2,
1617
14
      { "Reserved", "idn.zero_zero",
1618
14
      FT_UINT8, BASE_DEC,
1619
14
      NULL, 0xC,
1620
14
      NULL, HFILL }
1621
14
    },
1622
14
    { &hf_idn_scm,
1623
14
      { "Service configuration match (SCM)", "idn.scm",
1624
14
      FT_UINT8, BASE_DEC,
1625
14
      NULL, 0x30,
1626
14
      NULL, HFILL }
1627
14
    },
1628
14
    { &hf_idn_three_bits_reserved,
1629
14
      { "Reserved", "idn.three_bit_reserved",
1630
14
      FT_UINT8, BASE_DEC,
1631
14
      NULL, 0xE,
1632
14
      NULL, HFILL }
1633
14
    },
1634
14
    { &hf_idn_four_bits_reserved,
1635
14
      { "Reserved", "idn.three_bit_reserved",
1636
14
      FT_UINT8, BASE_DEC,
1637
14
      NULL, 0xF,
1638
14
      NULL, HFILL }
1639
14
    },
1640
14
    { &hf_idn_once,
1641
14
      { "Once", "idn.once",
1642
14
      FT_UINT8, BASE_DEC,
1643
14
      NULL, 0x1,
1644
14
      NULL, HFILL }
1645
14
    },
1646
14
    { &hf_idn_dlim,
1647
14
      { "Delimiter (DLIM)", "idn.dlim",
1648
14
      FT_UINT8, BASE_DEC,
1649
14
      NULL, 0x1,
1650
14
      NULL, HFILL }
1651
14
    },
1652
14
    { &hf_idn_duration,
1653
14
      { "Duration", "idn.frame_sample_duration",
1654
14
      FT_UINT24, BASE_DEC,
1655
14
      NULL, 0x0,
1656
14
      NULL, HFILL }
1657
14
    },
1658
14
    { &hf_idn_chunk_data_sequence,
1659
14
      { "Sequence", "idn.octet_segment_sequence",
1660
14
      FT_UINT8, BASE_DEC,
1661
14
      NULL, 0x0,
1662
14
      NULL, HFILL }
1663
14
    },
1664
14
    { &hf_idn_offset,
1665
14
      { "Offset", "idn.offset",
1666
14
      FT_UINT16, BASE_HEX,
1667
14
      NULL, 0x0,
1668
14
      NULL, HFILL }
1669
14
    },
1670
14
    { &hf_idn_reserved,
1671
14
      { "Reserved", "idn.reserved",
1672
14
      FT_BYTES, BASE_NONE,
1673
14
      NULL, 0x0,
1674
14
      NULL, HFILL }
1675
14
    },
1676
14
    { &hf_idn_gts,
1677
14
      { "Unknown", "idn.unknown",
1678
14
      FT_UINT16, BASE_HEX,
1679
14
      NULL, 0x0,
1680
14
      NULL, HFILL }
1681
14
    },
1682
14
    { &hf_idn_gts_void,
1683
14
      { "Void", "idn.gts_void",
1684
14
      FT_UINT16, BASE_HEX,
1685
14
      NULL, 0x0,
1686
14
      NULL, HFILL }
1687
14
    },
1688
14
    { &hf_idn_boundary,
1689
14
      { "Void (32-bit boundary)", "idn.gts_boundary",
1690
14
      FT_UINT32, BASE_HEX,
1691
14
      NULL, 0x0,
1692
14
      NULL, HFILL }
1693
14
    },
1694
14
    { &hf_idn_gts_word,
1695
14
      { "16-bit word", "idn.gts_word",
1696
14
      FT_UINT16, BASE_HEX,
1697
14
      NULL, 0x0,
1698
14
      NULL, HFILL }
1699
14
    },
1700
14
    { &hf_idn_gts_break,
1701
14
      { "Break", "idn.gts_break",
1702
14
      FT_UINT16, BASE_HEX,
1703
14
      NULL, 0x0,
1704
14
      NULL, HFILL }
1705
14
    },
1706
14
    { &hf_idn_gts_space_modifier,
1707
14
      { "Space Modifier", "idn.gts_space_modifier",
1708
14
      FT_UINT16, BASE_HEX,
1709
14
      NULL, 0x0,
1710
14
      NULL, HFILL }
1711
14
    },
1712
14
    { &hf_idn_gts_hint,
1713
14
      { "Hint", "idn.gts_hint",
1714
14
      FT_UINT16, BASE_HEX,
1715
14
      NULL, 0x0,
1716
14
      NULL, HFILL }
1717
14
    },
1718
14
    { &hf_idn_gts_category,
1719
14
      { "Category", "idn.gts_category",
1720
14
      FT_UINT16, BASE_DEC,
1721
14
      NULL, 0xF000,
1722
14
      NULL, HFILL }
1723
14
    },
1724
14
    { &hf_idn_gts_subcategory,
1725
14
      { "Subcategory", "idn.gts_subcategory",
1726
14
      FT_UINT16, BASE_DEC,
1727
14
      NULL, 0x0F00,
1728
14
      NULL, HFILL }
1729
14
    },
1730
14
    { &hf_idn_gts_identifier,
1731
14
      { "Identifier", "idn.gts_identifier",
1732
14
      FT_UINT16, BASE_DEC,
1733
14
      NULL, 0x00F0,
1734
14
      NULL, HFILL }
1735
14
    },
1736
14
    { &hf_idn_gts_parameter,
1737
14
      { "Parameter", "idn.gts_parameter",
1738
14
      FT_UINT16, BASE_DEC,
1739
14
      NULL, 0x000F,
1740
14
      NULL, HFILL }
1741
14
    },
1742
14
    { &hf_idn_gts_glin,
1743
14
      { "Graphic Space Linearity (GLIN)", "idn.gts_glin",
1744
14
      FT_UINT16, BASE_DEC,
1745
14
      VALS(gts_glin), 0x00C0,
1746
14
      NULL, HFILL }
1747
14
    },
1748
14
    { &hf_idn_gts_clin,
1749
14
      { "Color Space Linearity (CLIN)", "idn.gts_clin",
1750
14
      FT_UINT16, BASE_DEC,
1751
14
      VALS(gts_clin), 0x0030,
1752
14
      NULL, HFILL }
1753
14
    },
1754
14
    { &hf_idn_gts_cbal,
1755
14
      { "Color Balance (CBAL)", "idn.gts_cbal",
1756
14
      FT_UINT16, BASE_DEC,
1757
14
      VALS(gts_cbal), 0x000C,
1758
14
      NULL, HFILL }
1759
14
    },
1760
14
    { &hf_idn_gts_ctim,
1761
14
      { "Color Timing (CTIM)", "idn.gts_ctim",
1762
14
      FT_UINT16, BASE_DEC,
1763
14
      VALS(gts_ctim), 0x0003,
1764
14
      NULL, HFILL }
1765
14
    },
1766
14
    { &hf_idn_gts_nop,
1767
14
      { "No Operation (NOP)", "idn.gts_nop",
1768
14
      FT_UINT16, BASE_HEX,
1769
14
      NULL, 0x0,
1770
14
      NULL, HFILL }
1771
14
    },
1772
14
    { &hf_idn_gts_precision,
1773
14
      { "Precision", "idn.gts_precision",
1774
14
      FT_UINT16, BASE_HEX,
1775
14
      NULL, 0x0,
1776
14
      NULL, HFILL }
1777
14
    },
1778
14
    { &hf_idn_gts_cscl,
1779
14
      { "Color scale (CSCL)", "idn.gts_cscl",
1780
14
      FT_UINT16, BASE_DEC,
1781
14
      NULL, 0x00C0,
1782
14
      NULL, HFILL }
1783
14
    },
1784
14
    { &hf_idn_gts_iscl,
1785
14
      { "Intensity scale (ISCL)", "idn.gts_iscl",
1786
14
      FT_UINT16, BASE_DEC,
1787
14
      NULL, 0x0030,
1788
14
      NULL, HFILL }
1789
14
    },
1790
14
    { &hf_idn_gts_sht,
1791
14
      { "Shutter (SHT)", "idn.gts_sht",
1792
14
      FT_UINT16, BASE_DEC,
1793
14
      NULL, 0x000F,
1794
14
      NULL, HFILL }
1795
14
    },
1796
14
    { &hf_idn_gts_u4,
1797
14
      { "Optional(U4), used as X-prime", "idn.gts_u4",
1798
14
      FT_UINT16, BASE_HEX,
1799
14
      NULL, 0x0,
1800
14
      NULL, HFILL }
1801
14
    },
1802
14
    { &hf_idn_gts_x,
1803
14
      { "X", "idn.gts_x",
1804
14
      FT_UINT16, BASE_HEX,
1805
14
      NULL, 0x0,
1806
14
      NULL, HFILL }
1807
14
    },
1808
14
    { &hf_idn_gts_y,
1809
14
      { "Y", "idn.gts_y",
1810
14
      FT_UINT16, BASE_HEX,
1811
14
      NULL, 0x0,
1812
14
      NULL, HFILL }
1813
14
    },
1814
14
    { &hf_idn_gts_z,
1815
14
      { "Z", "idn.gts_z",
1816
14
      FT_UINT16, BASE_HEX,
1817
14
      NULL, 0x0,
1818
14
      NULL, HFILL }
1819
14
    },
1820
14
    { &hf_idn_gts_color,
1821
14
      { "Color", "idn.gts_color",
1822
14
      FT_UINT16, BASE_DEC,
1823
14
      VALS(idn_color), 0x03FF,
1824
14
      NULL, HFILL }
1825
14
    },
1826
14
    { &hf_idn_gts_wavelength_prefix,
1827
14
      { "Wavelength Prefix", "idn.gts_wavelength_prefix",
1828
14
      FT_UINT16, BASE_HEX,
1829
14
      NULL, 0x0,
1830
14
      NULL, HFILL }
1831
14
    },
1832
14
    { &hf_idn_gts_intensity,
1833
14
      { "Intensity/blanking", "idn.gts_intensity",
1834
14
      FT_UINT16, BASE_HEX,
1835
14
      NULL, 0x0,
1836
14
      NULL, HFILL }
1837
14
    },
1838
14
    { &hf_idn_gts_beam_brush,
1839
14
      { "Beam-Brush", "idn.gts_beam_brush",
1840
14
      FT_UINT16, BASE_HEX,
1841
14
      NULL, 0x0,
1842
14
      NULL, HFILL }
1843
14
    },
1844
14
    { &hf_idn_gts_sample,
1845
14
      { "Sample", "idn.gts_sample",
1846
14
      FT_BYTES, BASE_NONE,
1847
14
      NULL, 0x0,
1848
14
      NULL, HFILL }
1849
14
    },
1850
14
    { &hf_idn_dmx_octet,
1851
14
      { "Octet", "idn.gts_octet",
1852
14
      FT_UINT8, BASE_DEC,
1853
14
      NULL, 0x0,
1854
14
      NULL, HFILL }
1855
14
    },
1856
14
    { &hf_idn_dmx_identifier,
1857
14
      { "Identifier", "idn.gts_dmx_identifier",
1858
14
      FT_UINT8, BASE_DEC,
1859
14
      NULL, 0xF0,
1860
14
      NULL, HFILL }
1861
14
    },
1862
14
    { &hf_idn_dmx_parameter,
1863
14
      { "Parameter", "idn.gts_dmx_parameter",
1864
14
      FT_UINT8, BASE_DEC,
1865
14
      NULL, 0x0F,
1866
14
      NULL, HFILL }
1867
14
    },
1868
14
    { &hf_idn_dmx_void,
1869
14
      { "Void", "idn.gts_dmx_void",
1870
14
      FT_UINT8, BASE_HEX,
1871
14
      NULL, 0x0,
1872
14
      NULL, HFILL }
1873
14
    },
1874
14
    { &hf_idn_octet,
1875
14
      { "Octet", "idn.gts_dmx_octet",
1876
14
      FT_UINT8, BASE_HEX,
1877
14
      NULL, 0x0,
1878
14
      NULL, HFILL }
1879
14
    },
1880
14
    { &hf_idn_dmx_dls,
1881
14
      { "Dimmer Level Subset", "idn.dmx_dls",
1882
14
      FT_UINT8, BASE_HEX,
1883
14
      NULL, 0x0,
1884
14
      NULL, HFILL }
1885
14
    },
1886
14
    { &hf_idn_dmx_base,
1887
14
      { "Base", "idn.dmx_base",
1888
14
      FT_UINT16, BASE_DEC,
1889
14
      NULL, 0x0,
1890
14
      NULL, HFILL }
1891
14
    },
1892
14
    { &hf_idn_dmx_count,
1893
14
      { "Count", "idn.dmx_count",
1894
14
      FT_UINT8, BASE_DEC,
1895
14
      NULL, 0x0,
1896
14
      NULL, HFILL }
1897
14
    },
1898
14
    { &hf_idn_dmx_unknown,
1899
14
      { "Unknown", "idn.dmx_unknown",
1900
14
      FT_UINT8, BASE_HEX,
1901
14
      NULL, 0x0,
1902
14
      NULL, HFILL }
1903
14
    },
1904
14
    { &hf_idn_result_code,
1905
14
      { "Result Code", "idn.result_code",
1906
14
      FT_UINT8, BASE_DEC,
1907
14
      VALS(result_code), 0x0,
1908
14
      NULL, HFILL }
1909
14
    },
1910
14
    { &hf_idn_event_flags,
1911
14
      { "Event Flags", "idn.event_flags",
1912
14
      FT_UINT16, BASE_HEX,
1913
14
      NULL, 0x0,
1914
14
      NULL, HFILL }
1915
14
    },
1916
14
    { &hf_idn_audio_dictionary_tag,
1917
14
      { "Audio Dictionary Tag", "idn.audioheader",
1918
14
      FT_UINT16, BASE_HEX,
1919
14
      NULL, 0x0,
1920
14
      NULL, HFILL
1921
14
      }
1922
14
    },
1923
14
    { &hf_idn_category,
1924
14
      { "Category", "idn.category",
1925
14
      FT_UINT16, BASE_HEX,
1926
14
      VALS(category), 0xF000,
1927
14
      NULL, HFILL
1928
14
      }
1929
14
    },
1930
14
    { &hf_idn_format,
1931
14
      { "Format", "idn.format",
1932
14
      FT_UINT16, BASE_DEC,
1933
14
      VALS(format), 0x0F00,
1934
14
      NULL, HFILL
1935
14
      }
1936
14
    },
1937
14
    { &hf_idn_layout,
1938
14
      { "Layout", "idn.layout",
1939
14
      FT_UINT16, BASE_DEC,
1940
14
      NULL, 0x00F0,
1941
14
      NULL, HFILL
1942
14
      }
1943
14
    },
1944
14
    { &hf_idn_4bit_channels,
1945
14
      { "Channels", "idn.category6channels",
1946
14
      FT_UINT16, BASE_DEC,
1947
14
      NULL, 0x000F,
1948
14
      NULL, HFILL
1949
14
      }
1950
14
    },
1951
14
    { &hf_idn_subcategory,
1952
14
      { "Subcategory", "idn.subcategory",
1953
14
      FT_UINT16, BASE_DEC,
1954
14
      NULL, 0x0F00,
1955
14
      NULL, HFILL
1956
14
      }
1957
14
    },
1958
14
    { &hf_idn_parameter,
1959
14
      { "Format", "idn.format",
1960
14
      FT_UINT16, BASE_DEC,
1961
14
      NULL, 0x00F0,
1962
14
      NULL, HFILL
1963
14
      }
1964
14
    },
1965
14
    { &hf_idn_suffix_length,
1966
14
      { "Suffix length", "idn.suffix_length",
1967
14
      FT_UINT16, BASE_DEC,
1968
14
      NULL, 0x000F,
1969
14
      NULL, HFILL
1970
14
      }
1971
14
    },
1972
14
    { &hf_idn_8bit_channels,
1973
14
      { "Channels", "idn.channel",
1974
14
      FT_UINT16, BASE_DEC,
1975
14
      NULL, 0x00FF,
1976
14
      NULL, HFILL
1977
14
      }
1978
14
    },
1979
14
    { &hf_idn_audio_flags,
1980
14
      { "Flags", "idn.audio_flags",
1981
14
      FT_UINT8, BASE_HEX,
1982
14
      NULL, 0x0,
1983
14
      NULL, HFILL}
1984
14
    },
1985
14
    { &hf_idn_audio_duration,
1986
14
      { "Duration in microseconds", "idn.audio_duration",
1987
14
      FT_UINT24, BASE_DEC,
1988
14
      NULL, 0x0,
1989
14
      NULL, HFILL}
1990
14
    },
1991
14
    { &hf_idn_audio_flags_two_bits_reserved,
1992
14
      { "Reserved", "idn.audio_2",
1993
14
      FT_UINT8, BASE_HEX,
1994
14
      NULL, 0xC0,
1995
14
      NULL, HFILL}
1996
14
    },
1997
14
    { &hf_idn_audio_flags_four_bits_reserved,
1998
14
      { "Reserved", "idn.audio_4",
1999
14
      FT_UINT8, BASE_HEX,
2000
14
      NULL, 0x0F,
2001
14
      NULL, HFILL}
2002
14
    },
2003
14
    { &hf_idn_audio_flags_scm,
2004
14
      { "Service configuration match", "idn.audio_scm",
2005
14
      FT_UINT8, BASE_HEX,
2006
14
      NULL, 0x30,
2007
14
      NULL, HFILL}
2008
14
    },
2009
14
    { &hf_idn_audio_sample_format_zero,
2010
14
      { "Audio Sample (format 0)", "idn.audio_sample_0",
2011
14
      FT_UINT8, BASE_HEX,
2012
14
      NULL, 0x0,
2013
14
      NULL, HFILL}
2014
14
    },
2015
14
    { &hf_idn_audio_sample_format_one,
2016
14
      { "Audio Sample (format 1)", "idn.audio_sample_1",
2017
14
      FT_UINT16, BASE_HEX,
2018
14
      NULL, 0x0,
2019
14
      NULL, HFILL}
2020
14
    },
2021
14
    { &hf_idn_audio_sample_format_two,
2022
14
      { "Audio Sample (format 2)", "idn.audio_sample_2",
2023
14
      FT_UINT24, BASE_HEX,
2024
14
      NULL, 0x0,
2025
14
      NULL, HFILL}
2026
14
    }
2027
14
  };
2028
2029
14
  static int *ett[] = {
2030
14
    &ett_idn,
2031
14
    &ett_idn_header_tree,
2032
14
    &ett_idn_scanreply_header_tree,
2033
14
    &ett_idn_channel_message_header_tree,
2034
14
    &ett_protocol_version,
2035
14
    &ett_unit_id,
2036
14
    &ett_status,
2037
14
    &ett_idn_cnl,
2038
14
    &ett_cfl,
2039
14
    &ett_configuration_header,
2040
14
    &ett_chunk_header_tree,
2041
14
    &ett_chunk_header_flags,
2042
14
    &ett_dic,
2043
14
    &ett_dic_tree,
2044
14
    &ett_data,
2045
14
    &ett_subdata,
2046
14
    &ett_dmx_subtree,
2047
14
    &ett_audio_header,
2048
14
    &ett_audio_samples
2049
14
  };
2050
2051
14
  expert_module_t* expert_idn;
2052
14
  static ei_register_info ei[] = {
2053
14
    { &ei_idn_no_config, { "idn.no_config", PI_UNDECODED, PI_NOTE,
2054
14
      "No configuration is associated with this message", EXPFILL } },
2055
14
    { &ei_idn_scwc_unknown, { "idn.scwc.unknown", PI_SEQUENCE, PI_WARN,
2056
14
      "SCWC is zero/unknown", EXPFILL } },
2057
14
    { &ei_idn_channels_over, { "idn.channel.over", PI_PROTOCOL, PI_ERROR,
2058
14
      "Over number of channels", EXPFILL } },
2059
14
    { &ei_idn_scm_mismatch, { "idn.scm.mismatch", PI_PROTOCOL, PI_ERROR,
2060
14
      "SCM doesn't match configured SDM", EXPFILL } },
2061
14
  };
2062
2063
14
  proto_idn = proto_register_protocol (
2064
14
    "Ilda Digital Network Protocol",
2065
14
    "IDN",
2066
14
    "idn"
2067
14
  );
2068
2069
14
  proto_register_field_array(proto_idn, hf, array_length(hf));
2070
14
  proto_register_subtree_array(ett, array_length(ett));
2071
2072
14
  expert_idn = expert_register_protocol(proto_idn);
2073
14
  expert_register_field_array(expert_idn, ei, array_length(ei));
2074
2075
14
  idn_handle = register_dissector("idn", dissect_idn, proto_idn);
2076
14
}
2077
2078
14
void proto_reg_handoff_idn(void) {
2079
14
  dissector_add_uint("udp.port", IDN_PORT, idn_handle);
2080
14
}
2081
2082
/*
2083
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2084
 *
2085
 * Local variables:
2086
 * c-basic-offset: 8
2087
 * tab-width: 8
2088
 * indent-tabs-mode: t
2089
 * End:
2090
 *
2091
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2092
 * :indentSize=8:tabSize=8:noTabs=false:
2093
 */