epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-tecmp.c
blob5ea8e21df539bf62cc5ca82e0447ed22b934f828
1 /* packet-tecmp.c
2 * Technically Enhanced Capture Module Protocol (TECMP) dissector.
3 * By <lars.voelker@technica-engineering.de>
4 * Copyright 2019-2024 Dr. Lars Voelker
5 * Copyright 2020 Ayoub Kaanich
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
15 * This is a dissector for the Technically Enhanced Capture Module Protocol (TECMP).
16 * A new automotive protocol to carry data from a so called Capture Module (CM),
17 * which is somewhat similar to active network tap, towards a logger or PC to
18 * record or analyze the captured data.
19 * Capture Modules capture data of LIN, CAN, FlexRay, Ethernet, RS232, or other sources.
22 #include <config.h>
23 #include <epan/packet.h>
24 #include <epan/etypes.h>
25 #include <epan/expert.h>
26 #include <epan/uat.h>
27 #include <epan/proto_data.h>
28 #include <epan/tfs.h>
29 #include <epan/unit_strings.h>
31 #include <wsutil/array.h>
32 #include <wsutil/utf8_entities.h>
34 #include "packet-tecmp.h"
35 #include "packet-socketcan.h"
36 #include "packet-flexray.h"
37 #include "packet-lin.h"
40 void proto_register_tecmp(void);
41 void proto_reg_handoff_tecmp(void);
42 void proto_register_tecmp_payload(void);
43 void proto_reg_handoff_tecmp_payload(void);
45 static dissector_handle_t tecmp_handle;
47 static int proto_tecmp;
48 static int proto_tecmp_payload;
50 static dissector_handle_t eth_handle;
51 static int proto_vlan;
53 static bool heuristic_first;
54 static bool analog_samples_are_signed_int = true;
55 static bool show_ethernet_in_tecmp_tree;
56 static bool detect_asam_cmp = true;
57 static bool detect_asam_cmp_ignore_user_defined = true;
59 static dissector_table_t lin_subdissector_table;
60 static dissector_table_t data_subdissector_table;
61 static dissector_table_t data_type_subdissector_table;
62 static dissector_handle_t text_lines_handle;
64 /* Header fields */
65 /* TECMP */
66 static int hf_tecmp_device_id;
67 static int hf_tecmp_counter;
68 static int hf_tecmp_version;
69 static int hf_tecmp_msgtype;
70 static int hf_tecmp_data_type;
71 static int hf_tecmp_res;
73 static int hf_tecmp_flags;
74 static int hf_tecmp_flags_eos;
75 static int hf_tecmp_flags_sos;
76 static int hf_tecmp_flags_spy;
77 static int hf_tecmp_flags_multi_frame;
78 static int hf_tecmp_flags_dev_overflow;
80 /* TECMP Payload */
81 static int hf_tecmp_payload_interface_id;
82 static int hf_tecmp_payload_interface_name;
83 static int hf_tecmp_payload_timestamp;
84 static int hf_tecmp_payload_timestamp_ns;
85 static int hf_tecmp_payload_timestamp_async;
86 static int hf_tecmp_payload_timestamp_res;
87 static int hf_tecmp_payload_length;
88 static int hf_tecmp_payload_data;
89 static int hf_tecmp_payload_data_length;
90 static int hf_tecmp_payload_samples;
92 /* TECMP Payload flags */
93 /* Generic */
94 static int hf_tecmp_payload_data_flags;
95 static int hf_tecmp_payload_data_flags_crc;
96 static int hf_tecmp_payload_data_flags_checksum;
97 static int hf_tecmp_payload_data_flags_tx;
98 static int hf_tecmp_payload_data_flags_overflow;
100 /* ILaS*/
101 static int hf_tecmp_payload_data_flags_crc_enabled;
102 static int hf_tecmp_payload_data_flags_direction;
104 /* Ethernet Raw */
105 static int hf_tecmp_payload_data_ethernet_raw_data;
106 static int hf_tecmp_payload_data_ethernet_raw_preamble;
107 static int hf_tecmp_payload_data_ethernet_raw_sfd;
108 static int hf_tecmp_payload_data_ethernet_raw_eth_frame;
110 /* Ethernet 10BASE-T1S */
111 static int hf_tecmp_payload_data_flags_phy_event_error;
113 /* LIN */
114 static int hf_tecmp_payload_data_flags_coll;
115 static int hf_tecmp_payload_data_flags_parity;
116 static int hf_tecmp_payload_data_flags_no_resp;
117 static int hf_tecmp_payload_data_flags_wup;
118 static int hf_tecmp_payload_data_flags_short_wup;
119 static int hf_tecmp_payload_data_flags_sleep;
121 /* CAN and CAN-FD DATA */
122 static int hf_tecmp_payload_data_flags_ack;
123 static int hf_tecmp_payload_data_flags_rtr; /* CAN DATA only */
124 static int hf_tecmp_payload_data_flags_esi; /* CAN-FD DATA only */
125 static int hf_tecmp_payload_data_flags_ide;
126 static int hf_tecmp_payload_data_flags_err;
127 static int hf_tecmp_payload_data_flags_brs; /* CAN-FD DATA only */
129 static int hf_tecmp_payload_data_flags_can_bit_stuff_err;
130 static int hf_tecmp_payload_data_flags_can_crc_del_err;
131 static int hf_tecmp_payload_data_flags_can_ack_del_err;
132 static int hf_tecmp_payload_data_flags_can_eof_err;
133 static int hf_tecmp_payload_data_flags_canfd_bit_stuff_err;
134 static int hf_tecmp_payload_data_flags_canfd_crc_del_err;
135 static int hf_tecmp_payload_data_flags_canfd_ack_del_err;
136 static int hf_tecmp_payload_data_flags_canfd_eof_err;
138 /* FlexRay */
139 static int hf_tecmp_payload_data_flags_nf;
140 static int hf_tecmp_payload_data_flags_sf;
141 static int hf_tecmp_payload_data_flags_sync;
142 static int hf_tecmp_payload_data_flags_wus;
143 static int hf_tecmp_payload_data_flags_ppi;
144 static int hf_tecmp_payload_data_flags_cas;
145 static int hf_tecmp_payload_data_flags_header_crc_err;
146 static int hf_tecmp_payload_data_flags_frame_crc_err;
148 /* UART/RS232 ASCII*/
149 static int hf_tecmp_payload_data_flags_dl;
150 static int hf_tecmp_payload_data_flags_parity_error;
152 /* Analog */
153 static int hf_tecmp_payload_data_flags_sample_time;
154 static int hf_tecmp_payload_data_flags_factor;
155 static int hf_tecmp_payload_data_flags_unit;
156 static int hf_tecmp_payload_data_flags_threshold_u;
157 static int hf_tecmp_payload_data_flags_threshold_o;
159 /* Special TX Data Flags */
160 static int hf_tecmp_payload_data_flags_use_crc_value;
161 static int hf_tecmp_payload_data_flags_use_header_crc_value;
162 static int hf_tecmp_payload_data_flags_use_checksum_value;
163 static int hf_tecmp_payload_data_flags_use_parity_bits;
164 static int hf_tecmp_payload_data_flags_tx_mode;
166 static const unit_name_string tecmp_units_amp_hour = { "Ah", NULL };
168 #define TECMP_DATAFLAGS_FACTOR_MASK 0x0180
169 #define TECMP_DATAFLAGS_FACTOR_SHIFT 7
170 #define TECMP_DATAFLAGS_UNIT_MASK 0x001c
171 #define TECMP_DATAFLAGS_UNIT_SHIFT 2
173 /* TECMP Payload Fields */
174 /* Ethernet 10BASE-T1S */
175 static int hf_tecmp_payload_data_beacon_timestamp;
176 static int hf_tecmp_payload_data_beacon_timestamp_ns;
177 static int hf_tecmp_payload_data_beacon_to_timestamp_ns;
179 /* LIN */
180 static int hf_tecmp_payload_data_id_field_8bit;
181 static int hf_tecmp_payload_data_id_field_6bit;
182 static int hf_tecmp_payload_data_parity_bits;
183 static int hf_tecmp_payload_data_checksum_8bit;
185 /* CAN DATA / CAN-FD DATA */
186 static int hf_tecmp_payload_data_id_field_32bit;
187 static int hf_tecmp_payload_data_id_type;
188 static int hf_tecmp_payload_data_id_11;
189 static int hf_tecmp_payload_data_id_29;
190 static int hf_tecmp_payload_data_crc15;
191 static int hf_tecmp_payload_data_crc17;
192 static int hf_tecmp_payload_data_crc21;
194 /* FlexRay DATA */
195 static int hf_tecmp_payload_data_cycle;
196 static int hf_tecmp_payload_data_frame_id;
197 static int hf_tecmp_payload_data_header_crc;
198 static int hf_tecmp_payload_data_frame_crc;
200 /* Analog */
201 static int hf_tecmp_payload_data_analog_value_raw;
202 static int hf_tecmp_payload_data_analog_value_raw_signed;
203 static int hf_tecmp_payload_data_analog_value_volt;
204 static int hf_tecmp_payload_data_analog_value_amp;
205 static int hf_tecmp_payload_data_analog_value_watt;
206 static int hf_tecmp_payload_data_analog_value_amp_hour;
207 static int hf_tecmp_payload_data_analog_value_celsius;
209 /* Analog Alt */
210 static int hf_tecmp_payload_analog_alt_flags;
211 static int hf_tecmp_payload_analog_alt_flag_sample_dt;
212 static int hf_tecmp_payload_analog_alt_flag_reserved;
214 static int hf_tecmp_payload_analog_alt_reserved;
215 static int hf_tecmp_payload_analog_alt_unit;
216 static int hf_tecmp_payload_analog_alt_sample_interval;
217 static int hf_tecmp_payload_analog_alt_sample_offset;
218 static int hf_tecmp_payload_analog_alt_sample_scalar;
219 static int hf_tecmp_payload_analog_alt_sample_raw;
220 static int hf_tecmp_payload_analog_alt_sample;
222 /* ILaS */
223 static int hf_tecmp_payload_data_ilas_decoded_command;
224 static int hf_tecmp_payload_data_ilas_decoded_address;
225 static int hf_tecmp_payload_data_ilas_decoded_data;
226 static int hf_tecmp_payload_data_ilas_raw_sdu;
227 static int hf_tecmp_payload_data_ilas_raw_crc;
229 /* TECMP Status Messages */
230 /* Status Device */
231 static int hf_tecmp_payload_status_vendor_id;
232 static int hf_tecmp_payload_status_dev_version;
233 static int hf_tecmp_payload_status_dev_type;
234 static int hf_tecmp_payload_status_res;
235 static int hf_tecmp_payload_status_length_vendor_data;
236 static int hf_tecmp_payload_status_device_id;
237 static int hf_tecmp_payload_status_sn;
238 static int hf_tecmp_payload_status_vendor_data;
240 /* Status Bus */
241 static int hf_tecmp_payload_status_bus_data;
242 static int hf_tecmp_payload_status_bus_data_entry;
243 static int hf_tecmp_payload_status_bus_interface_id;
244 static int hf_tecmp_payload_status_bus_total;
245 static int hf_tecmp_payload_status_bus_errors;
247 /* Status Device Vendor Data Technica Engineering */
248 static int hf_tecmp_payload_status_dev_vendor_technica_res;
249 static int hf_tecmp_payload_status_dev_vendor_technica_sw;
250 static int hf_tecmp_payload_status_dev_vendor_technica_hw;
251 static int hf_tecmp_payload_status_dev_vendor_technica_buffer_fill_level;
252 static int hf_tecmp_payload_status_dev_vendor_technica_buffer_overflow;
253 static int hf_tecmp_payload_status_dev_vendor_technica_buffer_size;
254 static int hf_tecmp_payload_status_dev_vendor_technica_lifecycle;
255 static int hf_tecmp_payload_status_dev_vendor_technica_lifecycle_start;
256 static int hf_tecmp_payload_status_dev_vendor_technica_voltage;
257 static int hf_tecmp_payload_status_dev_vendor_technica_temperature;
258 static int hf_tecmp_payload_status_dev_vendor_technica_temperature_chassis;
259 static int hf_tecmp_payload_status_dev_vendor_technica_temperature_silicon;
261 #define VENDOR_TECHNICA_TEMP_MAX 127
262 #define VENDOR_TECHNICA_TEMP_NA -128
264 /* Status Bus Vendor Data Technica Engineering */
265 static int hf_tecmp_payload_status_bus_vendor_technica_link_status;
266 static int hf_tecmp_payload_status_bus_vendor_technica_link_quality;
267 static int hf_tecmp_payload_status_bus_vendor_technica_linkup_time;
269 static int hf_tecmp_payload_status_bus_vendor_technica_10m_flags;
270 static int hf_tecmp_payload_status_bus_vendor_technica_10m_flags_beacons_received;
271 static int hf_tecmp_payload_status_bus_vendor_technica_10m_flags_plca_enabled;
272 static int hf_tecmp_payload_status_bus_vendor_technica_res0;
273 static int hf_tecmp_payload_status_bus_vendor_technica_beacon_counter;
274 static int hf_tecmp_payload_status_bus_vendor_technica_res1;
275 static int hf_tecmp_payload_status_bus_vendor_technica_res2;
276 static int hf_tecmp_payload_status_bus_vendor_technica_5b_decode_err_cnt;
277 static int hf_tecmp_payload_status_bus_vendor_technica_eos_delim_err_cnt;
278 static int hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_detected_cnt;
279 static int hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_missing_cnt;
280 static int hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_empty_cycle_cnt;
283 /* Status Configuration Data Technica Engineering */
284 static int hf_tecmp_payload_status_cfg_vendor_technica_version;
285 static int hf_tecmp_payload_status_cfg_vendor_technica_reserved;
286 static int hf_tecmp_payload_status_cfg_vendor_technica_msg_id;
287 static int hf_tecmp_payload_status_cfg_vendor_technica_total_length;
288 static int hf_tecmp_payload_status_cfg_vendor_technica_total_num_seg;
289 static int hf_tecmp_payload_status_cfg_vendor_technica_segment_num;
290 static int hf_tecmp_payload_status_cfg_vendor_technica_segment_length;
291 static int hf_tecmp_payload_status_cfg_vendor_technica_segment_data;
293 /* TECMP Control Message */
294 static int hf_tecmp_payload_ctrl_msg_device_id;
295 static int hf_tecmp_payload_ctrl_msg_id;
296 static int hf_tecmp_payload_ctrl_msg_unparsed_bytes;
297 static int hf_tecmp_payload_ctrl_msg_can_replay_fill_level_fill_level;
298 static int hf_tecmp_payload_ctrl_msg_can_replay_fill_level_buffer_overflow;
299 static int hf_tecmp_payload_ctrl_msg_can_replay_fill_level_queue_size;
300 static int hf_tecmp_payload_ctrl_msg_can_replay_fill_level_queue_length;
301 static int hf_tecmp_payload_ctrl_msg_flexray_poc_interface_id;
302 static int hf_tecmp_payload_ctrl_msg_flexray_poc_state;
303 static int hf_tecmp_payload_ctrl_msg_10baset1s_interface_id;
304 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags;
305 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags_beacons_received;
306 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags_plca_enabled;
307 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_reserved;
308 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_events;
309 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_5b_decode_error;
310 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_eos_delim_error;
311 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_symb_detected;
312 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_symb_missing;
313 static int hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_empty_cycle;
315 /* Counter Event */
316 static int hf_tecmp_payload_counter_event_device_id;
317 static int hf_tecmp_payload_counter_event_interface_id;
318 static int hf_tecmp_payload_counter_event_counter_last;
319 static int hf_tecmp_payload_counter_event_counter_cur;
321 /* TimeSync Event */
322 static int hf_tecmp_payload_timesync_event_device_id;
323 static int hf_tecmp_payload_timesync_event_interface_id;
324 static int hf_tecmp_payload_timesync_event_reserved;
325 static int hf_tecmp_payload_timesync_event_async;
326 static int hf_tecmp_payload_timesync_event_time_delta;
329 /* protocol tree items */
330 static int ett_tecmp;
331 static int ett_tecmp_flags;
333 static int ett_tecmp_payload;
334 static int ett_tecmp_payload_interface_id;
335 static int ett_tecmp_payload_data;
336 static int ett_tecmp_payload_timestamp;
337 static int ett_tecmp_payload_dataflags;
338 static int ett_tecmp_payload_instruction_address;
339 static int ett_tecmp_payload_data_id;
340 static int ett_tecmp_payload_lin_id;
341 static int ett_tecmp_payload_analog_alt_flags;
342 static int ett_tecmp_payload_analog_alt_sample;
343 static int ett_tecmp_payload_eth_raw;
344 static int ett_tecmp_payload_eth_raw_frame;
345 static int ett_tecmp_status_bus_data;
346 static int ett_tecmp_status_bus_data_entry;
347 static int ett_tecmp_status_dev_vendor_data;
348 static int ett_tecmp_status_bus_vendor_data;
349 static int ett_tecmp_status_bus_vendor_data_flags;
350 static int ett_tecmp_ctrl_message_10baset1s_flags;
351 static int ett_tecmp_ctrl_message_10baset1s_events_errors;
353 /* dissector handle to hand off to ASAM CMP (successor protocol) */
354 static dissector_handle_t asam_cmp_handle;
356 /*** expert info items ***/
357 static expert_field ei_tecmp_payload_length_mismatch;
358 static expert_field ei_tecmp_payload_header_crc_overflow;
360 /* TECMP Type Names */
362 #define TECMP_MSG_TYPE_CTRL_MSG 0x00
363 #define TECMP_MSG_TYPE_STATUS_DEV 0x01
364 #define TECMP_MSG_TYPE_STATUS_BUS 0x02
365 #define TECMP_MSG_TYPE_LOG_STREAM 0x03
366 #define TECMP_MSG_TYPE_CFG_CM 0x04
367 #define TECMP_MSG_TYPE_REPLAY_DATA 0x0A
368 #define TECMP_MSG_TYPE_COUNTER_EVENT 0x0B
369 #define TECMP_MSG_TYPE_TIMESYNC_EVENT 0x0C
372 /* TECMP Type Names */
373 /* Updated by ID Registry */
374 static const value_string msg_type_names[] = {
375 {TECMP_MSG_TYPE_CTRL_MSG, "Control Message"},
376 {TECMP_MSG_TYPE_STATUS_DEV, "Status Device"},
377 {TECMP_MSG_TYPE_STATUS_BUS, "Status Bus"},
378 {TECMP_MSG_TYPE_LOG_STREAM, "Logging Stream"},
379 {TECMP_MSG_TYPE_CFG_CM, "Status Configuration"},
380 {TECMP_MSG_TYPE_REPLAY_DATA, "Replay Data"},
381 {TECMP_MSG_TYPE_COUNTER_EVENT, "Counter Event"},
382 {TECMP_MSG_TYPE_TIMESYNC_EVENT, "TimeSync Event"},
383 {0, NULL}
386 /* TECMP Message Type Names */
387 /* Updated by ID Registry */
388 #define TECMP_DATA_TYPE_NONE 0x0000
389 #define TECMP_DATA_TYPE_CAN_RAW 0x0001
390 #define TECMP_DATA_TYPE_CAN_DATA 0x0002
391 #define TECMP_DATA_TYPE_CAN_FD_DATA 0x0003
392 #define TECMP_DATA_TYPE_LIN 0x0004
393 #define TECMP_DATA_TYPE_FR_RAW 0x0007
394 #define TECMP_DATA_TYPE_FR_DATA 0x0008
395 #define TECMP_DATA_TYPE_GPIO 0x000A
396 #define TECMP_DATA_TYPE_ILAS 0x000E
397 #define TECMP_DATA_TYPE_RS232_ASCII 0x0010
398 #define TECMP_DATA_TYPE_RS232_RAW 0x0011
399 #define TECMP_DATA_TYPE_RS232_SLA 0x0012
400 #define TECMP_DATA_TYPE_ANALOG 0x0020
401 #define TECMP_DATA_TYPE_ANALOG_SLA 0x0021
402 #define TECMP_DATA_TYPE_ANALOG_ALT 0x0028
403 #define TECMP_DATA_TYPE_ETH 0x0080
404 #define TECMP_DATA_TYPE_ETH_RAW 0x0081
405 #define TECMP_DATA_TYPE_ETH_10BASE_T1S 0x0082
406 #define TECMP_DATA_TYPE_XCP_DATA 0x00A0
407 #define TECMP_DATA_TYPE_MIPI_CSI2_V 0x0101
408 #define TECMP_DATA_TYPE_MIPI_CSI2_L 0x0102
409 #define TECMP_DATA_TYPE_SPI 0x0103
410 #define TECMP_DATA_TYPE_I2C_7BIT 0x0104
411 #define TECMP_DATA_TYPE_TAPI 0x0200
412 #define TECMP_DATA_TYPE_TAPI_INIT_STATE 0x0201
413 #define TECMP_DATA_TYPE_TAPI_CORE_DUMP 0x0202
414 #define TECMP_DATA_TYPE_R 0x0400
415 #define TECMP_DATA_TYPE_TECMP_RAW 0xA000
416 #define TECMP_DATA_TYPE_PRE_LABEL 0xB000
418 static const value_string tecmp_msgtype_names[] = {
419 {TECMP_DATA_TYPE_NONE, "None (Undefined)"},
420 {TECMP_DATA_TYPE_CAN_RAW, "CAN(-FD) Raw"},
421 {TECMP_DATA_TYPE_CAN_DATA, "CAN Data"},
422 {TECMP_DATA_TYPE_CAN_FD_DATA, "CAN-FD Data"},
423 {TECMP_DATA_TYPE_LIN, "LIN"},
424 {TECMP_DATA_TYPE_FR_RAW, "Flexray Raw"},
425 {TECMP_DATA_TYPE_FR_DATA, "Flexray Data"},
426 {TECMP_DATA_TYPE_GPIO, "GPIO"},
427 {TECMP_DATA_TYPE_ILAS, "ILaS"},
428 {TECMP_DATA_TYPE_RS232_ASCII, "UART/RS232_ASCII"},
429 {TECMP_DATA_TYPE_RS232_RAW, "UART/RS232_RAW"},
430 {TECMP_DATA_TYPE_RS232_SLA, "UART/RS232_SLA"},
431 {TECMP_DATA_TYPE_ANALOG, "Analog"},
432 {TECMP_DATA_TYPE_ANALOG_SLA, "Analog_SLA"},
433 {TECMP_DATA_TYPE_ANALOG_ALT, "Analog Alternative"},
434 {TECMP_DATA_TYPE_ETH, "Ethernet II"},
435 {TECMP_DATA_TYPE_ETH_RAW, "Ethernet Raw"},
436 {TECMP_DATA_TYPE_ETH_10BASE_T1S, "Ethernet 10BASE-T1S"},
437 {TECMP_DATA_TYPE_XCP_DATA, "XCP-Data"},
438 {TECMP_DATA_TYPE_MIPI_CSI2_V, "MIPI-CSI2 V"},
439 {TECMP_DATA_TYPE_MIPI_CSI2_L, "MIPI-CSI2 L"},
440 {TECMP_DATA_TYPE_SPI, "SPI"},
441 {TECMP_DATA_TYPE_I2C_7BIT, "I2C 7 Bit"},
442 {TECMP_DATA_TYPE_TAPI, "TAPI"},
443 {TECMP_DATA_TYPE_TAPI_INIT_STATE, "TAPI Initial State"},
444 {TECMP_DATA_TYPE_TAPI_CORE_DUMP, "TAPI Core Dump"},
445 {TECMP_DATA_TYPE_R, "R"},
446 {TECMP_DATA_TYPE_TECMP_RAW, "TECMP_Raw"},
447 {TECMP_DATA_TYPE_PRE_LABEL, "PreLabel"},
448 {0, NULL}
451 /* Vendor IDs */
452 /* Updated by ID Registry */
453 #define TECMP_VENDOR_ID_TECHNICA 0x0c
454 static const value_string tecmp_vendor_ids[] = {
455 {TECMP_VENDOR_ID_TECHNICA, "Technica Engineering"},
456 {0, NULL}
459 /* Device IDs */
460 /* Can be overwritten/extended by config */
461 static const value_string tecmp_device_id_prefixes[] = {
462 {0x0030, "CM LIN Combo"},
463 {0x0040, "CM CAN Combo"},
464 {0x0060, "CM 100 High"},
465 {0x0080, "CM Eth Combo"},
466 {0x0090, "CM 1000 High"},
467 {0x00e0, "CM MultiGigabit"},
468 {0, NULL}
471 static const value_string tecmp_device_ids_specific[] = {
472 {0x0050, "CM Sense 0"},
473 {0x0051, "CM Sense 1"},
474 {0x0052, "CM Sense 2"},
475 {0x0053, "CM Sense 3"},
476 {0x0054, "CM Sense 4"},
477 {0x0055, "CM Sense 5"},
478 {0x0056, "CM Sense 6"},
479 {0x0057, "CM Sense 7"},
480 {0x0070, "CM 10BASE-T1S 0"},
481 {0x0071, "CM 10BASE-T1S 1"},
482 {0x0072, "CM 10BASE-T1S 2"},
483 {0x0073, "CM 10BASE-T1S 3"},
484 {0x0074, "CM 10BASE-T1S 4"},
485 {0x0075, "CM 10BASE-T1S 5"},
486 {0x0076, "CM 10BASE-T1S 6"},
487 {0x0077, "CM 10BASE-T1S 7"},
488 {0x0078, "CM 10BASE-T1S 8"},
489 {0x0079, "CM 10BASE-T1S 9"},
490 {0x007a, "ILaS Sniffer 0"},
491 {0x007b, "ILaS Sniffer 1"},
492 {0x007c, "ILaS Sniffer 2"},
493 {0x007d, "ILaS Sniffer 3"},
494 {0x007e, "ILaS Sniffer 4"},
495 {0x007f, "ILaS Sniffer 5"},
496 {0, NULL}
499 #define TECMP_DEVICE_TYPE_CM_10BASE_T1S 0x0c
500 #define TECMP_DEVICE_TYPE_CM_ILAS_COMBO 0x0e
502 /* Device Types */
503 /* Updated by ID Registry */
504 static const value_string tecmp_device_types[] = {
505 {0x02, "CM LIN Combo"},
506 {0x04, "CM CAN Combo"},
507 {0x06, "CM 100 High"},
508 {0x07, "CM 100 High TC10"},
509 {0x08, "CM Eth Combo"},
510 {0x0a, "CM 1000 High"},
511 {TECMP_DEVICE_TYPE_CM_10BASE_T1S, "CM 10BASE-T1S"},
512 {TECMP_DEVICE_TYPE_CM_ILAS_COMBO, "ILaS Sniffer"},
513 {0x10, "Sensor specific"},
514 {0x20, "Logger"},
515 {0x42, "CM MultiGigabit"},
516 {0x46, "CM Sense"},
517 {0, NULL}
520 /* Control Message IDs */
521 /* Updated by ID Registry */
522 #define TECMP_CTRL_MSG_LOGGER_READY 0x0002
523 #define TECMP_CTRL_MSG_CAN_REPLAY_FILL_LVL 0x00E0
524 #define TECMP_CTRL_MSG_FR_POC_STATE 0x00E1
525 #define TECMP_CTRL_MSG_10BASE_T1S 0x00E2
527 static const value_string tecmp_ctrl_msg_ids_types[] = {
528 {TECMP_CTRL_MSG_LOGGER_READY, "Logger Ready"},
529 {TECMP_CTRL_MSG_CAN_REPLAY_FILL_LVL, "CAN Replay Fill Level"},
530 {TECMP_CTRL_MSG_FR_POC_STATE, "FlexRay POC State"},
531 {TECMP_CTRL_MSG_10BASE_T1S, "10BASE-T1S"},
532 {0, NULL}
535 static const value_string tecmp_ctrl_msg_fr_poc_state[] = {
536 {0, "Config"},
537 {1, "Default Config"},
538 {2, "Halt"},
539 {3, "Normal Active"},
540 {4, "Normal Passive"},
541 {5, "Ready"},
542 {6, "Startup"},
543 {7, "Wakeup"},
544 {0, NULL}
547 static const true_false_string tfs_tecmp_payload_timestamp_async_type = {
548 "Not synchronized",
549 "Synchronized or Master"
552 static const true_false_string tfs_tecmp_technica_bufferoverflow = {
553 "Buffer Overflow occurred",
554 "No Buffer Overflow occurred"
557 static const true_false_string tfs_tecmp_payload_data_crc_received = {
558 "CRC present in received message",
559 "CRC not present in received message"
562 static const true_false_string tfs_tecmp_payload_data_direction = {
563 "Upstream (response)",
564 "Downstream (command)"
567 static const true_false_string tfs_tecmp_payload_data_id_type = {
568 "29bit CAN Identifier",
569 "11bit CAN Identifier"
572 static const value_string tecmp_payload_rs232_uart_dl_types[] = {
573 {0x2, "RS232 with 7 bit"},
574 {0x3, "RS232 with 8 bit"},
575 {0, NULL}
578 static const value_string tecmp_payload_analog_sample_time_types[] = {
579 {0x0, "Reserved"},
580 {0x1, "2500 ms"},
581 {0x2, "1000 ms"},
582 {0x3, "500 ms"},
583 {0x4, "250 ms"},
584 {0x5, "100 ms"},
585 {0x6, "50 ms"},
586 {0x7, "25 ms"},
587 {0x8, "10 ms"},
588 {0x9, "5 ms"},
589 {0xa, "2.5 ms"},
590 {0xb, "1 ms"},
591 {0xc, "0.5 ms"},
592 {0xd, "0.25 ms"},
593 {0xe, "0.1 ms"},
594 {0xf, "0.05 ms"},
595 {0, NULL}
598 static const double tecmp_payload_analog_scale_factor_values[] = {
599 0.1,
600 0.01,
601 0.001,
602 0.0001,
605 static const value_string tecmp_payload_analog_scale_factor_types[] = {
606 {0x0, "0.1"},
607 {0x1, "0.01"},
608 {0x2, "0.001"},
609 {0x3, "0.0001"},
610 {0, NULL}
613 static const value_string tecmp_payload_analog_unit_types[] = {
614 {0x0, "V"},
615 {0x1, "A"},
616 {0x2, "W"},
617 {0x3, "Ah"},
618 {0x4, UTF8_DEGREE_SIGN "C"},
619 {0x5, "undefined value"},
620 {0x6, "undefined value"},
621 {0x7, "undefined value"},
622 {0, NULL}
625 static const value_string analog_alt_units[] = {
626 {0x04, "A"},
627 {0x0e, "W"},
628 {0x0f, "C"},
629 {0x10, "V"},
630 {0x17, "°C"},
631 {0, NULL}
634 /* TECMP Analog Alt Data Message DT Values */
635 #define TECMP_ANALOG_ALT_DATA_MSG_DL_16 0x00
636 #define TECMP_ANALOG_ALT_DATA_MSG_DL_32 0x01
638 static const value_string analog_alt_sample_dt[] = {
639 {TECMP_ANALOG_ALT_DATA_MSG_DL_16, "A_INT16"},
640 {TECMP_ANALOG_ALT_DATA_MSG_DL_32, "A_INT32"},
641 {0, NULL}
644 static const value_string tecmp_ilas_command_types[] = {
645 {0, "Unknown Command"},
646 {1, "ILas_Reset"},
647 {2, "ILaS_Set_Config"},
648 {3, "ILaS_Set_PWM_Max_High_Ch2"},
649 {4, "ILaS_Set_PWM_Max_High_Ch1"},
650 {5, "ILaS_Set_PWM_Max_High_Ch0"},
651 {6, "ILaS_Set_Cur_Ch1"},
652 {7, "ILaS_Set_Cur_Ch0"},
653 {8, "ILaS_Set_Temp_Offset"},
654 {9, "ILaS_Trig_ADC_Cal"},
655 {11, "ILaS_Set_Bias"},
656 {12, "ILaS_Set_TC_Base"},
657 {13, "ILaS_Set_TC_Offset"},
658 {14, "ILaS_Set_Sig_High"},
659 {15, "ILaS_Set_ADC_DAC"},
660 {16, "ILaS_Burn_Item (part 1)"},
661 {17, "ILaS_Burn_Sig"},
662 {18, "ILaS_Burn_Item (part 2)"},
663 {19, "ILaS_Set_TC_LUT"},
664 {20, "ILaS_Define_Mcast"},
665 {21, "ILaS_Set_PWM_Max_Low_Ch2"},
666 {22, "ILaS_Set_PWM_Max_Low_Ch1"},
667 {23, "ILaS_Set_PWM_Max_Low_Ch0"},
668 {24, "ILaS_Set_Cur_Ch3"},
669 {25, "ILaS_Burn_Item (part 3)"},
670 {26, "ILaS_Set_Port"},
671 {27, "ILaS_Branch_Read_Temp"},
672 {28, "ILaS_Branch_Read_Status"},
673 {29, "ILaS_Branch_Read_ADC"},
674 {30, "ILaS_Branch_Read_Item (part 1)"},
675 {31, "ILaS_Branch_Read_PWM"},
676 {32, "ILaS_Branch_Read_Item (part 2)"},
677 {33, "ILaS_Network_Init"},
678 {34, "ILaS_Branch_Init"},
679 {35, "ILaS_Network_Ping"},
680 {36, "ILaS_Branch_Ping"},
681 {37, "ILaS_Read_Register"},
682 {38, "ILaS_BranchDevices_Read"},
683 {39, "ILaS_Read_Event"},
684 {40, "ILaS_Set_Fw_Mode"},
685 {41, "ILaS_Set_Ps_Mode"},
686 {42, "ILaS_Burn_Sniff_Mode"},
687 {43, "ILaS_NOP"},
688 {44, "ILaS_Trg_ADC_Meas"},
689 {45, "ILaS_Set_3PWM_Low"},
690 {46, "ILaS_Set_3PWM_High"},
691 {47, "ILaS_Set_DIM"},
692 {48, "ILaS_Set_PWM_Ch3"},
693 {49, "ILaS_Write_Register"},
694 {50, "ILaS_Burn_Register"},
695 {51, "ILaS_Branch_Read_Item (config)"},
696 {52, "ILaS_Branch_Read_Item (PWM_Max_Hi_Ch2)"},
697 {53, "ILaS_Branch_Read_Item (PWM_Max_Hi_Ch1)"},
698 {54, "ILaS_Branch_Read_Item (PWM_Max_Hi_Ch0)"},
699 {55, "ILaS_Branch_Read_Item (Peak_Ch1)"},
700 {56, "ILaS_Branch_Read_Item (Peak_Ch0)"},
701 {57, "ILaS_Branch_Read_Item (Temp_Offset)"},
702 {58, "ILaS_Branch_Read_Item (ADC_offset + ADC_ref)"},
703 {59, "ILaS_Branch_Read_Item (Bias)"},
704 {60, "ILaS_Branch_Read_Item (TC_Base_Ch2)"},
705 {61, "ILaS_Branch_Read_Item (TC_Offset_Ch2)"},
706 {62, "ILaS_Branch_Read_Item (last_fuse)"},
707 {63, "ILaS_Branch_Read_PWM (Hi_Ch2)"},
708 {64, "ILaS_Branch_Read_PWM (Hi_Ch1)"},
709 {65, "ILaS_Branch_Read_PWM (Hi_Ch0)"},
710 {66, "ILaS_Set_Fw_Mode (M0)"},
711 {67, "ILaS_Set_Fw_Mode (M1)"},
712 {68, "ILaS_Set_Fw_Mode (M2)"},
713 {69, "ILaS_Set_Fw_Mode (M3)"},
714 {70, "ILaS_Trg_ADC_Meas (Temperature)"},
715 {71, "ILaS_Trg_ADC_Meas (5V_PRG)"},
716 {72, "ILaS_Trg_ADC_Meas (1V5_DIG)"},
717 {73, "ILaS_Trg_ADC_Meas (RED)"},
718 {74, "ILaS_Trg_ADC_Meas (GREEN)"},
719 {75, "ILaS_Trg_ADC_Meas (BLUE)"},
720 {76, "ILaS_Trg_ADC_Meas (BG)"},
721 {77, "ILaS_Trg_ADC_Meas (VSUP)"},
722 {78, "ILaS_Trg_ADC_Meas (VCCA)"},
723 {79, "ILaS_Trg_ADC_Meas (1V5_AN)"},
724 {80, "ILaS_Trg_ADC_Meas (VSENSE)"},
725 {0, NULL}
728 static const value_string tecmp_payload_flexray_tx_mode[] = {
729 {0x0, "Reserved"},
730 {0x1, "Single Shot Transmission"},
731 {0x2, "Continuous Transmission"},
732 {0x3, "TX None"},
733 {0, NULL}
736 static const value_string tecmp_bus_status_link_status[] = {
737 {0x0, "Down"},
738 {0x1, "Up"},
739 {0, NULL}
742 static const value_string tecmp_bus_status_link_quality[] = {
743 {0x0, "Unacceptable or Down (0/5)"},
744 {0x1, "Poor (1/5)"},
745 {0x2, "Marginal (2/5)"},
746 {0x3, "Good (3/5)"},
747 {0x4, "Very good (4/5)"},
748 {0x5, "Excellent (5/5)"},
749 {0, NULL}
752 static const value_string tecmp_timesync_event_flags[] = {
753 {0x0, "No error occurred"},
754 {0x1, "Error occurred"},
755 {0, NULL}
759 #define DATA_FLAG_CAN_ACK 0x0001
760 #define DATA_FLAG_CAN_RTR 0x0002
761 #define DATA_FLAG_CANFD_ESI 0x0002
762 #define DATA_FLAG_CAN_IDE 0x0004
763 #define DATA_FLAG_CAN_ERR 0x0008
764 #define DATA_FLAG_CAN_BIT_STUFF_ERR 0x0010
765 #define DATA_FLAG_CAN_CRC_DEL_ERR 0x0020
766 #define DATA_FLAG_CAN_ACK_DEL_ERR 0x0040
767 #define DATA_FLAG_CAN_EOF_ERR 0x0080
768 #define DATA_FLAG_CANFD_BRS 0x0010
769 #define DATA_FLAG_CANFD_BIT_STUFF_ERR 0x0020
770 #define DATA_FLAG_CANFD_CRC_DEL_ERR 0x0040
771 #define DATA_FLAG_CANFD_ACK_DEL_ERR 0x0080
772 #define DATA_FLAG_CANFD_EOF_ERR 0x0100
774 #define DATA_FLAG_FR_NF 0x0001
775 #define DATA_FLAG_FR_ST 0x0002
776 #define DATA_FLAG_FR_SYNC 0x0004
777 #define DATA_FLAG_FR_WUS 0x0008
778 #define DATA_FLAG_FR_PPI 0x0010
779 #define DATA_FLAG_FR_CAS 0x0020
780 #define DATA_FLAG_FR_HDR_CRC_ERR 0x1000
781 #define DATA_FLAG_FR_FRAME_CRC_ERR 0x2000
783 #define DATA_LIN_ID_MASK 0x3F
784 #define DATA_FR_HEADER_CRC_MAX 0x07FF
786 #define TECMP_ETH_RAW_PREAMBLE 0x55
787 #define TECMP_ETH_RAW_SFD_ORIG 0xD5
788 #define TECMP_ETH_RAW_SFD_SMD_V 0x07
789 #define TECMP_ETH_RAW_SFD_SMD_R 0x19
790 #define TECMP_ETH_RAW_SFD_SMD_S0 0xE6
791 #define TECMP_ETH_RAW_SFD_SMD_S1 0x4C
792 #define TECMP_ETH_RAW_SFD_SMD_S2 0x7F
793 #define TECMP_ETH_RAW_SFD_SMD_S3 0xB3
794 #define TECMP_ETH_RAW_SFD_SMD_C0 0x61
795 #define TECMP_ETH_RAW_SFD_SMD_C1 0x52
796 #define TECMP_ETH_RAW_SFD_SMD_C2 0x9E
797 #define TECMP_ETH_RAW_SFD_SMD_C3 0x2A
799 static const value_string tecmp_eth_raw_sfd[] = {
800 {TECMP_ETH_RAW_SFD_ORIG, "SFD/SMD-E"},
801 {TECMP_ETH_RAW_SFD_SMD_V, "SMD-V"},
802 {TECMP_ETH_RAW_SFD_SMD_R, "SMD-R"},
803 {TECMP_ETH_RAW_SFD_SMD_S0, "SMD-S0"},
804 {TECMP_ETH_RAW_SFD_SMD_S1, "SMD-S1"},
805 {TECMP_ETH_RAW_SFD_SMD_S2, "SMD-S2"},
806 {TECMP_ETH_RAW_SFD_SMD_S3, "SMD-S3"},
807 {TECMP_ETH_RAW_SFD_SMD_C0, "SMD-C0"},
808 {TECMP_ETH_RAW_SFD_SMD_C1, "SMD-C1"},
809 {TECMP_ETH_RAW_SFD_SMD_C2, "SMD-C2"},
810 {TECMP_ETH_RAW_SFD_SMD_C3, "SMD-C3"},
811 {0, NULL}
814 /********* UATs *********/
816 typedef struct _generic_one_id_string {
817 unsigned id;
818 char *name;
819 } generic_one_id_string_t;
821 /* Interface UAT */
822 typedef struct _interface_config {
823 unsigned id;
824 unsigned bus_id;
825 char *name;
826 } interface_config_t;
828 #define DATAFILE_TECMP_DEVICE_IDS "TECMP_device_identifiers"
829 #define DATAFILE_TECMP_INTERFACE_IDS "TECMP_interface_identifiers"
830 #define DATAFILE_TECMP_CONTROL_MSG_IDS "TECMP_control_message_identifiers"
832 static GHashTable *data_tecmp_devices;
833 static generic_one_id_string_t* tecmp_devices;
834 static unsigned tecmp_devices_num;
836 UAT_HEX_CB_DEF(tecmp_devices, id, generic_one_id_string_t)
837 UAT_CSTRING_CB_DEF(tecmp_devices, name, generic_one_id_string_t)
839 static GHashTable *data_tecmp_interfaces;
840 static interface_config_t* tecmp_interfaces;
841 static unsigned tecmp_interfaces_num;
843 UAT_HEX_CB_DEF(tecmp_interfaces, id, interface_config_t)
844 UAT_CSTRING_CB_DEF(tecmp_interfaces, name, interface_config_t)
845 UAT_HEX_CB_DEF(tecmp_interfaces, bus_id, interface_config_t)
847 static GHashTable *data_tecmp_ctrlmsgids;
848 static generic_one_id_string_t* tecmp_ctrl_msgs;
849 static unsigned tecmp_ctrl_msg_num;
851 UAT_HEX_CB_DEF(tecmp_ctrl_msgs, id, generic_one_id_string_t)
852 UAT_CSTRING_CB_DEF(tecmp_ctrl_msgs, name, generic_one_id_string_t)
854 /* generic UAT */
855 static void
856 tecmp_free_key(void *key) {
857 wmem_free(wmem_epan_scope(), key);
860 static void
861 simple_free(void *data) {
862 /* we need to free because of the g_strdup in post_update*/
863 g_free(data);
866 /* ID -> Name */
867 static void *
868 copy_generic_one_id_string_cb(void *n, const void *o, size_t size _U_) {
869 generic_one_id_string_t *new_rec = (generic_one_id_string_t *)n;
870 const generic_one_id_string_t *old_rec = (const generic_one_id_string_t *)o;
872 new_rec->name = g_strdup(old_rec->name);
873 new_rec->id = old_rec->id;
874 return new_rec;
877 static bool
878 update_generic_one_identifier_16bit(void *r, char **err) {
879 generic_one_id_string_t *rec = (generic_one_id_string_t *)r;
881 if (rec->id > 0xffff) {
882 *err = ws_strdup_printf("We currently only support 16 bit identifiers (ID: %i Name: %s)", rec->id, rec->name);
883 return false;
886 if (rec->name == NULL || rec->name[0] == 0) {
887 *err = g_strdup("Name cannot be empty");
888 return false;
891 return true;
894 static void
895 free_generic_one_id_string_cb(void* r) {
896 generic_one_id_string_t *rec = (generic_one_id_string_t *)r;
897 /* freeing result of g_strdup */
898 g_free(rec->name);
899 rec->name = NULL;
902 static void
903 post_update_one_id_string_template_cb(generic_one_id_string_t *data, unsigned data_num, GHashTable *ht) {
904 unsigned i;
905 int *key = NULL;
907 for (i = 0; i < data_num; i++) {
908 key = wmem_new(wmem_epan_scope(), int);
909 *key = data[i].id;
911 g_hash_table_insert(ht, key, g_strdup(data[i].name));
915 static char *
916 ht_lookup_name(GHashTable *ht, unsigned int identifier) {
917 char *tmp = NULL;
918 unsigned int *id = NULL;
920 if (ht == NULL) {
921 return NULL;
924 id = wmem_new(wmem_epan_scope(), unsigned int);
925 *id = (unsigned int)identifier;
926 tmp = (char *)g_hash_table_lookup(ht, id);
927 wmem_free(wmem_epan_scope(), id);
929 return tmp;
932 /* ID -> ID, Name */
933 static void *
934 copy_interface_config_cb(void *n, const void *o, size_t size _U_) {
935 interface_config_t *new_rec = (interface_config_t *)n;
936 const interface_config_t *old_rec = (const interface_config_t *)o;
938 new_rec->id = old_rec->id;
939 new_rec->name = g_strdup(old_rec->name);
940 new_rec->bus_id = old_rec->bus_id;
941 return new_rec;
944 static bool
945 update_interface_config(void *r, char **err) {
946 interface_config_t *rec = (interface_config_t *)r;
948 if (rec->id > 0xffffffff) {
949 *err = ws_strdup_printf("We currently only support 32 bit identifiers (ID: %i Name: %s)", rec->id, rec->name);
950 return false;
953 if (rec->name == NULL || rec->name[0] == 0) {
954 *err = g_strdup("Name cannot be empty");
955 return false;
958 if (rec->bus_id > 0xffff) {
959 *err = ws_strdup_printf("We currently only support 16 bit bus identifiers (ID: %i Name: %s Bus-ID: %i)", rec->id, rec->name, rec->bus_id);
960 return false;
963 return true;
966 static void
967 free_interface_config_cb(void *r) {
968 interface_config_t *rec = (interface_config_t *)r;
969 /* freeing result of g_strdup */
970 g_free(rec->name);
971 rec->name = NULL;
974 static interface_config_t *
975 ht_lookup_interface_config(unsigned int identifier) {
976 interface_config_t *tmp = NULL;
977 unsigned int *id = NULL;
979 if (data_tecmp_interfaces == NULL) {
980 return NULL;
983 id = wmem_new(wmem_epan_scope(), unsigned int);
984 *id = (unsigned int)identifier;
985 tmp = (interface_config_t *)g_hash_table_lookup(data_tecmp_interfaces, id);
986 wmem_free(wmem_epan_scope(), id);
988 return tmp;
991 static char *
992 ht_interface_config_to_string(unsigned int identifier) {
993 interface_config_t *tmp = ht_lookup_interface_config(identifier);
994 if (tmp == NULL) {
995 return NULL;
998 return tmp->name;
1001 static uint16_t
1002 ht_interface_config_to_bus_id(unsigned int identifier) {
1003 interface_config_t *tmp = ht_lookup_interface_config(identifier);
1004 if (tmp == NULL) {
1005 /* 0 means basically any or none */
1006 return 0;
1009 return tmp->bus_id;
1012 /*** UAT TECMP_DEVICE_IDs ***/
1014 static void
1015 post_update_tecmp_devices_cb(void) {
1016 /* destroy old hash table, if it exists */
1017 if (data_tecmp_devices) {
1018 g_hash_table_destroy(data_tecmp_devices);
1019 data_tecmp_devices = NULL;
1022 /* create new hash table */
1023 data_tecmp_devices = g_hash_table_new_full(g_int_hash, g_int_equal, &tecmp_free_key, &simple_free);
1024 post_update_one_id_string_template_cb(tecmp_devices, tecmp_devices_num, data_tecmp_devices);
1027 static void
1028 add_device_id_text(proto_item *ti, uint16_t device_id) {
1029 /* lets check configured entries first */
1030 const char *descr = ht_lookup_name(data_tecmp_devices, device_id);
1032 if (descr == NULL) {
1033 /* lets check specific */
1034 descr = try_val_to_str(device_id, tecmp_device_ids_specific);
1037 if (descr == NULL) {
1038 /* lets check ranged prefixes */
1039 descr = try_val_to_str((device_id & 0xfff0), tecmp_device_id_prefixes);
1040 if (descr != NULL) {
1041 if ((device_id & 0x000f) == 0) {
1042 proto_item_append_text(ti, " (%s %d (Default))", descr, (device_id & 0x000f));
1043 } else {
1044 proto_item_append_text(ti, " (%s %d)", descr, (device_id & 0x000f));
1046 return;
1050 /* if, we found nothing before */
1051 if (descr == NULL) {
1052 descr = "Unknown/Unconfigured CM";
1055 proto_item_append_text(ti, " (%s)", descr);
1058 /*** UAT TECMP_INTERFACE_IDs ***/
1060 static void
1061 post_update_tecmp_interfaces_cb(void) {
1062 unsigned i;
1063 int *key = NULL;
1065 /* destroy old hash table, if it exists */
1066 if (data_tecmp_interfaces) {
1067 g_hash_table_destroy(data_tecmp_interfaces);
1068 data_tecmp_interfaces = NULL;
1071 /* create new hash table */
1072 data_tecmp_interfaces = g_hash_table_new_full(g_int_hash, g_int_equal, &tecmp_free_key, NULL);
1074 if (data_tecmp_interfaces == NULL || tecmp_interfaces == NULL || tecmp_interfaces_num == 0) {
1075 return;
1078 for (i = 0; i < tecmp_interfaces_num; i++) {
1079 key = wmem_new(wmem_epan_scope(), int);
1080 *key = tecmp_interfaces[i].id;
1081 g_hash_table_insert(data_tecmp_interfaces, key, &tecmp_interfaces[i]);
1085 static void
1086 add_interface_id_text_and_name(proto_item *ti, uint32_t interface_id, tvbuff_t *tvb, int offset) {
1087 const char *descr = ht_interface_config_to_string(interface_id);
1089 if (descr != NULL) {
1090 proto_item_append_text(ti, " (%s)", descr);
1091 proto_tree *subtree = proto_item_add_subtree(ti, ett_tecmp_payload_interface_id);
1092 proto_tree_add_string(subtree, hf_tecmp_payload_interface_name, tvb, offset, 4, descr);
1096 /*** UAT TECMP_CONTROL_MESSAGE_IDs ***/
1098 static void
1099 post_update_tecmp_control_messages_cb(void) {
1100 /* destroy old hash table, if it exists */
1101 if (data_tecmp_ctrlmsgids) {
1102 g_hash_table_destroy(data_tecmp_ctrlmsgids);
1103 data_tecmp_ctrlmsgids = NULL;
1106 /* create new hash table */
1107 data_tecmp_ctrlmsgids = g_hash_table_new_full(g_int_hash, g_int_equal, &tecmp_free_key, &simple_free);
1108 post_update_one_id_string_template_cb(tecmp_ctrl_msgs, tecmp_ctrl_msg_num, data_tecmp_ctrlmsgids);
1111 static const char*
1112 resolve_control_message_id(uint16_t control_message_id)
1114 const char *tmp = ht_lookup_name(data_tecmp_ctrlmsgids, control_message_id);
1116 /* lets look at the static values, if nothing is configured */
1117 if (tmp == NULL) {
1118 tmp = try_val_to_str(control_message_id, tecmp_ctrl_msg_ids_types);
1121 /* no configured or standardized name known */
1122 if (tmp != NULL) {
1123 return wmem_strdup_printf(wmem_packet_scope(), "%s (0x%04x)", tmp, control_message_id);
1126 /* just give back unknown */
1127 return wmem_strdup_printf(wmem_packet_scope(), "Unknown (0x%04x)", control_message_id);
1132 static bool
1133 tecmp_entry_header_present(tvbuff_t *tvb, unsigned offset) {
1134 uint32_t chan_id = 0;
1135 uint64_t tstamp = 0;
1136 uint16_t length = 0;
1138 chan_id = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
1139 tstamp = tvb_get_uint64(tvb, offset + 4, ENC_BIG_ENDIAN);
1140 length = tvb_get_uint16(tvb, offset + 12, ENC_BIG_ENDIAN);
1142 if (chan_id == 0 && tstamp == 0 && length == 0) {
1143 /* 0 is not valid and therefore we assume padding. */
1144 return false;
1146 return true;
1149 static unsigned
1150 dissect_tecmp_entry_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset_orig, unsigned tecmp_msg_type, uint16_t data_type,
1151 bool first, uint16_t *dataflags, uint32_t *interface_id, uint64_t *timestamp_ns) {
1152 proto_item *ti;
1153 proto_tree *subtree = NULL;
1154 unsigned offset = offset_orig;
1156 nstime_t timestamp;
1157 uint64_t ns = 0;
1158 bool async = false;
1159 unsigned tmp;
1161 static int * const dataflags_generic[] = {
1162 &hf_tecmp_payload_data_flags_overflow,
1163 &hf_tecmp_payload_data_flags_tx,
1164 &hf_tecmp_payload_data_flags_crc,
1165 NULL
1168 static int * const dataflags_ethernet_10base_t1s[] = {
1169 &hf_tecmp_payload_data_flags_overflow,
1170 &hf_tecmp_payload_data_flags_tx,
1171 &hf_tecmp_payload_data_flags_crc,
1172 &hf_tecmp_payload_data_flags_phy_event_error,
1173 NULL
1176 static int * const dataflags_lin[] = {
1177 &hf_tecmp_payload_data_flags_overflow,
1178 &hf_tecmp_payload_data_flags_tx,
1179 &hf_tecmp_payload_data_flags_checksum,
1181 &hf_tecmp_payload_data_flags_sleep,
1182 &hf_tecmp_payload_data_flags_short_wup,
1183 &hf_tecmp_payload_data_flags_wup,
1184 &hf_tecmp_payload_data_flags_no_resp,
1185 &hf_tecmp_payload_data_flags_parity,
1186 &hf_tecmp_payload_data_flags_coll,
1187 NULL
1190 static int * const dataflags_lin_tx[] = {
1191 &hf_tecmp_payload_data_flags_use_checksum_value,
1193 &hf_tecmp_payload_data_flags_short_wup,
1194 &hf_tecmp_payload_data_flags_wup,
1195 &hf_tecmp_payload_data_flags_use_parity_bits,
1196 NULL
1199 static int * const dataflags_can_data[] = {
1200 &hf_tecmp_payload_data_flags_overflow,
1201 &hf_tecmp_payload_data_flags_tx,
1202 &hf_tecmp_payload_data_flags_crc,
1204 &hf_tecmp_payload_data_flags_can_eof_err,
1205 &hf_tecmp_payload_data_flags_can_ack_del_err,
1206 &hf_tecmp_payload_data_flags_can_crc_del_err,
1207 &hf_tecmp_payload_data_flags_can_bit_stuff_err,
1208 &hf_tecmp_payload_data_flags_err,
1209 &hf_tecmp_payload_data_flags_ide,
1210 &hf_tecmp_payload_data_flags_rtr,
1211 &hf_tecmp_payload_data_flags_ack,
1212 NULL
1215 static int * const dataflags_can_tx_data[] = {
1216 &hf_tecmp_payload_data_flags_use_crc_value,
1218 &hf_tecmp_payload_data_flags_can_eof_err,
1219 &hf_tecmp_payload_data_flags_can_ack_del_err,
1220 &hf_tecmp_payload_data_flags_can_crc_del_err,
1221 &hf_tecmp_payload_data_flags_can_bit_stuff_err,
1222 NULL
1225 static int * const dataflags_can_fd_data[] = {
1226 &hf_tecmp_payload_data_flags_overflow,
1227 &hf_tecmp_payload_data_flags_tx,
1228 &hf_tecmp_payload_data_flags_crc,
1230 &hf_tecmp_payload_data_flags_canfd_eof_err,
1231 &hf_tecmp_payload_data_flags_canfd_ack_del_err,
1232 &hf_tecmp_payload_data_flags_canfd_crc_del_err,
1233 &hf_tecmp_payload_data_flags_canfd_bit_stuff_err,
1234 &hf_tecmp_payload_data_flags_brs,
1235 &hf_tecmp_payload_data_flags_err,
1236 &hf_tecmp_payload_data_flags_ide,
1237 &hf_tecmp_payload_data_flags_esi,
1238 &hf_tecmp_payload_data_flags_ack,
1239 NULL
1242 static int * const dataflags_can_fd_tx_data[] = {
1243 &hf_tecmp_payload_data_flags_use_crc_value,
1245 &hf_tecmp_payload_data_flags_canfd_eof_err,
1246 &hf_tecmp_payload_data_flags_canfd_ack_del_err,
1247 &hf_tecmp_payload_data_flags_canfd_crc_del_err,
1248 &hf_tecmp_payload_data_flags_canfd_bit_stuff_err,
1249 &hf_tecmp_payload_data_flags_brs,
1250 NULL
1253 static int * const dataflags_flexray_data[] = {
1254 &hf_tecmp_payload_data_flags_overflow,
1255 &hf_tecmp_payload_data_flags_tx,
1257 &hf_tecmp_payload_data_flags_frame_crc_err,
1258 &hf_tecmp_payload_data_flags_header_crc_err,
1259 &hf_tecmp_payload_data_flags_cas,
1260 &hf_tecmp_payload_data_flags_ppi,
1261 &hf_tecmp_payload_data_flags_wus,
1262 &hf_tecmp_payload_data_flags_sync,
1263 &hf_tecmp_payload_data_flags_sf,
1264 &hf_tecmp_payload_data_flags_nf,
1265 NULL
1268 static int * const dataflags_flexray_tx_data[] = {
1270 &hf_tecmp_payload_data_flags_use_header_crc_value,
1271 &hf_tecmp_payload_data_flags_tx_mode,
1272 NULL
1275 static int * const dataflags_ilas[] = {
1276 &hf_tecmp_payload_data_flags_crc,
1278 &hf_tecmp_payload_data_flags_direction,
1279 &hf_tecmp_payload_data_flags_crc_enabled,
1280 NULL
1283 static int * const dataflags_rs232_uart_ascii[] = {
1284 &hf_tecmp_payload_data_flags_tx,
1286 &hf_tecmp_payload_data_flags_dl,
1287 &hf_tecmp_payload_data_flags_parity_error,
1288 NULL
1291 static int * const dataflags_analog[] = {
1292 &hf_tecmp_payload_data_flags_overflow,
1294 &hf_tecmp_payload_data_flags_sample_time,
1295 &hf_tecmp_payload_data_flags_factor,
1296 &hf_tecmp_payload_data_flags_unit,
1297 &hf_tecmp_payload_data_flags_threshold_u,
1298 &hf_tecmp_payload_data_flags_threshold_o,
1299 NULL
1302 /* Can't use col_append_sep_str because we already set something before. */
1303 if (!first) {
1304 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1306 col_append_str(pinfo->cinfo, COL_INFO, val_to_str(data_type, tecmp_msgtype_names, "Unknown (%d)"));
1308 ti = proto_tree_add_item_ret_uint(tree, hf_tecmp_payload_interface_id, tvb, offset, 4, ENC_BIG_ENDIAN, &tmp);
1309 add_interface_id_text_and_name(ti, tmp, tvb, offset);
1310 if (interface_id != NULL) {
1311 *interface_id = tmp;
1314 ns = tvb_get_uint64(tvb, offset + 4, ENC_BIG_ENDIAN) & 0x3fffffffffffffff;
1316 if (timestamp_ns != NULL) {
1317 *timestamp_ns = ns;
1320 timestamp.secs = (time_t)(ns / 1000000000);
1321 timestamp.nsecs = (int)(ns % 1000000000);
1322 ti = proto_tree_add_time(tree, hf_tecmp_payload_timestamp, tvb, offset + 4, 8, &timestamp);
1323 subtree = proto_item_add_subtree(ti, ett_tecmp_payload_timestamp);
1324 proto_tree_add_item_ret_boolean(subtree, hf_tecmp_payload_timestamp_async, tvb, offset + 4, 1, ENC_NA, &async);
1325 proto_tree_add_item(subtree, hf_tecmp_payload_timestamp_res, tvb, offset + 4, 1, ENC_NA);
1327 if (async) {
1328 proto_item_append_text(ti, " (not synchronized)");
1329 } else {
1330 proto_item_append_text(ti, " (synchronized or master)");
1332 ti = proto_tree_add_uint64(tree, hf_tecmp_payload_timestamp_ns, tvb, offset + 4, 8, ns);
1333 proto_item_set_hidden(ti);
1335 proto_tree_add_item(tree, hf_tecmp_payload_length, tvb, offset+12, 2, ENC_BIG_ENDIAN);
1336 offset += 14;
1338 if (dataflags != NULL) {
1339 *dataflags = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1342 switch (tecmp_msg_type) {
1343 case TECMP_MSG_TYPE_LOG_STREAM:
1344 switch (data_type) {
1345 case TECMP_DATA_TYPE_LIN:
1346 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_lin, ENC_BIG_ENDIAN);
1347 break;
1349 case TECMP_DATA_TYPE_CAN_DATA:
1350 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_can_data, ENC_BIG_ENDIAN);
1351 break;
1353 case TECMP_DATA_TYPE_CAN_FD_DATA:
1354 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_can_fd_data, ENC_BIG_ENDIAN);
1355 break;
1357 case TECMP_DATA_TYPE_FR_DATA:
1358 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_flexray_data, ENC_BIG_ENDIAN);
1359 break;
1361 case TECMP_DATA_TYPE_ILAS:
1362 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_ilas, ENC_BIG_ENDIAN);
1363 break;
1365 case TECMP_DATA_TYPE_RS232_ASCII:
1366 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_rs232_uart_ascii, ENC_BIG_ENDIAN);
1367 break;
1369 case TECMP_DATA_TYPE_ANALOG:
1370 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_analog, ENC_BIG_ENDIAN);
1371 break;
1373 case TECMP_DATA_TYPE_ETH_10BASE_T1S:
1374 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_ethernet_10base_t1s, ENC_BIG_ENDIAN);
1375 break;
1377 case TECMP_DATA_TYPE_ETH_RAW:
1378 case TECMP_DATA_TYPE_ETH:
1379 default:
1380 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_generic, ENC_BIG_ENDIAN);
1382 break;
1384 case TECMP_MSG_TYPE_REPLAY_DATA:
1385 switch (data_type) {
1386 case TECMP_DATA_TYPE_LIN:
1387 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_lin_tx, ENC_BIG_ENDIAN);
1388 break;
1390 case TECMP_DATA_TYPE_CAN_DATA:
1391 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_can_tx_data, ENC_BIG_ENDIAN);
1392 break;
1394 case TECMP_DATA_TYPE_CAN_FD_DATA:
1395 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_can_fd_tx_data, ENC_BIG_ENDIAN);
1396 break;
1398 case TECMP_DATA_TYPE_FR_DATA:
1399 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_flexray_tx_data, ENC_BIG_ENDIAN);
1400 break;
1402 case TECMP_DATA_TYPE_RS232_ASCII:
1403 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_rs232_uart_ascii, ENC_BIG_ENDIAN);
1404 break;
1406 case TECMP_DATA_TYPE_ANALOG:
1407 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_analog, ENC_BIG_ENDIAN);
1408 break;
1410 case TECMP_DATA_TYPE_ETH_RAW:
1411 case TECMP_DATA_TYPE_ETH:
1412 default:
1413 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_data_flags, ett_tecmp_payload_dataflags, dataflags_generic, ENC_BIG_ENDIAN);
1415 break;
1417 case TECMP_MSG_TYPE_CTRL_MSG:
1418 case TECMP_MSG_TYPE_STATUS_DEV:
1419 case TECMP_MSG_TYPE_STATUS_BUS:
1420 case TECMP_MSG_TYPE_CFG_CM:
1421 case TECMP_MSG_TYPE_COUNTER_EVENT:
1422 case TECMP_MSG_TYPE_TIMESYNC_EVENT:
1423 default:
1424 proto_tree_add_item(tree, hf_tecmp_payload_data_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
1425 break;
1428 offset += 2;
1430 return offset - offset_orig;
1433 static void
1434 dissect_tecmp_status_config_vendor_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_item *ti_root, uint8_t device_type _U_,
1435 uint8_t vendor_id) {
1436 proto_tree *tree = NULL;
1437 int offset = 0;
1438 unsigned data_length = 0;
1440 proto_item_append_text(ti_root, " (%s)", val_to_str(vendor_id, tecmp_vendor_ids, "(Unknown Vendor: %d)"));
1441 tree = proto_item_add_subtree(ti_root, ett_tecmp_status_bus_vendor_data);
1443 switch (vendor_id) {
1444 case TECMP_VENDOR_ID_TECHNICA:
1445 proto_tree_add_item(tree, hf_tecmp_payload_status_cfg_vendor_technica_version, tvb, offset, 1, ENC_NA);
1446 proto_tree_add_item(tree, hf_tecmp_payload_status_cfg_vendor_technica_reserved, tvb, offset + 1, 1, ENC_NA);
1447 proto_tree_add_item(tree, hf_tecmp_payload_status_cfg_vendor_technica_msg_id, tvb, offset + 2, 2,
1448 ENC_BIG_ENDIAN);
1449 proto_tree_add_item(tree, hf_tecmp_payload_status_cfg_vendor_technica_total_length, tvb, offset + 4, 4,
1450 ENC_BIG_ENDIAN);
1451 proto_tree_add_item(tree, hf_tecmp_payload_status_cfg_vendor_technica_total_num_seg, tvb, offset + 8, 2,
1452 ENC_BIG_ENDIAN);
1453 proto_tree_add_item(tree, hf_tecmp_payload_status_cfg_vendor_technica_segment_num, tvb, offset + 10, 2,
1454 ENC_BIG_ENDIAN);
1455 proto_tree_add_item_ret_uint(tree, hf_tecmp_payload_status_cfg_vendor_technica_segment_length, tvb,
1456 offset + 12, 2, ENC_BIG_ENDIAN, &data_length);
1457 offset += 14;
1458 if (tvb_captured_length_remaining(tvb, offset) >= (int)data_length) {
1459 proto_tree_add_item(tree, hf_tecmp_payload_status_cfg_vendor_technica_segment_data, tvb, offset,
1460 data_length, ENC_NA);
1461 } else {
1462 proto_tree_add_item(tree, hf_tecmp_payload_status_cfg_vendor_technica_segment_data, tvb, offset,
1463 tvb_captured_length_remaining(tvb, offset), ENC_NA);
1466 break;
1470 static void
1471 dissect_tecmp_status_bus_vendor_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_item *ti_root,
1472 uint8_t entry_number, uint8_t device_type, uint8_t vendor_id) {
1473 proto_tree *tree = NULL;
1474 proto_item *ti = NULL;
1475 int offset = 0;
1476 int bytes_remaining = 0;
1477 unsigned tmp = 0;
1479 proto_item_append_text(ti_root, " (%s)", val_to_str(vendor_id, tecmp_vendor_ids, "(Unknown Vendor: %d)"));
1480 tree = proto_item_add_subtree(ti_root, ett_tecmp_status_bus_vendor_data);
1482 switch (vendor_id) {
1483 case TECMP_VENDOR_ID_TECHNICA:
1484 bytes_remaining = tvb_captured_length_remaining(tvb, offset);
1486 if (device_type == TECMP_DEVICE_TYPE_CM_ILAS_COMBO && entry_number < 5) {
1487 /* Currently no parameters for this format but might be specified in a later specification. */
1488 } else if ((device_type == TECMP_DEVICE_TYPE_CM_ILAS_COMBO && entry_number == 5) || device_type == TECMP_DEVICE_TYPE_CM_10BASE_T1S) {
1489 static int * const vendor_data_flags_10BASE_T1S[] = {
1490 &hf_tecmp_payload_status_bus_vendor_technica_10m_flags_plca_enabled,
1491 &hf_tecmp_payload_status_bus_vendor_technica_10m_flags_beacons_received,
1492 NULL
1495 proto_tree_add_bitmask(tree, tvb, offset, hf_tecmp_payload_status_bus_vendor_technica_10m_flags, ett_tecmp_status_bus_vendor_data_flags, vendor_data_flags_10BASE_T1S, ENC_BIG_ENDIAN);
1496 offset += 1;
1498 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_res0, tvb, offset, 1, ENC_NA);
1499 offset += 1;
1501 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_beacon_counter, tvb, offset, 4, ENC_NA);
1502 offset += 4;
1504 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_link_quality, tvb, offset, 1, ENC_NA);
1505 offset += 1;
1507 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_res1, tvb, offset, 1, ENC_NA);
1508 offset += 1;
1510 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_res2, tvb, offset, 2, ENC_NA);
1511 offset += 2;
1513 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_5b_decode_err_cnt, tvb, offset, 2, ENC_NA);
1514 offset += 2;
1516 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_eos_delim_err_cnt, tvb, offset, 2, ENC_NA);
1517 offset += 2;
1519 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_detected_cnt, tvb, offset, 2, ENC_NA);
1520 offset += 2;
1522 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_missing_cnt, tvb, offset, 2, ENC_NA);
1523 offset += 2;
1525 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_empty_cycle_cnt, tvb, offset, 2, ENC_NA);
1526 } else {
1527 if (bytes_remaining >= 1) {
1528 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_link_status, tvb, offset, 1, ENC_NA);
1529 offset += 1;
1531 if (bytes_remaining >= 2) {
1532 proto_tree_add_item(tree, hf_tecmp_payload_status_bus_vendor_technica_link_quality, tvb, offset, 1,
1533 ENC_NA);
1534 offset += 1;
1536 if (bytes_remaining >= 4) {
1537 ti = proto_tree_add_item_ret_uint(tree, hf_tecmp_payload_status_bus_vendor_technica_linkup_time, tvb,
1538 offset, 2, ENC_NA, &tmp);
1539 if (tmp == 0) {
1540 proto_item_append_text(ti, " %s", "(no linkup detected yet)");
1541 } else if (tmp == 0xffff) {
1542 proto_item_append_text(ti, " %s", "(no linkup detected and timeout occurred)");
1546 break;
1550 static void
1551 dissect_tecmp_status_device_vendor_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_item *ti_root, uint8_t device_type _U_, uint8_t vendor_id, uint64_t timestamp_ns) {
1552 proto_tree *tree = NULL;
1553 proto_item *ti = NULL;
1554 int offset = 0;
1555 unsigned tmp = 0;
1556 uint64_t tmp64 = 0;
1557 nstime_t timestamp;
1558 int temperature = 0;
1560 proto_item_append_text(ti_root, " (%s)", val_to_str(vendor_id, tecmp_vendor_ids, "(Unknown Vendor: %d)"));
1561 tree = proto_item_add_subtree(ti_root, ett_tecmp_status_dev_vendor_data);
1563 switch (vendor_id) {
1564 case TECMP_VENDOR_ID_TECHNICA:
1565 proto_tree_add_item(tree, hf_tecmp_payload_status_dev_vendor_technica_res, tvb, offset, 1, ENC_NA);
1566 offset += 1;
1567 tmp = tvb_get_uint24(tvb, offset, ENC_BIG_ENDIAN);
1568 proto_tree_add_string_format(tree, hf_tecmp_payload_status_dev_vendor_technica_sw, tvb, offset, 3, NULL,
1569 "Software Version: v%d.%d.%d", (tmp&0x00ff0000)>>16, (tmp&0x0000ff00)>>8, tmp&0x000000ff);
1570 offset += 3;
1572 tmp = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1573 proto_tree_add_string_format(tree, hf_tecmp_payload_status_dev_vendor_technica_hw, tvb, offset, 2, NULL,
1574 "Hardware Version: v%d.%x", (tmp & 0x0000ff00) >> 8, tmp & 0x000000ff);
1575 offset += 2;
1577 ti = proto_tree_add_item(tree, hf_tecmp_payload_status_dev_vendor_technica_buffer_fill_level, tvb, offset, 1, ENC_NA);
1578 proto_item_append_text(ti, "%s", "%");
1579 offset += 1;
1581 proto_tree_add_item(tree, hf_tecmp_payload_status_dev_vendor_technica_buffer_overflow, tvb, offset, 1, ENC_NA);
1582 offset += 1;
1584 tmp = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
1585 proto_tree_add_uint_format_value(tree, hf_tecmp_payload_status_dev_vendor_technica_buffer_size, tvb, offset,
1586 4, tmp * 128, "%d MB", tmp * 128);
1587 offset += 4;
1589 ti = proto_tree_add_item_ret_uint64(tree, hf_tecmp_payload_status_dev_vendor_technica_lifecycle, tvb, offset, 8, ENC_BIG_ENDIAN, &tmp64);
1591 uint64_t nanos = tmp64 % 1000000000;
1592 uint64_t secs = tmp64 / 1000000000;
1593 uint64_t mins = secs / 60;
1594 secs -= mins * 60;
1595 uint64_t hours = mins / 24;
1596 mins -= hours * 24;
1597 proto_item_append_text(ti, " ns (%d:%02d:%02d.%09d)", (uint32_t)hours, (uint32_t)mins, (uint32_t)secs, (uint32_t)nanos);
1599 if (tmp64 < timestamp_ns) {
1600 timestamp_ns -= tmp64;
1601 timestamp.secs = (time_t)(timestamp_ns / 1000000000);
1602 timestamp.nsecs = (int)(timestamp_ns % 1000000000);
1603 ti = proto_tree_add_time(tree, hf_tecmp_payload_status_dev_vendor_technica_lifecycle_start, tvb, offset, 8, &timestamp);
1604 proto_item_set_generated(ti);
1606 offset += 8;
1608 tmp = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
1610 double voltage_value = (double)((tmp & 0x0000ff00) >> 8) + (tmp & 0x000000ff) / 100.0;
1611 proto_tree_add_double(tree, hf_tecmp_payload_status_dev_vendor_technica_voltage, tvb, offset, 2, voltage_value);
1612 offset += 2;
1614 if (tvb_captured_length_remaining(tvb, offset) == 1) {
1615 proto_tree_add_item(tree, hf_tecmp_payload_status_dev_vendor_technica_temperature, tvb, offset, 1, ENC_NA);
1616 } else if (tvb_captured_length_remaining(tvb, offset) > 1) {
1617 /* TECMP 1.5 and later */
1618 temperature = tvb_get_int8(tvb, offset);
1619 if (temperature == VENDOR_TECHNICA_TEMP_NA) {
1620 proto_tree_add_int_format_value(tree, hf_tecmp_payload_status_dev_vendor_technica_temperature_chassis, tvb, offset, 1, temperature, "%s", "Not Available");
1621 } else {
1622 ti = proto_tree_add_item(tree, hf_tecmp_payload_status_dev_vendor_technica_temperature_chassis, tvb, offset, 1, ENC_NA);
1623 if (temperature == VENDOR_TECHNICA_TEMP_MAX) {
1624 proto_item_append_text(ti, " %s", "or more");
1627 offset += 1;
1629 temperature = tvb_get_int8(tvb, offset);
1630 if ( temperature == VENDOR_TECHNICA_TEMP_NA) {
1631 proto_tree_add_int_format_value(tree, hf_tecmp_payload_status_dev_vendor_technica_temperature_silicon, tvb, offset, 1, temperature, "%s", "Not Available");
1632 } else {
1633 ti = proto_tree_add_item(tree, hf_tecmp_payload_status_dev_vendor_technica_temperature_silicon, tvb, offset, 1, ENC_NA);
1634 if (temperature == VENDOR_TECHNICA_TEMP_MAX) {
1635 proto_item_append_text(ti, " %s", "or more");
1640 break;
1644 static int
1645 dissect_tecmp_control_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset_orig, uint16_t msg_type, unsigned tecmp_msg_type) {
1646 proto_item *root_ti = NULL;
1647 proto_item *ti = NULL;
1648 proto_tree *tecmp_tree = NULL;
1649 uint16_t length = 0;
1650 unsigned offset = offset_orig;
1651 unsigned device_id = 0;
1652 unsigned interface_id = 0;
1653 unsigned ctrl_msg_id = 0;
1655 if (tvb_captured_length_remaining(tvb, offset) >= (16 + 4)) {
1656 length = tvb_get_uint16(tvb, offset + 12, ENC_BIG_ENDIAN);
1657 root_ti = proto_tree_add_item(tree, proto_tecmp_payload, tvb, offset, (int)length + 16, ENC_NA);
1658 proto_item_append_text(root_ti, " Control Message");
1659 tecmp_tree = proto_item_add_subtree(root_ti, ett_tecmp_payload);
1661 offset += dissect_tecmp_entry_header(tvb, pinfo, tecmp_tree, offset, tecmp_msg_type, msg_type, true, NULL, NULL, NULL);
1663 col_set_str(pinfo->cinfo, COL_INFO, "TECMP Control Message");
1665 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_ctrl_msg_device_id, tvb, offset, 2, ENC_BIG_ENDIAN, &device_id);
1666 add_device_id_text(ti, (uint16_t)device_id);
1667 ctrl_msg_id = tvb_get_uint16(tvb, offset + 2, ENC_BIG_ENDIAN);
1668 proto_tree_add_uint_format(tecmp_tree, hf_tecmp_payload_ctrl_msg_id, tvb, offset + 2, 2, ctrl_msg_id, "Type: %s", resolve_control_message_id(ctrl_msg_id));
1669 offset += 4;
1671 proto_item_append_text(root_ti, ", %s", resolve_control_message_id(ctrl_msg_id));
1672 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", resolve_control_message_id(ctrl_msg_id));
1674 /* offset includes 16 byte header, while length is only for payload */
1675 int bytes_left = length + (unsigned)16 - (offset - offset_orig);
1676 if (bytes_left > 0) {
1677 int i;
1679 switch (ctrl_msg_id) {
1680 case TECMP_CTRL_MSG_CAN_REPLAY_FILL_LVL:
1681 ti = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_ctrl_msg_can_replay_fill_level_fill_level, tvb, offset, 1, ENC_NA);
1682 proto_item_append_text(ti, "%%");
1683 offset += 1;
1685 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_ctrl_msg_can_replay_fill_level_buffer_overflow, tvb, offset, 1, ENC_NA);
1686 offset += 1;
1688 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_ctrl_msg_can_replay_fill_level_queue_size, tvb, offset, 1, ENC_NA);
1689 offset += 1;
1691 for (i = 0; i < bytes_left - 3; i++) {
1692 uint8_t queue_level = tvb_get_uint8(tvb, offset);
1693 proto_tree_add_uint_format(tecmp_tree, hf_tecmp_payload_ctrl_msg_can_replay_fill_level_queue_length, tvb, offset, 1, queue_level, "Queue %d Fill Level: %d", i, queue_level);
1694 offset += 1;
1696 offset += 1;
1698 break;
1700 case TECMP_CTRL_MSG_FR_POC_STATE:
1701 ti = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_ctrl_msg_flexray_poc_interface_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1702 add_interface_id_text_and_name(ti, interface_id, tvb, offset);
1703 offset += 4;
1705 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_ctrl_msg_flexray_poc_state, tvb, offset, 1, ENC_NA);
1706 offset += 1;
1708 break;
1710 case TECMP_CTRL_MSG_10BASE_T1S:
1711 ti = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_ctrl_msg_10baset1s_interface_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1712 add_interface_id_text_and_name(ti, interface_id, tvb, offset);
1713 offset += 4;
1715 static int * const data_flags_10BASE_T1S[] = {
1716 &hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags_plca_enabled,
1717 &hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags_beacons_received,
1718 NULL
1721 proto_tree_add_bitmask(tecmp_tree, tvb, offset, hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags, ett_tecmp_ctrl_message_10baset1s_flags, data_flags_10BASE_T1S, ENC_BIG_ENDIAN);
1722 offset += 1;
1724 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_ctrl_msg_10baset1s_10m_reserved, tvb, offset, 1, ENC_NA);
1725 offset += 1;
1727 static int * const events_10BASE_T1S[] = {
1728 &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_empty_cycle,
1729 &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_symb_missing,
1730 &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_symb_detected,
1731 &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_eos_delim_error,
1732 &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_5b_decode_error,
1733 NULL
1736 proto_tree_add_bitmask(tecmp_tree, tvb, offset, hf_tecmp_payload_ctrl_msg_10baset1s_10m_events, ett_tecmp_ctrl_message_10baset1s_events_errors, events_10BASE_T1S, ENC_BIG_ENDIAN);
1737 offset += 2;
1739 break;
1742 if (length + (unsigned)16 - (offset - offset_orig) > 0) {
1743 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_ctrl_msg_unparsed_bytes, tvb, offset, length + (unsigned)16 - (offset - offset_orig), ENC_NA);
1748 return offset - offset_orig;
1751 static int
1752 dissect_tecmp_status_device(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset_orig, uint16_t msg_type, unsigned tecmp_msg_type) {
1753 proto_item *ti = NULL;
1754 proto_item *ti_tecmp_payload = NULL;
1755 proto_item *ti_tecmp_vendor_data = NULL;
1756 proto_item *ti_tecmp_bus = NULL;
1757 proto_tree *tecmp_tree = NULL;
1758 proto_tree *tecmp_tree_bus = NULL;
1759 tvbuff_t *sub_tvb = NULL;
1760 uint16_t length = 0;
1761 uint16_t vendor_data_len = 0;
1762 unsigned vendor_id = 0;
1763 unsigned device_type = 0;
1764 unsigned offset = offset_orig;
1765 unsigned i = 0;
1766 unsigned tmp = 0;
1767 const char *descr;
1768 uint64_t timestamp_ns;
1770 if (tvb_captured_length_remaining(tvb, offset) >= 12) {
1771 length = tvb_get_uint16(tvb, offset + 12, ENC_BIG_ENDIAN);
1772 ti_tecmp_payload = proto_tree_add_item(tree, proto_tecmp_payload, tvb, offset, (int)length + 16, ENC_NA);
1773 tecmp_tree = proto_item_add_subtree(ti_tecmp_payload, ett_tecmp_payload);
1775 offset += dissect_tecmp_entry_header(tvb, pinfo, tecmp_tree, offset, tecmp_msg_type, msg_type, true, NULL, NULL, &timestamp_ns);
1777 proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_status_vendor_id, tvb, offset, 1, ENC_NA, &vendor_id);
1778 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_status_dev_version, tvb, offset + 1, 1, ENC_NA);
1779 proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_status_dev_type, tvb, offset + 2, 1, ENC_NA, &device_type);
1780 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_status_res, tvb, offset + 3, 1, ENC_NA);
1781 offset += 4;
1783 proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_status_length_vendor_data, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp);
1784 vendor_data_len = (uint16_t)tmp;
1785 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_status_device_id, tvb, offset + 2, 2, ENC_BIG_ENDIAN, &tmp);
1786 add_device_id_text(ti, (uint16_t)tmp);
1787 offset += 4;
1789 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_status_sn, tvb, offset, 4, ENC_BIG_ENDIAN);
1790 offset += 4;
1792 switch (tecmp_msg_type) {
1793 case TECMP_MSG_TYPE_STATUS_DEV:
1794 col_set_str(pinfo->cinfo, COL_INFO, "TECMP Status Device");
1795 proto_item_append_text(ti_tecmp_payload, " Status Device");
1797 if (vendor_data_len > 0) {
1798 sub_tvb = tvb_new_subset_length(tvb, offset, (int)vendor_data_len);
1799 ti_tecmp_vendor_data = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_status_vendor_data, tvb, offset, (int)vendor_data_len, ENC_NA);
1801 dissect_tecmp_status_device_vendor_data(sub_tvb, pinfo, ti_tecmp_vendor_data, (uint8_t)device_type, (uint8_t)vendor_id, timestamp_ns);
1802 offset += vendor_data_len;
1804 break;
1806 case TECMP_MSG_TYPE_STATUS_BUS:
1807 col_set_str(pinfo->cinfo, COL_INFO, "TECMP Status Bus");
1808 proto_item_append_text(ti_tecmp_payload, " Status Bus");
1810 /* bytes left - entry header (16 bytes) */
1811 length = length - (uint16_t)(offset - offset_orig - 16);
1813 ti_tecmp_bus = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_status_bus_data, tvb, offset, length, ENC_NA);
1814 tecmp_tree = proto_item_add_subtree(ti_tecmp_bus, ett_tecmp_status_bus_data);
1815 i = 1; /* we start the numbering of the entries with 1. */
1816 while (length >= (12 + vendor_data_len)) {
1817 ti_tecmp_bus = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_status_bus_data_entry, tvb, offset, 12 + vendor_data_len, ENC_NA);
1818 proto_item_append_text(ti_tecmp_bus, " %d", i);
1819 tecmp_tree_bus = proto_item_add_subtree(ti_tecmp_bus, ett_tecmp_status_bus_data_entry);
1821 ti = proto_tree_add_item_ret_uint(tecmp_tree_bus, hf_tecmp_payload_status_bus_interface_id, tvb, offset, 4, ENC_NA, &tmp);
1822 descr = ht_interface_config_to_string(tmp);
1823 if (descr != NULL) {
1824 proto_item_append_text(ti, " (%s)", descr);
1825 proto_item_append_text(ti_tecmp_bus, ": (Interface ID: 0x%08x, %s)", tmp, descr);
1826 } else {
1827 proto_item_append_text(ti_tecmp_bus, ": (Interface ID: 0x%08x)", tmp);
1830 proto_tree_add_item(tecmp_tree_bus, hf_tecmp_payload_status_bus_total, tvb, offset + 4, 4, ENC_NA);
1831 proto_tree_add_item(tecmp_tree_bus, hf_tecmp_payload_status_bus_errors, tvb, offset + 8, 4, ENC_NA);
1832 offset += 12;
1834 if (vendor_data_len > 0) {
1835 sub_tvb = tvb_new_subset_length(tvb, offset, (int)vendor_data_len);
1836 ti_tecmp_vendor_data = proto_tree_add_item(tecmp_tree_bus, hf_tecmp_payload_status_vendor_data,
1837 tvb, offset, (int)vendor_data_len, ENC_NA);
1839 dissect_tecmp_status_bus_vendor_data(sub_tvb, pinfo, ti_tecmp_vendor_data, i, (uint8_t)device_type, (uint8_t)vendor_id);
1840 offset += vendor_data_len;
1843 i++;
1844 length -= (12 + vendor_data_len);
1846 break;
1848 case TECMP_MSG_TYPE_CFG_CM:
1849 col_set_str(pinfo->cinfo, COL_INFO, "TECMP Status Configuration");
1850 proto_item_append_text(ti_tecmp_payload, " Status Configuration");
1852 if (vendor_data_len > 0) {
1853 sub_tvb = tvb_new_subset_length(tvb, offset, (int)vendor_data_len);
1854 ti_tecmp_vendor_data = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_status_vendor_data, tvb,
1855 offset, (int)vendor_data_len, ENC_NA);
1857 dissect_tecmp_status_config_vendor_data(sub_tvb, pinfo, ti_tecmp_vendor_data, (uint8_t)device_type, (uint8_t)vendor_id);
1858 offset += vendor_data_len;
1860 break;
1862 default:
1863 proto_item_append_text(ti_tecmp_payload, " Status Device");
1866 } else {
1867 return tvb_captured_length_remaining(tvb, offset);
1870 return offset - offset_orig;
1873 static int
1874 dissect_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint16_t device_id, uint8_t msg_type, uint16_t data_type, uint32_t interface_id) {
1875 tecmp_info_t tecmp_info;
1876 int dissected_bytes;
1878 tecmp_info.interface_id = interface_id;
1879 tecmp_info.device_id = device_id;
1880 tecmp_info.data_type = data_type;
1881 tecmp_info.msg_type = msg_type;
1884 dissector_handle_t handle = dissector_get_uint_handle(data_subdissector_table, interface_id);
1885 if (handle != NULL) {
1886 dissected_bytes = call_dissector_only(handle, tvb, pinfo, tree, &tecmp_info);
1887 if (dissected_bytes > 0) {
1888 return dissected_bytes;
1892 if (tecmp_info.data_type == TECMP_DATA_TYPE_RS232_ASCII) {
1893 return call_dissector(text_lines_handle, tvb, pinfo, tree);
1894 } else {
1895 return call_data_dissector(tvb, pinfo, tree);
1899 static void
1900 dissect_ethernet_payload(tvbuff_t *sub_tvb, uint32_t offset, uint32_t length, packet_info *pinfo, proto_tree *tree, proto_tree *tecmp_tree) {
1902 tvbuff_t *payload_tvb = tvb_new_subset_length(sub_tvb, offset, length);
1904 /* resetting VLAN count since this is another embedded Ethernet packet. */
1905 p_set_proto_depth(pinfo, proto_vlan, 0);
1907 int32_t len_saved = pinfo->fd->pkt_len;
1908 pinfo->fd->pkt_len = length;
1910 if (show_ethernet_in_tecmp_tree) {
1911 call_dissector(eth_handle, payload_tvb, pinfo, tecmp_tree);
1912 } else {
1913 call_dissector(eth_handle, payload_tvb, pinfo, tree);
1916 pinfo->fd->pkt_len = len_saved;
1919 static int
1920 dissect_tecmp_log_or_replay_stream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset_orig,
1921 uint16_t data_type, uint8_t tecmp_msg_type, uint16_t device_id) {
1922 proto_item *ti = NULL;
1923 proto_item *ti_tecmp = NULL;
1924 proto_tree *tecmp_tree = NULL;
1925 uint16_t length = 0;
1926 uint32_t length2 = 0;
1927 unsigned offset = offset_orig;
1928 unsigned offset2 = 0;
1929 uint16_t dataflags = 0;
1930 uint32_t tmp = 0;
1931 tvbuff_t *sub_tvb;
1932 tvbuff_t *payload_tvb;
1933 bool first = true;
1934 uint32_t interface_id = 0;
1935 uint64_t timestamp_ns = 0;
1937 double analog_value_scale_factor;
1939 struct can_info can_info;
1940 flexray_info_t fr_info;
1941 lin_info_t lin_info;
1943 static int * const tecmp_payload_id_flags_can_11[] = {
1944 &hf_tecmp_payload_data_id_type,
1945 &hf_tecmp_payload_data_id_11,
1946 NULL
1949 static int * const tecmp_payload_id_flags_can_29[] = {
1950 &hf_tecmp_payload_data_id_type,
1951 &hf_tecmp_payload_data_id_29,
1952 NULL
1955 static int * const tecmp_payload_id_flags_lin[] = {
1956 &hf_tecmp_payload_data_parity_bits,
1957 &hf_tecmp_payload_data_id_field_6bit,
1958 NULL
1961 col_set_str(pinfo->cinfo, COL_INFO, "TECMP Payload: ");
1963 while (tvb_captured_length_remaining(tvb, offset) >= 16) {
1965 if (!tecmp_entry_header_present(tvb, offset)) {
1966 /* header not valid, we leave */
1967 break;
1970 length = tvb_get_uint16(tvb, offset+12, ENC_BIG_ENDIAN);
1971 ti_tecmp = proto_tree_add_item(tree, proto_tecmp_payload, tvb, offset, (int)length + 16, ENC_NA);
1972 proto_item_append_text(ti_tecmp, " (%s)", val_to_str(data_type, tecmp_msgtype_names, "Unknown (%d)"));
1973 tecmp_tree = proto_item_add_subtree(ti_tecmp, ett_tecmp_payload);
1975 offset += dissect_tecmp_entry_header(tvb, pinfo, tecmp_tree, offset, tecmp_msg_type, data_type, first, &dataflags, &interface_id, &timestamp_ns);
1977 first = false;
1979 if (length > 0) {
1980 sub_tvb = tvb_new_subset_length(tvb, offset, (int)length);
1981 offset2 = 0;
1983 switch (data_type) {
1984 case TECMP_DATA_TYPE_LIN:
1985 lin_info.id = tvb_get_uint8(sub_tvb, offset2) & DATA_LIN_ID_MASK;
1987 proto_tree_add_bitmask(tecmp_tree, sub_tvb, offset2, hf_tecmp_payload_data_id_field_8bit, ett_tecmp_payload_lin_id, tecmp_payload_id_flags_lin, ENC_BIG_ENDIAN);
1988 lin_info.bus_id = ht_interface_config_to_bus_id(interface_id);
1989 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_data_length, sub_tvb, offset2 + 1, 1, ENC_NA, &length2);
1990 offset2 += 2;
1992 lin_set_source_and_destination_columns(pinfo, &lin_info);
1994 if (length2 > 0 && tvb_captured_length_remaining(sub_tvb, offset2) < (int)(length2 + 1)) {
1995 expert_add_info(pinfo, ti, &ei_tecmp_payload_length_mismatch);
1996 length2 = MAX(0, MIN((int)length2, tvb_captured_length_remaining(sub_tvb, offset2) - 1));
1999 if (length2 > 0) {
2000 lin_info.len = tvb_captured_length_remaining(sub_tvb, offset2);
2001 payload_tvb = tvb_new_subset_length(sub_tvb, offset2, length2);
2002 uint32_t bus_frame_id = lin_info.id | (lin_info.bus_id << 16);
2003 if (!dissector_try_uint_with_data(lin_subdissector_table, bus_frame_id, payload_tvb, pinfo, tree, false, &lin_info)) {
2004 if (!dissector_try_uint_with_data(lin_subdissector_table, lin_info.id, payload_tvb, pinfo, tree, false, &lin_info)) {
2005 dissect_data(payload_tvb, pinfo, tree, device_id, tecmp_msg_type, data_type, interface_id);
2008 offset2 += (int)length2;
2009 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_checksum_8bit, sub_tvb, offset2, 1, ENC_NA);
2012 break;
2014 case TECMP_DATA_TYPE_CAN_DATA:
2015 case TECMP_DATA_TYPE_CAN_FD_DATA:
2016 tmp = tvb_get_uint32(sub_tvb, offset2, ENC_BIG_ENDIAN);
2017 if ((tmp & 0x80000000) == 0x80000000) {
2018 proto_tree_add_bitmask_with_flags(tecmp_tree, sub_tvb, offset2, hf_tecmp_payload_data_id_field_32bit,
2019 ett_tecmp_payload_data_id, tecmp_payload_id_flags_can_29, ENC_BIG_ENDIAN, BMT_NO_APPEND);
2020 } else {
2021 proto_tree_add_bitmask_with_flags(tecmp_tree, sub_tvb, offset2, hf_tecmp_payload_data_id_field_32bit,
2022 ett_tecmp_payload_data_id, tecmp_payload_id_flags_can_11, ENC_BIG_ENDIAN, BMT_NO_APPEND);
2024 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_data_length, sub_tvb, offset2 + 4, 1, ENC_NA,
2025 &length2);
2026 offset2 += 5;
2028 if (tvb_captured_length_remaining(sub_tvb, offset2) < (int)length2) {
2029 expert_add_info(pinfo, ti, &ei_tecmp_payload_length_mismatch);
2030 length2 = MAX(0, MIN((int)length2, tvb_captured_length_remaining(sub_tvb, offset2)));
2033 if (length2 > 0) {
2034 payload_tvb = tvb_new_subset_length(sub_tvb, offset2, length2);
2035 offset2 += length2;
2037 can_info.fd = (data_type == TECMP_DATA_TYPE_CAN_FD_DATA) ? CAN_TYPE_CAN_FD : CAN_TYPE_CAN_CLASSIC;
2038 can_info.len = length2;
2039 can_info.bus_id = ht_interface_config_to_bus_id(interface_id);
2041 /* luckily TECMP and SocketCAN share the first bit as indicator for 11 vs 29bit Identifiers */
2042 can_info.id = tmp;
2044 if (data_type == TECMP_DATA_TYPE_CAN_DATA && (dataflags & DATA_FLAG_CAN_RTR) == DATA_FLAG_CAN_RTR) {
2045 can_info.id |= CAN_RTR_FLAG;
2048 if ((dataflags & DATA_FLAG_CAN_ERR) == DATA_FLAG_CAN_ERR) {
2049 can_info.id |= CAN_ERR_FLAG;
2052 socketcan_set_source_and_destination_columns(pinfo, &can_info);
2054 if (!socketcan_call_subdissectors(payload_tvb, pinfo, tree, &can_info, heuristic_first)) {
2055 dissect_data(payload_tvb, pinfo, tree, device_id, tecmp_msg_type, data_type, interface_id);
2059 /* new for TECMP 1.6 */
2060 if (data_type == TECMP_DATA_TYPE_CAN_DATA && tvb_captured_length_remaining(sub_tvb, offset2) >= 2) {
2061 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_crc15, sub_tvb, offset2, 2, ENC_BIG_ENDIAN);
2062 } else if (data_type == TECMP_DATA_TYPE_CAN_FD_DATA && tvb_captured_length_remaining(sub_tvb, offset2) >= 3) {
2063 if (length2 <= 16) {
2064 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_crc17, sub_tvb, offset2, 3, ENC_BIG_ENDIAN);
2065 } else {
2066 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_crc21, sub_tvb, offset2, 3, ENC_BIG_ENDIAN);
2069 break;
2071 case TECMP_DATA_TYPE_FR_DATA:
2072 /* lets set it based on config */
2073 fr_info.bus_id = ht_interface_config_to_bus_id(interface_id);
2075 /* we assume "FlexRay Channel A" since we cannot know */
2076 fr_info.ch = 0;
2078 proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_data_cycle, sub_tvb, offset2, 1, ENC_NA, &tmp);
2079 fr_info.cc = (uint8_t)tmp;
2081 proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_data_frame_id, sub_tvb, offset2 + 1, 2, ENC_NA, &tmp);
2082 fr_info.id = (uint16_t)tmp;
2084 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_data_length, sub_tvb, offset2 + 3, 1, ENC_NA, &length2);
2085 offset2 += 4;
2087 flexray_set_source_and_destination_columns(pinfo, &fr_info);
2089 if (tvb_captured_length_remaining(sub_tvb, offset2) < (int)length2) {
2090 expert_add_info(pinfo, ti, &ei_tecmp_payload_length_mismatch);
2091 length2 = MAX(0, MIN((int)length2, tvb_captured_length_remaining(sub_tvb, offset2)));
2094 if (length2 > 0) {
2095 payload_tvb = tvb_new_subset_length(sub_tvb, offset2, length2);
2096 offset2 += length2;
2098 if ((dataflags & DATA_FLAG_FR_NF) != 0 || !flexray_call_subdissectors(payload_tvb, pinfo, tree, &fr_info, heuristic_first)) {
2099 dissect_data(payload_tvb, pinfo, tree, device_id, tecmp_msg_type, data_type, interface_id);
2103 /* new for TECMP 1.6 */
2104 if (tvb_captured_length_remaining(sub_tvb, offset2) >= 5) {
2105 uint32_t header_crc = 0;
2106 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_data_header_crc, sub_tvb, offset2, 2, ENC_BIG_ENDIAN, &header_crc);
2107 if (header_crc > DATA_FR_HEADER_CRC_MAX) {
2108 expert_add_info(pinfo, ti, &ei_tecmp_payload_header_crc_overflow);
2110 offset2 += 2;
2111 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_frame_crc, sub_tvb, offset2, 3, ENC_BIG_ENDIAN);
2113 break;
2115 case TECMP_DATA_TYPE_ILAS:
2116 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ilas_decoded_command, sub_tvb, offset2, 1, ENC_NA);
2117 offset2 += 1;
2118 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ilas_decoded_address, sub_tvb, offset2, 2, ENC_BIG_ENDIAN);
2119 offset2 += 2;
2120 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ilas_decoded_data, sub_tvb, offset2, 3, ENC_NA);
2121 offset2 += 3;
2122 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ilas_raw_sdu, sub_tvb, offset2, 7, ENC_NA);
2123 offset2 += 7;
2124 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ilas_raw_crc, sub_tvb, offset2, 2, ENC_BIG_ENDIAN);
2125 break;
2127 case TECMP_DATA_TYPE_RS232_ASCII:
2128 dissect_data(sub_tvb, pinfo, tree, device_id, tecmp_msg_type, data_type, interface_id);
2129 break;
2131 case TECMP_DATA_TYPE_ANALOG:
2132 ti_tecmp = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_samples, sub_tvb, offset2, length, ENC_NA);
2133 tecmp_tree = proto_item_add_subtree(ti_tecmp, ett_tecmp_payload_data);
2135 analog_value_scale_factor = tecmp_payload_analog_scale_factor_values[((dataflags & TECMP_DATAFLAGS_FACTOR_MASK) >> TECMP_DATAFLAGS_FACTOR_SHIFT)];
2137 tmp = offset2 + length;
2138 while (offset2 + 2 <= tmp) {
2139 double scaled_value;
2141 if (analog_samples_are_signed_int) {
2142 scaled_value = analog_value_scale_factor * tvb_get_int16(sub_tvb, offset2, ENC_BIG_ENDIAN);
2143 } else {
2144 scaled_value = analog_value_scale_factor * tvb_get_uint16(sub_tvb, offset2, ENC_BIG_ENDIAN);
2147 switch ((dataflags & TECMP_DATAFLAGS_UNIT_MASK) >> TECMP_DATAFLAGS_UNIT_SHIFT) {
2148 case 0x0:
2149 proto_tree_add_double(tecmp_tree, hf_tecmp_payload_data_analog_value_volt, sub_tvb, offset2, 2, scaled_value);
2150 break;
2151 case 0x01:
2152 proto_tree_add_double(tecmp_tree, hf_tecmp_payload_data_analog_value_amp, sub_tvb, offset2, 2, scaled_value);
2153 break;
2154 case 0x02:
2155 proto_tree_add_double(tecmp_tree, hf_tecmp_payload_data_analog_value_watt, sub_tvb, offset2, 2, scaled_value);
2156 break;
2157 case 0x03:
2158 proto_tree_add_double(tecmp_tree, hf_tecmp_payload_data_analog_value_amp_hour, sub_tvb, offset2, 2, scaled_value);
2159 break;
2160 case 0x04:
2161 proto_tree_add_double(tecmp_tree, hf_tecmp_payload_data_analog_value_celsius, sub_tvb, offset2, 2, scaled_value);
2162 break;
2163 default:
2164 if (analog_samples_are_signed_int) {
2165 ti = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_analog_value_raw_signed, sub_tvb, offset2, 2, ENC_BIG_ENDIAN);
2166 } else {
2167 ti = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_analog_value_raw, sub_tvb, offset2, 2, ENC_BIG_ENDIAN);
2169 proto_item_append_text(ti, "%s", " (raw)");
2171 offset2 += 2;
2173 break;
2175 case TECMP_DATA_TYPE_ANALOG_ALT:
2177 /* TECMP_DATA_TYPE_ANALOG_ALT is a backport of packet-asam-cmp.c CMP_DATA_MSG_ANALOG */
2179 static int * const analog_alt_flags[] = {
2180 &hf_tecmp_payload_analog_alt_flag_reserved,
2181 &hf_tecmp_payload_analog_alt_flag_sample_dt,
2182 NULL
2185 uint64_t flags;
2186 proto_tree_add_bitmask_ret_uint64(tecmp_tree, sub_tvb, offset2, hf_tecmp_payload_analog_alt_flags, ett_tecmp_payload_analog_alt_flags, analog_alt_flags, ENC_BIG_ENDIAN, &flags);
2187 offset2 += 2;
2189 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_analog_alt_reserved, sub_tvb, offset2, 1, ENC_NA);
2190 offset2 += 1;
2192 unsigned analog_unit;
2193 proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_analog_alt_unit, sub_tvb, offset2, 1, ENC_NA, &analog_unit);
2194 const char *unit_symbol;
2195 unit_symbol = try_val_to_str(analog_unit, analog_alt_units);
2196 offset2 += 1;
2198 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_analog_alt_sample_interval, sub_tvb, offset2, 4, ENC_BIG_ENDIAN);
2199 offset2 += 4;
2201 float sample_offset;
2202 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_analog_alt_sample_offset, sub_tvb, offset2, 4, ENC_BIG_ENDIAN);
2203 sample_offset = tvb_get_ieee_float(sub_tvb, offset2, ENC_BIG_ENDIAN);
2204 offset2 += 4;
2206 float sample_scalar;
2207 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_analog_alt_sample_scalar, sub_tvb, offset2, 4, ENC_BIG_ENDIAN);
2208 sample_scalar = tvb_get_ieee_float(sub_tvb, offset2, ENC_BIG_ENDIAN);
2209 offset2 += 4;
2211 ti_tecmp = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_samples, sub_tvb, offset2, length - offset2, ENC_NA);
2212 tecmp_tree = proto_item_add_subtree(ti_tecmp, ett_tecmp_payload_data);
2214 int data_left = length - offset2;
2215 if (data_left > 0) {
2217 switch (flags & 0x03) {
2218 case 0: /* INT16 */
2219 while (data_left >= 2) {
2220 double sample_value = ((double)tvb_get_int16(sub_tvb, offset2, ENC_BIG_ENDIAN) * sample_scalar + sample_offset);
2221 ti = proto_tree_add_double(tecmp_tree, hf_tecmp_payload_analog_alt_sample, sub_tvb, offset2, 2, sample_value);
2222 if (unit_symbol == NULL) {
2223 proto_item_append_text(ti, " (%.9f)", sample_value);
2224 } else {
2225 proto_item_append_text(ti, "%s (%.9f%s)", unit_symbol, sample_value, unit_symbol);
2227 PROTO_ITEM_SET_GENERATED(ti);
2229 proto_tree *sample_tree = proto_item_add_subtree(ti, ett_tecmp_payload_analog_alt_sample);
2230 proto_tree_add_item(sample_tree, hf_tecmp_payload_analog_alt_sample_raw, sub_tvb, offset2, 2, ENC_BIG_ENDIAN);
2231 PROTO_ITEM_SET_HIDDEN(ti);
2233 data_left -= 2;
2234 offset2 += 2;
2236 break;
2237 case 1: /* INT32 */
2238 while (data_left >= 4) {
2239 double sample_value = ((double)tvb_get_int32(sub_tvb, offset2, ENC_BIG_ENDIAN) * sample_scalar + sample_offset);
2240 ti = proto_tree_add_double(tecmp_tree, hf_tecmp_payload_analog_alt_sample, sub_tvb, offset2, 4, sample_value);
2241 if (unit_symbol == NULL) {
2242 proto_item_append_text(ti, " (%.9f)", sample_value);
2243 } else {
2244 proto_item_append_text(ti, "%s (%.9f%s)", unit_symbol, sample_value, unit_symbol);
2246 PROTO_ITEM_SET_GENERATED(ti);
2248 proto_tree *sample_tree = proto_item_add_subtree(ti, ett_tecmp_payload_analog_alt_sample);
2249 ti = proto_tree_add_item(sample_tree, hf_tecmp_payload_analog_alt_sample_raw, sub_tvb, offset2, 4, ENC_BIG_ENDIAN);
2250 PROTO_ITEM_SET_HIDDEN(ti);
2252 data_left -= 4;
2253 offset2 += 4;
2255 break;
2259 break;
2261 case TECMP_DATA_TYPE_ETH_RAW:
2263 length2 = length;
2264 uint32_t sub_tvb_end = offset2 + length2;
2266 ti = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ethernet_raw_data, sub_tvb, offset2, length2, ENC_NA);
2267 tecmp_tree = proto_item_add_subtree(ti, ett_tecmp_payload_eth_raw);
2269 uint32_t preamble_length = 0;
2270 while ((preamble_length < length2) && (TECMP_ETH_RAW_PREAMBLE == tvb_get_uint8(sub_tvb, offset2 + preamble_length))) {
2271 preamble_length += 1;
2274 if (preamble_length > 0) {
2275 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ethernet_raw_preamble, sub_tvb, offset2, preamble_length, ENC_NA);
2276 offset2 += preamble_length;
2278 if (offset2 < sub_tvb_end) {
2279 uint8_t sfd_candidate = tvb_get_uint8(sub_tvb, offset2);
2281 if (try_val_to_str(sfd_candidate, tecmp_eth_raw_sfd) != NULL) {
2282 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ethernet_raw_sfd, sub_tvb, offset2, 1, ENC_NA);
2283 offset2 += 1;
2285 if (offset2 < sub_tvb_end) {
2286 ti = proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data_ethernet_raw_eth_frame, sub_tvb, offset2, sub_tvb_end - offset2, ENC_NA);
2287 if (sfd_candidate == TECMP_ETH_RAW_SFD_ORIG) {
2288 tecmp_tree = proto_item_add_subtree(ti, ett_tecmp_payload_eth_raw_frame);
2290 dissect_ethernet_payload(sub_tvb, offset2, sub_tvb_end - offset2, pinfo, tree, tecmp_tree);
2297 break;
2299 case TECMP_DATA_TYPE_ETH_10BASE_T1S:
2300 case TECMP_DATA_TYPE_ETH:
2302 length2 = length;
2304 if (data_type == TECMP_DATA_TYPE_ETH_10BASE_T1S) {
2305 uint64_t ns = tvb_get_uint64(sub_tvb, offset2, ENC_BIG_ENDIAN);
2307 nstime_t timestamp;
2308 timestamp.secs = (time_t)(ns / 1000000000);
2309 timestamp.nsecs = (int)(ns % 1000000000);
2310 proto_tree_add_time(tecmp_tree, hf_tecmp_payload_data_beacon_timestamp, sub_tvb, offset2, 8, &timestamp);
2311 ti = proto_tree_add_uint64(tecmp_tree, hf_tecmp_payload_data_beacon_timestamp_ns, sub_tvb, offset2, 8, ns);
2312 proto_item_set_hidden(ti);
2314 ti = proto_tree_add_int64(tecmp_tree, hf_tecmp_payload_data_beacon_to_timestamp_ns, sub_tvb, offset2, 8, (int64_t)timestamp_ns - (int64_t)ns);
2315 proto_item_set_generated(ti);
2316 proto_item_set_hidden(ti);
2318 offset2 += 8;
2319 length2 -= 8;
2321 dissect_ethernet_payload(sub_tvb, offset2, length2, pinfo, tree, tecmp_tree);
2323 break;
2325 default:
2327 tecmp_info_t tecmp_info;
2328 tecmp_info.interface_id = interface_id;
2329 tecmp_info.device_id = device_id;
2330 tecmp_info.data_type = data_type;
2331 tecmp_info.data_flags = tvb_get_uint16(tvb, offset - 2, ENC_BIG_ENDIAN);
2332 tecmp_info.msg_type = tecmp_msg_type;
2334 dissector_handle_t handle = dissector_get_uint_handle(data_type_subdissector_table, data_type);
2335 if (handle != NULL) {
2336 call_dissector_only(handle, sub_tvb, pinfo, tecmp_tree, &tecmp_info);
2337 } else {
2338 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_data, sub_tvb, 0, length, ENC_NA);
2343 offset += length;
2347 return offset - offset_orig;
2350 static int
2351 dissect_tecmp_counter_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset_orig, uint16_t data_type, unsigned tecmp_msg_type) {
2352 proto_item *ti = NULL;
2353 proto_tree *tecmp_tree = NULL;
2354 uint16_t length = 0;
2355 unsigned offset = offset_orig;
2356 unsigned tmp = 0;
2358 if (tvb_captured_length_remaining(tvb, offset) >= (16 + 8)) {
2359 length = tvb_get_uint16(tvb, offset + 12, ENC_BIG_ENDIAN);
2360 ti = proto_tree_add_item(tree, proto_tecmp_payload, tvb, offset, (int)length + 16, ENC_NA);
2361 proto_item_append_text(ti, " Counter Event");
2362 tecmp_tree = proto_item_add_subtree(ti, ett_tecmp_payload);
2364 offset += dissect_tecmp_entry_header(tvb, pinfo, tecmp_tree, offset, tecmp_msg_type, data_type, true, NULL, NULL, NULL);
2366 col_set_str(pinfo->cinfo, COL_INFO, "TECMP Counter Event");
2368 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_counter_event_device_id, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp);
2369 add_device_id_text(ti, (uint16_t)tmp);
2370 offset += 2;
2372 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_counter_event_interface_id, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp);
2373 add_interface_id_text_and_name(ti, tmp, tvb, offset);
2374 offset += 2;
2376 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_counter_event_counter_last, tvb, offset, 2, ENC_BIG_ENDIAN);
2377 offset += 2;
2379 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_counter_event_counter_cur, tvb, offset, 2, ENC_BIG_ENDIAN);
2380 offset += 2;
2383 return offset - offset_orig;
2386 static int
2387 dissect_tecmp_timesync_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset_orig, uint16_t data_type, unsigned tecmp_msg_type) {
2388 proto_item *ti = NULL;
2389 proto_tree *tecmp_tree = NULL;
2390 uint16_t length = 0;
2391 unsigned offset = offset_orig;
2392 unsigned tmp = 0;
2394 if (tvb_captured_length_remaining(tvb, offset) >= (16 + 8)) {
2395 length = tvb_get_uint16(tvb, offset + 12, ENC_BIG_ENDIAN);
2396 ti = proto_tree_add_item(tree, proto_tecmp_payload, tvb, offset, (int)length + 16, ENC_NA);
2397 proto_item_append_text(ti, " TimeSync Event");
2398 tecmp_tree = proto_item_add_subtree(ti, ett_tecmp_payload);
2400 offset += dissect_tecmp_entry_header(tvb, pinfo, tecmp_tree, offset, tecmp_msg_type, data_type, true, NULL, NULL, NULL);
2402 col_set_str(pinfo->cinfo, COL_INFO, "TECMP TimeSync Event");
2404 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_timesync_event_device_id, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp);
2405 add_device_id_text(ti, (uint16_t)tmp);
2406 offset += 2;
2408 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_payload_timesync_event_interface_id, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp);
2409 add_interface_id_text_and_name(ti, tmp, tvb, offset);
2410 offset += 2;
2412 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_timesync_event_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
2413 offset += 2;
2415 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_timesync_event_async, tvb, offset, 1, ENC_NA);
2416 offset += 1;
2418 proto_tree_add_item(tecmp_tree, hf_tecmp_payload_timesync_event_time_delta, tvb, offset, 1, ENC_NA);
2419 offset += 1;
2422 return offset - offset_orig;
2425 static int
2426 dissect_tecmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
2427 proto_item *ti = NULL;
2428 proto_item *ti_root = NULL;
2429 proto_tree *tecmp_tree = NULL;
2430 unsigned offset = 0;
2431 unsigned tecmp_type = 0;
2432 unsigned data_type = 0;
2433 unsigned device_id = 0;
2435 static int * const tecmp_flags[] = {
2436 &hf_tecmp_flags_eos,
2437 &hf_tecmp_flags_sos,
2438 &hf_tecmp_flags_spy,
2439 &hf_tecmp_flags_multi_frame,
2440 &hf_tecmp_flags_dev_overflow,
2441 NULL
2444 /* ASAM CMP is the successor of TECMP and uses the same EtherType.
2446 * How to detect what the message is:
2447 * The first byte in TECMP 1.7 and later is always 0.
2448 * The first byte in TECMP 1.6 and older allowed 0xff for user-defined IDs.
2449 * The first byte in ASAM CMP is defined as version and is required to be > 0.
2450 * If the first byte is not 0, we pass it be ASAM CMP.
2451 * For backward compatibility: If 0xff allow as TECMP.
2453 if ( (detect_asam_cmp && asam_cmp_handle != 0 && tvb_get_uint8(tvb, offset) != 0) &&
2454 (!detect_asam_cmp_ignore_user_defined || tvb_get_uint8(tvb, offset) != 0xff) ) {
2455 return call_dissector_with_data(asam_cmp_handle, tvb, pinfo, tree, data);
2458 col_clear(pinfo->cinfo, COL_INFO);
2459 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TECMP");
2460 ti_root = proto_tree_add_item(tree, proto_tecmp, tvb, 0, -1, ENC_NA);
2461 tecmp_tree = proto_item_add_subtree(ti_root, ett_tecmp);
2463 if (!proto_field_is_referenced(tree, proto_tecmp)) {
2464 tecmp_tree = NULL;
2467 ti = proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_device_id, tvb, offset, 2, ENC_BIG_ENDIAN, &device_id);
2468 add_device_id_text(ti, (uint16_t)device_id);
2469 offset += 2;
2471 proto_tree_add_item(tecmp_tree, hf_tecmp_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
2472 offset += 2;
2474 proto_tree_add_item(tecmp_tree, hf_tecmp_version, tvb, offset, 1, ENC_NA);
2475 offset += 1;
2477 proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_msgtype, tvb, offset, 1, ENC_NA, &tecmp_type);
2478 offset += 1;
2480 proto_tree_add_item_ret_uint(tecmp_tree, hf_tecmp_data_type, tvb, offset, 2, ENC_BIG_ENDIAN, &data_type);
2481 offset += 2;
2483 proto_tree_add_item(tecmp_tree, hf_tecmp_res, tvb, offset, 2, ENC_BIG_ENDIAN);
2484 offset += 2;
2486 proto_tree_add_bitmask(tecmp_tree, tvb, offset, hf_tecmp_flags, ett_tecmp_flags, tecmp_flags,
2487 ENC_BIG_ENDIAN);
2488 offset += 2;
2490 switch (tecmp_type) {
2491 case TECMP_MSG_TYPE_CTRL_MSG:
2492 offset += dissect_tecmp_control_msg(tvb, pinfo, tree, offset, (uint16_t)data_type, (uint8_t)tecmp_type);
2493 break;
2495 case TECMP_MSG_TYPE_STATUS_BUS:
2496 case TECMP_MSG_TYPE_CFG_CM:
2497 case TECMP_MSG_TYPE_STATUS_DEV:
2498 offset += dissect_tecmp_status_device(tvb, pinfo, tree, offset, (uint16_t)data_type, (uint8_t)tecmp_type);
2499 break;
2501 case TECMP_MSG_TYPE_LOG_STREAM:
2502 case TECMP_MSG_TYPE_REPLAY_DATA:
2503 offset += dissect_tecmp_log_or_replay_stream(tvb, pinfo, tree, offset, (uint16_t)data_type, (uint8_t)tecmp_type, (uint16_t)device_id);
2504 break;
2506 case TECMP_MSG_TYPE_COUNTER_EVENT:
2507 offset += dissect_tecmp_counter_event(tvb, pinfo, tree, offset, (uint16_t)data_type, (uint8_t)tecmp_type);
2508 break;
2510 case TECMP_MSG_TYPE_TIMESYNC_EVENT:
2511 offset += dissect_tecmp_timesync_event(tvb, pinfo, tree, offset, (uint16_t)data_type, (uint8_t)tecmp_type);
2512 break;
2516 proto_item_set_end(ti_root, tvb, offset);
2517 return offset;
2520 void
2521 proto_register_tecmp_payload(void) {
2522 expert_module_t *expert_module_tecmp_payload;
2524 static hf_register_info hf[] = {
2525 { &hf_tecmp_payload_interface_id,
2526 { "Interface ID", "tecmp.payload.interface_id",
2527 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2528 { &hf_tecmp_payload_interface_name,
2529 { "Interface Name", "tecmp.payload.interface_name",
2530 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2531 { &hf_tecmp_payload_timestamp,
2532 { "Timestamp", "tecmp.payload.timestamp",
2533 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL }},
2534 { &hf_tecmp_payload_timestamp_async,
2535 { "Timestamp Synchronisation Status", "tecmp.payload.timestamp_synch_status",
2536 FT_BOOLEAN, 8, TFS(&tfs_tecmp_payload_timestamp_async_type), 0x80, NULL, HFILL }},
2537 { &hf_tecmp_payload_timestamp_res,
2538 { "Timestamp Synchronisation reserved", "tecmp.payload.timestamp_reserved",
2539 FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }},
2540 { &hf_tecmp_payload_timestamp_ns,
2541 { "Timestamp ns", "tecmp.payload.timestamp_ns",
2542 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2544 { &hf_tecmp_payload_length,
2545 { "Length", "tecmp.payload.length",
2546 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2547 { &hf_tecmp_payload_data,
2548 { "Data", "tecmp.payload.data",
2549 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2550 { &hf_tecmp_payload_samples,
2551 { "Samples", "tecmp.payload.samples",
2552 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2554 { &hf_tecmp_payload_data_ethernet_raw_data,
2555 { "Raw Data", "tecmp.payload.ethernet_raw.data",
2556 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2557 { &hf_tecmp_payload_data_ethernet_raw_preamble,
2558 { "Preamble", "tecmp.payload.ethernet_raw.preamble",
2559 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2560 { &hf_tecmp_payload_data_ethernet_raw_sfd,
2561 { "SFD", "tecmp.payload.ethernet_raw.sfd",
2562 FT_UINT8, BASE_HEX, VALS(tecmp_eth_raw_sfd), 0x0, NULL, HFILL }},
2563 { &hf_tecmp_payload_data_ethernet_raw_eth_frame,
2564 { "Ethernet Frame", "tecmp.payload.ethernet_raw.ethernet_frame",
2565 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2567 { &hf_tecmp_payload_data_beacon_timestamp,
2568 { "Beacon Timestamp", "tecmp.payload.beacon_timestamp",
2569 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL }},
2570 { &hf_tecmp_payload_data_beacon_timestamp_ns,
2571 { "Beacon Timestamp ns", "tecmp.payload.beacon_timestamp_ns",
2572 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2573 { &hf_tecmp_payload_data_beacon_to_timestamp_ns,
2574 { "Beacon to Timestamp ns", "tecmp.payload.beacon_to_timestamp_ns",
2575 FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2576 { &hf_tecmp_payload_data_id_field_8bit,
2577 { "ID", "tecmp.payload.data.lin_id_with_parity",
2578 FT_UINT8, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2579 { &hf_tecmp_payload_data_id_field_6bit,
2580 { "LIN ID", "tecmp.payload.data.lin_id",
2581 FT_UINT8, BASE_HEX_DEC, NULL, DATA_LIN_ID_MASK, NULL, HFILL }},
2582 { &hf_tecmp_payload_data_parity_bits,
2583 { "Parity Bits", "tecmp.payload.data.lin_parity_bits",
2584 FT_UINT8, BASE_HEX_DEC, NULL, 0xc0, NULL, HFILL }},
2585 { &hf_tecmp_payload_data_checksum_8bit,
2586 { "Checksum", "tecmp.payload.data.checksum",
2587 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2589 { &hf_tecmp_payload_data_id_field_32bit,
2590 { "ID Field", "tecmp.payload.data.can_id_field",
2591 FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2592 { &hf_tecmp_payload_data_id_type,
2593 { "CAN ID Type", "tecmp.payload.data.can_id_type",
2594 FT_BOOLEAN, 32, TFS(&tfs_tecmp_payload_data_id_type), 0x80000000, NULL, HFILL }},
2595 { &hf_tecmp_payload_data_id_11,
2596 { "ID (11bit)", "tecmp.payload.data.can_id_11",
2597 FT_UINT32, BASE_HEX_DEC, NULL, 0x000007FF, NULL, HFILL }},
2598 { &hf_tecmp_payload_data_id_29,
2599 { "ID (29bit)", "tecmp.payload.data.can_id_29",
2600 FT_UINT32, BASE_HEX_DEC, NULL, 0x1FFFFFFF, NULL, HFILL }},
2601 { &hf_tecmp_payload_data_crc15,
2602 { "CRC15", "tecmp.payload.data.crc15",
2603 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2604 { &hf_tecmp_payload_data_crc17,
2605 { "CRC17", "tecmp.payload.data.crc17",
2606 FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2607 { &hf_tecmp_payload_data_crc21,
2608 { "CRC21", "tecmp.payload.data.crc21",
2609 FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2611 { &hf_tecmp_payload_data_cycle,
2612 { "Cycle", "tecmp.payload.data.cycle",
2613 FT_UINT8, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2614 { &hf_tecmp_payload_data_frame_id,
2615 { "Frame ID", "tecmp.payload.data.frame_id",
2616 FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
2617 { &hf_tecmp_payload_data_header_crc,
2618 { "Header CRC", "tecmp.payload.data.header_crc",
2619 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2620 { &hf_tecmp_payload_data_frame_crc,
2621 { "Frame CRC", "tecmp.payload.data.frame_crc",
2622 FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2624 { &hf_tecmp_payload_data_length,
2625 { "Payload Length", "tecmp.payload.data.payload_length",
2626 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2628 { &hf_tecmp_payload_data_flags,
2629 { "Data Flags", "tecmp.payload.data_flags",
2630 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2631 { &hf_tecmp_payload_data_flags_crc,
2632 { "CRC Error", "tecmp.payload.data_flags.crc_error",
2633 FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
2634 { &hf_tecmp_payload_data_flags_checksum,
2635 { "Checksum Error", "tecmp.payload.data_flags.checksum_error",
2636 FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
2637 { &hf_tecmp_payload_data_flags_tx,
2638 { "TX (sent by Device)", "tecmp.payload.data_flags.tx",
2639 FT_BOOLEAN, 16, NULL, 0x4000, NULL, HFILL }},
2640 { &hf_tecmp_payload_data_flags_overflow,
2641 { "Overflow (lost data)", "tecmp.payload.data_flags.Overflow",
2642 FT_BOOLEAN, 16, NULL, 0x8000, NULL, HFILL }},
2644 /* Control Message */
2645 { &hf_tecmp_payload_ctrl_msg_device_id,
2646 { "Device ID", "tecmp.payload.ctrl_msg.device_id",
2647 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2648 { &hf_tecmp_payload_ctrl_msg_id,
2649 { "Control Message ID", "tecmp.payload.ctrl_msg.id",
2650 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2651 { &hf_tecmp_payload_ctrl_msg_unparsed_bytes,
2652 { "Unparsed Bytes", "tecmp.payload.ctrl_msg.unparsed",
2653 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2655 /* Control Message: CAN Replay Fill Level */
2656 { &hf_tecmp_payload_ctrl_msg_can_replay_fill_level_fill_level,
2657 { "Fill Level RAM", "tecmp.payload.ctrl_msg.can_replay_fill_level.fill_level_ram",
2658 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2659 { &hf_tecmp_payload_ctrl_msg_can_replay_fill_level_buffer_overflow,
2660 { "Buffer Overflow RAM", "tecmp.payload.ctrl_msg.can_replay_fill_level.buffer_overflow_ram",
2661 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2662 { &hf_tecmp_payload_ctrl_msg_can_replay_fill_level_queue_size,
2663 { "Queue Size", "tecmp.payload.ctrl_msg.can_replay_fill_level.queue_size",
2664 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2665 { &hf_tecmp_payload_ctrl_msg_can_replay_fill_level_queue_length,
2666 { "Queue Fill Level", "tecmp.payload.ctrl_msg.can_replay_fill_level.queue_fill_level",
2667 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2669 /* Control Message: FlexRay POC State */
2670 { &hf_tecmp_payload_ctrl_msg_flexray_poc_interface_id,
2671 { "Interface ID", "tecmp.payload.ctrl_msg.flexray_poc.interface_id",
2672 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2673 { &hf_tecmp_payload_ctrl_msg_flexray_poc_state,
2674 { "Protocol Operation Control State", "tecmp.payload.ctrl_msg.flexray_poc.state",
2675 FT_UINT8, BASE_DEC, VALS(tecmp_ctrl_msg_fr_poc_state), 0x0, NULL, HFILL } },
2677 /* Control Message: 10BASE-T1S */
2678 { &hf_tecmp_payload_ctrl_msg_10baset1s_interface_id,
2679 { "Interface ID", "tecmp.payload.ctrl_msg.10baset1s.interface_id",
2680 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2681 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags,
2682 { "Flags", "tecmp.payload.ctrl_msg.10baset1s.flags",
2683 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2684 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags_beacons_received,
2685 { "Beacons Received", "tecmp.payload.ctrl_msg.10baset1s.flags.beacons_received",
2686 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01, NULL, HFILL } },
2687 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_flags_plca_enabled,
2688 { "PLCA Enabled", "tecmp.payload.ctrl_msg.10baset1s.flags.plca_enabled",
2689 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02, NULL, HFILL } },
2690 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_reserved,
2691 { "Reserved", "tecmp.payload.ctrl_msg.10baset1s.reserved",
2692 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2693 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events,
2694 { "Events/Errors", "tecmp.payload.ctrl_msg.10baset1s.events",
2695 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2696 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_5b_decode_error,
2697 { "5B Decode Error", "tecmp.payload.ctrl_msg.10baset1s.events.5b_decode_error",
2698 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0001, NULL, HFILL } },
2699 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_eos_delim_error,
2700 { "End of Stream Delimiter Error", "tecmp.payload.ctrl_msg.10baset1s.events.end_of_stream_delimiter_error",
2701 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0002, NULL, HFILL } },
2702 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_symb_detected,
2703 { "PLCA Symbols Detected", "tecmp.payload.ctrl_msg.10baset1s.events.plca_symbols_detected",
2704 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0004, NULL, HFILL } },
2705 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_symb_missing,
2706 { "PLCA Symbols Missing", "tecmp.payload.ctrl_msg.10baset1s.events.plca_symbols_missing",
2707 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0008, NULL, HFILL } },
2708 { &hf_tecmp_payload_ctrl_msg_10baset1s_10m_events_plca_empty_cycle,
2709 { "PLCA Empty Cycle", "tecmp.payload.ctrl_msg.10baset1s.events.plca_empty_cycle",
2710 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x0010, NULL, HFILL } },
2712 /* Status Device / Status Bus / Status Configuration */
2713 { &hf_tecmp_payload_status_vendor_id,
2714 { "Vendor ID", "tecmp.payload.status.vendor_id",
2715 FT_UINT8, BASE_HEX, VALS(tecmp_vendor_ids), 0x0, NULL, HFILL }},
2716 { &hf_tecmp_payload_status_dev_version,
2717 { "Device Version", "tecmp.payload.status.device_version",
2718 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2719 { &hf_tecmp_payload_status_dev_type,
2720 { "Device Type", "tecmp.payload.status.device_type",
2721 FT_UINT8, BASE_HEX, VALS(tecmp_device_types), 0x0, NULL, HFILL }},
2722 { &hf_tecmp_payload_status_res,
2723 { "Reserved", "tecmp.payload.status.reserved",
2724 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2725 { &hf_tecmp_payload_status_length_vendor_data,
2726 { "Length of Vendor Data", "tecmp.payload.status.vdata_len",
2727 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2728 { &hf_tecmp_payload_status_device_id,
2729 { "Device ID", "tecmp.payload.status.device_id",
2730 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2731 { &hf_tecmp_payload_status_sn,
2732 { "Serial Number", "tecmp.payload.status.sn",
2733 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2734 { &hf_tecmp_payload_status_vendor_data,
2735 { "Vendor Data", "tecmp.payload.status.vendor_data",
2736 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2737 { &hf_tecmp_payload_status_bus_data,
2738 { "Bus Data", "tecmp.payload.status.bus_data",
2739 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2740 { &hf_tecmp_payload_status_bus_data_entry,
2741 { "Bus Data Entry", "tecmp.payload.status.bus_data_entry",
2742 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2743 { &hf_tecmp_payload_status_bus_interface_id,
2744 { "Interface ID", "tecmp.payload.status.bus.interface_id",
2745 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2746 { &hf_tecmp_payload_status_bus_total,
2747 { "Messages Total", "tecmp.payload.status.bus.total",
2748 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2749 { &hf_tecmp_payload_status_bus_errors,
2750 { "Errors Total", "tecmp.payload.status.bus.errors",
2751 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2753 /* Status Device Vendor Data */
2754 { &hf_tecmp_payload_status_dev_vendor_technica_res,
2755 { "Reserved", "tecmp.payload.status_dev.vendor_technica.res",
2756 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2757 { &hf_tecmp_payload_status_dev_vendor_technica_sw,
2758 { "Software Version", "tecmp.payload.status_dev.vendor_technica.sw_version",
2759 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2760 { &hf_tecmp_payload_status_dev_vendor_technica_hw,
2761 { "Hardware Version", "tecmp.payload.status_dev.vendor_technica.hw_version",
2762 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2763 { &hf_tecmp_payload_status_dev_vendor_technica_buffer_fill_level,
2764 { "Buffer Fill Level", "tecmp.payload.status_dev.vendor_technica.buffer_fill_level",
2765 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2766 { &hf_tecmp_payload_status_dev_vendor_technica_buffer_overflow,
2767 { "Buffer Overflow", "tecmp.payload.status_dev.vendor_technica.buffer_overflow",
2768 FT_BOOLEAN, BASE_NONE, TFS(&tfs_tecmp_technica_bufferoverflow), 0x0, NULL, HFILL }},
2769 { &hf_tecmp_payload_status_dev_vendor_technica_buffer_size,
2770 { "Buffer Size", "tecmp.payload.status_dev.vendor_technica.buffer_size",
2771 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2772 { &hf_tecmp_payload_status_dev_vendor_technica_lifecycle,
2773 { "Lifecycle", "tecmp.payload.status_dev.vendor_technica.lifecycle",
2774 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2775 { &hf_tecmp_payload_status_dev_vendor_technica_lifecycle_start,
2776 { "Lifecycle Start", "tecmp.payload.status_dev.vendor_technica.lifecycle.start",
2777 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL } },
2778 { &hf_tecmp_payload_status_dev_vendor_technica_voltage,
2779 { "Voltage", "tecmp.payload.status_dev.vendor_technica.voltage",
2780 FT_DOUBLE, BASE_NONE | BASE_UNIT_STRING, UNS(&units_volt), 0x0, NULL, HFILL } },
2781 { &hf_tecmp_payload_status_dev_vendor_technica_temperature,
2782 { "Temperature", "tecmp.payload.status_dev.vendor_technica.temperature",
2783 FT_UINT8, BASE_DEC | BASE_UNIT_STRING, UNS(&units_degree_celsius), 0x0, NULL, HFILL }},
2784 { &hf_tecmp_payload_status_dev_vendor_technica_temperature_chassis,
2785 { "Temperature Chassis", "tecmp.payload.status_dev.vendor_technica.temperature_chassis",
2786 FT_INT8, BASE_DEC | BASE_UNIT_STRING, UNS(&units_degree_celsius), 0x0, NULL, HFILL }},
2787 { &hf_tecmp_payload_status_dev_vendor_technica_temperature_silicon,
2788 { "Temperature Silicon", "tecmp.payload.status_dev.vendor_technica.temperature_silicon",
2789 FT_INT8, BASE_DEC | BASE_UNIT_STRING, UNS(&units_degree_celsius), 0x0, NULL, HFILL }},
2791 /* Status Bus Vendor Data */
2792 { &hf_tecmp_payload_status_bus_vendor_technica_link_status,
2793 { "Link Status", "tecmp.payload.status.bus.vendor_technica.link_status",
2794 FT_UINT8, BASE_DEC, VALS(tecmp_bus_status_link_status), 0x0, NULL, HFILL }},
2795 { &hf_tecmp_payload_status_bus_vendor_technica_link_quality,
2796 { "Link Quality", "tecmp.payload.status.bus.vendor_technica.link_quality",
2797 FT_UINT8, BASE_DEC, VALS(tecmp_bus_status_link_quality), 0x0, NULL, HFILL }},
2798 { &hf_tecmp_payload_status_bus_vendor_technica_linkup_time,
2799 { "Linkup Time", "tecmp.payload.status.bus.vendor_technica.linkup_time",
2800 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2802 { &hf_tecmp_payload_status_bus_vendor_technica_10m_flags,
2803 { "Flags", "tecmp.payload.status.bus.vendor_technica.flags",
2804 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2805 { &hf_tecmp_payload_status_bus_vendor_technica_10m_flags_beacons_received,
2806 { "Beacons Received", "tecmp.payload.status.bus.vendor_technica.flags.beacons_received",
2807 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01, NULL, HFILL } },
2808 { &hf_tecmp_payload_status_bus_vendor_technica_10m_flags_plca_enabled,
2809 { "PLCA Enabled", "tecmp.payload.status.bus.vendor_technica.flags.plca_enabled",
2810 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02, NULL, HFILL } },
2811 { &hf_tecmp_payload_status_bus_vendor_technica_res0,
2812 { "Reserved", "tecmp.payload.status.bus.vendor_technica.reserved_0",
2813 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2814 { &hf_tecmp_payload_status_bus_vendor_technica_beacon_counter,
2815 { "Beacon Counter", "tecmp.payload.status.bus.vendor_technica.beacon_counter",
2816 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2817 { &hf_tecmp_payload_status_bus_vendor_technica_res1,
2818 { "Reserved", "tecmp.payload.status.bus.vendor_technica.reserved_1",
2819 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2820 { &hf_tecmp_payload_status_bus_vendor_technica_res2,
2821 { "Reserved", "tecmp.payload.status.bus.vendor_technica.reserved_2",
2822 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2823 { &hf_tecmp_payload_status_bus_vendor_technica_5b_decode_err_cnt,
2824 { "5B Decode Error Count", "tecmp.payload.status.bus.vendor_technica.5b_decode_err_count",
2825 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2826 { &hf_tecmp_payload_status_bus_vendor_technica_eos_delim_err_cnt,
2827 { "End of Stream Delimiter Error Count", "tecmp.payload.status.bus.vendor_technica.eos_delim_err_count",
2828 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2829 { &hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_detected_cnt,
2830 { "PLCA Symbols Detected Count", "tecmp.payload.status.bus.vendor_technica.plca_symbols_detected_count",
2831 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2832 { &hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_missing_cnt,
2833 { "PLCA Symbols Missing Count", "tecmp.payload.status.bus.vendor_technica.plca_symbols_missing_count",
2834 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2835 { &hf_tecmp_payload_status_bus_vendor_technica_plca_symbols_empty_cycle_cnt,
2836 { "PLCA Empty Cycle Count", "tecmp.payload.status.bus.vendor_technica.plca_empty_cycle_count",
2837 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2839 /* Status Config Vendor Data */
2840 { &hf_tecmp_payload_status_cfg_vendor_technica_version,
2841 { "Version", "tecmp.payload.status.config.vendor_technica.version",
2842 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2843 { &hf_tecmp_payload_status_cfg_vendor_technica_reserved,
2844 { "Reserved", "tecmp.payload.status.config.vendor_technica.res",
2845 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2846 { &hf_tecmp_payload_status_cfg_vendor_technica_msg_id,
2847 { "Message ID", "tecmp.payload.status.config.vendor_technica.message_id",
2848 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2849 { &hf_tecmp_payload_status_cfg_vendor_technica_total_length,
2850 { "Total Length", "tecmp.payload.status.config.vendor_technica.total_length",
2851 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2852 { &hf_tecmp_payload_status_cfg_vendor_technica_total_num_seg,
2853 { "Total Number of Segments", "tecmp.payload.status.config.vendor_technica.total_number_segments",
2854 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2855 { &hf_tecmp_payload_status_cfg_vendor_technica_segment_num,
2856 { "Segment Number", "tecmp.payload.status.config.vendor_technica.segment_number",
2857 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2858 { &hf_tecmp_payload_status_cfg_vendor_technica_segment_length,
2859 { "Segment Length", "tecmp.payload.status.config.vendor_technica.segment_length",
2860 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2861 { &hf_tecmp_payload_status_cfg_vendor_technica_segment_data,
2862 { "Segment Data", "tecmp.payload.status.config.vendor_technica.segment_data",
2863 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2865 /* ILaS */
2866 { &hf_tecmp_payload_data_flags_crc_enabled,
2867 { "CRC Received", "tecmp.payload.data_flags.crc_received",
2868 FT_BOOLEAN, 16, TFS(&tfs_tecmp_payload_data_crc_received), 0x0001, NULL, HFILL } },
2869 { &hf_tecmp_payload_data_flags_direction,
2870 { "Direction", "tecmp.payload.data_flags.direction",
2871 FT_BOOLEAN, 16, TFS(&tfs_tecmp_payload_data_direction), 0x0002, NULL, HFILL } },
2873 /* Ethernet 10BASE-T1S */
2874 { &hf_tecmp_payload_data_flags_phy_event_error,
2875 { "PHY Event/Error", "tecmp.payload.data_flags.phy_event_error",
2876 FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL } },
2878 /* LIN */
2879 { &hf_tecmp_payload_data_flags_coll,
2880 { "Collision", "tecmp.payload.data_flags.collision",
2881 FT_BOOLEAN, 16, NULL, 0x0001, NULL, HFILL }},
2882 { &hf_tecmp_payload_data_flags_parity,
2883 { "Parity Error", "tecmp.payload.data_flags.parity_error",
2884 FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL }},
2885 { &hf_tecmp_payload_data_flags_no_resp,
2886 { "No Slave Response", "tecmp.payload.data_flags.no_resp",
2887 FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }},
2888 { &hf_tecmp_payload_data_flags_wup,
2889 { "Wake Up Signal", "tecmp.payload.data_flags.wup",
2890 FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL }},
2891 { &hf_tecmp_payload_data_flags_short_wup,
2892 { "Short Wake Up Signal", "tecmp.payload.data_flags.short_wup",
2893 FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL }},
2894 { &hf_tecmp_payload_data_flags_sleep,
2895 { "Sleep Signal", "tecmp.payload.data_flags.sleep",
2896 FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL }},
2898 /* CAN DATA, CAN-FD Data */
2899 { &hf_tecmp_payload_data_flags_ack,
2900 { "Ack'ed", "tecmp.payload.data_flags.ack",
2901 FT_BOOLEAN, 16, NULL, DATA_FLAG_CAN_ACK, NULL, HFILL }},
2902 { &hf_tecmp_payload_data_flags_rtr,
2903 { "Remote Frame", "tecmp.payload.data_flags.rtr",
2904 FT_BOOLEAN, 16, NULL, DATA_FLAG_CAN_RTR, NULL, HFILL }},
2905 { &hf_tecmp_payload_data_flags_esi,
2906 { "Error Node Active", "tecmp.payload.data_flags.esi",
2907 FT_BOOLEAN, 16, NULL, DATA_FLAG_CANFD_ESI, NULL, HFILL }},
2908 { &hf_tecmp_payload_data_flags_ide,
2909 { "Extended CAN-ID", "tecmp.payload.data_flags.ext_can_id",
2910 FT_BOOLEAN, 16, NULL, DATA_FLAG_CAN_IDE, NULL, HFILL }},
2911 { &hf_tecmp_payload_data_flags_err,
2912 { "Error Frame", "tecmp.payload.data_flags.error_frame",
2913 FT_BOOLEAN, 16, NULL, DATA_FLAG_CAN_ERR, NULL, HFILL }},
2914 { &hf_tecmp_payload_data_flags_brs,
2915 { "Bit Rate Switch", "tecmp.payload.data_flags.bit_rate_switch",
2916 FT_BOOLEAN, 16, NULL, DATA_FLAG_CANFD_BRS, NULL, HFILL }},
2918 { &hf_tecmp_payload_data_flags_can_bit_stuff_err,
2919 { "Bit Stuff Error", "tecmp.payload.data_flags.bit_stuff_error",
2920 FT_BOOLEAN, 16, NULL, DATA_FLAG_CAN_BIT_STUFF_ERR, NULL, HFILL }},
2921 { &hf_tecmp_payload_data_flags_can_crc_del_err,
2922 { "CRC Delimiter Error", "tecmp.payload.data_flags.crc_del_error",
2923 FT_BOOLEAN, 16, NULL, DATA_FLAG_CAN_CRC_DEL_ERR, NULL, HFILL }},
2924 { &hf_tecmp_payload_data_flags_can_ack_del_err,
2925 { "Ack Delimiter Error", "tecmp.payload.data_flags.ack_del_error",
2926 FT_BOOLEAN, 16, NULL, DATA_FLAG_CAN_ACK_DEL_ERR, NULL, HFILL }},
2927 { &hf_tecmp_payload_data_flags_can_eof_err,
2928 { "End of Frame Field Error", "tecmp.payload.data_flags.eof_error",
2929 FT_BOOLEAN, 16, NULL, DATA_FLAG_CAN_EOF_ERR, NULL, HFILL }},
2930 { &hf_tecmp_payload_data_flags_canfd_bit_stuff_err,
2931 { "Bit Stuff Error", "tecmp.payload.data_flags.bit_stuff_error",
2932 FT_BOOLEAN, 16, NULL, DATA_FLAG_CANFD_BIT_STUFF_ERR, NULL, HFILL }},
2933 { &hf_tecmp_payload_data_flags_canfd_crc_del_err,
2934 { "CRC Delimiter Error", "tecmp.payload.data_flags.crc_del_error",
2935 FT_BOOLEAN, 16, NULL, DATA_FLAG_CANFD_CRC_DEL_ERR, NULL, HFILL }},
2936 { &hf_tecmp_payload_data_flags_canfd_ack_del_err,
2937 { "Ack Delimiter Error", "tecmp.payload.data_flags.ack_del_error",
2938 FT_BOOLEAN, 16, NULL, DATA_FLAG_CANFD_ACK_DEL_ERR, NULL, HFILL }},
2939 { &hf_tecmp_payload_data_flags_canfd_eof_err,
2940 { "End of Frame Field Error", "tecmp.payload.data_flags.eof_error",
2941 FT_BOOLEAN, 16, NULL, DATA_FLAG_CANFD_EOF_ERR, NULL, HFILL }},
2943 /* FlexRay Data */
2944 { &hf_tecmp_payload_data_flags_nf,
2945 { "Null Frame", "tecmp.payload.data_flags.null_frame",
2946 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_NF, NULL, HFILL }},
2947 { &hf_tecmp_payload_data_flags_sf,
2948 { "Startup Frame", "tecmp.payload.data_flags.startup_frame",
2949 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_ST, NULL, HFILL }},
2950 { &hf_tecmp_payload_data_flags_sync,
2951 { "Sync Frame", "tecmp.payload.data_flags.sync_frame",
2952 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_SYNC, NULL, HFILL }},
2953 { &hf_tecmp_payload_data_flags_wus,
2954 { "Wakeup Symbol", "tecmp.payload.data_flags.wakeup_symbol",
2955 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_WUS, NULL, HFILL }},
2956 { &hf_tecmp_payload_data_flags_ppi,
2957 { "Payload Preamble Indicator", "tecmp.payload.data_flags.payload_preamble_indicator",
2958 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_PPI, NULL, HFILL }},
2959 { &hf_tecmp_payload_data_flags_cas,
2960 { "Collision Avoidance Symbol", "tecmp.payload.data_flags.collision_avoidance_symbol",
2961 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_CAS, NULL, HFILL }},
2962 { &hf_tecmp_payload_data_flags_header_crc_err,
2963 { "Header CRC Error", "tecmp.payload.data_flags.header_crc_error",
2964 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_HDR_CRC_ERR, NULL, HFILL }},
2965 { &hf_tecmp_payload_data_flags_frame_crc_err,
2966 { "Frame CRC Error", "tecmp.payload.data_flags.frame_crc_error",
2967 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_FRAME_CRC_ERR, NULL, HFILL }},
2969 /* UART/RS232 ASCII */
2970 { &hf_tecmp_payload_data_flags_dl,
2971 { "DL", "tecmp.payload.data_flags.dl",
2972 FT_UINT16, BASE_DEC, VALS(tecmp_payload_rs232_uart_dl_types), 0x000e, NULL, HFILL }},
2973 { &hf_tecmp_payload_data_flags_parity_error,
2974 { "Parity Error", "tecmp.payload.data_flags.parity_error",
2975 FT_BOOLEAN, 16, NULL, 0x0001, NULL, HFILL }},
2977 /* Analog */
2978 { &hf_tecmp_payload_data_flags_sample_time,
2979 { "Sample Time", "tecmp.payload.data_flags.sample_time",
2980 FT_UINT16, BASE_DEC, VALS(tecmp_payload_analog_sample_time_types), 0x7800, NULL, HFILL }},
2981 { &hf_tecmp_payload_data_flags_factor,
2982 { "Factor", "tecmp.payload.data_flags.factor",
2983 FT_UINT16, BASE_DEC, VALS(tecmp_payload_analog_scale_factor_types), TECMP_DATAFLAGS_FACTOR_MASK, NULL, HFILL }},
2984 { &hf_tecmp_payload_data_flags_unit,
2985 { "Unit", "tecmp.payload.data_flags.unit",
2986 FT_UINT16, BASE_DEC, VALS(tecmp_payload_analog_unit_types), TECMP_DATAFLAGS_UNIT_MASK, NULL, HFILL }},
2987 { &hf_tecmp_payload_data_flags_threshold_u,
2988 { "Threshold Undershot (deprecated)", "tecmp.payload.data_flags.threshold_undershot",
2989 FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL }},
2990 { &hf_tecmp_payload_data_flags_threshold_o,
2991 { "Threshold Exceeded (deprecated)", "tecmp.payload.data_flags.threshold_exceeded",
2992 FT_BOOLEAN, 16, NULL, 0x0001, NULL, HFILL }},
2993 { &hf_tecmp_payload_data_analog_value_raw,
2994 { "Analog Value", "tecmp.payload.data.analog_value",
2995 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2996 { &hf_tecmp_payload_data_analog_value_raw_signed,
2997 { "Analog Value", "tecmp.payload.data.analog_value_signed",
2998 FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2999 { &hf_tecmp_payload_data_analog_value_volt,
3000 { "Analog Value", "tecmp.payload.data.analog_value_volt",
3001 FT_DOUBLE, BASE_NONE | BASE_UNIT_STRING, UNS(&units_volt), 0x0, NULL, HFILL }},
3002 { &hf_tecmp_payload_data_analog_value_amp,
3003 { "Analog Value", "tecmp.payload.data.analog_value_amp",
3004 FT_DOUBLE, BASE_NONE | BASE_UNIT_STRING, UNS(&units_amp), 0x0, NULL, HFILL }},
3005 { &hf_tecmp_payload_data_analog_value_watt,
3006 { "Analog Value", "tecmp.payload.data.analog_value_watt",
3007 FT_DOUBLE, BASE_NONE | BASE_UNIT_STRING, UNS(&units_watt), 0x0, NULL, HFILL }},
3008 { &hf_tecmp_payload_data_analog_value_amp_hour,
3009 { "Analog Value", "tecmp.payload.data.analog_value_amp_hour",
3010 FT_DOUBLE, BASE_NONE | BASE_UNIT_STRING, UNS(&tecmp_units_amp_hour), 0x0, NULL, HFILL }},
3011 { &hf_tecmp_payload_data_analog_value_celsius,
3012 { "Analog Value", "tecmp.payload.data.analog_value_celsius",
3013 FT_DOUBLE, BASE_NONE | BASE_UNIT_STRING, UNS(&units_degree_celsius), 0x0, NULL, HFILL }},
3015 /* Analog Alt */
3016 { &hf_tecmp_payload_analog_alt_flags,
3017 { "Flags", "tecmp.payload.analog_alt.flags",
3018 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3019 { &hf_tecmp_payload_analog_alt_flag_sample_dt,
3020 { "Sample Datatype", "tecmp.payload.analog_alt.flags.sample_dt",
3021 FT_UINT16, BASE_HEX, VALS(analog_alt_sample_dt), 0x0003, NULL, HFILL } },
3022 { &hf_tecmp_payload_analog_alt_flag_reserved,
3023 { "Reserved", "tecmp.payload.analog_alt.flags.reserved",
3024 FT_UINT16, BASE_HEX, NULL, 0xfffc, NULL, HFILL } },
3026 { &hf_tecmp_payload_analog_alt_reserved,
3027 { "Reserved", "tecmp.payload.analog_alt.reserved",
3028 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3029 { &hf_tecmp_payload_analog_alt_unit,
3030 { "Unit", "tecmp.payload.analog_alt.unit",
3031 FT_UINT8, BASE_HEX, VALS(analog_alt_units), 0x0, NULL, HFILL } },
3032 { &hf_tecmp_payload_analog_alt_sample_interval,
3033 { "Sample Interval", "tecmp.payload.analog_alt.sample_interval",
3034 FT_FLOAT, BASE_NONE | BASE_UNIT_STRING, UNS(&units_seconds), 0x0, NULL, HFILL } },
3035 { &hf_tecmp_payload_analog_alt_sample_offset,
3036 { "Sample Offset", "tecmp.payload.analog_alt.sample_offset",
3037 FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3038 { &hf_tecmp_payload_analog_alt_sample_scalar,
3039 { "Sample Scalar", "tecmp.payload.analog_alt.sample_scalar",
3040 FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3041 { &hf_tecmp_payload_analog_alt_sample_raw,
3042 { "Sample Raw", "tecmp.payload.analog_alt.sample_raw",
3043 FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3044 { &hf_tecmp_payload_analog_alt_sample,
3045 { "Sample", "tecmp.payload.analog_alt.sample",
3046 FT_DOUBLE, BASE_EXP, NULL, 0x0, NULL, HFILL } },
3048 /* ILaS */
3049 { &hf_tecmp_payload_data_ilas_decoded_command,
3050 { "Decoded API Command", "tecmp.payload.ilas_decoded_command",
3051 FT_UINT8, BASE_DEC, VALS(tecmp_ilas_command_types), 0x0, NULL, HFILL } },
3052 { &hf_tecmp_payload_data_ilas_decoded_address,
3053 { "Decoded Address", "tecmp.payload.ilas_decoded_address",
3054 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3055 { &hf_tecmp_payload_data_ilas_decoded_data,
3056 { "Decoded Data", "tecmp.payload.ilas_decoded_data",
3057 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3058 { &hf_tecmp_payload_data_ilas_raw_sdu,
3059 { "Raw SDU", "tecmp.payload.ilas_raw_sdu",
3060 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3061 { &hf_tecmp_payload_data_ilas_raw_crc,
3062 { "Raw CRC", "tecmp.payload.ilas_raw_crc",
3063 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3065 /* TX Data Flags */
3066 { &hf_tecmp_payload_data_flags_use_crc_value,
3067 { "Use CRC Value", "tecmp.payload.data_flags.use_crc_value",
3068 FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
3069 { &hf_tecmp_payload_data_flags_use_header_crc_value,
3070 { "Use Header CRC Value", "tecmp.payload.data_flags.use_header_crc_value",
3071 FT_BOOLEAN, 16, NULL, DATA_FLAG_FR_HDR_CRC_ERR, NULL, HFILL }},
3072 { &hf_tecmp_payload_data_flags_use_checksum_value,
3073 { "Use Checksum Value", "tecmp.payload.data_flags.use_checksum_value",
3074 FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
3075 { &hf_tecmp_payload_data_flags_use_parity_bits,
3076 { "Use Parity Bits", "tecmp.payload.data_flags.use_parity_bits",
3077 FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL }},
3078 { &hf_tecmp_payload_data_flags_tx_mode,
3079 { "TX Mode", "tecmp.payload.data_flags.set_tx_mode",
3080 FT_UINT16, BASE_DEC, VALS(tecmp_payload_flexray_tx_mode), 0x0380, NULL, HFILL }},
3082 /* Counter Event */
3083 { &hf_tecmp_payload_counter_event_device_id,
3084 { "Device ID", "tecmp.payload.counter_event.device_id",
3085 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3086 { &hf_tecmp_payload_counter_event_interface_id,
3087 { "Interface ID", "tecmp.payload.counter_event.interface_id",
3088 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3089 { &hf_tecmp_payload_counter_event_counter_last,
3090 { "Last Counter", "tecmp.payload.counter_event.counter_last",
3091 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3092 { &hf_tecmp_payload_counter_event_counter_cur,
3093 { "Current Counter", "tecmp.payload.counter_event.counter_current",
3094 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3096 /* TimeSync Event */
3097 { &hf_tecmp_payload_timesync_event_device_id,
3098 { "Device ID", "tecmp.payload.timesync_event.device_id",
3099 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3100 { &hf_tecmp_payload_timesync_event_interface_id,
3101 { "Interface ID", "tecmp.payload.timesync_event.interface_id",
3102 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3103 { &hf_tecmp_payload_timesync_event_reserved,
3104 { "Reserved", "tecmp.payload.timesync_event.reserved",
3105 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3106 { &hf_tecmp_payload_timesync_event_async,
3107 { "Async", "tecmp.payload.timesync_event.async",
3108 FT_UINT16, BASE_HEX, VALS(tecmp_timesync_event_flags), 0x0, NULL, HFILL } },
3109 { &hf_tecmp_payload_timesync_event_time_delta,
3110 { "TimeDelta", "tecmp.payload.timesync_event.time_delta",
3111 FT_UINT16, BASE_HEX, VALS(tecmp_timesync_event_flags), 0x0, NULL, HFILL } },
3114 static int *ett[] = {
3115 &ett_tecmp_payload,
3116 &ett_tecmp_payload_interface_id,
3117 &ett_tecmp_payload_data,
3118 &ett_tecmp_payload_timestamp,
3119 &ett_tecmp_payload_dataflags,
3120 &ett_tecmp_payload_instruction_address,
3121 &ett_tecmp_payload_data_id,
3122 &ett_tecmp_payload_lin_id,
3123 &ett_tecmp_payload_analog_alt_flags,
3124 &ett_tecmp_payload_analog_alt_sample,
3125 &ett_tecmp_payload_eth_raw,
3126 &ett_tecmp_payload_eth_raw_frame,
3127 &ett_tecmp_status_dev_vendor_data,
3128 &ett_tecmp_status_bus_data,
3129 &ett_tecmp_status_bus_data_entry,
3130 &ett_tecmp_status_bus_vendor_data,
3131 &ett_tecmp_status_bus_vendor_data_flags,
3132 &ett_tecmp_ctrl_message_10baset1s_flags,
3133 &ett_tecmp_ctrl_message_10baset1s_events_errors,
3136 static ei_register_info ei[] = {
3137 { &ei_tecmp_payload_length_mismatch, { "tecmp.payload.payload_length_mismatch",
3138 PI_PROTOCOL, PI_WARN, "Payload Length and the length of Payload present in packet do not match!", EXPFILL }},
3139 { &ei_tecmp_payload_header_crc_overflow, { "tecmp.payload.header_crc_overflow",
3140 PI_PROTOCOL, PI_WARN, "Header CRC may only be up to 0x07ff!", EXPFILL }},
3143 proto_tecmp_payload = proto_register_protocol("Technically Enhanced Capture Module Protocol Payload",
3144 "TECMP Payload", "tecmp.payload");
3145 proto_register_field_array(proto_tecmp_payload, hf, array_length(hf));
3146 proto_register_subtree_array(ett, array_length(ett));
3147 expert_module_tecmp_payload = expert_register_protocol(proto_tecmp_payload);
3148 expert_register_field_array(expert_module_tecmp_payload, ei, array_length(ei));
3152 * Dissectors can register themselves in this table.
3154 data_subdissector_table = register_dissector_table(TECMP_PAYLOAD_INTERFACE_ID, "TECMP Interface ID", proto_tecmp_payload, FT_UINT32, BASE_HEX);
3155 data_type_subdissector_table = register_dissector_table(TECMP_DATA_TYPE, "TECMP Data Type", proto_tecmp_payload, FT_UINT16, BASE_HEX);
3159 void
3160 proto_reg_handoff_tecmp_payload(void) {
3161 eth_handle = find_dissector("eth_withfcs");
3162 proto_vlan = proto_get_id_by_filter_name("vlan");
3165 void
3166 proto_register_tecmp(void) {
3167 module_t *tecmp_module = NULL;
3168 uat_t *tecmp_device_id_uat = NULL;
3169 uat_t *tecmp_interface_id_uat = NULL;
3170 uat_t *tecmp_control_message_id_uat = NULL;
3172 static hf_register_info hf[] = {
3173 { &hf_tecmp_device_id,
3174 { "Device ID", "tecmp.device_id",
3175 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3176 { &hf_tecmp_counter,
3177 { "Counter", "tecmp.counter",
3178 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3179 { &hf_tecmp_version,
3180 { "Version", "tecmp.version",
3181 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3182 { &hf_tecmp_msgtype,
3183 { "Message Type", "tecmp.message_type",
3184 FT_UINT8, BASE_HEX, VALS(msg_type_names), 0x0, NULL, HFILL }},
3185 { &hf_tecmp_data_type,
3186 { "Data Type", "tecmp.data_type",
3187 FT_UINT16, BASE_HEX, VALS(tecmp_msgtype_names), 0x0, NULL, HFILL }},
3188 { &hf_tecmp_res,
3189 { "Reserved", "tecmp.reserved",
3190 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3191 { &hf_tecmp_flags,
3192 { "Device Flags", "tecmp.dev_flags",
3193 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3194 { &hf_tecmp_flags_eos,
3195 { "End of Segment", "tecmp.dev_flags.eos",
3196 FT_BOOLEAN, 16, NULL, 0x0001, NULL, HFILL }},
3197 { &hf_tecmp_flags_sos,
3198 { "Start of Segment", "tecmp.dev_flags.sos",
3199 FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL }},
3200 { &hf_tecmp_flags_spy,
3201 { "Spy", "tecmp.dev_flags.spy",
3202 FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }},
3203 { &hf_tecmp_flags_multi_frame,
3204 { "Multi Frame", "tecmp.dev_flags.multi_frame",
3205 FT_BOOLEAN, 16, NULL, 0x0008, NULL, HFILL }},
3206 { &hf_tecmp_flags_dev_overflow,
3207 { "Device Overflow", "tecmp.dev_flags.device_overflow",
3208 FT_BOOLEAN, 16, NULL, 0x8000, NULL, HFILL }},
3211 static int *ett[] = {
3212 &ett_tecmp,
3213 &ett_tecmp_flags,
3216 /* UATs for user_data fields */
3217 static uat_field_t tecmp_device_id_uat_fields[] = {
3218 UAT_FLD_HEX(tecmp_devices, id, "ID", "ID of the Device (hex uint16 without leading 0x)"),
3219 UAT_FLD_CSTRING(tecmp_devices, name, "Device Name", "Name of the Device (string)"),
3220 UAT_END_FIELDS
3223 static uat_field_t tecmp_interface_id_uat_fields[] = {
3224 UAT_FLD_HEX(tecmp_interfaces, id, "ID", "ID of the Interface (hex uint32 without leading 0x)"),
3225 UAT_FLD_CSTRING(tecmp_interfaces, name, "Interface Name", "Name of the Interface (string)"),
3226 UAT_FLD_HEX(tecmp_interfaces, bus_id, "Bus ID", "Bus ID of the Interface (hex uint16 without leading 0x)"),
3227 UAT_END_FIELDS
3230 static uat_field_t tecmp_control_message_id_uat_fields[] = {
3231 UAT_FLD_HEX(tecmp_ctrl_msgs, id, "ID", "ID of the Control Message"),
3232 UAT_FLD_CSTRING(tecmp_ctrl_msgs, name, "Control Message Name", "Name of the Control Message"),
3233 UAT_END_FIELDS
3236 proto_tecmp = proto_register_protocol("Technically Enhanced Capture Module Protocol", "TECMP", "tecmp");
3237 proto_register_field_array(proto_tecmp, hf, array_length(hf));
3238 proto_register_subtree_array(ett, array_length(ett));
3239 tecmp_handle = register_dissector("tecmp", dissect_tecmp, proto_tecmp);
3240 tecmp_module = prefs_register_protocol(proto_tecmp, NULL);
3242 /* UATs */
3243 tecmp_device_id_uat = uat_new("TECMP Devices",
3244 sizeof(generic_one_id_string_t), /* record size */
3245 DATAFILE_TECMP_DEVICE_IDS, /* filename */
3246 true, /* from profile */
3247 (void**)&tecmp_devices, /* data_ptr */
3248 &tecmp_devices_num, /* numitems_ptr */
3249 UAT_AFFECTS_DISSECTION, /* but not fields */
3250 NULL, /* help */
3251 copy_generic_one_id_string_cb, /* copy callback */
3252 update_generic_one_identifier_16bit, /* update callback */
3253 free_generic_one_id_string_cb, /* free callback */
3254 post_update_tecmp_devices_cb, /* post update callback */
3255 NULL, /* reset callback */
3256 tecmp_device_id_uat_fields /* UAT field definitions */
3259 prefs_register_uat_preference(tecmp_module, "_udf_tecmp_devicess", "Devices",
3260 "A table to define names of Devices, which override default names.", tecmp_device_id_uat);
3262 tecmp_interface_id_uat = uat_new("TECMP Interfaces",
3263 sizeof(interface_config_t), /* record size */
3264 DATAFILE_TECMP_INTERFACE_IDS, /* filename */
3265 true, /* from profile */
3266 (void**)&tecmp_interfaces, /* data_ptr */
3267 &tecmp_interfaces_num, /* numitems_ptr */
3268 UAT_AFFECTS_DISSECTION, /* but not fields */
3269 NULL, /* help */
3270 copy_interface_config_cb, /* copy callback */
3271 update_interface_config, /* update callback */
3272 free_interface_config_cb, /* free callback */
3273 post_update_tecmp_interfaces_cb, /* post update callback */
3274 NULL, /* reset callback */
3275 tecmp_interface_id_uat_fields /* UAT field definitions */
3278 prefs_register_uat_preference(tecmp_module, "_udf_tecmp_interfaces", "Interfaces",
3279 "A table to define names of Interfaces.", tecmp_interface_id_uat);
3281 tecmp_control_message_id_uat = uat_new("TECMP Control Messages",
3282 sizeof(generic_one_id_string_t), /* record size */
3283 DATAFILE_TECMP_CONTROL_MSG_IDS, /* filename */
3284 true, /* from profile */
3285 (void**)&tecmp_ctrl_msgs, /* data_ptr */
3286 &tecmp_ctrl_msg_num, /* numitems_ptr */
3287 UAT_AFFECTS_DISSECTION, /* but not fields */
3288 NULL, /* help */
3289 copy_generic_one_id_string_cb, /* copy callback */
3290 update_generic_one_identifier_16bit, /* update callback */
3291 free_generic_one_id_string_cb, /* free callback */
3292 post_update_tecmp_control_messages_cb, /* post update callback */
3293 NULL, /* reset callback */
3294 tecmp_control_message_id_uat_fields /* UAT field definitions */
3297 prefs_register_uat_preference(tecmp_module, "_udf_tecmp_control_msg_id", "Control Messages",
3298 "A table to define names of Control Messages.", tecmp_control_message_id_uat);
3300 prefs_register_bool_preference(tecmp_module, "try_heuristic_first",
3301 "Try heuristic sub-dissectors first",
3302 "Try to decode a packet using an heuristic sub-dissector"
3303 " before using a sub-dissector registered to \"decode as\"",
3304 &heuristic_first);
3306 prefs_register_bool_preference(tecmp_module, "analog_samples_sint",
3307 "Decode Analog Samples as Signed Integer",
3308 "Treat the analog samples as signed integers and decode them accordingly.",
3309 &analog_samples_are_signed_int);
3311 prefs_register_bool_preference(tecmp_module, "move_ethernet_in_tecmp_tree",
3312 "More compact Ethernet representation (move into TECMP Tree)",
3313 "Move Ethernet into the TECMP Tree to be more space efficient.",
3314 &show_ethernet_in_tecmp_tree);
3316 prefs_register_bool_preference(tecmp_module, "detect_asam_cmp",
3317 "Detect ASAM CMP",
3318 "Detect ASAM CMP messages and the ASAM CMP dissector handle them.",
3319 &detect_asam_cmp);
3321 prefs_register_bool_preference(tecmp_module, "detect_asam_cmp_ignore_user_defined",
3322 "Ignore Device IDs 0xff00-0xffff for ASAM CMP Detection",
3323 "Ignore Device IDs 0xff00-0xffff (user-defined range) for ASAM CMP Detection",
3324 &detect_asam_cmp_ignore_user_defined);
3327 void
3328 proto_reg_handoff_tecmp(void) {
3329 dissector_add_uint("ethertype", ETHERTYPE_TECMP, tecmp_handle);
3331 lin_subdissector_table = find_dissector_table("lin.frame_id");
3333 text_lines_handle = find_dissector_add_dependency("data-text-lines", proto_tecmp);
3334 asam_cmp_handle = find_dissector("asam-cmp");
3338 * Editor modelines
3340 * Local Variables:
3341 * c-basic-offset: 4
3342 * tab-width: 8
3343 * indent-tabs-mode: nil
3344 * End:
3346 * ex: set shiftwidth=4 tabstop=8 expandtab:
3347 * :indentSize=4:tabSize=8:noTabs=true: