Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-idn.c
blob340c966a2890ecf7d871667df17238ffc4d63cd0
1 /* packet-idn.c
2 * Routines for IDN dissection
3 * By Maxim Kropp <maxim.kropp@hotmail.de>
4 * Copyright 2017 Maxim Kropp
6 * Supervised by Matthias Frank <matthew@cs.uni-bonn.de>
7 * Copyright 2017 Matthias Frank, Institute of Computer Science 4, University of Bonn
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.
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <config.h>
21 #include <epan/packet.h>
22 #include <epan/conversation.h>
24 #include <wsutil/array.h>
26 #define IDN_PORT 7255
28 #define MAX_CHANNELS 512
29 #define MAX_BUFFER 2048
31 /* Packet Commands */
32 #define IDNCMD_VOID 0x00
33 #define IDNCMD_PING_REQUEST 0x08
34 #define IDNCMD_PING_RESPONSE 0x09
35 #define IDNCMD_SCAN_REQUEST 0x10
36 #define IDNCMD_SCAN_RESPONSE 0x11
37 #define IDNCMD_SERVICEMAP_REQUEST 0x12
38 #define IDNCMD_SERVICEMAP_RESPONSE 0x13
39 #define IDNCMD_MESSAGE 0x40
40 #define IDNCMD_MESSAGE_ACKREQ 0x41
41 #define IDNCMD_MESSAGE_CLOSE 0x44
42 #define IDNCMD_MESSAGE_ACKREQ_CLOSE 0x45
43 #define IDNCMD_MESSAGE_ACK 0x47
45 /* Chunk Types */
46 #define IDNCT_VOID 0x00
47 #define IDNCT_LP_WAVE_SAMPLE 0x01
48 #define IDNCT_LP_FRAME_CHUNK 0x02
49 #define IDNCT_LP_FRAME_FF 0x03
50 #define IDNCT_LP_FRAME_SF 0xC0
51 #define IDNCT_OCTET_SEGMENT 0x10
52 #define IDNCT_OCTET_STRING 0x11
53 #define IDNCT_DIMMER_LEVELS 0x18
55 /* Service Modes (CONT = continuous stream, DISC = discrete stream) */
56 #define IDNSM_VOID 0x00
57 #define IDNSM_LP_GRAPHIC_CONT 0x01
58 #define IDNSM_LP_GRAPHIC_DISC 0x02
59 #define IDNSM_LP_EFFECTS_CONT 0x03
60 #define IDNSM_LP_EFFECTS_DISC 0x04
61 #define IDNSM_DMX512_CONT 0x05
62 #define IDNSM_DMX512_DISC 0x06
64 /* Dictionary Tags */
65 #define IDNTAG_PRECISION 0x4010
66 #define IDNTAG_WAVELENGTH_PREFIX 0x5C00
67 #define IDNTAG_INTENSITY 0x5C10
68 #define IDNTAG_BEAM_BRUSH 0x5C20
69 #define IDNTAG_BREAK_START 0x1000
70 #define IDNTAG_BREAK_END 0x100F
71 #define IDNTAG_SPACE_MOD_START 0x1100
72 #define IDNTAG_SPACE_MOD_END 0x11FF
73 #define IDNTAG_NOP 0x4000
74 #define IDNTAG_HINT0 0x4100
75 #define IDNTAG_HINT1 0x4101
76 #define IDNTAG_COLOR_START 0x5000
77 #define IDNTAG_COLOR_END 0x53FF
78 #define IDNTAG_COLOR_RED 0x527E
79 #define IDNTAG_COLOR_GREEN 0x5214
80 #define IDNTAG_COLOR_BLUE 0x51CC
81 #define IDNTAG_OPTIONAL_U1 0x51BD
82 #define IDNTAG_OPTIONAL_U2 0x5241
83 #define IDNTAG_OPTIONAL_U3 0x51E8
84 #define IDNTAG_OPTIONAL_U4 0x4201
85 #define IDNTAG_COORD_X 0x4200
86 #define IDNTAG_COORD_X_END 0x420F
87 #define IDNTAG_COORD_Y 0x4210
88 #define IDNTAG_COORD_Y_END 0x421F
89 #define IDNTAG_COORD_Z 0x4220
90 #define IDNTAG_COORD_Z_END 0x422F
91 #define IDNTAG_DIMMER_START 0x0040
92 #define IDNTAG_DIMMER_END 0x004F
94 /* Other */
95 #define IDNO_VOID_AREA 0xF
97 typedef struct {
98 bool has_config_header;
99 bool is_dmx;
100 uint16_t total_size;
101 uint8_t channel_id;
102 uint8_t chunk_type;
103 } message_info;
105 typedef struct {
106 uint8_t word_count;
107 uint8_t sdm;
108 char *dic_precision;
109 char *sample_column_string;
110 int sample_size;
111 int *count;
112 int *base;
113 } configuration_info;
115 void proto_register_idn(void);
116 void proto_reg_handoff_idn(void);
118 static dissector_handle_t idn_handle;
120 static int proto_idn;
122 static int ett_idn;
123 static int ett_idn_header_tree;
124 static int ett_idn_scanreply_header_tree;
125 static int ett_idn_channel_message_header_tree;
126 static int ett_protocol_version;
127 static int ett_status;
128 static int ett_idn_cnl;
129 static int ett_configuration_header;
130 static int ett_chunk_header_tree;
131 static int ett_chunk_header_flags;
132 static int ett_cfl;
133 static int ett_dic;
134 static int ett_dic_tree;
135 static int ett_data;
136 static int ett_subdata;
137 static int ett_dmx_subtree;
139 /* IDN-Header */
140 static int hf_idn_command;
141 static int hf_idn_flags;
142 static int hf_idn_sequence;
143 static int hf_idn_total_size;
145 /* Scanreply Header */
146 static int hf_idn_struct_size;
147 static int hf_idn_protocol_version;
148 static int hf_idn_protocol_version_major;
149 static int hf_idn_protocol_version_minor;
150 static int hf_idn_status;
151 static int hf_idn_malfn;
152 static int hf_idn_offline;
153 static int hf_idn_xcld;
154 static int hf_idn_ocpd;
155 static int hf_idn_rt;
156 static int hf_idn_reserved8;
157 static int hf_idn_unit_id;
158 static int hf_idn_name;
160 /* Service Map Response */
161 static int hf_idn_entry_size;
162 static int hf_idn_relay_count;
163 static int hf_idn_service_count;
164 static int hf_idn_relay_number;
166 /* Channel Message Header */
167 static int hf_idn_cnl;
168 static int hf_idn_most_significant_bit_cnl;
169 static int hf_idn_cclf;
170 static int hf_idn_channel_id;
171 static int hf_idn_chunk_type;
172 static int hf_idn_timestamp;
174 /* Configuration Header */
175 static int hf_idn_scwc;
176 static int hf_idn_cfl;
177 static int hf_idn_sdm;
178 static int hf_idn_close;
179 static int hf_idn_routing;
180 static int hf_idn_service_id;
181 static int hf_idn_service_mode;
183 /* Chunk Header */
184 static int hf_idn_chunk_header_flags;
185 static int hf_idn_two_bits_reserved_1;
186 static int hf_idn_two_bits_reserved_2;
187 static int hf_idn_three_bits_reserved;
188 static int hf_idn_four_bits_reserved;
189 static int hf_idn_scm;
190 static int hf_idn_once;
191 static int hf_idn_duration;
192 static int hf_idn_chunk_data_sequence;
193 static int hf_idn_offset;
194 static int hf_idn_dlim;
195 static int hf_idn_reserved;
197 /* Tags */
198 static int hf_idn_gts;
199 static int hf_idn_gts_void;
200 static int hf_idn_boundary;
201 static int hf_idn_gts_word;
202 static int hf_idn_gts_break;
203 static int hf_idn_gts_space_modifier;
204 static int hf_idn_gts_hint;
205 static int hf_idn_gts_category;
206 static int hf_idn_gts_subcategory;
207 static int hf_idn_gts_identifier;
208 static int hf_idn_gts_parameter;
209 static int hf_idn_gts_glin;
210 static int hf_idn_gts_clin;
211 static int hf_idn_gts_cbal;
212 static int hf_idn_gts_ctim;
213 static int hf_idn_gts_nop;
214 static int hf_idn_gts_precision;
215 static int hf_idn_gts_cscl;
216 static int hf_idn_gts_iscl;
217 static int hf_idn_gts_sht;
218 static int hf_idn_gts_u4;
219 static int hf_idn_gts_x;
220 static int hf_idn_gts_y;
221 static int hf_idn_gts_z;
222 static int hf_idn_gts_color;
223 static int hf_idn_gts_wavelength_prefix;
224 static int hf_idn_gts_intensity;
225 static int hf_idn_gts_beam_brush;
226 static int hf_idn_gts_sample;
227 static int hf_idn_dmx_octet;
228 static int hf_idn_dmx_identifier;
229 static int hf_idn_dmx_parameter;
230 static int hf_idn_dmx_void;
231 static int hf_idn_octet;
232 static int hf_idn_dmx_base;
233 static int hf_idn_dmx_count;
234 static int hf_idn_dmx_dls;
235 static int hf_idn_dmx_unknown;
237 /* Acknowledgement */
238 static int hf_idn_result_code;
239 static int hf_idn_event_flags;
241 static const value_string command_code[] = {
242 { IDNCMD_VOID, "VOID" },
243 { IDNCMD_PING_REQUEST, "PING_REQUEST" },
244 { IDNCMD_PING_RESPONSE, "PING_RESPONSE" },
245 { IDNCMD_SCAN_REQUEST, "SCAN_REQUEST" },
246 { IDNCMD_SCAN_RESPONSE, "SCAN_RESPONSE" },
247 { IDNCMD_SERVICEMAP_REQUEST, "SERVICEMAP_REQUEST" },
248 { IDNCMD_SERVICEMAP_RESPONSE, "SERVICEMAP_RESPONSE" },
249 { IDNCMD_MESSAGE, "MESSAGE" },
250 { IDNCMD_MESSAGE_ACKREQ, "MESSAGE_ACKREQ" },
251 { IDNCMD_MESSAGE_CLOSE, "MESSAGE_CLOSE" },
252 { IDNCMD_MESSAGE_ACKREQ_CLOSE, "MESSAGE_ACKREQ_CLOSE" },
253 { IDNCMD_MESSAGE_ACK, "MESSAGE_ACK" },
254 { 0, NULL}
256 static const value_string chunk_type[] = {
257 { IDNCT_VOID, "VOID" },
258 { IDNCT_LP_WAVE_SAMPLE, "Laser Projector Wave Samples" },
259 { IDNCT_LP_FRAME_CHUNK, "Laser Projector Frame Samples (entire chunk)" },
260 { IDNCT_LP_FRAME_FF, "Laser Projector Frame Samples (first fragment)" },
261 { IDNCT_OCTET_SEGMENT, "Octet Segment" },
262 { IDNCT_OCTET_STRING, "Octet String" },
263 { IDNCT_DIMMER_LEVELS, "Dimmer Levels" },
264 { IDNCT_LP_FRAME_SF, "Laser Projector Frame Samples (sequel fragment)" },
265 { 0, NULL}
267 static const value_string cfl_string[] = {
268 { 0x30, "DATA_MATCH" },
269 { 0x01, "ROUTING" },
270 { 0x02, "CLOSE" },
271 { 0, NULL}
273 static const value_string service_mode_string[] = {
274 { IDNSM_VOID, "VOID" },
275 { IDNSM_LP_GRAPHIC_CONT, "Laser Projector Graphic (Continuous)" },
276 { IDNSM_LP_GRAPHIC_DISC, "Laser Projector Graphic (Discrete)" },
277 { IDNSM_LP_EFFECTS_CONT, "Laser Projector Effects (Continuous)" },
278 { IDNSM_LP_EFFECTS_DISC, "Laser Projector Effects (Discrete)" },
279 { IDNSM_DMX512_CONT, "DMX512 (Continuous)" },
280 { IDNSM_DMX512_DISC, "DMX512 (Discrete)" },
281 { 0, NULL}
283 static const value_string gts_glin[] = {
284 { 0, "Projector specific" },
285 { 1, "Geometrically corrected and linear, aspect ratio 1:1" },
286 { 2, "Reserved" },
287 { 3, "No transformation" },
288 { 0, NULL}
290 static const value_string gts_clin[] = {
291 { 0, "Projector specific" },
292 { 1, "Power linear (half value SHALL be half power)" },
293 { 2, "Visually linear (half value SHALL be half brightness)" },
294 { 3, "No transformation" },
295 { 0, NULL}
297 static const value_string gts_cbal[] = {
298 { 0, "Projector specific" },
299 { 1, "White balanced" },
300 { 2, "Reserved" },
301 { 3, "No transformation" },
302 { 0, NULL}
304 static const value_string gts_ctim[] = {
305 { 0, "Projector specific" },
306 { 1, "Coordinates and colors correlated in time" },
307 { 2, "Reserved" },
308 { 3, "No transformation" },
309 { 0, NULL}
311 static const value_string idn_color[] = {
312 { 638, "Red" },
313 { 532, "Green" },
314 { 460, "Blue" },
315 { 445, "Optional(U1), used as deep blue" },
316 { 577, "Optional(U2), used as yellow" },
317 { 488, "Optional(U3), used as cyan" },
318 { 0, NULL}
320 static const value_string result_code[] = {
321 { 0x00, "Message successfully received and passed to the IDN session" },
322 { 0xEB, "Empty (no message) close command without established connection" },
323 { 0xEC, "All sessions are occupied by clients (new connection refused)" },
324 { 0xED, "The client group is excluded from streaming" },
325 { 0xEE, "Invalid payload" },
326 { 0xEF, "Any other processing error" },
327 { 0, NULL}
330 static int get_service_match(uint8_t flags) {
331 return flags >> 4;
334 static void determine_message_type(packet_info *pinfo, message_info *minfo) {
335 minfo->is_dmx = 0;
336 switch(minfo->chunk_type) {
337 case IDNCT_VOID:
338 col_append_str(pinfo->cinfo, COL_INFO, "-VOID");
339 break;
340 case IDNCT_LP_WAVE_SAMPLE:
341 col_append_str(pinfo->cinfo, COL_INFO, "-WAVE");
342 break;
343 case IDNCT_LP_FRAME_CHUNK:
344 col_append_str(pinfo->cinfo, COL_INFO, "-FRAME");
345 break;
346 case IDNCT_LP_FRAME_FF:
347 col_append_str(pinfo->cinfo, COL_INFO, "-FIRST");
348 break;
349 case IDNCT_DIMMER_LEVELS:
350 col_append_str(pinfo->cinfo, COL_INFO, "-DMX");
351 minfo->is_dmx = 1;
352 break;
353 case IDNCT_OCTET_STRING:
354 col_append_str(pinfo->cinfo, COL_INFO, "-DMX");
355 minfo->is_dmx = 1;
356 break;
357 case IDNCT_OCTET_SEGMENT:
358 col_append_str(pinfo->cinfo, COL_INFO, "-DMX");
359 minfo->is_dmx = 1;
360 break;
361 case IDNCT_LP_FRAME_SF:
362 if(minfo->has_config_header) {
363 col_append_str(pinfo->cinfo, COL_INFO, "-LAST");
364 }else {
365 col_append_str(pinfo->cinfo, COL_INFO, "-SEQ");
367 break;
368 default:
369 col_append_str(pinfo->cinfo, COL_INFO, "-UNKNOWN");
373 static void determine_color(uint16_t catsub, configuration_info *config) {
374 char *column_str = config->sample_column_string;
375 const int l = (const int)strlen(column_str);
376 switch(catsub) {
377 case IDNTAG_COLOR_RED:
378 snprintf(column_str+l, MAX_BUFFER-l, " R");
379 break;
380 case IDNTAG_COLOR_GREEN:
381 snprintf(column_str+l, MAX_BUFFER-l, " G");
382 break;
383 case IDNTAG_COLOR_BLUE:
384 snprintf(column_str+l, MAX_BUFFER-l, " B");
385 break;
386 case IDNTAG_OPTIONAL_U1:
387 snprintf(column_str+l, MAX_BUFFER-l, " U1");
388 break;
389 case IDNTAG_OPTIONAL_U2:
390 snprintf(column_str+l, MAX_BUFFER-l, " U2");
391 break;
392 case IDNTAG_OPTIONAL_U3:
393 snprintf(column_str+l, MAX_BUFFER-l, " U3");
394 break;
395 default:
396 snprintf(column_str+l, MAX_BUFFER-l, " C");
400 static int dissect_idn_message_acknowledgement(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
401 proto_tree *idn_message_acknowledgement_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_idn_header_tree, NULL, "Message Acknowledgement");
402 proto_tree_add_item(idn_message_acknowledgement_tree, hf_idn_struct_size, tvb, offset, 1, ENC_BIG_ENDIAN);
403 offset += 1;
404 proto_tree_add_item(idn_message_acknowledgement_tree, hf_idn_result_code, tvb, offset, 1, ENC_BIG_ENDIAN);
405 offset += 1;
406 proto_tree_add_item(idn_message_acknowledgement_tree, hf_idn_event_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
407 offset += 2;
408 return offset;
411 static configuration_info *get_configuration_info(packet_info *pinfo, int channel_id) {
412 configuration_info *config = NULL;
414 conversation_element_t *conv_key = wmem_alloc_array(pinfo->pool, conversation_element_t, 6);
415 conv_key[0].type = CE_ADDRESS;
416 conv_key[0].addr_val = pinfo->src;
417 conv_key[1].type = CE_PORT;
418 conv_key[1].port_val = pinfo->srcport;
419 conv_key[2].type = CE_ADDRESS;
420 conv_key[2].addr_val = pinfo->dst;
421 conv_key[3].type = CE_PORT;
422 conv_key[3].port_val = pinfo->destport;
423 conv_key[4].type = CE_UINT;
424 conv_key[4].uint_val = channel_id;
425 conv_key[5].type = CE_CONVERSATION_TYPE;
426 conv_key[5].conversation_type_val = CONVERSATION_IDN;
428 conversation_t *conv = find_conversation_full(pinfo->num, conv_key);
429 if(conv) {
430 wmem_tree_t *config_tree = (wmem_tree_t*)conversation_get_proto_data(conv, proto_idn);
431 if (config_tree) {
432 config = (configuration_info *)wmem_tree_lookup32_le(config_tree, pinfo->num);
435 if(!config)
436 col_append_str(pinfo->cinfo, COL_INFO, ", no valid Configuration");
437 return config;
440 static int dissect_idn_dmx_sample_values(tvbuff_t *tvb, int offset, proto_tree *idn_dmx_subtree, uint16_t data_size, int base) {
441 int i, j, l;
442 short int rest;
443 char values[MAX_BUFFER];
445 for(i=0; i+16<=data_size; i+=16) {
446 l = 0;
447 for(j=1; j<16; j++){
448 l += snprintf(values+l, MAX_BUFFER-l, " %3d", tvb_get_uint8(tvb, offset+j));
450 proto_tree_add_int_format(idn_dmx_subtree, hf_idn_gts_sample, tvb, offset, 16, 16, "%3d: %s", base+i, values);
451 offset += 16;
453 rest = data_size - i;
454 if(rest > 0) {
455 l = 0;
456 for(j=0; j<rest; j++){
457 l += snprintf(values+l, MAX_BUFFER-l, " %3d", tvb_get_uint8(tvb, offset+j));
459 proto_tree_add_int_format(idn_dmx_subtree, hf_idn_gts_sample, tvb, offset, rest, rest, "%3d: %s", base+i, values);
460 offset += rest;
462 return offset;
465 static void set_laser_sample_values_string(tvbuff_t *tvb, int offset, configuration_info *config, char *values) {
466 int i;
467 int l = 0;
469 if((config->dic_precision)[2] == 1)
470 l += snprintf(values, MAX_BUFFER, "%5d", tvb_get_uint16(tvb, offset, 2));
471 else
472 l += snprintf(values, MAX_BUFFER, "%5d", tvb_get_uint8(tvb, offset));
474 for(i=1; i<config->sample_size && (l < MAX_BUFFER-100); i++){
475 if((config->dic_precision)[i+1] == 1) {
476 //do nothing
477 }else if((config->dic_precision)[i+2] == 1) {
478 l += snprintf(values+l, MAX_BUFFER-l, " %5d", tvb_get_uint16(tvb, offset+i, 2));
479 i++;
480 }else {
481 l += snprintf(values+l, MAX_BUFFER-l, " %5d", tvb_get_uint8(tvb, offset+i));
486 static int dissect_idn_octet_segment(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
487 int i, j, l;
488 short int rest;
489 char values[MAX_BUFFER];
490 values[0] = '\0';
491 int data_size = tvb_reported_length_remaining(tvb, offset);
492 proto_tree *idn_samples_tree = proto_tree_add_subtree(idn_tree, tvb, offset, data_size, ett_data, NULL, "Octets");
494 for(i=0; i+16<=data_size; i+=16) {
495 l = 0;
496 for(j=0; j<16 && (l < MAX_BUFFER-100); j++){
497 l += snprintf(values+l, MAX_BUFFER-l, " %3d", tvb_get_int8(tvb, offset+j));
499 proto_tree_add_int_format(idn_samples_tree, hf_idn_gts_sample, tvb, offset, 16, 16, "%s", values);
500 offset += 16;
502 rest = data_size - i;
503 if(rest > 0) {
504 l = 0;
505 for(j=0; j<rest && (l < MAX_BUFFER-100); j++){
506 l += snprintf(values+l, MAX_BUFFER-l, " %3d", tvb_get_int8(tvb, offset+j));
508 proto_tree_add_int_format(idn_samples_tree, hf_idn_gts_sample, tvb, offset, rest, rest, "%s", values);
509 offset += rest;
511 return offset;
514 static int dissect_idn_dmx_data(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *idn_tree, configuration_info *config) {
515 int i;
516 int *count = config->count;
517 int *base = config->base;
518 int base_value;
519 int data_size = tvb_reported_length_remaining(tvb, offset);
520 proto_tree *idn_samples_tree = proto_tree_add_subtree(idn_tree, tvb, offset, data_size, ett_data, NULL, "Channels");
521 proto_tree *idn_dmx_subtree;
523 for(i=0; i<config->word_count; i++) {
524 base_value = base[i]-1;
525 if(base_value == -1)
526 break;
527 if(count[i] != -1) {
528 data_size = count[i];
529 if(data_size + base_value > MAX_CHANNELS) {
530 col_append_fstr(pinfo->cinfo, COL_INFO, " (Error: over %5d Channels)", MAX_CHANNELS);
531 return offset;
533 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);
534 }else {
535 int base_size = MAX_CHANNELS - base_value;
536 data_size = tvb_reported_length_remaining(tvb, offset);
537 if(data_size > base_size) {
538 data_size = base_size;
540 if(data_size + base_value > MAX_CHANNELS) {
541 data_size = MAX_CHANNELS - base_value;
543 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);
545 offset = dissect_idn_dmx_sample_values(tvb, offset, idn_dmx_subtree, data_size, base_value);
547 return offset;
550 static int dissect_idn_laser_data(tvbuff_t *tvb, int offset, proto_tree *idn_tree, configuration_info *config) {
551 char values[MAX_BUFFER];
552 values[0] = '\0';
553 int i;
554 int laser_data_size = tvb_reported_length_remaining(tvb, offset);
556 if (config->sample_size == 0) {
557 /* TODO: log expert info error? */
558 return 0;
561 int sample_size = laser_data_size/config->sample_size;
562 proto_tree *idn_samples_tree = proto_tree_add_subtree_format(idn_tree, tvb, offset, laser_data_size, ett_data, NULL, "Samples %s", config->sample_column_string);
563 proto_tree *idn_samples_subtree = NULL;
565 for(i=1; i<=sample_size; i++) {
566 if((i-1)%10 == 0 && i+10 > sample_size) {
567 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);
568 }else if((i-1)%10 == 0) {
569 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);
571 set_laser_sample_values_string(tvb, offset, config, values);
572 proto_tree_add_int_format(idn_samples_subtree, hf_idn_gts_sample, tvb, offset, config->sample_size, config->sample_size, "Sample %3d: %s", i, values);
573 offset += config->sample_size;
575 return offset;
578 static int dissect_idn_dimmer_levels_chunk_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
579 static int * const dimmer_levels_chunk_flags[] = {
580 &hf_idn_two_bits_reserved_1,
581 &hf_idn_scm,
582 &hf_idn_four_bits_reserved,
583 NULL
585 proto_tree *chunk_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_chunk_header_tree, NULL, "Dimmer Levels Chunk Header");
586 proto_tree_add_bitmask(chunk_header_tree, tvb, offset, hf_idn_chunk_header_flags, ett_chunk_header_flags, dimmer_levels_chunk_flags, ENC_BIG_ENDIAN);
587 offset += 1;
588 proto_tree_add_item(chunk_header_tree, hf_idn_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
589 offset += 1;
590 proto_tree_add_item(chunk_header_tree, hf_idn_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
591 offset += 1;
592 proto_tree_add_item(chunk_header_tree, hf_idn_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
593 offset += 1;
594 return offset;
597 static int dissect_idn_octet_string_chunk_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
598 static int * const octet_string_chunk_flags[] = {
599 &hf_idn_two_bits_reserved_1,
600 &hf_idn_scm,
601 &hf_idn_four_bits_reserved,
602 NULL
604 proto_tree *chunk_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_chunk_header_tree, NULL, "Octet String Chunk Header");
605 proto_tree_add_bitmask(chunk_header_tree, tvb, offset, hf_idn_chunk_header_flags, ett_chunk_header_flags, octet_string_chunk_flags, ENC_BIG_ENDIAN);
606 offset += 1;
607 proto_tree_add_item(chunk_header_tree, hf_idn_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
608 offset += 1;
609 proto_tree_add_item(chunk_header_tree, hf_idn_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
610 offset += 1;
611 proto_tree_add_item(chunk_header_tree, hf_idn_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
612 offset += 1;
613 return offset;
616 static int dissect_idn_octet_segment_chunk_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
617 static int * const octet_segment_chunk_flags[] = {
618 &hf_idn_two_bits_reserved_1,
619 &hf_idn_scm,
620 &hf_idn_three_bits_reserved,
621 &hf_idn_dlim,
622 NULL
624 proto_tree *chunk_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_chunk_header_tree, NULL, "Octet Segment Chunk Header");
625 proto_tree_add_bitmask(chunk_header_tree, tvb, offset, hf_idn_chunk_header_flags, ett_chunk_header_flags, octet_segment_chunk_flags, ENC_BIG_ENDIAN);
626 offset += 1;
627 proto_tree_add_item(chunk_header_tree, hf_idn_chunk_data_sequence, tvb, offset, 1, ENC_BIG_ENDIAN);
628 offset += 1;
629 proto_tree_add_item(chunk_header_tree, hf_idn_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
630 offset += 2;
631 return offset;
634 static int dissect_idn_frame_chunk_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
635 static int * const frame_sample_chunk_flags[] = {
636 &hf_idn_two_bits_reserved_1,
637 &hf_idn_scm,
638 &hf_idn_three_bits_reserved,
639 &hf_idn_once,
640 NULL
642 proto_tree *chunk_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_chunk_header_tree, NULL, "Frame Sample Chunk Header");
643 proto_tree_add_bitmask(chunk_header_tree, tvb, offset, hf_idn_chunk_header_flags, ett_chunk_header_flags, frame_sample_chunk_flags, ENC_BIG_ENDIAN);
644 offset += 1;
645 proto_tree_add_item(chunk_header_tree, hf_idn_duration, tvb, offset, 3, ENC_BIG_ENDIAN);
646 offset += 3;
647 return offset;
650 static int dissect_idn_wave_chunk_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
651 static int * const wave_sample_chunk_flags[] = {
652 &hf_idn_two_bits_reserved_1,
653 &hf_idn_scm,
654 &hf_idn_four_bits_reserved,
655 NULL
657 proto_tree *chunk_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_chunk_header_tree, NULL, "Wave Sample Chunk Header");
658 proto_tree_add_bitmask(chunk_header_tree, tvb, offset, hf_idn_chunk_header_flags, ett_chunk_header_flags, wave_sample_chunk_flags, ENC_BIG_ENDIAN);
659 offset += 1;
660 proto_tree_add_item(chunk_header_tree, hf_idn_duration, tvb, offset, 3, ENC_BIG_ENDIAN);
661 offset += 3;
662 return offset;
665 static int dissect_idn_chunk_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree, message_info *minfo) {
666 switch(minfo->chunk_type) {
667 case IDNCT_LP_WAVE_SAMPLE:
668 offset = dissect_idn_wave_chunk_header(tvb, offset, idn_tree);
669 break;
670 case IDNCT_LP_FRAME_CHUNK:
671 offset = dissect_idn_frame_chunk_header(tvb, offset, idn_tree);
672 break;
673 case IDNCT_LP_FRAME_FF:
674 offset = dissect_idn_frame_chunk_header(tvb, offset, idn_tree);
675 break;
676 case IDNCT_OCTET_SEGMENT:
677 offset = dissect_idn_octet_segment_chunk_header(tvb, offset, idn_tree);
678 break;
679 case IDNCT_OCTET_STRING:
680 offset = dissect_idn_octet_string_chunk_header(tvb, offset, idn_tree);
681 break;
682 case IDNCT_DIMMER_LEVELS:
683 offset = dissect_idn_dimmer_levels_chunk_header(tvb, offset, idn_tree);
684 break;
685 default:
686 return offset;
688 return offset;
691 static int dissect_idn_dmx_gts(tvbuff_t *tvb, int offset, proto_tree *gts_tree, const int hf_hdr, int *dictionary_size) {
692 static int * const gts[] = {
693 &hf_idn_dmx_identifier,
694 &hf_idn_dmx_parameter,
695 NULL
697 proto_tree_add_bitmask(gts_tree, tvb, offset, hf_hdr, ett_dic, gts, ENC_BIG_ENDIAN);
698 offset++;
699 if(dictionary_size)
700 (*dictionary_size)++;
702 return offset;
705 static int dissect_idn_dimmer_level_subset(tvbuff_t *tvb, int offset, proto_tree *gts_tree, configuration_info *config, int i, int *dictionary_size) {
706 uint8_t dls = tvb_get_uint8(tvb, offset);
707 offset = dissect_idn_dmx_gts(tvb, offset, gts_tree, hf_idn_dmx_dls, dictionary_size);
709 if(dls & 2) {
710 proto_tree_add_item(gts_tree, hf_idn_dmx_base, tvb, offset, 2, ENC_BIG_ENDIAN);
711 config->base[i-1] = tvb_get_uint16(tvb, offset, 2);
712 offset += 2;
713 (*dictionary_size) += 2;
714 if(dls & 1) {
715 proto_tree_add_item(gts_tree, hf_idn_dmx_count, tvb, offset, 1, ENC_BIG_ENDIAN);
716 config->count[i-1] = tvb_get_uint8(tvb, offset);
717 offset++;
718 (*dictionary_size)++;
719 }else {
720 config->count[i-1] = -1;
724 return offset;
727 static int dissect_idn_dmx_dictionary(tvbuff_t *tvb, int offset, proto_tree *idn_tree, configuration_info *config) {
728 int i, j, curr_size;
729 bool words_found = 0;
730 int dictionary_size = 0;
731 uint8_t idepar; /* idetifier + parameter */
732 proto_tree *gts_tree = proto_tree_add_subtree(idn_tree, tvb, offset, -1, ett_dic_tree, NULL, "Dictionary");
734 for(i=1; i<=config->word_count; i++) {
735 idepar = tvb_get_uint8(tvb, offset);
737 if(idepar <= IDNO_VOID_AREA) {
738 if(idepar == 0) {
739 proto_tree_add_item(gts_tree, hf_idn_dmx_void, tvb, offset, 1, ENC_BIG_ENDIAN);
740 offset += 1;
741 dictionary_size += 1;
742 if(!words_found)
743 i -= 1;
744 }else {
745 offset = dissect_idn_dmx_gts(tvb, offset, gts_tree, hf_idn_dmx_unknown, NULL);
746 for(j=1; j<=idepar; j++) {
747 proto_tree_add_item(gts_tree, hf_idn_octet, tvb, offset, 1, ENC_BIG_ENDIAN);
748 offset += 1;
749 dictionary_size += 1;
750 if(words_found)
751 i += 1;
753 if(!words_found)
754 i -= 1;
756 }else if(idepar >= IDNTAG_DIMMER_START && idepar <= IDNTAG_DIMMER_END) {
757 offset = dissect_idn_dimmer_level_subset(tvb, offset, gts_tree, config, i, &dictionary_size);
758 }else {
759 offset = dissect_idn_dmx_gts(tvb, offset, gts_tree, hf_idn_dmx_unknown, &dictionary_size);
762 if(i == config->word_count && !words_found) {
763 curr_size = dictionary_size;
764 while(curr_size%4 != 0 && i > 0) {
765 i -= 1;
766 curr_size += 1;
768 words_found = 1;
771 proto_item_set_len(gts_tree, dictionary_size);
773 return offset;
776 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) {
777 static int * const gts[] = {
778 &hf_idn_gts_category,
779 &hf_idn_gts_subcategory,
780 &hf_idn_gts_identifier,
781 &hf_idn_gts_parameter,
782 NULL
785 proto_tree_add_bitmask(gts_tree, tvb, offset, hf_hdr, ett_dic, gts, ENC_BIG_ENDIAN);
787 if(dictionary_size)
788 *dictionary_size += 2;
789 if(config && is_sample)
790 config->sample_size++;
792 return offset + 2;
795 static int dissect_idn_x_area(tvbuff_t *tvb, int offset, proto_tree *gts_tree, uint16_t catsub, int *dictionary_size, configuration_info *config) {
796 char *column_str = config->sample_column_string;
797 const int l = (const int)strlen(column_str);
799 if(catsub == IDNTAG_OPTIONAL_U4) {
800 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_u4, dictionary_size, config, 1);
801 snprintf(column_str+l, MAX_BUFFER-l, " U4");
802 }else {
803 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_x, dictionary_size, config, 1);
804 snprintf(column_str+l, MAX_BUFFER-l, " X");
807 return offset;
810 static int dissect_idn_laser_dictionary(tvbuff_t *tvb, int offset, proto_tree *idn_tree, configuration_info *config) {
811 int i, j;
812 int dictionary_size = 0;
813 char *column_str = config->sample_column_string;
814 uint16_t catsub; /* category + subcategory */
815 proto_tree *gts_tree = proto_tree_add_subtree(idn_tree, tvb, offset, -1, ett_dic_tree, NULL, "Dictionary");
817 snprintf(column_str, MAX_BUFFER, "(");
818 for(i=1; i<=config->word_count*2; i++) {
819 catsub = tvb_get_uint16(tvb, offset, 2);
820 const int l = (const int)strlen(column_str);
822 if(catsub <= IDNO_VOID_AREA) {
823 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_void, &dictionary_size, config, 0);
824 if(catsub > 0) {
825 for(j=0; j<catsub; j++) {
826 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_void, &dictionary_size, config, 0);
829 }else if(catsub == IDNTAG_PRECISION) {
830 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_precision, &dictionary_size, config, 1);
831 (config->dic_precision)[i] = 1;
832 }else if(catsub >= IDNTAG_BREAK_START && catsub <= IDNTAG_BREAK_END) {
833 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_break, &dictionary_size, config, 0);
834 }else if(catsub >= IDNTAG_SPACE_MOD_START && catsub <= IDNTAG_SPACE_MOD_END) {
835 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_space_modifier, &dictionary_size, config, 0);
836 }else if(catsub == IDNTAG_NOP) {
837 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_nop, &dictionary_size, config, 1);
838 snprintf(column_str+l, MAX_BUFFER-l, " NOP");
839 }else if(catsub >= IDNTAG_HINT0 && catsub <= IDNTAG_HINT1) {
840 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_hint, &dictionary_size, config, 1);
841 snprintf(column_str+l, MAX_BUFFER-l, " H");
842 }else if(catsub >= IDNTAG_COORD_X && catsub <= IDNTAG_COORD_X_END) {
843 offset = dissect_idn_x_area(tvb, offset, gts_tree, catsub, &dictionary_size, config);
844 }else if(catsub >= IDNTAG_COORD_Y && catsub <= IDNTAG_COORD_Y_END) {
845 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_y, &dictionary_size, config, 1);
846 snprintf(column_str+l, MAX_BUFFER-l, " Y");
847 }else if(catsub >= IDNTAG_COORD_Z && catsub <= IDNTAG_COORD_Z_END) {
848 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_z, &dictionary_size, config, 1);
849 snprintf(column_str+l, MAX_BUFFER-l, " Z");
850 }else if(catsub >= IDNTAG_COLOR_START && catsub <= IDNTAG_COLOR_END) {
851 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_color, &dictionary_size, config, 1);
852 determine_color(catsub, config);
853 }else if(catsub == IDNTAG_WAVELENGTH_PREFIX) {
854 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_wavelength_prefix, &dictionary_size, config, 1);
855 snprintf(column_str+l, MAX_BUFFER-l, " WP");
856 }else if(catsub == IDNTAG_INTENSITY) {
857 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_intensity, &dictionary_size, config, 1);
858 snprintf(column_str+l, MAX_BUFFER-l, " I");
859 }else if(catsub == IDNTAG_BEAM_BRUSH) {
860 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts_beam_brush, &dictionary_size, config, 1);
861 snprintf(column_str+l, MAX_BUFFER-l, " BB");
862 }else {
863 offset = dissect_idn_laser_gts(tvb, offset, gts_tree, hf_idn_gts, &dictionary_size, config, 1);
864 snprintf(column_str+l, MAX_BUFFER-l, " U/R");
867 proto_item_set_len(gts_tree, dictionary_size);
868 const int l = (const int)strlen(column_str);
869 snprintf(column_str+l, MAX_BUFFER-l, " )");
871 return offset;
874 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) {
875 conversation_t *conv;
876 uint8_t word_count;
877 uint8_t sdm;
878 static int * const channel_and_service_configuration_flags[] = {
879 &hf_idn_two_bits_reserved_1,
880 &hf_idn_sdm,
881 &hf_idn_two_bits_reserved_2,
882 &hf_idn_close,
883 &hf_idn_routing,
884 NULL
887 col_append_str(pinfo->cinfo, COL_INFO, " (Configuration Header)");
888 proto_tree *configuration_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 4, ett_configuration_header, NULL, "Channel Configuration Header");
889 proto_tree_add_item(configuration_header_tree, hf_idn_scwc, tvb, offset, 1, ENC_BIG_ENDIAN);
890 word_count = tvb_get_uint8(tvb, offset);
891 offset += 1;
892 proto_tree_add_bitmask(configuration_header_tree, tvb, offset, hf_idn_cfl, ett_cfl, channel_and_service_configuration_flags, ENC_BIG_ENDIAN);
893 sdm = get_service_match(tvb_get_uint8(tvb, offset));
894 offset += 1;
895 proto_tree_add_item(configuration_header_tree, hf_idn_service_id, tvb, offset, 1, ENC_BIG_ENDIAN);
896 offset += 1;
897 proto_tree_add_item(configuration_header_tree, hf_idn_service_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
898 offset += 1;
901 conversation_element_t *conv_key = wmem_alloc_array(pinfo->pool, conversation_element_t, 6);
902 conv_key[0].type = CE_ADDRESS;
903 conv_key[0].addr_val = pinfo->src;
904 conv_key[1].type = CE_PORT;
905 conv_key[1].port_val = pinfo->srcport;
906 conv_key[2].type = CE_ADDRESS;
907 conv_key[2].addr_val = pinfo->dst;
908 conv_key[3].type = CE_PORT;
909 conv_key[3].port_val = pinfo->destport;
910 conv_key[4].type = CE_UINT;
911 conv_key[4].uint_val = channel_id;
912 conv_key[5].type = CE_CONVERSATION_TYPE;
913 conv_key[5].conversation_type_val = CONVERSATION_IDN;
915 configuration_info *config;
916 conv = find_conversation_full(pinfo->num, conv_key);
917 if (!(conv && conv->setup_frame == pinfo->num)) {
918 conv = conversation_new_full(pinfo->num, conv_key);
920 wmem_tree_t *config_tree = (wmem_tree_t*)conversation_get_proto_data(conv, proto_idn);
921 if (!config_tree) {
922 config_tree = wmem_tree_new(wmem_file_scope());
923 conversation_add_proto_data(conv, proto_idn, config_tree);
925 /* XXX: It wastes some memory to allocate a new configuration if it
926 * hasn't changed since the last time it was sent, so we could use
927 * lookup32_le and see if it's the same as the previous, but that
928 * requires doing so after parsing the rest of the configuration.
930 config = (configuration_info *)wmem_tree_lookup32(config_tree, pinfo->num);
931 if (config) {
932 /* sample size increments as we parse the dictionary, so reset.
933 * The other values shouldn't change, though we'll waste time
934 * overwriting the array with the same values.
936 config->sample_size = 0;
937 } else {
938 config = wmem_new0(wmem_file_scope(), configuration_info);
939 config->word_count = word_count;
940 config->sdm = sdm;
941 config->sample_size = 0;
942 config->dic_precision = wmem_alloc0_array(wmem_file_scope(), char, (255*2)+1);
943 config->sample_column_string = wmem_alloc0_array(wmem_file_scope(), char, MAX_BUFFER);
944 config->count = wmem_alloc0_array(wmem_file_scope(), int, word_count+1);
945 config->base = wmem_alloc0_array(wmem_file_scope(), int, word_count+1);
946 wmem_tree_insert32(config_tree, pinfo->num, config);
949 *config_p = config;
951 return offset;
954 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) {
955 offset = dissect_idn_channel_configuration_header(tvb, pinfo, offset, idn_tree, minfo->channel_id, config_p);
957 configuration_info *config = *config_p;
958 if(config->word_count > 0) {
959 if(minfo->chunk_type == IDNCT_OCTET_SEGMENT) {
960 return offset;
961 }else if(minfo->is_dmx) {
962 offset = dissect_idn_dmx_dictionary(tvb, offset, idn_tree, config);
963 }else {
964 offset = dissect_idn_laser_dictionary(tvb, offset, idn_tree, config);
968 return offset;
971 static int dissect_idn_message_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree, message_info *minfo) {
972 uint8_t cnl;
973 static int * const cnl_data[] = {
974 &hf_idn_most_significant_bit_cnl,
975 &hf_idn_cclf,
976 &hf_idn_channel_id,
977 NULL
980 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");
981 proto_tree_add_item(idn_channel_message_header_tree, hf_idn_total_size, tvb, offset, 2, ENC_BIG_ENDIAN);
982 minfo->total_size = tvb_get_uint16(tvb, offset, 2);
983 offset += 2;
984 proto_tree_add_bitmask(idn_channel_message_header_tree, tvb, offset, hf_idn_cnl, ett_idn_cnl, cnl_data, ENC_BIG_ENDIAN);
986 cnl = tvb_get_uint8(tvb, offset);
987 minfo->has_config_header = cnl & 0x40;
988 minfo->channel_id = cnl & 0x3f;
990 offset += 1;
991 proto_tree_add_item(idn_channel_message_header_tree, hf_idn_chunk_type, tvb, offset, 1, ENC_BIG_ENDIAN);
992 minfo->chunk_type = tvb_get_uint8(tvb, offset);
993 offset += 1;
994 proto_tree_add_item(idn_channel_message_header_tree, hf_idn_timestamp, tvb, offset, 4, ENC_BIG_ENDIAN);
995 offset += 4;
997 return offset;
1000 static int dissect_idn_message(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *idn_tree) {
1001 int scm;
1002 configuration_info *config = NULL;
1003 message_info *minfo = wmem_new(pinfo->pool, message_info);
1005 offset = dissect_idn_message_header(tvb, offset, idn_tree, minfo);
1006 determine_message_type(pinfo, minfo);
1007 if(minfo->total_size == 8)
1008 return offset;
1010 if(minfo->has_config_header && minfo->chunk_type != IDNCT_LP_FRAME_SF) {
1011 offset = dissect_idn_channel_configuration(tvb, pinfo, offset, idn_tree, minfo, &config);
1012 }else if(minfo->chunk_type != IDNCT_VOID) {
1013 config = get_configuration_info(pinfo, minfo->channel_id);
1016 if(config) {
1017 if(config->word_count == 0 && minfo->chunk_type != IDNCT_OCTET_SEGMENT) {
1018 col_append_str(pinfo->cinfo, COL_INFO, ", SCWC is zero/unknown");
1019 return offset;
1022 if(minfo->chunk_type != IDNCT_VOID && minfo->chunk_type != IDNCT_LP_FRAME_SF) {
1023 scm = get_service_match(tvb_get_uint8(tvb, offset));
1025 offset = dissect_idn_chunk_header(tvb, offset, idn_tree, minfo);
1027 if(config->sdm != scm) {
1028 col_append_str(pinfo->cinfo, COL_INFO, ", SCM doesn't match SDM");
1029 return offset;
1031 }else if(minfo->chunk_type == IDNCT_VOID) {
1032 return offset;
1035 if(minfo->chunk_type == IDNCT_OCTET_SEGMENT) {
1036 offset = dissect_idn_octet_segment(tvb, offset, idn_tree);
1037 }else if(minfo->is_dmx) {
1038 offset = dissect_idn_dmx_data(tvb, pinfo, offset, idn_tree, config);
1039 }else {
1040 offset = dissect_idn_laser_data(tvb, offset, idn_tree, config);
1043 return offset;
1046 static int dissect_idn_servicemap_entry(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
1047 uint8_t service_id = tvb_get_uint8(tvb, offset);
1048 proto_tree *idn_servicemap_entry_tree = NULL;
1049 char *name = (char *)tvb_get_string_enc(wmem_file_scope(), tvb, offset+4, 20, ENC_ASCII);
1051 char tree_title[MAX_BUFFER];
1052 if(service_id == 0) {
1053 snprintf(tree_title, MAX_BUFFER, "Relay Entry - %s", name);
1054 idn_servicemap_entry_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 24, ett_idn_header_tree, NULL, tree_title);
1055 }else {
1056 snprintf(tree_title, MAX_BUFFER, "Service Entry - %s", name);
1057 idn_servicemap_entry_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 24, ett_idn_header_tree, NULL, tree_title);
1060 proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_service_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1061 offset += 1;
1062 proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_service_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
1063 offset += 1;
1064 proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1065 offset += 1;
1066 proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_relay_number, tvb, offset, 1, ENC_BIG_ENDIAN);
1067 offset += 1;
1068 proto_tree_add_item(idn_servicemap_entry_tree, hf_idn_name, tvb, offset, 20, ENC_ASCII);
1069 offset += 20;
1070 return offset;
1073 static int dissect_idn_servicemap_response_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree, uint8_t *relay_count, uint8_t *service_count) {
1074 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");
1075 proto_tree_add_item(idn_servicemap_response_header_tree, hf_idn_struct_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1076 offset += 1;
1077 proto_tree_add_item(idn_servicemap_response_header_tree, hf_idn_entry_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1078 offset += 1;
1079 *relay_count = tvb_get_uint8(tvb, offset);
1080 proto_tree_add_item(idn_servicemap_response_header_tree, hf_idn_relay_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1081 offset += 1;
1082 *service_count = tvb_get_uint8(tvb, offset);
1083 proto_tree_add_item(idn_servicemap_response_header_tree, hf_idn_service_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1084 offset += 1;
1085 return offset;
1088 static int dissect_idn_servicemap_response(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
1089 uint8_t relay_count, service_count;
1090 uint16_t map_entries_size;
1092 offset = dissect_idn_servicemap_response_header(tvb, offset, idn_tree, &relay_count, &service_count);
1093 map_entries_size = relay_count + service_count;
1094 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");
1095 for(int i=0; i<map_entries_size; i++)
1096 offset = dissect_idn_servicemap_entry(tvb, offset, idn_servicemap_entries_tree);
1098 return offset;
1101 static int dissect_idn_scan_response(tvbuff_t *tvb, int offset, proto_tree *idn_tree) {
1102 static int * const protocol_version[] = {
1103 &hf_idn_protocol_version_major,
1104 &hf_idn_protocol_version_minor,
1105 NULL
1107 static int * const status[] = {
1108 &hf_idn_malfn,
1109 &hf_idn_offline,
1110 &hf_idn_xcld,
1111 &hf_idn_ocpd,
1112 &hf_idn_three_bits_reserved,
1113 &hf_idn_rt,
1114 NULL
1117 proto_tree *idn_scanreply_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, 40, ett_idn_header_tree, NULL, "Scan Response");
1118 proto_tree_add_item(idn_scanreply_header_tree, hf_idn_struct_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1119 offset += 1;
1120 proto_tree_add_bitmask(idn_scanreply_header_tree, tvb, offset, hf_idn_protocol_version, ett_protocol_version, protocol_version, ENC_BIG_ENDIAN);
1121 offset += 1;
1122 proto_tree_add_bitmask(idn_scanreply_header_tree, tvb, offset, hf_idn_status, ett_status, status, ENC_BIG_ENDIAN);
1123 offset += 1;
1124 proto_tree_add_item(idn_scanreply_header_tree, hf_idn_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
1125 offset += 1;
1126 proto_tree_add_item(idn_scanreply_header_tree, hf_idn_unit_id, tvb, offset, 16, ENC_NA);
1127 offset += 16;
1128 proto_tree_add_item(idn_scanreply_header_tree, hf_idn_name, tvb, offset, 20, ENC_ASCII);
1129 offset += 20;
1130 return offset;
1133 static int dissect_idn_header(tvbuff_t *tvb, int offset, proto_tree *idn_tree, uint8_t packet_type) {
1134 proto_tree *idn_header_tree = proto_tree_add_subtree(idn_tree, tvb, offset, -1, ett_idn_header_tree, NULL, "IDN Header");
1135 proto_tree_add_item(idn_header_tree, hf_idn_command, tvb, offset, 1, ENC_BIG_ENDIAN);
1136 offset += 1;
1137 if(packet_type == IDNCMD_VOID || packet_type == IDNCMD_PING_RESPONSE) {
1138 proto_item_set_len(idn_header_tree, offset);
1139 return offset;
1141 proto_tree_add_item(idn_header_tree, hf_idn_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1142 offset += 1;
1143 proto_tree_add_item(idn_header_tree, hf_idn_sequence, tvb, offset, 2, ENC_BIG_ENDIAN);
1144 offset += 2;
1145 proto_item_set_len(idn_header_tree, offset);
1146 return offset;
1149 static int dissect_idn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
1150 int offset = 0;
1151 uint8_t packet_type = tvb_get_uint8(tvb, 0);
1152 proto_item *ti = proto_tree_add_item(tree, proto_idn, tvb, 0, -1, ENC_NA);
1153 proto_tree *idn_tree = proto_item_add_subtree(ti, ett_idn);
1155 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IDN");
1156 col_clear(pinfo->cinfo, COL_INFO);
1157 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type, command_code, "Unknown (0x%02x)"));
1159 offset = dissect_idn_header(tvb, offset, idn_tree, packet_type);
1161 switch (packet_type) {
1162 case IDNCMD_SCAN_RESPONSE:
1163 dissect_idn_scan_response(tvb, offset, idn_tree);
1164 break;
1165 case IDNCMD_SERVICEMAP_RESPONSE:
1166 offset = dissect_idn_servicemap_response(tvb, offset, idn_tree);
1167 break;
1168 case IDNCMD_MESSAGE:
1169 case IDNCMD_MESSAGE_ACKREQ:
1170 case IDNCMD_MESSAGE_CLOSE:
1171 case IDNCMD_MESSAGE_ACKREQ_CLOSE:
1172 offset = dissect_idn_message(tvb, pinfo, offset, idn_tree);
1173 break;
1174 case IDNCMD_MESSAGE_ACK:
1175 offset = dissect_idn_message_acknowledgement(tvb, offset, idn_tree);
1176 break;
1177 default:
1178 break;
1181 return offset;
1184 void proto_register_idn(void) {
1185 static hf_register_info hf[] = {
1186 { &hf_idn_command,
1187 { "Command code", "idn.command",
1188 FT_UINT8, BASE_HEX,
1189 VALS(command_code), 0x0,
1190 NULL, HFILL }
1192 { &hf_idn_flags,
1193 { "Flags", "idn.flags",
1194 FT_UINT8, BASE_HEX,
1195 NULL, 0x0,
1196 NULL, HFILL }
1198 { &hf_idn_sequence,
1199 { "Sequence counter", "idn.sequence",
1200 FT_UINT16, BASE_DEC,
1201 NULL, 0x0,
1202 NULL, HFILL }
1204 { &hf_idn_total_size,
1205 { "Total Size", "idn.total_size",
1206 FT_UINT16, BASE_DEC,
1207 NULL, 0x0,
1208 NULL, HFILL }
1210 { &hf_idn_struct_size,
1211 { "Struct Size", "idn.struct_size",
1212 FT_UINT8, BASE_DEC,
1213 NULL, 0x0,
1214 NULL, HFILL }
1216 { &hf_idn_protocol_version,
1217 { "Protocol Version", "idn.protocol_version",
1218 FT_UINT8, BASE_DEC,
1219 NULL, 0x0,
1220 NULL, HFILL }
1222 { &hf_idn_protocol_version_major,
1223 { "Major", "idn.protocol_version_major",
1224 FT_UINT8, BASE_DEC,
1225 NULL, 0xF0,
1226 NULL, HFILL }
1228 { &hf_idn_protocol_version_minor,
1229 { "Minor", "idn.protocol_version_minor",
1230 FT_UINT8, BASE_DEC,
1231 NULL, 0x0F,
1232 NULL, HFILL }
1234 { &hf_idn_status,
1235 { "Status", "idn.status",
1236 FT_UINT8, BASE_HEX,
1237 NULL, 0x0,
1238 NULL, HFILL }
1240 { &hf_idn_malfn,
1241 { "Malfunction", "idn.status_malfn",
1242 FT_UINT8, BASE_DEC,
1243 NULL, 0x80,
1244 NULL, HFILL }
1246 { &hf_idn_offline,
1247 { "Offline", "idn.offline",
1248 FT_UINT8, BASE_DEC,
1249 NULL, 0x40,
1250 NULL, HFILL }
1252 { &hf_idn_xcld,
1253 { "Excluded", "idn.xcld",
1254 FT_UINT8, BASE_DEC,
1255 NULL, 0x20,
1256 NULL, HFILL }
1258 { &hf_idn_ocpd,
1259 { "Occupied", "idn.ocpd",
1260 FT_UINT8, BASE_DEC,
1261 NULL, 0x10,
1262 NULL, HFILL }
1264 { &hf_idn_rt,
1265 { "Realtime", "idn.rt",
1266 FT_UINT8, BASE_DEC,
1267 NULL, 0x1,
1268 NULL, HFILL }
1270 { &hf_idn_reserved8,
1271 { "Reserved", "idn.reserved8",
1272 FT_UINT8, BASE_HEX,
1273 NULL, 0x0,
1274 NULL, HFILL }
1276 { &hf_idn_unit_id,
1277 { "Unit ID", "idn.unit_id",
1278 FT_BYTES, SEP_SPACE,
1279 NULL, 0x0,
1280 NULL, HFILL }
1282 { &hf_idn_name,
1283 { "Name", "idn.name",
1284 FT_STRING, BASE_NONE,
1285 NULL, 0x0,
1286 NULL, HFILL }
1288 { &hf_idn_entry_size,
1289 { "Entry Size", "idn.entry_size",
1290 FT_UINT8, BASE_DEC,
1291 NULL, 0x0,
1292 NULL, HFILL }
1294 { &hf_idn_relay_count,
1295 { "Relay Count", "idn.relay_count",
1296 FT_UINT8, BASE_DEC,
1297 NULL, 0x0,
1298 NULL, HFILL }
1300 { &hf_idn_service_count,
1301 { "Service Count", "idn.service_count",
1302 FT_UINT8, BASE_DEC,
1303 NULL, 0x0,
1304 NULL, HFILL }
1306 { &hf_idn_cnl,
1307 { "Channel configuration and routing information (CNL)", "idn.cnl",
1308 FT_UINT8, BASE_HEX,
1309 NULL, 0x0,
1310 NULL, HFILL }
1312 { &hf_idn_most_significant_bit_cnl,
1313 { "Most significant bit (always 1)", "idn.most_significant_bit_cnl",
1314 FT_UINT8, BASE_DEC,
1315 NULL, 0x80,
1316 NULL, HFILL }
1318 { &hf_idn_cclf,
1319 { "Channel Configuration and Last Fragment bit (CCLF)", "idn.cclf",
1320 FT_UINT8, BASE_DEC,
1321 NULL, 0x40,
1322 NULL, HFILL }
1324 { &hf_idn_channel_id,
1325 { "Channel ID (opened Channels)", "idn.channel_id",
1326 FT_UINT8, BASE_DEC,
1327 NULL, 0x3F,
1328 NULL, HFILL }
1330 { &hf_idn_chunk_type,
1331 { "Chunk Type", "idn.chunk_type",
1332 FT_UINT8, BASE_HEX,
1333 VALS(chunk_type), 0x0,
1334 NULL, HFILL }
1336 { &hf_idn_timestamp,
1337 { "Timestamp", "idn.timestamp",
1338 FT_UINT32, BASE_DEC,
1339 NULL, 0x0,
1340 NULL, HFILL }
1342 { &hf_idn_scwc,
1343 { "Service Configuration Word Count (SCWC)", "idn.scwc",
1344 FT_UINT8, BASE_DEC,
1345 NULL, 0x0,
1346 NULL, HFILL }
1348 { &hf_idn_cfl,
1349 { "Channel and service configuration Flags (CFL)", "idn.cfl",
1350 FT_UINT8, BASE_HEX,
1351 VALS(cfl_string), 0x0,
1352 NULL, HFILL }
1354 { &hf_idn_sdm,
1355 { "Service Data Match (SDM)", "idn.sdm",
1356 FT_UINT8, BASE_DEC,
1357 NULL, 0x30,
1358 NULL, HFILL }
1360 { &hf_idn_close,
1361 { "Close", "idn.close",
1362 FT_UINT8, BASE_DEC,
1363 NULL, 0x2,
1364 NULL, HFILL }
1366 { &hf_idn_routing,
1367 { "Routing", "idn.routing",
1368 FT_UINT8, BASE_DEC,
1369 NULL, 0x1,
1370 NULL, HFILL }
1372 { &hf_idn_service_id,
1373 { "Service ID", "idn.service_id",
1374 FT_UINT8, BASE_HEX,
1375 NULL, 0x0,
1376 NULL, HFILL }
1378 { &hf_idn_relay_number,
1379 { "Relay Number", "idn.relay_number",
1380 FT_UINT8, BASE_HEX,
1381 NULL, 0x0,
1382 NULL, HFILL }
1384 { &hf_idn_service_mode,
1385 { "Service Mode", "idn.service_mode",
1386 FT_UINT8, BASE_HEX,
1387 VALS(service_mode_string), 0x0,
1388 NULL, HFILL }
1390 { &hf_idn_chunk_header_flags,
1391 { "Chunk Header Flags", "idn.chunk_header_flags",
1392 FT_UINT8, BASE_HEX,
1393 NULL, 0x0,
1394 NULL, HFILL }
1396 { &hf_idn_two_bits_reserved_1,
1397 { "Reserved", "idn.zero_zero",
1398 FT_UINT8, BASE_DEC,
1399 NULL, 0xC0,
1400 NULL, HFILL }
1402 { &hf_idn_two_bits_reserved_2,
1403 { "Reserved", "idn.zero_zero",
1404 FT_UINT8, BASE_DEC,
1405 NULL, 0xC,
1406 NULL, HFILL }
1408 { &hf_idn_scm,
1409 { "Service configuration match (SCM)", "idn.scm",
1410 FT_UINT8, BASE_DEC,
1411 NULL, 0x30,
1412 NULL, HFILL }
1414 { &hf_idn_three_bits_reserved,
1415 { "Reserved", "idn.three_bit_reserved",
1416 FT_UINT8, BASE_DEC,
1417 NULL, 0xE,
1418 NULL, HFILL }
1420 { &hf_idn_four_bits_reserved,
1421 { "Reserved", "idn.three_bit_reserved",
1422 FT_UINT8, BASE_DEC,
1423 NULL, 0xF,
1424 NULL, HFILL }
1426 { &hf_idn_once,
1427 { "Once", "idn.once",
1428 FT_UINT8, BASE_DEC,
1429 NULL, 0x1,
1430 NULL, HFILL }
1432 { &hf_idn_dlim,
1433 { "Delimiter (DLIM)", "idn.dlim",
1434 FT_UINT8, BASE_DEC,
1435 NULL, 0x1,
1436 NULL, HFILL }
1438 { &hf_idn_duration,
1439 { "Duration", "idn.frame_sample_duration",
1440 FT_UINT24, BASE_DEC,
1441 NULL, 0x0,
1442 NULL, HFILL }
1444 { &hf_idn_chunk_data_sequence,
1445 { "Sequence", "idn.octet_segment_sequence",
1446 FT_UINT8, BASE_DEC,
1447 NULL, 0x0,
1448 NULL, HFILL }
1450 { &hf_idn_offset,
1451 { "Offset", "idn.offset",
1452 FT_UINT16, BASE_HEX,
1453 NULL, 0x0,
1454 NULL, HFILL }
1456 { &hf_idn_reserved,
1457 { "Reserved", "idn.reserved",
1458 FT_UINT8, BASE_HEX,
1459 NULL, 0x0,
1460 NULL, HFILL }
1462 { &hf_idn_gts,
1463 { "Unknown", "idn.unknown",
1464 FT_UINT16, BASE_HEX,
1465 NULL, 0x0,
1466 NULL, HFILL }
1468 { &hf_idn_gts_void,
1469 { "Void", "idn.gts_void",
1470 FT_UINT16, BASE_HEX,
1471 NULL, 0x0,
1472 NULL, HFILL }
1474 { &hf_idn_boundary,
1475 { "Void (32-bit boundary)", "idn.gts_boundary",
1476 FT_UINT32, BASE_HEX,
1477 NULL, 0x0,
1478 NULL, HFILL }
1480 { &hf_idn_gts_word,
1481 { "16-bit word", "idn.gts_word",
1482 FT_UINT16, BASE_HEX,
1483 NULL, 0x0,
1484 NULL, HFILL }
1486 { &hf_idn_gts_break,
1487 { "Break", "idn.gts_break",
1488 FT_UINT16, BASE_HEX,
1489 NULL, 0x0,
1490 NULL, HFILL }
1492 { &hf_idn_gts_space_modifier,
1493 { "Space Modifier", "idn.gts_space_modifier",
1494 FT_UINT16, BASE_HEX,
1495 NULL, 0x0,
1496 NULL, HFILL }
1498 { &hf_idn_gts_hint,
1499 { "Hint", "idn.gts_hint",
1500 FT_UINT16, BASE_HEX,
1501 NULL, 0x0,
1502 NULL, HFILL }
1504 { &hf_idn_gts_category,
1505 { "Category", "idn.gts_category",
1506 FT_UINT16, BASE_DEC,
1507 NULL, 0xF000,
1508 NULL, HFILL }
1510 { &hf_idn_gts_subcategory,
1511 { "Subcategory", "idn.gts_subcategory",
1512 FT_UINT16, BASE_DEC,
1513 NULL, 0x0F00,
1514 NULL, HFILL }
1516 { &hf_idn_gts_identifier,
1517 { "Identifier", "idn.gts_identifier",
1518 FT_UINT16, BASE_DEC,
1519 NULL, 0x00F0,
1520 NULL, HFILL }
1522 { &hf_idn_gts_parameter,
1523 { "Parameter", "idn.gts_parameter",
1524 FT_UINT16, BASE_DEC,
1525 NULL, 0x000F,
1526 NULL, HFILL }
1528 { &hf_idn_gts_glin,
1529 { "Graphic Space Linearity (GLIN)", "idn.gts_glin",
1530 FT_UINT16, BASE_DEC,
1531 VALS(gts_glin), 0x00C0,
1532 NULL, HFILL }
1534 { &hf_idn_gts_clin,
1535 { "Color Space Linearity (CLIN)", "idn.gts_clin",
1536 FT_UINT16, BASE_DEC,
1537 VALS(gts_clin), 0x0030,
1538 NULL, HFILL }
1540 { &hf_idn_gts_cbal,
1541 { "Color Balance (CBAL)", "idn.gts_cbal",
1542 FT_UINT16, BASE_DEC,
1543 VALS(gts_cbal), 0x000C,
1544 NULL, HFILL }
1546 { &hf_idn_gts_ctim,
1547 { "Color Timing (CTIM)", "idn.gts_ctim",
1548 FT_UINT16, BASE_DEC,
1549 VALS(gts_ctim), 0x0003,
1550 NULL, HFILL }
1552 { &hf_idn_gts_nop,
1553 { "No Operation (NOP)", "idn.gts_nop",
1554 FT_UINT16, BASE_HEX,
1555 NULL, 0x0,
1556 NULL, HFILL }
1558 { &hf_idn_gts_precision,
1559 { "Precision", "idn.gts_precision",
1560 FT_UINT16, BASE_HEX,
1561 NULL, 0x0,
1562 NULL, HFILL }
1564 { &hf_idn_gts_cscl,
1565 { "Color scale (CSCL)", "idn.gts_cscl",
1566 FT_UINT16, BASE_DEC,
1567 NULL, 0x00C0,
1568 NULL, HFILL }
1570 { &hf_idn_gts_iscl,
1571 { "Intensity scale (ISCL)", "idn.gts_iscl",
1572 FT_UINT16, BASE_DEC,
1573 NULL, 0x0030,
1574 NULL, HFILL }
1576 { &hf_idn_gts_sht,
1577 { "Shutter (SHT)", "idn.gts_sht",
1578 FT_UINT16, BASE_DEC,
1579 NULL, 0x000F,
1580 NULL, HFILL }
1582 { &hf_idn_gts_u4,
1583 { "Optional(U4), used as X-prime", "idn.gts_u4",
1584 FT_UINT16, BASE_HEX,
1585 NULL, 0x0,
1586 NULL, HFILL }
1588 { &hf_idn_gts_x,
1589 { "X", "idn.gts_x",
1590 FT_UINT16, BASE_HEX,
1591 NULL, 0x0,
1592 NULL, HFILL }
1594 { &hf_idn_gts_y,
1595 { "Y", "idn.gts_y",
1596 FT_UINT16, BASE_HEX,
1597 NULL, 0x0,
1598 NULL, HFILL }
1600 { &hf_idn_gts_z,
1601 { "Z", "idn.gts_z",
1602 FT_UINT16, BASE_HEX,
1603 NULL, 0x0,
1604 NULL, HFILL }
1606 { &hf_idn_gts_color,
1607 { "Color", "idn.gts_color",
1608 FT_UINT16, BASE_DEC,
1609 VALS(idn_color), 0x03FF,
1610 NULL, HFILL }
1612 { &hf_idn_gts_wavelength_prefix,
1613 { "Wavelength Prefix", "idn.gts_wavelength_prefix",
1614 FT_UINT16, BASE_HEX,
1615 NULL, 0x0,
1616 NULL, HFILL }
1618 { &hf_idn_gts_intensity,
1619 { "Intensity/blanking", "idn.gts_intensity",
1620 FT_UINT16, BASE_HEX,
1621 NULL, 0x0,
1622 NULL, HFILL }
1624 { &hf_idn_gts_beam_brush,
1625 { "Beam-Brush", "idn.gts_beam_brush",
1626 FT_UINT16, BASE_HEX,
1627 NULL, 0x0,
1628 NULL, HFILL }
1630 { &hf_idn_gts_sample,
1631 { "Sample", "idn.gts_sample",
1632 FT_INT8, BASE_DEC,
1633 NULL, 0x0,
1634 NULL, HFILL }
1636 { &hf_idn_dmx_octet,
1637 { "Octet", "idn.gts_octet",
1638 FT_UINT8, BASE_DEC,
1639 NULL, 0x0,
1640 NULL, HFILL }
1642 { &hf_idn_dmx_identifier,
1643 { "Identifier", "idn.gts_dmx_identifier",
1644 FT_UINT8, BASE_DEC,
1645 NULL, 0xF0,
1646 NULL, HFILL }
1648 { &hf_idn_dmx_parameter,
1649 { "Parameter", "idn.gts_dmx_parameter",
1650 FT_UINT8, BASE_DEC,
1651 NULL, 0x0F,
1652 NULL, HFILL }
1654 { &hf_idn_dmx_void,
1655 { "Void", "idn.gts_dmx_void",
1656 FT_UINT8, BASE_HEX,
1657 NULL, 0x0,
1658 NULL, HFILL }
1660 { &hf_idn_octet,
1661 { "Octet", "idn.gts_dmx_octet",
1662 FT_UINT8, BASE_HEX,
1663 NULL, 0x0,
1664 NULL, HFILL }
1666 { &hf_idn_dmx_dls,
1667 { "Dimmer Level Subset", "idn.dmx_dls",
1668 FT_UINT8, BASE_HEX,
1669 NULL, 0x0,
1670 NULL, HFILL }
1672 { &hf_idn_dmx_base,
1673 { "Base", "idn.dmx_base",
1674 FT_UINT16, BASE_DEC,
1675 NULL, 0x0,
1676 NULL, HFILL }
1678 { &hf_idn_dmx_count,
1679 { "Count", "idn.dmx_count",
1680 FT_UINT8, BASE_DEC,
1681 NULL, 0x0,
1682 NULL, HFILL }
1684 { &hf_idn_dmx_unknown,
1685 { "Unknown", "idn.dmx_unknown",
1686 FT_UINT8, BASE_HEX,
1687 NULL, 0x0,
1688 NULL, HFILL }
1690 { &hf_idn_result_code,
1691 { "Result Code", "idn.result_code",
1692 FT_UINT8, BASE_DEC,
1693 VALS(result_code), 0x0,
1694 NULL, HFILL }
1696 { &hf_idn_event_flags,
1697 { "Event Flags", "idn.event_flags",
1698 FT_UINT16, BASE_HEX,
1699 NULL, 0x0,
1700 NULL, HFILL }
1704 static int *ett[] = {
1705 &ett_idn,
1706 &ett_idn_header_tree,
1707 &ett_idn_scanreply_header_tree,
1708 &ett_idn_channel_message_header_tree,
1709 &ett_protocol_version,
1710 &ett_status,
1711 &ett_idn_cnl,
1712 &ett_cfl,
1713 &ett_configuration_header,
1714 &ett_chunk_header_tree,
1715 &ett_chunk_header_flags,
1716 &ett_dic,
1717 &ett_dic_tree,
1718 &ett_data,
1719 &ett_subdata,
1720 &ett_dmx_subtree
1723 proto_idn = proto_register_protocol (
1724 "Ilda Digital Network Protocol",
1725 "IDN",
1726 "idn"
1729 proto_register_field_array(proto_idn, hf, array_length(hf));
1730 proto_register_subtree_array(ett, array_length(ett));
1732 idn_handle = register_dissector("idn", dissect_idn, proto_idn);
1735 void proto_reg_handoff_idn(void) {
1736 dissector_add_uint("udp.port", IDN_PORT, idn_handle);
1740 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1742 * Local variables:
1743 * c-basic-offset: 8
1744 * tab-width: 8
1745 * indent-tabs-mode: t
1746 * End:
1748 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1749 * :indentSize=8:tabSize=8:noTabs=false: