/src/wireshark/epan/dissectors/packet-locamation-im.c
Line | Count | Source |
1 | | /* packet-locamation-im.c |
2 | | * Routines for Locamation Interface Modules packet disassembly. |
3 | | * |
4 | | * Copyright (c) 2022 Locamation BV. |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | /* |
14 | | * Locamation Interface Modules |
15 | | * |
16 | | * The modules send SNAP packets. |
17 | | * |
18 | | * Several types of IMs are supported: |
19 | | * - Current Interface Module (CIM), version 1 |
20 | | * - Current Interface Module (CIM), version 2, revision 0 |
21 | | * - Voltage Interface Module (VIM), version 1 |
22 | | * - Voltage Interface Module (VIM), version 2, revision 0 |
23 | | */ |
24 | | |
25 | | /* clang-format off */ |
26 | | #include "config.h" |
27 | | #include <epan/packet.h> |
28 | | /* clang-format on */ |
29 | | |
30 | | #include <epan/expert.h> |
31 | | #include <epan/tfs.h> |
32 | | #include <wsutil/array.h> |
33 | | |
34 | | #include "packet-llc.h" |
35 | | |
36 | | #ifndef ETH_FRAME_LEN |
37 | | #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ |
38 | | #endif |
39 | | |
40 | | /* |
41 | | * ######################################################################## |
42 | | * # |
43 | | * # Forward Declarations |
44 | | * # |
45 | | * ######################################################################## |
46 | | */ |
47 | | |
48 | | void proto_register_locamation_im(void); |
49 | | void proto_reg_handoff_locamation_im(void); |
50 | | |
51 | | /* |
52 | | * ######################################################################## |
53 | | * # |
54 | | * # Defines |
55 | | * # |
56 | | * ######################################################################## |
57 | | */ |
58 | | |
59 | 56 | #define COMPANY_NAME "Locamation" |
60 | 14 | #define COMPANY_OUI 0x0040d6 |
61 | | |
62 | | #define COMPANY_IM_TEXT "Interface Module" |
63 | | |
64 | 14 | #define COMPANY_PID_CALIBRATION 0x0000 |
65 | 14 | #define COMPANY_PID_IDENT 0xffff |
66 | 14 | #define COMPANY_PID_SAMPLES_IM1 0x0002 |
67 | 14 | #define COMPANY_PID_SAMPLES_IM2R0 0x000e |
68 | | |
69 | 28 | #define PROTOCOL_NAME_IM_CALIBRATION "CALIBRATION" |
70 | 28 | #define PROTOCOL_NAME_IM_IDENT "IDENT" |
71 | 28 | #define PROTOCOL_NAME_IM_SAMPLES_IM1 "SAMPLES - IM1" |
72 | 28 | #define PROTOCOL_NAME_IM_SAMPLES_IM2R0 "SAMPLES - IM2R0" |
73 | | |
74 | 14 | #define PROTOCOL_NAME_CALIBRATION (COMPANY_NAME " " COMPANY_IM_TEXT " " PROTOCOL_NAME_IM_CALIBRATION) |
75 | 14 | #define PROTOCOL_NAME_IDENT (COMPANY_NAME " " COMPANY_IM_TEXT " " PROTOCOL_NAME_IM_IDENT) |
76 | 14 | #define PROTOCOL_NAME_SAMPLES_IM1 (COMPANY_NAME " " COMPANY_IM_TEXT " " PROTOCOL_NAME_IM_SAMPLES_IM1) |
77 | 14 | #define PROTOCOL_NAME_SAMPLES_IM2R0 (COMPANY_NAME " " COMPANY_IM_TEXT " " PROTOCOL_NAME_IM_SAMPLES_IM2R0) |
78 | | |
79 | 14 | #define PROTOCOL_SHORTNAME_CALIBRATION PROTOCOL_NAME_IM_CALIBRATION |
80 | 14 | #define PROTOCOL_SHORTNAME_IDENT PROTOCOL_NAME_IM_IDENT |
81 | 14 | #define PROTOCOL_SHORTNAME_SAMPLES_IM1 PROTOCOL_NAME_IM_SAMPLES_IM1 |
82 | 14 | #define PROTOCOL_SHORTNAME_SAMPLES_IM2R0 PROTOCOL_NAME_IM_SAMPLES_IM2R0 |
83 | | |
84 | 0 | #define MASK_SAMPLES_CONTROL_TYPE 0x80 |
85 | | #define MASK_SAMPLES_CONTROL_SIMULATED 0x40 |
86 | 0 | #define MASK_SAMPLES_CONTROL_VERSION 0x30 |
87 | | #define MASK_SAMPLES_CONTROL_SEQUENCE_NUMBER 0x0f |
88 | | |
89 | 0 | #define MASK_RANGES_SAMPLE_8 0xc000 |
90 | 0 | #define MASK_RANGES_SAMPLE_7 0x3000 |
91 | 0 | #define MASK_RANGES_SAMPLE_6 0x0c00 |
92 | 0 | #define MASK_RANGES_SAMPLE_5 0x0300 |
93 | 0 | #define MASK_RANGES_SAMPLE_4 0x00c0 |
94 | 0 | #define MASK_RANGES_SAMPLE_3 0x0030 |
95 | 0 | #define MASK_RANGES_SAMPLE_2 0x000c |
96 | 0 | #define MASK_RANGES_SAMPLE_1 0x0003 |
97 | | |
98 | | #define MASK_TIMESTAMP_ADDITIONAL_STATUS_HOLDOVER_STATE 0x01 |
99 | | #define MASK_TIMESTAMP_ADDITIONAL_STATUS_MASTER_CLOCK_SWITCH 0x02 |
100 | | |
101 | | /* |
102 | | * ######################################################################## |
103 | | * # |
104 | | * # PID Table |
105 | | * # |
106 | | * ######################################################################## |
107 | | */ |
108 | | |
109 | | static const value_string company_pid_vals[] = { |
110 | | {COMPANY_PID_CALIBRATION, PROTOCOL_NAME_IM_CALIBRATION}, |
111 | | {COMPANY_PID_IDENT, PROTOCOL_NAME_IM_IDENT}, |
112 | | {COMPANY_PID_SAMPLES_IM1, PROTOCOL_NAME_IM_SAMPLES_IM1}, |
113 | | {COMPANY_PID_SAMPLES_IM2R0, PROTOCOL_NAME_IM_SAMPLES_IM2R0}, |
114 | | {0, NULL}}; |
115 | | |
116 | | /* |
117 | | * ######################################################################## |
118 | | * # |
119 | | * # Types |
120 | | * # |
121 | | * ######################################################################## |
122 | | */ |
123 | | |
124 | | /* |
125 | | * struct _sample_set_t { |
126 | | * uint16_t ranges; |
127 | | * int32_t sample_1; |
128 | | * int32_t sample_2; |
129 | | * int32_t sample_3; |
130 | | * int32_t sample_4; |
131 | | * int32_t sample_5; |
132 | | * int32_t sample_6; |
133 | | * int32_t sample_7; |
134 | | * int32_t sample_8; |
135 | | * }; |
136 | | */ |
137 | 0 | #define SAMPLE_SET_SIZE 34 |
138 | | |
139 | | /* |
140 | | * struct _timestamp_t { |
141 | | * uint8_t sync_status; |
142 | | * uint8_t additional_status; |
143 | | * uint32_t sec; |
144 | | * uint32_t nsec; |
145 | | * }; |
146 | | */ |
147 | 0 | #define TIMESTAMP_SIZE 10 |
148 | | |
149 | | /* |
150 | | * struct _timestamps_t { |
151 | | * uint8_t version; |
152 | | * uint24_t reserved; |
153 | | * struct _timestamp_t timestamps[8]; |
154 | | * }; |
155 | | */ |
156 | 0 | #define TIMESTAMPS_SIZE 84 |
157 | | |
158 | | /* |
159 | | * ######################################################################## |
160 | | * # |
161 | | * # Helpers |
162 | | * # |
163 | | * ######################################################################## |
164 | | */ |
165 | | |
166 | 0 | static void add_split_lines(packet_info *pinfo, tvbuff_t *tvb, int tvb_offset, proto_tree *tree, int hf) { |
167 | 0 | int offset = tvb_offset; |
168 | 0 | int next_offset; |
169 | 0 | while (tvb_offset_exists(tvb, offset)) { |
170 | 0 | int len = tvb_find_line_end(tvb, offset, -1, &next_offset, false); |
171 | 0 | if (len == -1) { |
172 | 0 | break; |
173 | 0 | } |
174 | | |
175 | 0 | char *line = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, len, ENC_UTF_8); |
176 | 0 | proto_tree_add_string(tree, hf, tvb, offset, (next_offset - offset), line); |
177 | 0 | offset = next_offset; |
178 | 0 | } |
179 | 0 | } |
180 | | |
181 | | /* |
182 | | * ######################################################################## |
183 | | * # |
184 | | * # CALIBRATION |
185 | | * # |
186 | | * ######################################################################## |
187 | | * |
188 | | * Calibration Packets |
189 | | * |
190 | | * Calibration Packets are sent by IM1 sensors. |
191 | | * |
192 | | * The calibration packets are sent in a burst, with a header packet |
193 | | * followed by a number of chunk packets. Both packet types start with a |
194 | | * Sequence Number. |
195 | | * |
196 | | * The calibration file can be reconstructed by appending all chunk packets |
197 | | * in the Sequence Number order. |
198 | | * |
199 | | * Sequence Number: 2 bytes, unsigned |
200 | | * == 0: Header Packet |
201 | | * != 0: Chunk Packet |
202 | | * |
203 | | * Header Packet |
204 | | * ============= |
205 | | * Sequence Number : 2 bytes, unsigned (fixed value 0) |
206 | | * First Sequence Number: 2 bytes, unsigned (fixed value 1) |
207 | | * Last Sequence Number : 2 bytes, unsigned (N) |
208 | | * Name : string |
209 | | * |
210 | | * Chunk Packet |
211 | | * ============ |
212 | | * Sequence Number : 2 bytes, unsigned (1 <= Sequence Number <= N) |
213 | | * Calibration Chunk: string |
214 | | */ |
215 | | |
216 | | static int hf_calibration_sequence_number; |
217 | | static int hf_calibration_first_sequence_number; |
218 | | static int hf_calibration_last_sequence_number; |
219 | | static int hf_calibration_name; |
220 | | static int hf_calibration_name_line; |
221 | | static int hf_calibration_chunk; |
222 | | static int hf_calibration_chunk_line; |
223 | | |
224 | | static hf_register_info protocol_registration_calibration[] = { |
225 | | {&hf_calibration_sequence_number, {"Sequence Number", "locamation-im.calibration.sequence_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
226 | | {&hf_calibration_first_sequence_number, {"First Sequence Number", "locamation-im.calibration.first_sequence_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
227 | | {&hf_calibration_last_sequence_number, {"Last Sequence Number", "locamation-im.calibration.last_sequence_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
228 | | {&hf_calibration_name, {"Name", "locamation-im.calibration.name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
229 | | {&hf_calibration_name_line, {"Name Line", "locamation-im.calibration.name.line", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
230 | | {&hf_calibration_chunk, {"Chunk", "locamation-im.calibration.chunk", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
231 | | {&hf_calibration_chunk_line, {"Chunk Line", "locamation-im.calibration.chunk.line", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}}; |
232 | | |
233 | | static expert_field ei_calibration_header; |
234 | | |
235 | | static ei_register_info ei_calibration[] = { |
236 | | {&ei_calibration_header, {"locamation-im.calibration.header", PI_SEQUENCE, PI_NOTE, "Header Packet", EXPFILL}}}; |
237 | | |
238 | | static int h_protocol_calibration = -1; |
239 | | |
240 | | static int ett_protocol_calibration; |
241 | | static int ett_calibration_lines; |
242 | | |
243 | 0 | static int dissect_calibration(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
244 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTOCOL_SHORTNAME_CALIBRATION); |
245 | 0 | col_set_str(pinfo->cinfo, COL_INFO, PROTOCOL_NAME_CALIBRATION); |
246 | |
|
247 | 0 | proto_item *calibration_item = proto_tree_add_item(tree, h_protocol_calibration, tvb, 0, -1, ENC_NA); |
248 | 0 | proto_tree *calibration_item_subtree = proto_item_add_subtree(calibration_item, ett_protocol_calibration); |
249 | |
|
250 | 0 | int tvb_offset = 0; |
251 | | |
252 | | /* Sequence Number */ |
253 | 0 | int item_size = 2; |
254 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
255 | 0 | uint16_t sequence_number = tvb_get_uint16(tvb, 0, ENC_BIG_ENDIAN); |
256 | 0 | if (sequence_number == 0) { |
257 | 0 | expert_add_info(pinfo, calibration_item, &ei_calibration_header); |
258 | 0 | } |
259 | 0 | proto_tree_add_item(calibration_item_subtree, hf_calibration_sequence_number, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
260 | 0 | tvb_offset += item_size; |
261 | |
|
262 | 0 | if (sequence_number == 0) { |
263 | | /* Header Packet */ |
264 | | |
265 | | /* First Sequence Number */ |
266 | 0 | item_size = 2; |
267 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
268 | 0 | proto_tree_add_item(calibration_item_subtree, hf_calibration_first_sequence_number, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
269 | 0 | tvb_offset += item_size; |
270 | | |
271 | | /* Last Sequence Number */ |
272 | 0 | item_size = 2; |
273 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
274 | 0 | proto_tree_add_item(calibration_item_subtree, hf_calibration_last_sequence_number, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
275 | 0 | tvb_offset += item_size; |
276 | | |
277 | | /* Name */ |
278 | 0 | int name_length = tvb_reported_length_remaining(tvb, tvb_offset); |
279 | 0 | proto_item *name_item = proto_tree_add_item(calibration_item_subtree, hf_calibration_name, tvb, tvb_offset, name_length, ENC_UTF_8); |
280 | | |
281 | | /* Name - Lines */ |
282 | 0 | proto_tree *name_item_subtree = proto_item_add_subtree(name_item, ett_calibration_lines); |
283 | 0 | add_split_lines(pinfo, tvb, tvb_offset, name_item_subtree, hf_calibration_name_line); |
284 | 0 | } else { |
285 | | /* Chunk Packet */ |
286 | | |
287 | | /* Chunk */ |
288 | 0 | int chunk_length = tvb_reported_length_remaining(tvb, tvb_offset); |
289 | 0 | proto_item *chunk_item = proto_tree_add_item(calibration_item_subtree, hf_calibration_chunk, tvb, tvb_offset, chunk_length, ENC_UTF_8); |
290 | | |
291 | | /* Chunk - Lines */ |
292 | 0 | proto_tree *chunk_item_subtree = proto_item_add_subtree(chunk_item, ett_calibration_lines); |
293 | 0 | add_split_lines(pinfo, tvb, tvb_offset, chunk_item_subtree, hf_calibration_chunk_line); |
294 | 0 | } |
295 | |
|
296 | 0 | return tvb_captured_length(tvb); |
297 | 0 | } |
298 | | |
299 | | /* |
300 | | * ######################################################################## |
301 | | * # |
302 | | * # IDENT |
303 | | * # |
304 | | * ######################################################################## |
305 | | * |
306 | | * Ident Packets |
307 | | * |
308 | | * Ident Packets are sent by IM1 and IM2R0 sensors. |
309 | | * |
310 | | * Ident Packet |
311 | | * ============ |
312 | | * Content: string |
313 | | */ |
314 | | |
315 | | static int hf_ident_contents; |
316 | | static int hf_ident_contents_line; |
317 | | |
318 | | static hf_register_info protocol_registration_ident[] = { |
319 | | {&hf_ident_contents, {"Contents", "locamation-im.ident.contents", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
320 | | {&hf_ident_contents_line, {"Contents Line", "locamation-im.ident.contents.line", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}}; |
321 | | |
322 | | static int h_protocol_ident = -1; |
323 | | |
324 | | static int ett_protocol_ident; |
325 | | static int ett_ident_lines; |
326 | | |
327 | 0 | static int dissect_ident(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
328 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTOCOL_SHORTNAME_IDENT); |
329 | 0 | col_set_str(pinfo->cinfo, COL_INFO, PROTOCOL_NAME_IDENT); |
330 | |
|
331 | 0 | proto_item *ident_item = proto_tree_add_item(tree, h_protocol_ident, tvb, 0, -1, ENC_NA); |
332 | 0 | proto_tree *ident_item_subtree = proto_item_add_subtree(ident_item, ett_protocol_ident); |
333 | | |
334 | | /* Contents */ |
335 | 0 | int contents_length = tvb_reported_length_remaining(tvb, 0); |
336 | 0 | proto_item *contents_item = proto_tree_add_item(ident_item_subtree, hf_ident_contents, tvb, 0, contents_length, ENC_UTF_8); |
337 | | |
338 | | /* Contents - Lines */ |
339 | 0 | proto_tree *contents_item_subtree = proto_item_add_subtree(contents_item, ett_ident_lines); |
340 | 0 | add_split_lines(pinfo, tvb, 0, contents_item_subtree, hf_ident_contents_line); |
341 | |
|
342 | 0 | return tvb_captured_length(tvb); |
343 | 0 | } |
344 | | |
345 | | /* |
346 | | * ######################################################################## |
347 | | * # |
348 | | * # SAMPLES - Common |
349 | | * # |
350 | | * ######################################################################## |
351 | | */ |
352 | | |
353 | | static expert_field ei_samples_ranges_sample_1_invalid; |
354 | | static expert_field ei_samples_ranges_sample_2_invalid; |
355 | | static expert_field ei_samples_ranges_sample_3_invalid; |
356 | | static expert_field ei_samples_ranges_sample_4_invalid; |
357 | | static expert_field ei_samples_ranges_sample_5_invalid; |
358 | | static expert_field ei_samples_ranges_sample_6_invalid; |
359 | | static expert_field ei_samples_ranges_sample_7_invalid; |
360 | | static expert_field ei_samples_ranges_sample_8_invalid; |
361 | | |
362 | 0 | static void check_ranges(tvbuff_t *tvb, packet_info *pinfo, int tvb_offset, proto_item *item) { |
363 | 0 | uint16_t ranges = tvb_get_uint16(tvb, tvb_offset, ENC_BIG_ENDIAN); |
364 | |
|
365 | 0 | if ((ranges & MASK_RANGES_SAMPLE_8) == MASK_RANGES_SAMPLE_8) { |
366 | 0 | expert_add_info(pinfo, item, &ei_samples_ranges_sample_8_invalid); |
367 | 0 | } |
368 | 0 | if ((ranges & MASK_RANGES_SAMPLE_7) == MASK_RANGES_SAMPLE_7) { |
369 | 0 | expert_add_info(pinfo, item, &ei_samples_ranges_sample_7_invalid); |
370 | 0 | } |
371 | 0 | if ((ranges & MASK_RANGES_SAMPLE_6) == MASK_RANGES_SAMPLE_6) { |
372 | 0 | expert_add_info(pinfo, item, &ei_samples_ranges_sample_6_invalid); |
373 | 0 | } |
374 | 0 | if ((ranges & MASK_RANGES_SAMPLE_5) == MASK_RANGES_SAMPLE_5) { |
375 | 0 | expert_add_info(pinfo, item, &ei_samples_ranges_sample_5_invalid); |
376 | 0 | } |
377 | 0 | if ((ranges & MASK_RANGES_SAMPLE_4) == MASK_RANGES_SAMPLE_4) { |
378 | 0 | expert_add_info(pinfo, item, &ei_samples_ranges_sample_4_invalid); |
379 | 0 | } |
380 | 0 | if ((ranges & MASK_RANGES_SAMPLE_3) == MASK_RANGES_SAMPLE_3) { |
381 | 0 | expert_add_info(pinfo, item, &ei_samples_ranges_sample_3_invalid); |
382 | 0 | } |
383 | 0 | if ((ranges & MASK_RANGES_SAMPLE_2) == MASK_RANGES_SAMPLE_2) { |
384 | 0 | expert_add_info(pinfo, item, &ei_samples_ranges_sample_2_invalid); |
385 | 0 | } |
386 | 0 | if ((ranges & MASK_RANGES_SAMPLE_1) == MASK_RANGES_SAMPLE_1) { |
387 | 0 | expert_add_info(pinfo, item, &ei_samples_ranges_sample_1_invalid); |
388 | 0 | } |
389 | 0 | } |
390 | | |
391 | | static int ett_samples_sample_set_ranges; |
392 | | |
393 | | static int hf_samples_sample_set_ranges; |
394 | | |
395 | | static int hf_samples_sample_set_ranges_sample_1; |
396 | | static int hf_samples_sample_set_ranges_sample_2; |
397 | | static int hf_samples_sample_set_ranges_sample_3; |
398 | | static int hf_samples_sample_set_ranges_sample_4; |
399 | | static int hf_samples_sample_set_ranges_sample_5; |
400 | | static int hf_samples_sample_set_ranges_sample_6; |
401 | | static int hf_samples_sample_set_ranges_sample_7; |
402 | | static int hf_samples_sample_set_ranges_sample_8; |
403 | | |
404 | | static int *const rangesBits[] = { |
405 | | &hf_samples_sample_set_ranges_sample_8, |
406 | | &hf_samples_sample_set_ranges_sample_7, |
407 | | &hf_samples_sample_set_ranges_sample_6, |
408 | | &hf_samples_sample_set_ranges_sample_5, |
409 | | &hf_samples_sample_set_ranges_sample_4, |
410 | | &hf_samples_sample_set_ranges_sample_3, |
411 | | &hf_samples_sample_set_ranges_sample_2, |
412 | | &hf_samples_sample_set_ranges_sample_1, |
413 | | NULL}; |
414 | | |
415 | | static int hf_samples_sample_set_sample_1; |
416 | | static int hf_samples_sample_set_sample_2; |
417 | | static int hf_samples_sample_set_sample_3; |
418 | | static int hf_samples_sample_set_sample_4; |
419 | | static int hf_samples_sample_set_sample_5; |
420 | | static int hf_samples_sample_set_sample_6; |
421 | | static int hf_samples_sample_set_sample_7; |
422 | | static int hf_samples_sample_set_sample_8; |
423 | | |
424 | 0 | static void add_sample_set(tvbuff_t *tvb, packet_info *pinfo, int *tvb_offset, int hf, proto_tree *tree) { |
425 | 0 | int item_size = SAMPLE_SET_SIZE; |
426 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
427 | 0 | proto_item *sample_set_item = proto_tree_add_item(tree, hf, tvb, *tvb_offset, item_size, ENC_BIG_ENDIAN); |
428 | |
|
429 | 0 | proto_tree *sample_set_item_subtree = proto_item_add_subtree(sample_set_item, ett_samples_sample_set_ranges); |
430 | | |
431 | | /* Ranges */ |
432 | 0 | item_size = 2; |
433 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
434 | 0 | proto_item *ranges_item = proto_tree_add_bitmask(sample_set_item_subtree, tvb, *tvb_offset, hf_samples_sample_set_ranges, ett_samples_sample_set_ranges, rangesBits, ENC_BIG_ENDIAN); |
435 | 0 | check_ranges(tvb, pinfo, *tvb_offset, ranges_item); |
436 | 0 | *tvb_offset += item_size; |
437 | | |
438 | | /* Samples */ |
439 | 0 | int const hfs[] = { |
440 | 0 | hf_samples_sample_set_sample_1, |
441 | 0 | hf_samples_sample_set_sample_2, |
442 | 0 | hf_samples_sample_set_sample_3, |
443 | 0 | hf_samples_sample_set_sample_4, |
444 | 0 | hf_samples_sample_set_sample_5, |
445 | 0 | hf_samples_sample_set_sample_6, |
446 | 0 | hf_samples_sample_set_sample_7, |
447 | 0 | hf_samples_sample_set_sample_8}; |
448 | |
|
449 | 0 | item_size = 4; |
450 | 0 | for (unsigned index_sample = 0; index_sample < array_length(hfs); index_sample++) { |
451 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
452 | 0 | proto_tree_add_item(sample_set_item_subtree, hfs[index_sample], tvb, *tvb_offset, item_size, ENC_BIG_ENDIAN); |
453 | 0 | *tvb_offset += item_size; |
454 | 0 | } |
455 | 0 | } |
456 | | |
457 | 0 | static void add_sample_sets(tvbuff_t *tvb, packet_info *pinfo, int *tvb_offset, int *hfs, unsigned hfs_size, proto_tree *tree) { |
458 | 0 | for (unsigned index_sample_set = 0; index_sample_set < hfs_size; index_sample_set++) { |
459 | 0 | add_sample_set(tvb, pinfo, tvb_offset, hfs[index_sample_set], tree); |
460 | 0 | } |
461 | 0 | } |
462 | | |
463 | 0 | static void add_rms_values(tvbuff_t *tvb, int *tvb_offset, int *hfs, unsigned hfs_size, proto_tree *tree) { |
464 | 0 | int item_size = 4; |
465 | 0 | for (unsigned index_rms_value = 0; index_rms_value < hfs_size; index_rms_value++) { |
466 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
467 | 0 | proto_tree_add_item(tree, hfs[index_rms_value], tvb, *tvb_offset, item_size, ENC_BIG_ENDIAN); |
468 | 0 | *tvb_offset += item_size; |
469 | 0 | } |
470 | 0 | } |
471 | | |
472 | | static int ett_samples_timestamps_sample; |
473 | | static int ett_samples_timestamps_sample_reserved; |
474 | | static int ett_samples_timestamps_sample_timestamp; |
475 | | |
476 | | static int hf_samples_timestamps_sample_sync_status; |
477 | | static int hf_samples_timestamps_sample_additional_status; |
478 | | static int hf_samples_timestamps_sample_additional_status_holdover_state; |
479 | | static int hf_samples_timestamps_sample_additional_status_master_clock_switch; |
480 | | static int hf_samples_timestamps_sample_timestamp; |
481 | | static int hf_samples_timestamps_sample_timestamp_seconds; |
482 | | static int hf_samples_timestamps_sample_timestamp_nanoseconds; |
483 | | |
484 | | static const value_string samples_timestamps_sample_sync_status[] = { |
485 | | {0, "None"}, |
486 | | {1, "Local"}, |
487 | | {2, "Global"}, |
488 | | {0, NULL}}; |
489 | | |
490 | | static int *const timestamp_additional_status_bits[] = { |
491 | | &hf_samples_timestamps_sample_additional_status_holdover_state, |
492 | | &hf_samples_timestamps_sample_additional_status_master_clock_switch, |
493 | | NULL}; |
494 | | |
495 | | static expert_field ei_samples_timestamp_sync_status_invalid; |
496 | | |
497 | 0 | static void add_timestamp_sample(tvbuff_t *tvb, packet_info *pinfo, int *tvb_offset_previous, int *tvb_offset, int hf, proto_tree *tree) { |
498 | 0 | int item_size = TIMESTAMP_SIZE; |
499 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
500 | | |
501 | | /* Get the timestamp components */ |
502 | 0 | uint8_t sync_status = tvb_get_uint8(tvb, *tvb_offset); |
503 | 0 | uint32_t seconds = tvb_get_uint32(tvb, *tvb_offset + 2, ENC_BIG_ENDIAN); |
504 | 0 | uint32_t nanoseconds = tvb_get_uint32(tvb, *tvb_offset + 6, ENC_BIG_ENDIAN); |
505 | | |
506 | | /* Convert the timestamp seconds to a split time type */ |
507 | 0 | time_t sample_time = (time_t)seconds; |
508 | 0 | struct tm *sample_time_split = gmtime(&sample_time); |
509 | | |
510 | | /* Construct the readable sync status */ |
511 | 0 | const char *sync_status_buf = val_to_str(pinfo->pool, sync_status, samples_timestamps_sample_sync_status, "Unknown (%u)"); |
512 | | |
513 | | /* Construct the readable timestamp */ |
514 | 0 | char timestamp_buf[ITEM_LABEL_LENGTH]; |
515 | 0 | size_t timestamp_length = 0; |
516 | 0 | if (sample_time_split != NULL) { |
517 | 0 | timestamp_length += strftime(×tamp_buf[timestamp_length], ITEM_LABEL_LENGTH - timestamp_length, "%Y-%m-%d %H:%M:%S.", sample_time_split); |
518 | 0 | } else { |
519 | 0 | timestamp_length += snprintf(×tamp_buf[timestamp_length], ITEM_LABEL_LENGTH - timestamp_length, "\?\?\?\?-\?\?-\?\? \?\?:\?\?:\?\?."); |
520 | 0 | } |
521 | 0 | snprintf(×tamp_buf[timestamp_length], ITEM_LABEL_LENGTH - timestamp_length, "%09u TAI", nanoseconds); |
522 | | |
523 | | /* Construct the readable sample text */ |
524 | 0 | char title_buf[ITEM_LABEL_LENGTH]; |
525 | 0 | size_t title_length = 0; |
526 | 0 | title_length += snprintf(&title_buf[title_length], ITEM_LABEL_LENGTH - title_length, "%s (Sync: %s", timestamp_buf, sync_status_buf); |
527 | 0 | if (tvb_offset_previous != NULL) { |
528 | | /* Get the previous timestamp components and calculate the time difference */ |
529 | 0 | uint32_t seconds_previous = tvb_get_uint32(tvb, *tvb_offset_previous + 2, ENC_BIG_ENDIAN); |
530 | 0 | uint32_t nanoseconds_previous = tvb_get_uint32(tvb, *tvb_offset_previous + 6, ENC_BIG_ENDIAN); |
531 | 0 | uint64_t time_previous = ((uint64_t)seconds_previous * 1000000000) + nanoseconds_previous; |
532 | 0 | uint64_t time_now = ((uint64_t)seconds * 1000000000) + nanoseconds; |
533 | 0 | uint64_t time_diff = 0; |
534 | 0 | char time_difference_sign[2] = {'\0', '\0'}; |
535 | 0 | if (time_now > time_previous) { |
536 | 0 | time_diff = time_now - time_previous; |
537 | 0 | time_difference_sign[0] = '\0'; |
538 | 0 | } else if (time_now < time_previous) { |
539 | 0 | time_diff = time_previous - time_now; |
540 | 0 | time_difference_sign[0] = '-'; |
541 | 0 | } |
542 | 0 | double frequency = 0.0; |
543 | 0 | if (time_diff != 0) { |
544 | 0 | frequency = 1.0 / ((double)time_diff * 1.0E-09); |
545 | 0 | } |
546 | 0 | title_length += snprintf(&title_buf[title_length], ITEM_LABEL_LENGTH - title_length, ", Time Difference: %s%" PRIu64 " nsec", time_difference_sign, time_diff); |
547 | 0 | if (frequency != 0.0) { |
548 | 0 | title_length += snprintf(&title_buf[title_length], ITEM_LABEL_LENGTH - title_length, " = %f Hz", frequency); |
549 | 0 | } |
550 | 0 | } |
551 | 0 | snprintf(&title_buf[title_length], ITEM_LABEL_LENGTH - title_length, ")"); |
552 | |
|
553 | 0 | proto_item *sample_timestamp_item = proto_tree_add_string(tree, hf, tvb, *tvb_offset, item_size, title_buf); |
554 | |
|
555 | 0 | proto_tree *sample_timestamp_item_subtree = proto_item_add_subtree(sample_timestamp_item, ett_samples_timestamps_sample); |
556 | | |
557 | | /* Sync Status */ |
558 | 0 | item_size = 1; |
559 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
560 | 0 | proto_item *sync_status_item = proto_tree_add_item(sample_timestamp_item_subtree, hf_samples_timestamps_sample_sync_status, tvb, *tvb_offset, item_size, ENC_BIG_ENDIAN); |
561 | 0 | *tvb_offset += item_size; |
562 | |
|
563 | 0 | if (sync_status > 2) { |
564 | 0 | expert_add_info(pinfo, sync_status_item, &ei_samples_timestamp_sync_status_invalid); |
565 | 0 | } |
566 | | |
567 | | /* Additional Status */ |
568 | 0 | item_size = 1; |
569 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
570 | 0 | proto_tree_add_bitmask(sample_timestamp_item_subtree, tvb, *tvb_offset, hf_samples_timestamps_sample_additional_status, ett_samples_timestamps_sample_reserved, timestamp_additional_status_bits, ENC_BIG_ENDIAN); |
571 | 0 | *tvb_offset += item_size; |
572 | | |
573 | | /* Timestamp */ |
574 | 0 | item_size = 8; |
575 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
576 | 0 | proto_item *sample_timestamp_timestamp_item = proto_tree_add_string(sample_timestamp_item_subtree, hf_samples_timestamps_sample_timestamp, tvb, *tvb_offset, item_size, timestamp_buf); |
577 | |
|
578 | 0 | proto_tree *sample_timestamp_timestamp_item_subtree = proto_item_add_subtree(sample_timestamp_timestamp_item, ett_samples_timestamps_sample_timestamp); |
579 | | |
580 | | /* Seconds */ |
581 | 0 | item_size = 4; |
582 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
583 | 0 | proto_tree_add_item(sample_timestamp_timestamp_item_subtree, hf_samples_timestamps_sample_timestamp_seconds, tvb, *tvb_offset, item_size, ENC_BIG_ENDIAN); |
584 | 0 | *tvb_offset += item_size; |
585 | | |
586 | | /* Nanoseconds */ |
587 | 0 | item_size = 4; |
588 | 0 | tvb_ensure_bytes_exist(tvb, *tvb_offset, item_size); |
589 | 0 | proto_tree_add_item(sample_timestamp_timestamp_item_subtree, hf_samples_timestamps_sample_timestamp_nanoseconds, tvb, *tvb_offset, item_size, ENC_BIG_ENDIAN); |
590 | 0 | *tvb_offset += item_size; |
591 | 0 | } |
592 | | |
593 | 0 | static void add_timestamps_set(tvbuff_t *tvb, packet_info *pinfo, int *tvb_offset, int *hfs, unsigned hfs_size, proto_tree *tree) { |
594 | 0 | int tvb_offset_previous = 0; |
595 | 0 | for (unsigned index_timestamp = 0; index_timestamp < hfs_size; index_timestamp++) { |
596 | 0 | int tvb_offset_saved = *tvb_offset; |
597 | 0 | add_timestamp_sample(tvb, pinfo, (index_timestamp == 0) ? NULL : &tvb_offset_previous, tvb_offset, hfs[index_timestamp], tree); |
598 | 0 | tvb_offset_previous = tvb_offset_saved; |
599 | 0 | } |
600 | 0 | } |
601 | | |
602 | | /* |
603 | | * Samples Packets |
604 | | * |
605 | | * Samples Packets are sent by IM1 and IM2R0 sensors. |
606 | | * However, details of the packets differ between the sensors. |
607 | | * |
608 | | * Samples Packet |
609 | | * ============== |
610 | | * Transport Delay: 2 bytes, unsigned (resolution = 10ns) |
611 | | * Hop Count: 1 byte, unsigned |
612 | | * Control data: 1 byte, bitmap |
613 | | * bit [7] : type : 0 = CIM, 1 = VIM |
614 | | * bit [6] : simulated: 0 = Real Samples, 1 = Simulated Samples |
615 | | * bits [5..4]: version : 00 = IM1, 11 = IM2R0 |
616 | | * bits [3..0]: seqnr : Sequence Number, in the range [0,15], monotonically |
617 | | * increasing and wrapping |
618 | | * Temperature: 2 bytes, signed (resolution = 0.25C) |
619 | | * Padding: 1 byte |
620 | | * ADC Status: 1 byte, unsigned |
621 | | * Sample Data |
622 | | * * Sample data is stored in sample data sets. |
623 | | * Each sample data set contains ranges and the data of 8 samples, and |
624 | | * samples are equi-distant in time. |
625 | | * |
626 | | * Sample Data Set |
627 | | * =============== |
628 | | * Range: 2 bytes, bitmap |
629 | | * - bits [15,14]: Range of sample 8 (newest sample) |
630 | | * - bits [13,12]: Range of sample 7 |
631 | | * - bits [11,10]: Range of sample 6 |
632 | | * - bits [ 9, 8]: Range of sample 5 |
633 | | * - bits [ 7, 6]: Range of sample 4 |
634 | | * - bits [ 5, 4]: Range of sample 3 |
635 | | * - bits [ 3, 2]: Range of sample 2 |
636 | | * - bits [ 1, 0]: Range of sample 1 (oldest sample) |
637 | | * Range values: |
638 | | * 00 = measurement ADC channel |
639 | | * 01 = protection ADC channel, range low |
640 | | * 10 = protection ADC channel, range high |
641 | | * 11 = unused |
642 | | * Sample 1: 4 bytes, signed (oldest sample) |
643 | | * Sample 2: 4 bytes, signed |
644 | | * Sample 3: 4 bytes, signed |
645 | | * Sample 4: 4 bytes, signed |
646 | | * Sample 5: 4 bytes, signed |
647 | | * Sample 6: 4 bytes, signed |
648 | | * Sample 7: 4 bytes, signed |
649 | | * Sample 8: 4 bytes, signed (newest sample) |
650 | | * |
651 | | * * IM1 |
652 | | * 6 sample data sets, one set per ADC channel: |
653 | | * |
654 | | * Sample Data |
655 | | * =========== |
656 | | * CIM VIM |
657 | | * set 1 channel 1, measurement channel 1 |
658 | | * set 2 channel 2, measurement channel 2 |
659 | | * set 3 channel 3, measurement channel 3 |
660 | | * set 4 channel 1, protection 0 |
661 | | * set 5 channel 2, protection 0 |
662 | | * set 6 channel 3, protection 0 |
663 | | * |
664 | | * * IM2R0 |
665 | | * 8 sample data sets, one set per ADC channel: |
666 | | * |
667 | | * Sample Data |
668 | | * =========== |
669 | | * CIM VIM |
670 | | * set 1 channel 1, measurement channel 1 |
671 | | * set 2 channel 2, measurement channel 2 |
672 | | * set 3 channel 3, measurement channel 3 |
673 | | * set 4 channel 1, protection neutral channel |
674 | | * set 5 channel 2, protection 0 |
675 | | * set 6 channel 3, protection 0 |
676 | | * set 7 neutral channel, measurement 0 |
677 | | * set 8 neutral channel, protection 0 |
678 | | * RMS values |
679 | | * * RMS values are stored as 4 byte signed values. |
680 | | * |
681 | | * * IM1 |
682 | | * 6 values, one per ADC-channel: |
683 | | * |
684 | | * RMS values |
685 | | * ========== |
686 | | * CIM VIM |
687 | | * value 1 channel 1, measurement channel 1 |
688 | | * value 2 channel 2, measurement channel 2 |
689 | | * value 3 channel 3, measurement channel 3 |
690 | | * value 4 channel 1, protection 0 |
691 | | * value 5 channel 2, protection 0 |
692 | | * value 6 channel 3, protection 0 |
693 | | * |
694 | | * * IM2R0 |
695 | | * 8 values, one per ADC-channel: |
696 | | * |
697 | | * RMS values |
698 | | * ========== |
699 | | * CIM VIM |
700 | | * value 1 0 0 |
701 | | * value 2 0 0 |
702 | | * value 3 0 0 |
703 | | * value 4 0 0 |
704 | | * value 5 0 0 |
705 | | * value 6 0 0 |
706 | | * value 7 0 0 |
707 | | * value 8 0 0 |
708 | | * Timestamps |
709 | | * * Timestamps are PTP driven and are stored in a versioned block. |
710 | | * Each timestamp also has status information. |
711 | | * |
712 | | * * IM1 |
713 | | * Timestamps are not applicable for IM1. |
714 | | * |
715 | | * * IM2R0 |
716 | | * Timestamps are optional. |
717 | | * |
718 | | * Timestamps Block |
719 | | * ================ |
720 | | * Version 1 byte, unsigned |
721 | | * Reserved 3 bytes, unsigned |
722 | | * Sample 1 Timestamp (oldest sample) |
723 | | * Sample 2 Timestamp |
724 | | * Sample 3 Timestamp |
725 | | * Sample 4 Timestamp |
726 | | * Sample 5 Timestamp |
727 | | * Sample 6 Timestamp |
728 | | * Sample 7 Timestamp |
729 | | * Sample 8 Timestamp (newest sample) |
730 | | * |
731 | | * Timestamp |
732 | | * ========= |
733 | | * Sync Status 1 byte, unsigned |
734 | | * 0 = Not synchronized (during start-up or synchronization lost) |
735 | | * 1 = Synchronized but not to a Grand Master Clock |
736 | | * 2 = Synchronized to a Grand Master Clock |
737 | | * 3-255 = Invalid |
738 | | * Additional Status 1 byte, bitmap |
739 | | * bits [7, 2]: Reserved |
740 | | * bits [1] : Master clock switch |
741 | | * 1 = The device switched to a different master clock or |
742 | | * became synchronized to a master clock for the first time. |
743 | | * 0 = The device did not switch to a different master clock nor |
744 | | * became synchronized to a master clock for the first time. |
745 | | * bits [0] : Holdover state |
746 | | * 1 = The device is in its holdover state. |
747 | | * 0 = The device is not in its holdover state. |
748 | | * Seconds 4 bytes, unsigned |
749 | | * Nanoseconds 4 bytes, unsigned |
750 | | */ |
751 | | |
752 | | static int ett_protocol_samples; |
753 | | static int ett_samples_control; |
754 | | static int ett_samples_sets; |
755 | | static int ett_samples_sets_set; |
756 | | static int ett_samples_rms; |
757 | | static int ett_samples_rms_values; |
758 | | static int ett_samples_timestamps; |
759 | | static int ett_samples_timestamps_set; |
760 | | |
761 | | static expert_field ei_samples_im_version_invalid; |
762 | | |
763 | | static int hf_samples_transport_delay; |
764 | | static int hf_samples_hop_count; |
765 | | static int hf_samples_control; |
766 | | static int hf_samples_control_type; |
767 | | static int hf_samples_control_simulated; |
768 | | static int hf_samples_control_version; |
769 | | static int hf_samples_control_sequence_number; |
770 | | static int hf_samples_temperature; |
771 | | static int hf_samples_padding; |
772 | | static int hf_samples_adc_status; |
773 | | static int hf_samples_sample_set; |
774 | | static int hf_samples_rms_values; |
775 | | static int hf_samples_timestamps; |
776 | | |
777 | | static int *const controlBits[] = { |
778 | | &hf_samples_control_type, |
779 | | &hf_samples_control_simulated, |
780 | | &hf_samples_control_version, |
781 | | &hf_samples_control_sequence_number, |
782 | | NULL}; |
783 | | |
784 | | static int hf_samples_sample_set_measurement_channel_1; |
785 | | static int hf_samples_sample_set_measurement_channel_2; |
786 | | static int hf_samples_sample_set_measurement_channel_3; |
787 | | static int hf_samples_sample_set_measurement_channel_n; |
788 | | static int hf_samples_sample_set_protection_channel_1; |
789 | | static int hf_samples_sample_set_protection_channel_2; |
790 | | static int hf_samples_sample_set_protection_channel_3; |
791 | | static int hf_samples_sample_set_protection_channel_n; |
792 | | static int hf_samples_sample_set_channel_unused; |
793 | | |
794 | | static int hf_samples_rms_values_measurement_channel_1; |
795 | | static int hf_samples_rms_values_measurement_channel_2; |
796 | | static int hf_samples_rms_values_measurement_channel_3; |
797 | | static int hf_samples_rms_values_protection_channel_1; |
798 | | static int hf_samples_rms_values_protection_channel_2; |
799 | | static int hf_samples_rms_values_protection_channel_3; |
800 | | static int hf_samples_rms_values_channel_unused; |
801 | | |
802 | | static int hf_samples_timestamps_version; |
803 | | static int hf_samples_timestamps_reserved; |
804 | | static int hf_samples_timestamps_sample_1; |
805 | | static int hf_samples_timestamps_sample_2; |
806 | | static int hf_samples_timestamps_sample_3; |
807 | | static int hf_samples_timestamps_sample_4; |
808 | | static int hf_samples_timestamps_sample_5; |
809 | | static int hf_samples_timestamps_sample_6; |
810 | | static int hf_samples_timestamps_sample_7; |
811 | | static int hf_samples_timestamps_sample_8; |
812 | | |
813 | 0 | static int dissect_samples_im(bool im1, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_, int h_protocol_samples) { |
814 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, im1 ? PROTOCOL_SHORTNAME_SAMPLES_IM1 : PROTOCOL_SHORTNAME_SAMPLES_IM2R0); |
815 | 0 | col_set_str(pinfo->cinfo, COL_INFO, im1 ? PROTOCOL_NAME_SAMPLES_IM1 : PROTOCOL_NAME_SAMPLES_IM2R0); |
816 | |
|
817 | 0 | proto_item *samples_item = proto_tree_add_item(tree, h_protocol_samples, tvb, 0, -1, ENC_NA); |
818 | 0 | proto_tree *samples_item_subtree = proto_item_add_subtree(samples_item, ett_protocol_samples); |
819 | |
|
820 | 0 | int tvb_offset = 0; |
821 | | |
822 | | /* Transport Delay */ |
823 | 0 | int item_size = 2; |
824 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
825 | 0 | proto_tree_add_item(samples_item_subtree, hf_samples_transport_delay, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
826 | 0 | tvb_offset += item_size; |
827 | | |
828 | | /* Hop Count */ |
829 | 0 | item_size = 1; |
830 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
831 | 0 | proto_tree_add_item(samples_item_subtree, hf_samples_hop_count, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
832 | 0 | tvb_offset += item_size; |
833 | | |
834 | | /* Get Control */ |
835 | 0 | uint8_t control = tvb_get_uint8(tvb, tvb_offset); |
836 | 0 | bool isIM1 = ((control & MASK_SAMPLES_CONTROL_VERSION) == 0); |
837 | 0 | bool isIM2R0 = ((control & MASK_SAMPLES_CONTROL_VERSION) == MASK_SAMPLES_CONTROL_VERSION); |
838 | 0 | bool isCIM = ((control & MASK_SAMPLES_CONTROL_TYPE) == 0); |
839 | | |
840 | | /* Control */ |
841 | 0 | item_size = 1; |
842 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
843 | 0 | proto_item *control_item = proto_tree_add_bitmask(samples_item_subtree, tvb, tvb_offset, hf_samples_control, ett_samples_control, controlBits, ENC_BIG_ENDIAN); |
844 | 0 | tvb_offset += item_size; |
845 | 0 | if (!isIM1 && !isIM2R0) { |
846 | 0 | expert_add_info(pinfo, control_item, &ei_samples_im_version_invalid); |
847 | 0 | } |
848 | | |
849 | | /* Temperature */ |
850 | 0 | item_size = 2; |
851 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
852 | 0 | proto_tree_add_item(samples_item_subtree, hf_samples_temperature, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
853 | 0 | tvb_offset += item_size; |
854 | | |
855 | | /* Padding */ |
856 | 0 | item_size = 1; |
857 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
858 | 0 | proto_tree_add_item(samples_item_subtree, hf_samples_padding, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
859 | 0 | tvb_offset += item_size; |
860 | | |
861 | | /* ADC status */ |
862 | 0 | item_size = 1; |
863 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
864 | 0 | proto_tree_add_item(samples_item_subtree, hf_samples_adc_status, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
865 | 0 | tvb_offset += item_size; |
866 | | |
867 | | /* Sample Sets */ |
868 | 0 | { |
869 | 0 | proto_tree *sample_sets_subtree = proto_item_add_subtree(samples_item, ett_samples_sets); |
870 | |
|
871 | 0 | if (im1) { |
872 | 0 | item_size = SAMPLE_SET_SIZE * 6; |
873 | 0 | } else { |
874 | 0 | item_size = SAMPLE_SET_SIZE * 8; |
875 | 0 | } |
876 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
877 | 0 | proto_item *sample_sets_subtree_item = proto_tree_add_item(sample_sets_subtree, hf_samples_sample_set, tvb, tvb_offset, item_size, ENC_NA); |
878 | |
|
879 | 0 | proto_tree *sample_sets_subtree_item_subtree = proto_item_add_subtree(sample_sets_subtree_item, ett_samples_sets_set); |
880 | |
|
881 | 0 | if (isIM1) { |
882 | 0 | if (isCIM) { |
883 | | /* IM1 CIM */ |
884 | |
|
885 | 0 | int hfs[] = { |
886 | 0 | hf_samples_sample_set_measurement_channel_1, |
887 | 0 | hf_samples_sample_set_measurement_channel_2, |
888 | 0 | hf_samples_sample_set_measurement_channel_3, |
889 | 0 | hf_samples_sample_set_protection_channel_1, |
890 | 0 | hf_samples_sample_set_protection_channel_2, |
891 | 0 | hf_samples_sample_set_protection_channel_3}; |
892 | |
|
893 | 0 | add_sample_sets(tvb, pinfo, &tvb_offset, hfs, array_length(hfs), sample_sets_subtree_item_subtree); |
894 | 0 | } else { |
895 | | /* IM1 VIM */ |
896 | |
|
897 | 0 | int hfs[] = { |
898 | 0 | hf_samples_sample_set_measurement_channel_1, |
899 | 0 | hf_samples_sample_set_measurement_channel_2, |
900 | 0 | hf_samples_sample_set_measurement_channel_3, |
901 | 0 | hf_samples_sample_set_channel_unused, |
902 | 0 | hf_samples_sample_set_channel_unused, |
903 | 0 | hf_samples_sample_set_channel_unused}; |
904 | |
|
905 | 0 | add_sample_sets(tvb, pinfo, &tvb_offset, hfs, array_length(hfs), sample_sets_subtree_item_subtree); |
906 | 0 | } |
907 | 0 | } else if (isIM2R0) { |
908 | 0 | if (isCIM) { |
909 | | /* IM2R0 CIM */ |
910 | |
|
911 | 0 | int hfs[] = { |
912 | 0 | hf_samples_sample_set_measurement_channel_1, |
913 | 0 | hf_samples_sample_set_measurement_channel_2, |
914 | 0 | hf_samples_sample_set_measurement_channel_3, |
915 | 0 | hf_samples_sample_set_protection_channel_1, |
916 | 0 | hf_samples_sample_set_protection_channel_2, |
917 | 0 | hf_samples_sample_set_protection_channel_3, |
918 | 0 | hf_samples_sample_set_measurement_channel_n, |
919 | 0 | hf_samples_sample_set_protection_channel_n}; |
920 | |
|
921 | 0 | add_sample_sets(tvb, pinfo, &tvb_offset, hfs, array_length(hfs), sample_sets_subtree_item_subtree); |
922 | 0 | } else { |
923 | | /* IM2R0 VIM */ |
924 | |
|
925 | 0 | int hfs[] = { |
926 | 0 | hf_samples_sample_set_measurement_channel_1, |
927 | 0 | hf_samples_sample_set_measurement_channel_2, |
928 | 0 | hf_samples_sample_set_measurement_channel_3, |
929 | 0 | hf_samples_sample_set_measurement_channel_n, |
930 | 0 | hf_samples_sample_set_channel_unused, |
931 | 0 | hf_samples_sample_set_channel_unused, |
932 | 0 | hf_samples_sample_set_channel_unused, |
933 | 0 | hf_samples_sample_set_channel_unused}; |
934 | |
|
935 | 0 | add_sample_sets(tvb, pinfo, &tvb_offset, hfs, array_length(hfs), sample_sets_subtree_item_subtree); |
936 | 0 | } |
937 | 0 | } |
938 | 0 | } |
939 | | |
940 | | /* RMS Values */ |
941 | 0 | { |
942 | 0 | proto_tree *rms_values_subtree = proto_item_add_subtree(samples_item, ett_samples_rms); |
943 | |
|
944 | 0 | if (im1) { |
945 | 0 | item_size = 4 * 6; |
946 | 0 | } else { |
947 | 0 | item_size = 4 * 8; |
948 | 0 | } |
949 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
950 | 0 | proto_item *rms_values_item = proto_tree_add_item(rms_values_subtree, hf_samples_rms_values, tvb, tvb_offset, item_size, ENC_NA); |
951 | |
|
952 | 0 | proto_tree *rms_values_item_subtree = proto_item_add_subtree(rms_values_item, ett_samples_rms_values); |
953 | |
|
954 | 0 | if (isIM1) { |
955 | 0 | if (isCIM) { |
956 | | /* IM1 CIM */ |
957 | |
|
958 | 0 | int hfs[] = { |
959 | 0 | hf_samples_rms_values_measurement_channel_1, |
960 | 0 | hf_samples_rms_values_measurement_channel_2, |
961 | 0 | hf_samples_rms_values_measurement_channel_3, |
962 | 0 | hf_samples_rms_values_protection_channel_1, |
963 | 0 | hf_samples_rms_values_protection_channel_2, |
964 | 0 | hf_samples_rms_values_protection_channel_3}; |
965 | |
|
966 | 0 | add_rms_values(tvb, &tvb_offset, hfs, array_length(hfs), rms_values_item_subtree); |
967 | 0 | } else { |
968 | | /* IM1 VIM */ |
969 | |
|
970 | 0 | int hfs[] = { |
971 | 0 | hf_samples_rms_values_measurement_channel_1, |
972 | 0 | hf_samples_rms_values_measurement_channel_2, |
973 | 0 | hf_samples_rms_values_measurement_channel_3, |
974 | 0 | hf_samples_rms_values_channel_unused, |
975 | 0 | hf_samples_rms_values_channel_unused, |
976 | 0 | hf_samples_rms_values_channel_unused}; |
977 | |
|
978 | 0 | add_rms_values(tvb, &tvb_offset, hfs, array_length(hfs), rms_values_item_subtree); |
979 | 0 | } |
980 | 0 | } else if (isIM2R0) { |
981 | 0 | int hfs[] = { |
982 | 0 | hf_samples_rms_values_channel_unused, |
983 | 0 | hf_samples_rms_values_channel_unused, |
984 | 0 | hf_samples_rms_values_channel_unused, |
985 | 0 | hf_samples_rms_values_channel_unused, |
986 | 0 | hf_samples_rms_values_channel_unused, |
987 | 0 | hf_samples_rms_values_channel_unused, |
988 | 0 | hf_samples_rms_values_channel_unused, |
989 | 0 | hf_samples_rms_values_channel_unused}; |
990 | |
|
991 | 0 | add_rms_values(tvb, &tvb_offset, hfs, array_length(hfs), rms_values_item_subtree); |
992 | 0 | } |
993 | 0 | } |
994 | | |
995 | | /* Timestamps */ |
996 | 0 | if (isIM2R0 && tvb_bytes_exist(tvb, tvb_offset, TIMESTAMPS_SIZE)) { |
997 | 0 | proto_tree *samples_timestamps_subtree = proto_item_add_subtree(samples_item, ett_samples_timestamps); |
998 | |
|
999 | 0 | item_size = TIMESTAMPS_SIZE; |
1000 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
1001 | 0 | proto_item *samples_timestamps_subtree_item = proto_tree_add_item(samples_timestamps_subtree, hf_samples_timestamps, tvb, tvb_offset, item_size, ENC_NA); |
1002 | |
|
1003 | 0 | proto_tree *samples_timestamps_subtree_item_subtree = proto_item_add_subtree(samples_timestamps_subtree_item, ett_samples_timestamps_set); |
1004 | | |
1005 | | /* Version */ |
1006 | 0 | item_size = 1; |
1007 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
1008 | 0 | proto_tree_add_item(samples_timestamps_subtree_item_subtree, hf_samples_timestamps_version, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
1009 | 0 | tvb_offset += item_size; |
1010 | | |
1011 | | /* Reserved */ |
1012 | 0 | item_size = 3; |
1013 | 0 | tvb_ensure_bytes_exist(tvb, tvb_offset, item_size); |
1014 | 0 | proto_tree_add_item(samples_timestamps_subtree_item_subtree, hf_samples_timestamps_reserved, tvb, tvb_offset, item_size, ENC_BIG_ENDIAN); |
1015 | 0 | tvb_offset += item_size; |
1016 | | |
1017 | | /* Sample Timestamps */ |
1018 | |
|
1019 | 0 | int hfs[] = { |
1020 | 0 | hf_samples_timestamps_sample_1, |
1021 | 0 | hf_samples_timestamps_sample_2, |
1022 | 0 | hf_samples_timestamps_sample_3, |
1023 | 0 | hf_samples_timestamps_sample_4, |
1024 | 0 | hf_samples_timestamps_sample_5, |
1025 | 0 | hf_samples_timestamps_sample_6, |
1026 | 0 | hf_samples_timestamps_sample_7, |
1027 | 0 | hf_samples_timestamps_sample_8}; |
1028 | |
|
1029 | 0 | add_timestamps_set(tvb, pinfo, &tvb_offset, hfs, array_length(hfs), samples_timestamps_subtree_item_subtree); |
1030 | 0 | } |
1031 | |
|
1032 | 0 | return tvb_captured_length(tvb); |
1033 | 0 | } |
1034 | | |
1035 | | /* |
1036 | | * ######################################################################## |
1037 | | * # |
1038 | | * # Samples - IM1 |
1039 | | * # |
1040 | | * ######################################################################## |
1041 | | */ |
1042 | | |
1043 | 0 | static void samples_transport_delay(char *result, uint16_t transport_delay) { |
1044 | 0 | snprintf(result, ITEM_LABEL_LENGTH, "%u ns", transport_delay * 10); |
1045 | 0 | } |
1046 | | |
1047 | | static const value_string samples_control_type_vals[] = { |
1048 | | {0, "Current Interface Module"}, |
1049 | | {1, "Voltage Interface Module"}, |
1050 | | {0, NULL}}; |
1051 | | |
1052 | | static const value_string samples_control_simulated_vals[] = { |
1053 | | {0, "Sampled"}, |
1054 | | {1, "Simulated"}, |
1055 | | {0, NULL}}; |
1056 | | |
1057 | | static const value_string samples_control_version_vals[] = { |
1058 | | {0, "IM1"}, |
1059 | | {1, "Unused"}, |
1060 | | {2, "Unused"}, |
1061 | | {3, "IM2R0"}, |
1062 | | {0, NULL}}; |
1063 | | |
1064 | 0 | static void samples_sequence_number(char *result, uint8_t sequence_number) { |
1065 | 0 | snprintf(result, ITEM_LABEL_LENGTH, "%u", sequence_number); |
1066 | 0 | } |
1067 | | |
1068 | 0 | static void samples_temperature(char *result, int16_t temperature) { |
1069 | 0 | snprintf(result, ITEM_LABEL_LENGTH, "%.2f C", (0.25f * temperature)); |
1070 | 0 | } |
1071 | | |
1072 | | static const value_string ranges_vals[] = { |
1073 | | {0, "Measurement ADC Channel"}, |
1074 | | {1, "Protection ADC Channel, Range Low"}, |
1075 | | {2, "Protection ADC Channel, Range High"}, |
1076 | | {3, "Unused"}, |
1077 | | {0, NULL}}; |
1078 | | |
1079 | | static hf_register_info protocol_registration_samples[] = { |
1080 | | {&hf_samples_transport_delay, {"Transport Delay", "locamation-im.samples.transport_delay", FT_UINT16, BASE_CUSTOM, CF_FUNC(samples_transport_delay), 0x0, NULL, HFILL}}, |
1081 | | {&hf_samples_hop_count, {"Hop Count", "locamation-im.samples.hop_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1082 | | {&hf_samples_control, {"Control", "locamation-im.samples.control", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, |
1083 | | {&hf_samples_control_type, {"Type", "locamation-im.samples.control.type", FT_UINT8, BASE_DEC, VALS(samples_control_type_vals), MASK_SAMPLES_CONTROL_TYPE, NULL, HFILL}}, |
1084 | | {&hf_samples_control_simulated, {"Simulated", "locamation-im.samples.control.simulated", FT_UINT8, BASE_DEC, VALS(samples_control_simulated_vals), MASK_SAMPLES_CONTROL_SIMULATED, NULL, HFILL}}, |
1085 | | {&hf_samples_control_version, {"Version", "locamation-im.samples.control.version", FT_UINT8, BASE_DEC, VALS(samples_control_version_vals), MASK_SAMPLES_CONTROL_VERSION, NULL, HFILL}}, |
1086 | | {&hf_samples_control_sequence_number, {"Sequence Number", "locamation-im.samples.control.sequence_number", FT_UINT8, BASE_CUSTOM, CF_FUNC(samples_sequence_number), MASK_SAMPLES_CONTROL_SEQUENCE_NUMBER, NULL, HFILL}}, |
1087 | | {&hf_samples_temperature, {"Temperature", "locamation-im.samples.temperature", FT_INT16, BASE_CUSTOM, CF_FUNC(samples_temperature), 0x0, NULL, HFILL}}, |
1088 | | {&hf_samples_padding, {"Padding", "locamation-im.samples.padding", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, |
1089 | | {&hf_samples_adc_status, {"ADC Status", "locamation-im.samples.adc_status", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, |
1090 | | {&hf_samples_sample_set, {"Sample Sets", "locamation-im.samples.sets", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1091 | | {&hf_samples_rms_values, {"RMS Values", "locamation-im.samples.rms_values", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1092 | | {&hf_samples_sample_set_measurement_channel_1, {"Measurement Channel 1", "locamation-im.samples.sets.measurement.channel.1", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1093 | | {&hf_samples_sample_set_measurement_channel_2, {"Measurement Channel 2", "locamation-im.samples.sets.measurement.channel.2", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1094 | | {&hf_samples_sample_set_measurement_channel_3, {"Measurement Channel 3", "locamation-im.samples.sets.measurement.channel.3", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1095 | | {&hf_samples_sample_set_measurement_channel_n, {"Measurement Channel N", "locamation-im.samples.sets.measurement.channel.n", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1096 | | {&hf_samples_sample_set_protection_channel_1, {"Protection Channel 1", "locamation-im.samples.sets.protection.channel.1", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1097 | | {&hf_samples_sample_set_protection_channel_2, {"Protection Channel 2", "locamation-im.samples.sets.protection.channel.2", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1098 | | {&hf_samples_sample_set_protection_channel_3, {"Protection Channel 3", "locamation-im.samples.sets.protection.channel.3", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1099 | | {&hf_samples_sample_set_protection_channel_n, {"Protection Channel N", "locamation-im.samples.sets.protection.channel.n", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1100 | | {&hf_samples_sample_set_channel_unused, {"Unused Channel", "locamation-im.samples.sets.channel.unused", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1101 | | {&hf_samples_sample_set_ranges, {"Ranges", "locamation-im.samples.sets.measurement.ranges", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}}, |
1102 | | {&hf_samples_sample_set_ranges_sample_1, {"Sample 1", "locamation-im.samples.sets.measurement.ranges.sample.1", FT_UINT16, BASE_DEC, VALS(ranges_vals), MASK_RANGES_SAMPLE_1, NULL, HFILL}}, |
1103 | | {&hf_samples_sample_set_ranges_sample_2, {"Sample 2", "locamation-im.samples.sets.measurement.ranges.sample.2", FT_UINT16, BASE_DEC, VALS(ranges_vals), MASK_RANGES_SAMPLE_2, NULL, HFILL}}, |
1104 | | {&hf_samples_sample_set_ranges_sample_3, {"Sample 3", "locamation-im.samples.sets.measurement.ranges.sample.3", FT_UINT16, BASE_DEC, VALS(ranges_vals), MASK_RANGES_SAMPLE_3, NULL, HFILL}}, |
1105 | | {&hf_samples_sample_set_ranges_sample_4, {"Sample 4", "locamation-im.samples.sets.measurement.ranges.sample.4", FT_UINT16, BASE_DEC, VALS(ranges_vals), MASK_RANGES_SAMPLE_4, NULL, HFILL}}, |
1106 | | {&hf_samples_sample_set_ranges_sample_5, {"Sample 5", "locamation-im.samples.sets.measurement.ranges.sample.5", FT_UINT16, BASE_DEC, VALS(ranges_vals), MASK_RANGES_SAMPLE_5, NULL, HFILL}}, |
1107 | | {&hf_samples_sample_set_ranges_sample_6, {"Sample 6", "locamation-im.samples.sets.measurement.ranges.sample.6", FT_UINT16, BASE_DEC, VALS(ranges_vals), MASK_RANGES_SAMPLE_6, NULL, HFILL}}, |
1108 | | {&hf_samples_sample_set_ranges_sample_7, {"Sample 7", "locamation-im.samples.sets.measurement.ranges.sample.7", FT_UINT16, BASE_DEC, VALS(ranges_vals), MASK_RANGES_SAMPLE_7, NULL, HFILL}}, |
1109 | | {&hf_samples_sample_set_ranges_sample_8, {"Sample 8", "locamation-im.samples.sets.measurement.ranges.sample.8", FT_UINT16, BASE_DEC, VALS(ranges_vals), MASK_RANGES_SAMPLE_8, NULL, HFILL}}, |
1110 | | {&hf_samples_sample_set_sample_1, {"Sample 1", "locamation-im.samples.sets.sample.1", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1111 | | {&hf_samples_sample_set_sample_2, {"Sample 2", "locamation-im.samples.sets.sample.2", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1112 | | {&hf_samples_sample_set_sample_3, {"Sample 3", "locamation-im.samples.sets.sample.3", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1113 | | {&hf_samples_sample_set_sample_4, {"Sample 4", "locamation-im.samples.sets.sample.4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1114 | | {&hf_samples_sample_set_sample_5, {"Sample 5", "locamation-im.samples.sets.sample.5", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1115 | | {&hf_samples_sample_set_sample_6, {"Sample 6", "locamation-im.samples.sets.sample.6", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1116 | | {&hf_samples_sample_set_sample_7, {"Sample 7", "locamation-im.samples.sets.sample.7", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1117 | | {&hf_samples_sample_set_sample_8, {"Sample 8", "locamation-im.samples.sets.sample.8", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1118 | | {&hf_samples_rms_values_measurement_channel_1, {"Measurement Channel 1", "locamation-im.samples.rms.measurement.channel.1", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1119 | | {&hf_samples_rms_values_measurement_channel_2, {"Measurement Channel 2", "locamation-im.samples.rms.measurement.channel.2", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1120 | | {&hf_samples_rms_values_measurement_channel_3, {"Measurement Channel 3", "locamation-im.samples.rms.measurement.channel.3", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1121 | | {&hf_samples_rms_values_protection_channel_1, {"Protection Channel 1", "locamation-im.samples.rms.protection.channel.1", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1122 | | {&hf_samples_rms_values_protection_channel_2, {"Protection Channel 2", "locamation-im.samples.rms.protection.channel.2", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1123 | | {&hf_samples_rms_values_protection_channel_3, {"Protection Channel 3", "locamation-im.samples.rms.protection.channel.3", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1124 | | {&hf_samples_rms_values_channel_unused, {"Unused Channel", "locamation-im.samples.rms.channel.unused", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}}; |
1125 | | |
1126 | | static ei_register_info ei_samples_im1[] = { |
1127 | | {&ei_samples_ranges_sample_1_invalid, {"locamation-im.samples.sets.measurement.ranges.sample.1.invalid", PI_MALFORMED, PI_ERROR, "Invalid Range for sample 1", EXPFILL}}, |
1128 | | {&ei_samples_ranges_sample_2_invalid, {"locamation-im.samples.sets.measurement.ranges.sample.2.invalid", PI_MALFORMED, PI_ERROR, "Invalid Range for sample 2", EXPFILL}}, |
1129 | | {&ei_samples_ranges_sample_3_invalid, {"locamation-im.samples.sets.measurement.ranges.sample.3.invalid", PI_MALFORMED, PI_ERROR, "Invalid Range for sample 3", EXPFILL}}, |
1130 | | {&ei_samples_ranges_sample_4_invalid, {"locamation-im.samples.sets.measurement.ranges.sample.4.invalid", PI_MALFORMED, PI_ERROR, "Invalid Range for sample 4", EXPFILL}}, |
1131 | | {&ei_samples_ranges_sample_5_invalid, {"locamation-im.samples.sets.measurement.ranges.sample.5.invalid", PI_MALFORMED, PI_ERROR, "Invalid Range for sample 5", EXPFILL}}, |
1132 | | {&ei_samples_ranges_sample_6_invalid, {"locamation-im.samples.sets.measurement.ranges.sample.6.invalid", PI_MALFORMED, PI_ERROR, "Invalid Range for sample 6", EXPFILL}}, |
1133 | | {&ei_samples_ranges_sample_7_invalid, {"locamation-im.samples.sets.measurement.ranges.sample.7.invalid", PI_MALFORMED, PI_ERROR, "Invalid Range for sample 7", EXPFILL}}, |
1134 | | {&ei_samples_ranges_sample_8_invalid, {"locamation-im.samples.sets.measurement.ranges.sample.8.invalid", PI_MALFORMED, PI_ERROR, "Invalid Range for sample 8", EXPFILL}}}; |
1135 | | |
1136 | | static int h_protocol_samples_im1 = -1; |
1137 | | |
1138 | 0 | static int dissect_samples_im1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
1139 | 0 | return dissect_samples_im(true, tvb, pinfo, tree, data, h_protocol_samples_im1); |
1140 | 0 | } |
1141 | | |
1142 | | /* |
1143 | | * ######################################################################## |
1144 | | * # |
1145 | | * # Samples - IM2R0 |
1146 | | * # |
1147 | | * ######################################################################## |
1148 | | */ |
1149 | | |
1150 | | static hf_register_info protocol_registration_samples_im2[] = { |
1151 | | {&hf_samples_timestamps, {"Timestamps", "locamation-im.samples.timestamps", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1152 | | {&hf_samples_timestamps_version, {"Version", "locamation-im.samples.timestamps.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1153 | | {&hf_samples_timestamps_reserved, {"Reserved", "locamation-im.samples.timestamps.reserved", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1154 | | {&hf_samples_timestamps_sample_1, {"Sample 1", "locamation-im.samples.timestamps.sample.1", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1155 | | {&hf_samples_timestamps_sample_2, {"Sample 2", "locamation-im.samples.timestamps.sample.2", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1156 | | {&hf_samples_timestamps_sample_3, {"Sample 3", "locamation-im.samples.timestamps.sample.3", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1157 | | {&hf_samples_timestamps_sample_4, {"Sample 4", "locamation-im.samples.timestamps.sample.4", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1158 | | {&hf_samples_timestamps_sample_5, {"Sample 5", "locamation-im.samples.timestamps.sample.5", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1159 | | {&hf_samples_timestamps_sample_6, {"Sample 6", "locamation-im.samples.timestamps.sample.6", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1160 | | {&hf_samples_timestamps_sample_7, {"Sample 7", "locamation-im.samples.timestamps.sample.7", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1161 | | {&hf_samples_timestamps_sample_8, {"Sample 8", "locamation-im.samples.timestamps.sample.8", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1162 | | {&hf_samples_timestamps_sample_sync_status, {"Sync Status", "locamation-im.samples.timestamps.sample.sync.status", FT_UINT8, BASE_DEC, VALS(samples_timestamps_sample_sync_status), 0x0, NULL, HFILL}}, |
1163 | | {&hf_samples_timestamps_sample_additional_status, {"Additional Status", "locamation-im.samples.timestamps.sample.additional.status", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, |
1164 | | {&hf_samples_timestamps_sample_additional_status_holdover_state, {"Holdover", "locamation-im.samples.timestamps.sample.additional.status.holdover.state", FT_BOOLEAN, 8, TFS(&tfs_active_inactive), MASK_TIMESTAMP_ADDITIONAL_STATUS_HOLDOVER_STATE, NULL, HFILL}}, |
1165 | | {&hf_samples_timestamps_sample_additional_status_master_clock_switch, {"Master Clock Switch", "locamation-im.samples.timestamps.sample.additional.status.master.clock.switch", FT_BOOLEAN, 8, TFS(&tfs_yes_no), MASK_TIMESTAMP_ADDITIONAL_STATUS_MASTER_CLOCK_SWITCH, NULL, HFILL}}, |
1166 | | {&hf_samples_timestamps_sample_timestamp, {"Timestamp", "locamation-im.samples.timestamps.sample.timestamp", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
1167 | | {&hf_samples_timestamps_sample_timestamp_seconds, {"Seconds", "locamation-im.samples.timestamps.sample.timestamp.seconds", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
1168 | | {&hf_samples_timestamps_sample_timestamp_nanoseconds, {"Nanoseconds", "locamation-im.samples.timestamps.sample.timestamp.nanoseconds", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}}; |
1169 | | |
1170 | | static ei_register_info ei_samples_im2r0[] = { |
1171 | | {&ei_samples_im_version_invalid, {"locamation-im.samples.control.version.invalid", PI_MALFORMED, PI_ERROR, "Invalid Version", EXPFILL}}, |
1172 | | {&ei_samples_timestamp_sync_status_invalid, {"locamation-im.samples.timestamps.sample.sync.status.invalid", PI_MALFORMED, PI_ERROR, "Invalid Status", EXPFILL}}}; |
1173 | | |
1174 | | static int h_protocol_samples_im2r0 = -1; |
1175 | | |
1176 | 0 | static int dissect_samples_im2r0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
1177 | 0 | return dissect_samples_im(false, tvb, pinfo, tree, data, h_protocol_samples_im2r0); |
1178 | 0 | } |
1179 | | |
1180 | | /* |
1181 | | * ######################################################################## |
1182 | | * # |
1183 | | * # LLC |
1184 | | * # |
1185 | | * ######################################################################## |
1186 | | */ |
1187 | | |
1188 | | static int hf_llc_company_pid; |
1189 | | |
1190 | | static hf_register_info llc_registration[] = { |
1191 | | {&hf_llc_company_pid, {"PID", "locamation-im.llc.pid", FT_UINT16, BASE_HEX, VALS(company_pid_vals), 0x0, "Protocol ID", HFILL}}}; |
1192 | | |
1193 | | /* |
1194 | | * ######################################################################## |
1195 | | * # |
1196 | | * # Registration |
1197 | | * # |
1198 | | * ######################################################################## |
1199 | | */ |
1200 | | |
1201 | | static int *ett[] = { |
1202 | | &ett_protocol_calibration, |
1203 | | &ett_calibration_lines, |
1204 | | |
1205 | | &ett_protocol_ident, |
1206 | | &ett_ident_lines, |
1207 | | |
1208 | | &ett_samples_sample_set_ranges, |
1209 | | &ett_protocol_samples, |
1210 | | &ett_samples_control, |
1211 | | &ett_samples_sets, |
1212 | | &ett_samples_sets_set, |
1213 | | &ett_samples_rms, |
1214 | | &ett_samples_rms_values, |
1215 | | &ett_samples_timestamps, |
1216 | | &ett_samples_timestamps_set, |
1217 | | &ett_samples_timestamps_sample, |
1218 | | &ett_samples_timestamps_sample_timestamp, |
1219 | | &ett_samples_timestamps_sample_reserved |
1220 | | }; |
1221 | | |
1222 | | static dissector_handle_t h_calibration; |
1223 | | static dissector_handle_t h_ident; |
1224 | | static dissector_handle_t h_samples_im1; |
1225 | | static dissector_handle_t h_samples_im2r0; |
1226 | | |
1227 | 14 | void proto_register_locamation_im(void) { |
1228 | | /* Setup subtrees */ |
1229 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1230 | | |
1231 | | /* Register Protocols */ |
1232 | | |
1233 | | /* Calibration */ |
1234 | 14 | h_protocol_calibration = proto_register_protocol(PROTOCOL_NAME_CALIBRATION, PROTOCOL_SHORTNAME_CALIBRATION, "locamation-im.calibration"); |
1235 | 14 | proto_register_field_array(h_protocol_calibration, protocol_registration_calibration, array_length(protocol_registration_calibration)); |
1236 | 14 | expert_module_t *expert_calibration = expert_register_protocol(h_protocol_calibration); |
1237 | 14 | expert_register_field_array(expert_calibration, ei_calibration, array_length(ei_calibration)); |
1238 | | |
1239 | | /* Ident */ |
1240 | 14 | h_protocol_ident = proto_register_protocol(PROTOCOL_NAME_IDENT, PROTOCOL_SHORTNAME_IDENT, "locamation-im.ident"); |
1241 | 14 | proto_register_field_array(h_protocol_ident, protocol_registration_ident, array_length(protocol_registration_ident)); |
1242 | | |
1243 | | /* Samples - IM1 */ |
1244 | 14 | h_protocol_samples_im1 = proto_register_protocol(PROTOCOL_NAME_SAMPLES_IM1, PROTOCOL_SHORTNAME_SAMPLES_IM1, "locamation-im.samples.im1"); |
1245 | 14 | proto_register_field_array(h_protocol_samples_im1, protocol_registration_samples, array_length(protocol_registration_samples)); |
1246 | 14 | expert_module_t *expert_samples_im1 = expert_register_protocol(h_protocol_samples_im1); |
1247 | 14 | expert_register_field_array(expert_samples_im1, ei_samples_im1, array_length(ei_samples_im1)); |
1248 | | |
1249 | | /* Samples - IM2R0 */ |
1250 | 14 | h_protocol_samples_im2r0 = proto_register_protocol(PROTOCOL_NAME_SAMPLES_IM2R0, PROTOCOL_SHORTNAME_SAMPLES_IM2R0, "locamation-im.samples.im2r0"); |
1251 | 14 | proto_register_field_array(h_protocol_samples_im2r0, protocol_registration_samples_im2, array_length(protocol_registration_samples_im2)); |
1252 | 14 | expert_module_t *expert_samples_im2r0 = expert_register_protocol(h_protocol_samples_im2r0); |
1253 | 14 | expert_register_field_array(expert_samples_im2r0, ei_samples_im2r0, array_length(ei_samples_im2r0)); |
1254 | | |
1255 | | /* LLC Handler Registration */ |
1256 | 14 | llc_add_oui(COMPANY_OUI, "locamation-im.llc.pid", "LLC " COMPANY_NAME " OUI PID", llc_registration, -1); |
1257 | 14 | } |
1258 | | |
1259 | 14 | void proto_reg_handoff_locamation_im(void) { |
1260 | | /* Calibration */ |
1261 | 14 | h_calibration = create_dissector_handle(dissect_calibration, h_protocol_calibration); |
1262 | 14 | dissector_add_uint("locamation-im.llc.pid", COMPANY_PID_CALIBRATION, h_calibration); |
1263 | | |
1264 | | /* Ident */ |
1265 | 14 | h_ident = create_dissector_handle(dissect_ident, h_protocol_ident); |
1266 | 14 | dissector_add_uint("locamation-im.llc.pid", COMPANY_PID_IDENT, h_ident); |
1267 | | |
1268 | | /* Samples - IM1 */ |
1269 | 14 | h_samples_im1 = create_dissector_handle(dissect_samples_im1, h_protocol_samples_im1); |
1270 | 14 | dissector_add_uint("locamation-im.llc.pid", COMPANY_PID_SAMPLES_IM1, h_samples_im1); |
1271 | | |
1272 | | /* Samples - IM2R0 */ |
1273 | 14 | h_samples_im2r0 = create_dissector_handle(dissect_samples_im2r0, h_protocol_samples_im2r0); |
1274 | 14 | dissector_add_uint("locamation-im.llc.pid", COMPANY_PID_SAMPLES_IM2R0, h_samples_im2r0); |
1275 | 14 | } |
1276 | | |
1277 | | /* |
1278 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1279 | | * |
1280 | | * Local variables: |
1281 | | * c-basic-offset: 8 |
1282 | | * tab-width: 8 |
1283 | | * indent-tabs-mode: t |
1284 | | * End: |
1285 | | * |
1286 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
1287 | | * :indentSize=8:tabSize=8:noTabs=false: |
1288 | | */ |