1 /* packet-ebhscr.c
2 * Routines for EBHSCR dissection
3 * Copyright 2019, Ana Pantar <ana.pantar@gmail.com> for Elektrobit
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * For more information on this protocol see:
10 * https://www.elektrobit.com/ebhscr
11 *
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 */
14
15 #include <config.h>
16 #include <epan/packet.h>
17 #include <epan/decode_as.h>
18 #include <epan/prefs.h>
19 #include <wiretap/wtap.h>
20 #include <epan/expert.h>
21
22 void proto_reg_handoff_ebhscr(void);
23 void proto_register_ebhscr(void);
24
25 static int proto_ebhscr = -1;
26
27 static int hf_ebhscr_packet_header = -1;
28 static int hf_ebhscr_major_number = -1;
29 static int hf_ebhscr_slot = -1;
30 static int hf_ebhscr_channel = -1;
31 static int hf_ebhscr_status = -1;
32 static int hf_ebhscr_status_unused = -1;
33
34 static int hf_can_proto_type = -1;
35 static int hf_can_status_available = -1;
36 static int hf_can_LEC = -1;
37 static int hf_can_ERRP = -1;
38 static int hf_can_ERRW = -1;
39 static int hf_can_BOFF = -1;
40 static int hf_can_DLEC = -1;
41 static int hf_can_TEC = -1;
42 static int hf_can_REC = -1;
43 static int hf_can_CEL = -1;
44 static int hf_can_reserved_bytes = -1;
45
46 static int hf_eth_reserved_bytes = -1;
47 static int hf_eth_tx_trunc = -1;
48 static int hf_eth_trans_undrun = -1;
49 static int hf_eth_retrans_limit = -1;
50 static int hf_eth_late_collision = -1;
51 static int hf_eth_link_up_down = -1;
52 static int hf_eth_master_slave = -1;
53 static int hf_eth_fcs_unavailable = -1;
54 static int hf_eth_rsvd_bit = -1;
55 static int hf_eth_speed = -1;
56
57 static int hf_eth_crc_error = -1;
58 static int hf_eth_mii_foe = -1;
59 static int hf_eth_payload_foe = -1;
60 static int hf_eth_hdr_foe = -1;
61 static int hf_eth_rcv_dec_err = -1;
62 static int hf_eth_sym_error = -1;
63 static int hf_eth_jabber_event = -1;
64 static int hf_eth_pol_ch_event = -1;
65 static int hf_eth_fls_carrier_event = -1;
66 static int hf_eth_rx_trunc = -1;
67
68 static int hf_ts_time_offset_valid = -1;
69 static int hf_ts_last_offset_change_valid = -1;
70 static int hf_ts_nano_seconds_last_jump_valid = -1;
71 static int hf_ts_UTC_leap_seconds_valid = -1;
72 static int hf_ts_sync_state_valid = -1;
73 static int hf_ts_time_source = -1;
74
75 static int hf_ts_time_offset_ns = -1;
76 static int hf_ts_last_offset_ns = -1;
77 static int hf_ts_last_jump_ns = -1;
78 static int hf_ts_utc_leap_sec = -1;
79 static int hf_ts_sync_state = -1;
80
81 static int hf_dio_overflow_mon_unit = -1;
82 static int hf_dio_jump_occurred = -1;
83 static int hf_dio_value_type = -1;
84 static int hf_dio_reserved_bytes = -1;
85
86 static int hf_ebhscr_version = -1;
87 static int hf_ebhscr_length = -1;
88 static int hf_ebhscr_start_timestamp = -1;
89 static int hf_ebhscr_stop_timestamp = -1;
90 static int hf_ebhscr_mjr_hdr = -1;
91 static int hf_ebhscr_mjr_hdr_unused = -1;
92
93 static gint ett_ebhscr = -1;
94 static gint ett_ebhscr_packet_header = -1;
95 static gint ett_ebhscr_status = -1;
96 static gint ett_ebhscr_mjr_hdr = -1;
97
98 static int * const can_status_bits[] = {
99 &hf_can_proto_type,
100 &hf_can_status_available,
101 NULL
102 };
103
104 static int * const can_mjr_hdr_bits[] = {
105 & hf_can_reserved_bytes,
106 & hf_can_LEC,
107 & hf_can_ERRP,
108 & hf_can_ERRW,
109 & hf_can_BOFF,
110 & hf_can_DLEC,
111 & hf_can_TEC,
112 & hf_can_REC,
113 & hf_can_CEL,
114 NULL
115 };
116
117 static const value_string can_proto_type_strings[] = {
118 { 0, "Classical CAN" },
119 { 1, "CAN FD data frame" },
120 { 0, NULL },
121 };
122
123 static const value_string can_status_available_strings[] = {
124 { 0, "CAN protocol status not available" },
125 { 1, "CAN protocol status available" },
126 { 0, NULL },
127 };
128
129 static const val64_string can_last_err_code_strings[] = {
130 { 0, "No Error" },
131 { 1, "Stuff Error" },
132 { 2, "Form Error" },
133 { 3, "Ack Error" },
134 { 4, "Bit1 Error" },
135 { 5, "Bit0 Error" },
136 { 6, "CRC Error" },
137 { 7, "Reserved" },
138 { 0, NULL },
139 };
140
141 static const val64_string can_ERRP_strings[] = {
142 { 0, "Error counters are below the error passive limit (128)" },
143 { 1, "One of the error counters has reached the error passive limit (128)" },
144 { 0, NULL },
145 };
146
147 static const val64_string can_ERRW_strings[] = {
148 { 0, "Error counters are below the error warning limit (96)" },
149 { 1, "One of the error counters has reached the error warning limit (96)" },
150 { 0, NULL },
151 };
152 static const val64_string can_BOFF_strings[] = {
153 { 0, "Not in Bus Off state" },
154 { 1, "In Bus Off state." },
155 { 0, NULL },
156 };
157
158
159 static int * const eth_rx_error_bits[] = {
160 &hf_eth_crc_error,
161 &hf_eth_mii_foe,
162 &hf_eth_payload_foe,
163 &hf_eth_hdr_foe,
164 &hf_eth_rcv_dec_err,
165 &hf_eth_sym_error,
166 &hf_eth_jabber_event,
167 &hf_eth_pol_ch_event,
168 &hf_eth_fls_carrier_event,
169 &hf_eth_rx_trunc,
170 NULL
171 };
172
173 static int * const eth_mjr_hdr_bits[] = {
174 &hf_eth_reserved_bytes,
175 &hf_eth_tx_trunc,
176 &hf_eth_trans_undrun,
177 &hf_eth_retrans_limit,
178 &hf_eth_late_collision,
179 &hf_eth_link_up_down,
180 &hf_eth_master_slave,
181 &hf_eth_fcs_unavailable,
182 &hf_eth_rsvd_bit,
183 &hf_eth_speed,
184 NULL
185 };
186
187 static const val64_string eth_link_strings[] = {
188 { 0, "Link Down" },
189 { 1, "Link Up" },
190 { 0, NULL },
191 };
192
193 static const val64_string eth_master_strings[] = {
194 { 0, "Slave" },
195 { 1, "Master" },
196 { 0, NULL },
197 };
198
199 static const val64_string eth_fcs_strings[] = {
200 { 0, "FCS appended to payload" },
201 { 1, "FCS not appended to payload." },
202 { 0, NULL },
203 };
204
205 static const val64_string eth_speed_strings[] = {
206 { 0, "Speed 10M" },
207 { 1, "Speed 100M" },
208 { 2, "Speed 1000M" },
209 { 3, "Speed 2.5G" },
210 { 4, "Speed 5G" },
211 { 5, "Speed 10G" },
212 { 6, "Speed 25G" },
213 { 7, "Speed 40G" },
214 { 8, "Speed 100G" },
215 { 9, "Reserved" },
216 { 10, "Reserved" },
217 { 11, "Reserved" },
218 { 12, "Reserved" },
219 { 13, "Reserved" },
220 { 14, "Reserved" },
221 { 15, "Speed unknown. This value can be used when the speed could not be detected." },
222 { 0, NULL },
223 };
224
225 static int * const ts_status_bits[] = {
226 &hf_ts_time_offset_valid,
227 &hf_ts_last_offset_change_valid,
228 &hf_ts_nano_seconds_last_jump_valid,
229 &hf_ts_UTC_leap_seconds_valid,
230 &hf_ts_sync_state_valid,
231 NULL
232 };
233
234 static const val64_string ts_time_source_strings[] = {
235 { 0x00, "TimeSourceNone" },
236 { 0x01, "TimeSourceEBTimesyncHard" },
237 { 0x02, "TimeSourceXTSS" },
238 { 0x03, "TimeSourcePTPHW" },
239 { 0x10, "TimeSourcePTPSW" },
240 { 0x20, "TimeSourceGPS" },
241 { 0x30, "TimeSourceEBTimesyncSoft" },
242 { 0x40, "TimeSourceCAN" },
243 { 0x50, "TimeSourceEBVirt" },
244 { 0, NULL },
245 };
246 static const value_string ts_sync_state_strings[] = {
247 { 0, "Free running" },
248 { 1, "Locked to master" },
249 { 0, NULL },
250 };
251
252 static int * const dio_status_bits[] = {
253 &hf_dio_overflow_mon_unit,
254 &hf_dio_jump_occurred,
255 NULL
256 };
257
258 static int * const dio_mjr_hdr_bits[] = {
259 &hf_dio_value_type,
260 &hf_dio_reserved_bytes,
261 NULL
262 };
263
264 static const val64_string dio_val_type_strings[] = {
265 { 0, "Event triggered falling edge" },
266 { 1, "Event triggered rising edge" },
267 { 0, NULL },
268 };
269
270 static expert_field ei_ebhscr_frame_header = EI_INIT;
271 static expert_field ei_ebhscr_err_status_flag = EI_INIT;
272 static expert_field ei_ebhscr_info_status_flag = EI_INIT;
273
274 static dissector_handle_t can_handle;
275 static dissector_handle_t can_fd_handle;
276 static dissector_handle_t eth_withfcs_handle;
277 static dissector_handle_t eth_withoutfcs_handle;
278 static dissector_handle_t ebhscr_user_handle;
279
280 static dissector_table_t subdissector_table;
281
282 #define EBHSCR_USER_FIRST 0X43
283 #define EBHSCR_USER_LAST 0X4F
284
285 #define ETHERNET_FRAME 0x50
286 #define NMEA_FRAME 0x51
287 #define TIME_STATE_FRAME 0x52
288 #define CAN_FRAME 0x53
289 #define DIO_FRAME 0x56
290 #define EBHSCR_HEADER_LENGTH 32
291
dissect_ebhscr_can(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * ebhscr_packet_header_tree,guint16 ebhscr_status,guint32 ebhscr_frame_length)292 static int dissect_ebhscr_can(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
293 proto_tree *ebhscr_packet_header_tree, guint16 ebhscr_status,
294 guint32 ebhscr_frame_length)
295 {
296 guint16 can_proto_status, can_type;
297 guint32 ebhscr_current_payload_length;
298 tvbuff_t* next_tvb;
299 proto_item *ti;
300
301 ti = proto_tree_add_bitmask(ebhscr_packet_header_tree, tvb, 2, hf_ebhscr_status, ett_ebhscr_status,
302 can_status_bits, ENC_BIG_ENDIAN);
303
304 can_proto_status = (ebhscr_status & 0x0002);
305 if (can_proto_status) {
306 proto_tree_add_bitmask(ebhscr_packet_header_tree, tvb, 24, hf_ebhscr_mjr_hdr, ett_ebhscr_mjr_hdr,
307 can_mjr_hdr_bits, ENC_BIG_ENDIAN);
308 expert_add_info(pinfo, ti, &ei_ebhscr_info_status_flag);
309 }
310 else {
311 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_mjr_hdr, tvb, 24, 8, ENC_BIG_ENDIAN);
312 }
313
314 /* received hdr only and no data */
315 if (ebhscr_frame_length == EBHSCR_HEADER_LENGTH) {
316 return tvb_captured_length(tvb);
317 }
318 ebhscr_current_payload_length = ebhscr_frame_length - EBHSCR_HEADER_LENGTH;
319 /* payload is CAN or CAN FD frame */
320 next_tvb = tvb_new_subset_length(tvb, 32, ebhscr_current_payload_length);
321
322 can_type = (ebhscr_status & 0x0001);
323
324 if (can_type) {
325 call_dissector(can_fd_handle, next_tvb, pinfo, tree);
326 }
327 else {
328 call_dissector(can_handle, next_tvb, pinfo, tree);
329 }
330 return tvb_captured_length(tvb);
331 }
332
dissect_ebhscr_eth(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * ebhscr_packet_header_tree,guint16 ebhscr_status,guint32 ebhscr_frame_length)333 static int dissect_ebhscr_eth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
334 proto_tree *ebhscr_packet_header_tree, guint16 ebhscr_status,
335 guint32 ebhscr_frame_length)
336 {
337 tvbuff_t* next_tvb;
338 proto_item *ti;
339 guint64 major_hrd, fsc_not_present;
340 guint32 ebhscr_current_payload_length;
341 ebhscr_current_payload_length = ebhscr_frame_length - EBHSCR_HEADER_LENGTH;
342
343 ti = proto_tree_add_bitmask(ebhscr_packet_header_tree, tvb, 2, hf_ebhscr_status,
344 ett_ebhscr_status, eth_rx_error_bits, ENC_BIG_ENDIAN);
345
346 if (ebhscr_status) {
347 expert_add_info(pinfo, ti, &ei_ebhscr_err_status_flag);
348 }
349
350 major_hrd = tvb_get_guint64(tvb, 24, ENC_BIG_ENDIAN);
351
352 proto_tree_add_bitmask(ebhscr_packet_header_tree, tvb, 24, hf_ebhscr_mjr_hdr, ett_ebhscr_mjr_hdr,
353 eth_mjr_hdr_bits, ENC_BIG_ENDIAN);
354
355 fsc_not_present = (major_hrd & 0x0000000400000000);
356
357 /* received hdr only and no data */
358 if (ebhscr_frame_length == EBHSCR_HEADER_LENGTH) {
359 return tvb_captured_length(tvb);
360 }
361 /* payload is 802.3 Ethernet frame */
362 next_tvb = tvb_new_subset_length(tvb, 32, ebhscr_current_payload_length);
363 if (fsc_not_present) {
364 call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
365 }
366 else {
367 call_dissector(eth_withfcs_handle, next_tvb, pinfo, tree);
368 }
369 return tvb_captured_length(tvb);
370 }
371
dissect_ebhscr_nmea(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * ebhscr_packet_header_tree,guint32 ebhscr_frame_length,guint32 ebhscr_length)372 static int dissect_ebhscr_nmea(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
373 proto_tree *ebhscr_packet_header_tree, guint32 ebhscr_frame_length,
374 guint32 ebhscr_length)
375 {
376 tvbuff_t* next_tvb;
377 guint8 *nmea_str;
378 guint32 ebhscr_current_payload_length;
379
380 if (ebhscr_frame_length == EBHSCR_HEADER_LENGTH) {
381 return tvb_captured_length(tvb);
382 }
383
384 ebhscr_current_payload_length = ebhscr_frame_length - EBHSCR_HEADER_LENGTH;
385
386 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_status_unused, tvb, 2, 2, ENC_BIG_ENDIAN);
387 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_mjr_hdr_unused, tvb, 24, 8, ENC_BIG_ENDIAN);
388
389 next_tvb = tvb_new_subset_length(tvb, 32, ebhscr_current_payload_length);
390 call_data_dissector(next_tvb, pinfo, tree);
391 nmea_str = tvb_get_string_enc(pinfo->pool, tvb, 32, ebhscr_length, ENC_UTF_8);
392 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", "NMEA:", nmea_str);
393 return tvb_captured_length(tvb);
394 }
395
dissect_ebhscr_ts(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * ebhscr_packet_header_tree,guint16 ebhscr_status,guint32 ebhscr_frame_length)396 static int dissect_ebhscr_ts(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
397 proto_tree *ebhscr_packet_header_tree, guint16 ebhscr_status,
398 guint32 ebhscr_frame_length)
399 {
400 tvbuff_t* next_tvb;
401 guint32 ebhscr_current_payload_length;
402 guint64 time_source = 0;
403 proto_item *ti;
404
405 col_set_str(pinfo->cinfo, COL_INFO, "TimeState ");
406 ti = proto_tree_add_bitmask(ebhscr_packet_header_tree, tvb, 2, hf_ebhscr_status, ett_ebhscr_status,
407 ts_status_bits, ENC_BIG_ENDIAN);
408
409 if (ebhscr_status) {
410 expert_add_info(pinfo, ti, &ei_ebhscr_info_status_flag);
411 }
412 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_mjr_hdr, tvb, 24, 8, ENC_BIG_ENDIAN);
413 proto_tree_add_item_ret_uint64(ebhscr_packet_header_tree, hf_ts_time_source, tvb, 24, 8, ENC_BIG_ENDIAN, &time_source);
414 col_append_str(pinfo->cinfo, COL_INFO, val64_to_str_const(time_source, ts_time_source_strings, "Unknown Time Source"));
415
416 if (ebhscr_frame_length == EBHSCR_HEADER_LENGTH) {
417 return tvb_captured_length(tvb);
418 }
419
420 ebhscr_current_payload_length = ebhscr_frame_length - EBHSCR_HEADER_LENGTH;
421 if (ebhscr_current_payload_length < 28) {
422 return tvb_captured_length(tvb);
423 }
424
425 /* display params only if the appropriate valid bit is set */
426 if ((ebhscr_status & 0x001) != 0) {
427 proto_tree_add_item(ebhscr_packet_header_tree, hf_ts_time_offset_ns, tvb, 32, 8, ENC_BIG_ENDIAN);
428 }
429 if ((ebhscr_status & 0x002) != 0) {
430 proto_tree_add_item(ebhscr_packet_header_tree, hf_ts_last_offset_ns, tvb, 40, 8, ENC_BIG_ENDIAN);
431 }
432 if ((ebhscr_status & 0x004) != 0) {
433 proto_tree_add_item(ebhscr_packet_header_tree, hf_ts_last_jump_ns, tvb, 48, 8, ENC_BIG_ENDIAN);
434 }
435 if ((ebhscr_status & 0x008) != 0) {
436 proto_tree_add_item(ebhscr_packet_header_tree, hf_ts_utc_leap_sec, tvb, 56, 2, ENC_BIG_ENDIAN);
437 }
438 if ((ebhscr_status & 0x010) != 0) {
439 proto_tree_add_item(ebhscr_packet_header_tree, hf_ts_sync_state, tvb, 58, 2, ENC_BIG_ENDIAN);
440 }
441
442 next_tvb = tvb_new_subset_length(tvb, 32, ebhscr_current_payload_length);
443 call_data_dissector(next_tvb, pinfo, tree);
444
445 return tvb_captured_length(tvb);
446 }
447
448 static int
dissect_ebhscr_dio(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * ebhscr_packet_header_tree,guint16 ebhscr_status,guint32 ebhscr_frame_length)449 dissect_ebhscr_dio(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
450 proto_tree *ebhscr_packet_header_tree, guint16 ebhscr_status, guint32 ebhscr_frame_length)
451 {
452 tvbuff_t* next_tvb;
453 proto_item *ti;
454 guint32 ebhscr_current_payload_length;
455
456 col_set_str(pinfo->cinfo, COL_INFO, "DIO");
457 ebhscr_current_payload_length = ebhscr_frame_length - EBHSCR_HEADER_LENGTH;
458
459 ti = proto_tree_add_bitmask(ebhscr_packet_header_tree, tvb, 2, hf_ebhscr_status,
460 ett_ebhscr_status, dio_status_bits, ENC_BIG_ENDIAN);
461
462 if (ebhscr_status) {
463 expert_add_info(pinfo, ti, &ei_ebhscr_err_status_flag);
464 }
465 proto_tree_add_bitmask(ebhscr_packet_header_tree, tvb, 24, hf_ebhscr_mjr_hdr, ett_ebhscr_mjr_hdr,
466 dio_mjr_hdr_bits, ENC_BIG_ENDIAN);
467
468 if (ebhscr_frame_length == EBHSCR_HEADER_LENGTH) {
469 return tvb_captured_length(tvb);
470 }
471
472 next_tvb = tvb_new_subset_length(tvb, 32, ebhscr_current_payload_length);
473 call_data_dissector(next_tvb, pinfo, tree);
474
475 return tvb_captured_length(tvb);
476 }
477
478 static int
dissect_ebhscr(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)479 dissect_ebhscr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
480 {
481 proto_item *ti;
482 proto_tree *ebhscr_packet_header_tree;
483 proto_tree *ebhscr_tree;
484 tvbuff_t* next_tvb;
485 guint32 ebhscr_frame_length, ebhscr_length;
486 gint ebhscr_current_payload_length;
487 guint8 ebhscr_major_num;
488 guint16 ebhscr_status = 0;
489
490 col_set_str(pinfo->cinfo, COL_PROTOCOL, "EBHSCR");
491 col_clear(pinfo->cinfo, COL_INFO);
492
493 ebhscr_frame_length = tvb_captured_length(tvb);
494
495 ti = proto_tree_add_item(tree, proto_ebhscr, tvb, 0, -1, ENC_NA);
496 ebhscr_tree = proto_item_add_subtree(ti, ett_ebhscr);
497
498 if (ebhscr_frame_length < EBHSCR_HEADER_LENGTH) {
499 expert_add_info(pinfo, ebhscr_tree, &ei_ebhscr_frame_header);
500 return tvb_captured_length(tvb);
501 }
502
503 ebhscr_major_num = tvb_get_guint8(tvb, 0);
504 ebhscr_status = tvb_get_guint16(tvb, 2, ENC_BIG_ENDIAN) & 0x0FFF;
505
506 ti = proto_tree_add_item(ebhscr_tree, hf_ebhscr_packet_header, tvb, 0, 4, ENC_BIG_ENDIAN);
507 ebhscr_packet_header_tree = proto_item_add_subtree(ti, ett_ebhscr_packet_header);
508 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_major_number, tvb, 0, 1, ENC_BIG_ENDIAN);
509 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_slot, tvb, 1, 1, ENC_BIG_ENDIAN);
510 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_channel, tvb, 1, 1, ENC_BIG_ENDIAN);
511 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_version, tvb, 2, 2, ENC_BIG_ENDIAN);
512 proto_tree_add_item_ret_uint(ebhscr_packet_header_tree, hf_ebhscr_length, tvb, 4, 4, ENC_BIG_ENDIAN, &ebhscr_length);
513 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_start_timestamp, tvb, 8, 8, ENC_BIG_ENDIAN);
514 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_stop_timestamp, tvb, 16, 8, ENC_BIG_ENDIAN);
515
516 ebhscr_current_payload_length = ebhscr_frame_length - EBHSCR_HEADER_LENGTH;
517
518 if ((ebhscr_major_num >= EBHSCR_USER_FIRST) && (ebhscr_major_num <= EBHSCR_USER_LAST)) {
519 if (ebhscr_user_handle != NULL) {
520 next_tvb = tvb_new_subset_length(tvb, 0, ebhscr_frame_length);
521 call_dissector(ebhscr_user_handle, next_tvb, pinfo, ebhscr_tree);
522 }
523 else {
524 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_status, tvb, 2, 2, ENC_BIG_ENDIAN);
525 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_mjr_hdr, tvb, 24, 8, ENC_BIG_ENDIAN);
526 next_tvb = tvb_new_subset_length(tvb, 32, ebhscr_current_payload_length);
527 call_data_dissector(next_tvb, pinfo, tree);
528 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", tvb_bytes_to_str_punct(pinfo->pool, tvb, 32,
529 ebhscr_current_payload_length, ' '));
530 }
531 return tvb_captured_length(tvb);
532 }
533
534 /* each dissect function handles Status and Major number specific header bits */
535 if (ebhscr_major_num == CAN_FRAME) {
536 dissect_ebhscr_can(tvb, pinfo, tree, ebhscr_packet_header_tree, ebhscr_status, ebhscr_frame_length);
537 }
538
539 else if (ebhscr_major_num == ETHERNET_FRAME) {
540 dissect_ebhscr_eth(tvb, pinfo, tree, ebhscr_packet_header_tree, ebhscr_status, ebhscr_frame_length);
541 }
542
543 else if (ebhscr_major_num == NMEA_FRAME)
544 {
545 dissect_ebhscr_nmea(tvb, pinfo, tree, ebhscr_packet_header_tree, ebhscr_frame_length, ebhscr_length);
546 }
547
548 else if (ebhscr_major_num == TIME_STATE_FRAME) {
549 dissect_ebhscr_ts(tvb, pinfo, tree, ebhscr_packet_header_tree, ebhscr_status, ebhscr_frame_length);
550 }
551 else if (ebhscr_major_num == DIO_FRAME) {
552 dissect_ebhscr_dio(tvb, pinfo, tree, ebhscr_packet_header_tree, ebhscr_status, ebhscr_frame_length);
553 }
554
555 else {
556 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_status, tvb, 2, 2, ENC_BIG_ENDIAN);
557 proto_tree_add_item(ebhscr_packet_header_tree, hf_ebhscr_mjr_hdr, tvb, 24, 8, ENC_BIG_ENDIAN);
558 next_tvb = tvb_new_subset_length(tvb, 32, ebhscr_current_payload_length);
559 call_data_dissector(next_tvb, pinfo, tree);
560 }
561
562 return tvb_captured_length(tvb);
563 }
564
565 void
proto_register_ebhscr(void)566 proto_register_ebhscr(void)
567 {
568 expert_module_t *expert_ebhscr;
569
570 static hf_register_info hf[] = {
571 { &hf_ebhscr_packet_header,
572 { "Packet header", "ebhscr.hdr",
573 FT_UINT32, BASE_HEX,
574 NULL, 0x0,
575 NULL, HFILL }
576 },
577 { &hf_ebhscr_major_number,
578 { "Major number", "ebhscr.mjr",
579 FT_UINT8, BASE_HEX,
580 NULL, 0x0,
581 NULL, HFILL }
582 },
583 { &hf_ebhscr_slot,
584 { "Slot", "ebhscr.slot",
585 FT_UINT8, BASE_HEX,
586 NULL, 0xc0,
587 NULL, HFILL }
588 },
589 { &hf_ebhscr_channel,
590 { "Channel", "ebhscr.channel",
591 FT_UINT8, BASE_HEX,
592 NULL, 0x3f,
593 NULL, HFILL }
594 },
595 { &hf_ebhscr_status,
596 { "Status", "ebhscr.sts",
597 FT_UINT16, BASE_HEX,
598 NULL, 0x0FFF,
599 NULL, HFILL }
600 },
601 { &hf_ebhscr_status_unused,{
602 "Status [Unused]", "ebhscr.sts.unused",
603 FT_UINT32, BASE_HEX,
604 NULL, 0x0FFF,
605 NULL, HFILL }
606 },
607 { &hf_ebhscr_version,
608 { "Version", "ebhscr.ver",
609 FT_UINT16, BASE_HEX,
610 NULL, 0xF000,
611 NULL, HFILL }
612 },
613 { &hf_ebhscr_length,
614 { "Length", "ebhscr.len",
615 FT_UINT32, BASE_DEC,
616 NULL, 0x0,
617 NULL, HFILL }
618 },
619 { &hf_ebhscr_start_timestamp,
620 { "Start timestamp", "ebhscr.strt",
621 FT_UINT64, BASE_HEX,
622 NULL, 0x0,
623 NULL, HFILL }
624 },
625 { &hf_ebhscr_stop_timestamp,
626 { "Stop timestamp", "ebhscr.stpt",
627 FT_UINT64, BASE_HEX,
628 NULL, 0x0,
629 NULL, HFILL }
630 },
631 { &hf_ebhscr_mjr_hdr,
632 { "Major number specific header", "ebhscr.mjrhdr",
633 FT_UINT64, BASE_HEX,
634 NULL, 0x0,
635 NULL, HFILL }
636 },
637 { &hf_ebhscr_mjr_hdr_unused,
638 { "Major number specific header [Unused]", "ebhscr.mjrhdr.unused",
639 FT_UINT64, BASE_HEX,
640 NULL, 0x0,
641 NULL, HFILL }
642 },
643 { &hf_can_proto_type,
644 { "CAN FD flag", "ebhscr.can.type",
645 FT_UINT16, BASE_HEX,
646 VALS(can_proto_type_strings), 0x0001,
647 NULL, HFILL }
648 },
649 { &hf_can_status_available,
650 { "CAN protocol status availability", "ebhscr.can.asts",
651 FT_UINT16, BASE_HEX,
652 VALS(can_status_available_strings), 0x0002,
653 NULL, HFILL }
654 },
655 { &hf_can_LEC,
656 { "CAN Last error code", "ebhscr.can.LEC",
657 FT_UINT64, BASE_DEC | BASE_VAL64_STRING,
658 VALS64(can_last_err_code_strings), 0x0000000700000000,
659 NULL, HFILL }
660 },
661 { &hf_can_ERRP,
662 { "CAN Counters reached Error passive limit", "ebhscr.can.errp",
663 FT_UINT64, BASE_DEC | BASE_VAL64_STRING,
664 VALS64(can_ERRP_strings), 0x0000002000000000,
665 NULL, HFILL }
666 },
667 { &hf_can_ERRW,
668 { "CAN Counters reached Error warning limit", "ebhscr.can.errw",
669 FT_UINT64, BASE_DEC | BASE_VAL64_STRING,
670 VALS64(can_ERRW_strings), 0x0000004000000000,
671 NULL, HFILL }
672 },
673 { &hf_can_BOFF,
674 { "CAN Bus Off state", "ebhscr.can.boff",
675 FT_UINT64, BASE_DEC | BASE_VAL64_STRING,
676 VALS64(can_BOFF_strings), 0x0000008000000000,
677 NULL, HFILL }
678 },
679 { &hf_can_DLEC,
680 { "CAN Data phase of CAN FD frame (with BRS flag set) last error code.", "ebhscr.can.dlec",
681 FT_UINT64, BASE_HEX | BASE_VAL64_STRING,
682 VALS64(can_last_err_code_strings), 0x0000070000000000,
683 NULL, HFILL }
684 },
685 { &hf_can_TEC,
686 { "CAN Transmit Error Counter", "ebhscr.can.tec",
687 FT_UINT64, BASE_HEX,
688 NULL, 0x00FF000000000000,
689 NULL, HFILL }
690 },
691 { &hf_can_REC,
692 { "CAN Receive Error Counter", "ebhscr.can.rec",
693 FT_UINT64, BASE_DEC | BASE_VAL64_STRING,
694 NULL, 0x7F00000000000000,
695 NULL, HFILL }
696 },
697 { &hf_can_CEL,
698 { "Can Error Logging Counter", "ebhscr.can.cel",
699 FT_UINT64, BASE_DEC | BASE_VAL64_STRING,
700 NULL, 0x00000000000000FF,
701 NULL, HFILL }
702 },
703 { &hf_can_reserved_bytes,
704 { "Reserved Flags", "ebhscr.can.rsv",
705 FT_BOOLEAN, 64, NULL,
706 0x00000000FFFFFF00,
707 NULL, HFILL }
708 },
709 { &hf_eth_reserved_bytes,
710 { "Reserved Flags", "ebhscr.eth.rsv",
711 FT_BOOLEAN, 64, NULL,
712 0xFFF0FF00FFFFFFFF,
713 NULL, HFILL }
714 },
715 { &hf_eth_link_up_down,
716 { "Link Up or Down", "ebhscr.eth.lud",
717 FT_UINT64, BASE_HEX | BASE_VAL64_STRING,
718 VALS64(eth_link_strings), 0x0000000100000000,
719 NULL, HFILL }
720 },
721 { &hf_eth_master_slave,
722 { "Master or Slave (if supported)", "ebhscr.eth.ms",
723 FT_UINT64, BASE_HEX | BASE_VAL64_STRING,
724 VALS64(eth_master_strings), 0x0000000200000000,
725 NULL, HFILL }
726 },
727 { &hf_eth_fcs_unavailable,
728 { "FCS unavailable", "ebhscr.eth.fcsua",
729 FT_UINT64, BASE_HEX | BASE_VAL64_STRING,
730 VALS64(eth_fcs_strings), 0x0000000400000000,
731 NULL, HFILL }
732 },
733 { &hf_eth_rsvd_bit,
734 { "Reserved", "ebhscr.eth.rsvd",
735 FT_BOOLEAN, 64, NULL,
736 0x0000000800000000,
737 NULL, HFILL }
738 },
739 { &hf_eth_speed,
740 { "Ethernet speed", "ebhscr.eth.spd",
741 FT_UINT64, BASE_HEX | BASE_VAL64_STRING,
742 VALS64(eth_speed_strings), 0x000000F000000000,
743 NULL, HFILL }
744 },
745 { &hf_eth_crc_error,
746 { "Ethernet CRC Error", "ebhscr.eth.crc",
747 FT_BOOLEAN, 16,
748 NULL, 0x0001,
749 NULL, HFILL }
750 },
751 { &hf_eth_mii_foe,
752 { "Media-independent interface FIFO Overflow Error", "ebhscr.eth.miifoe",
753 FT_BOOLEAN, 16,
754 NULL, 0x0002,
755 NULL, HFILL }
756 },
757 { &hf_eth_payload_foe,
758 { "Payload FIFO Overflow Error", "ebhscr.eth.pfoe",
759 FT_BOOLEAN, 16,
760 NULL, 0x0004,
761 NULL, HFILL }
762 },
763 { &hf_eth_hdr_foe,
764 { "Header FIFO Overflow Error", "ebhscr.eth.hfoe",
765 FT_BOOLEAN, 16,
766 NULL, 0x0008,
767 NULL, HFILL }
768 },
769 { &hf_eth_rcv_dec_err,
770 { "Receiver Decoder Error", "ebhscr.eth.rde",
771 FT_BOOLEAN, 16,
772 NULL, 0x0010,
773 NULL, HFILL }
774 },
775 { &hf_eth_sym_error,
776 { "Symbol Error", "ebhscr.eth.se",
777 FT_BOOLEAN, 16,
778 NULL, 0x0020,
779 NULL, HFILL }
780 },
781 { &hf_eth_jabber_event,
782 { "Jabber", "ebhscr.eth.jbr",
783 FT_BOOLEAN, 16,
784 NULL, 0x0040,
785 NULL, HFILL }
786 },
787 { &hf_eth_pol_ch_event,
788 { "Polarity Change", "ebhscr.eth.pche",
789 FT_BOOLEAN, 16,
790 NULL, 0x0080,
791 NULL, HFILL }
792 },
793 { &hf_eth_fls_carrier_event,
794 { "False Carrier", "ebhscr.eth.flsc",
795 FT_BOOLEAN, 16,
796 NULL, 0x0100,
797 NULL, HFILL }
798 },
799 { &hf_eth_rx_trunc,
800 { "Truncation", "ebhscr.eth.rxtrc",
801 FT_BOOLEAN, 16,
802 NULL, 0x0200,
803 NULL, HFILL }
804 },
805 { &hf_eth_tx_trunc,
806 { "If value 1 then a Truncation occurred. The frame is sent truncated.", "ebhscr.eth.trc",
807 FT_BOOLEAN, 64, NULL,
808 0x0001000000000000,
809 NULL, HFILL }
810 },
811 { &hf_eth_trans_undrun,
812 { "If value 1 then a Transmitter Underrun occurred.", "ebhscr.eth.trudr",
813 FT_BOOLEAN, 64, NULL,
814 0x0002000000000000,
815 NULL, HFILL }
816 },
817 { &hf_eth_retrans_limit,
818 { "If value 1 then the Retransmission Limit was reached", "ebhscr.eth.rtrlmt",
819 FT_BOOLEAN, 64, NULL,
820 0x0004000000000000,
821 NULL, HFILL }
822 },
823 { &hf_eth_late_collision,
824 { "If value 1 then a Late collision was detected.", "ebhscr.eth.ltcls",
825 FT_BOOLEAN, 64, NULL,
826 0x0008000000000000,
827 NULL, HFILL }
828 },
829 { &hf_ts_time_offset_valid,
830 { "Time offset in ns valid (byte 0-7)", "ebhscr.ts.tov",
831 FT_BOOLEAN, 16, NULL,
832 0x0001,
833 NULL, HFILL }
834 },
835 { &hf_ts_last_offset_change_valid,
836 { "Last offset change in ns valid (byte 8-15)", "ebhscr.ts.locv",
837 FT_BOOLEAN, 16,
838 NULL, 0x0002,
839 NULL, HFILL }
840 },
841 { &hf_ts_nano_seconds_last_jump_valid,
842 { "Nano seconds last jump valid (byte 16-23)", "ebhscr.ts.nsljv",
843 FT_BOOLEAN, 16,
844 NULL, 0x0004,
845 NULL, HFILL }
846 },
847 { &hf_ts_UTC_leap_seconds_valid,
848 { "UTC leap seconds valid (byte 24-25)", "ebhscr.ts.utclsv",
849 FT_BOOLEAN, 16,
850 NULL, 0x0008,
851 NULL, HFILL }
852 },
853 { &hf_ts_sync_state_valid,
854 { "Sync state valid (byte 26-27)", "ebhscr.ts.ssv",
855 FT_BOOLEAN, 16,
856 NULL, 0x0010,
857 NULL, HFILL }
858 },
859 { &hf_ts_time_source,
860 { "Time source", "ebhscr.ts.tsrc",
861 FT_UINT64, BASE_DEC | BASE_VAL64_STRING, VALS64(ts_time_source_strings), 0x0,
862 NULL, HFILL }
863 },
864 { &hf_ts_time_offset_ns,
865 { "Time offset in nanoseconds", "ebhscr.ts.off", FT_UINT64, BASE_HEX,
866 NULL, 0, "The offset is the difference of the zero-based capture counter to TAI", HFILL }
867 },
868 { &hf_ts_last_offset_ns,
869 { "Last offset change in nano seconds", "ebhscr.ts.lstoff", FT_UINT64, BASE_HEX,
870 NULL, 0, "Point in time of last change of time offset.", HFILL }
871 },
872 { &hf_ts_last_jump_ns,
873 { "Nano seconds last jump", "ebhscr.ts.lstjmp", FT_UINT64, BASE_HEX,
874 NULL, 0, "Point in time of last hard change/jump of time count after the jump.", HFILL }
875 },
876 { &hf_ts_utc_leap_sec,
877 { "UTC leap-seconds", "ebhscr.ts.leap", FT_UINT16, BASE_HEX,
878 NULL, 0, NULL, HFILL }
879 },
880 { &hf_ts_sync_state,
881 { "Sync state", "ebhscr.ts.syn", FT_UINT16, BASE_HEX,
882 VALS(ts_sync_state_strings), 0, NULL, HFILL }
883 },
884 { &hf_dio_overflow_mon_unit,
885 { "Overflow in the monitoring unit", "ebhscr.dio.ofw_mon",
886 FT_BOOLEAN, 16,
887 NULL, 0x0001,
888 "Set to 1 in case of an overflow in the monitoring unit. In this case all remaining fields are invalid.", HFILL }
889 },
890 { &hf_dio_jump_occurred,
891 { "Time jump occurred", "ebhscr.dio.jump_occ",
892 FT_BOOLEAN, 16,
893 NULL, 0x0400,
894 "Set to 1 if a time jump occurred near the edge and thus the timestamp was estimated.", HFILL }
895 },
896 { &hf_dio_value_type,
897 { "Digital IO value type", "ebhscr.dio.valtype",
898 FT_UINT64, BASE_DEC | BASE_VAL64_STRING,
899 VALS64(dio_val_type_strings), 0x0100000000000000,
900 NULL, HFILL }
901 },
902 { &hf_dio_reserved_bytes,
903 { "Reserved Flags", "ebhscr.dio.rsv",
904 FT_BOOLEAN, 64, NULL,
905 0x00FFFFFFFFFFFFFF,
906 NULL, HFILL }
907 },
908
909 };
910
911 static gint *ett[] = {
912 &ett_ebhscr,
913 &ett_ebhscr_packet_header,
914 &ett_ebhscr_status,
915 &ett_ebhscr_mjr_hdr,
916 };
917
918 static ei_register_info ei[] = {
919 { &ei_ebhscr_frame_header,
920 { "ebhscr.frame_header", PI_MALFORMED, PI_ERROR,
921 "Frame Header is malformed", EXPFILL }
922 },
923 { &ei_ebhscr_err_status_flag,
924 { "ebhscr.sts.err.status", PI_PROTOCOL, PI_WARN,
925 "Status Flag is set", EXPFILL }
926 },
927 { &ei_ebhscr_info_status_flag,
928 { "ebhscr.sts.info.status", PI_PROTOCOL, PI_CHAT,
929 "Status Flag is set", EXPFILL }
930 },
931 };
932
933 proto_ebhscr = proto_register_protocol(
934 "EBHSCR Protocol",
935 "EBHSCR",
936 "ebhscr"
937 );
938
939 proto_register_field_array(proto_ebhscr, hf, array_length(hf));
940 proto_register_subtree_array(ett, array_length(ett));
941
942 expert_ebhscr = expert_register_protocol(proto_ebhscr);
943 expert_register_field_array(expert_ebhscr, ei, array_length(ei));
944
945 register_dissector("ebhscr", dissect_ebhscr, proto_ebhscr);
946 subdissector_table = register_decode_as_next_proto(proto_ebhscr, "ebhscr.subdissector",
947 "ebhscr next level dissector", NULL);
948 }
949
950 void
proto_reg_handoff_ebhscr(void)951 proto_reg_handoff_ebhscr(void)
952 {
953 static dissector_handle_t ebhscr_handle;
954
955 can_handle = find_dissector_add_dependency("can-hostendian", proto_ebhscr);
956 can_fd_handle = find_dissector_add_dependency("canfd", proto_ebhscr);
957
958 eth_withfcs_handle = find_dissector_add_dependency("eth_withfcs", proto_ebhscr);
959 eth_withoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_ebhscr);
960 ebhscr_user_handle = find_dissector_add_dependency("ebhscr_user", proto_ebhscr);
961
962 ebhscr_handle = create_dissector_handle( dissect_ebhscr, proto_ebhscr);
963 dissector_add_uint("wtap_encap", WTAP_ENCAP_EBHSCR, ebhscr_handle);
964 }
965
966 /*
967 * Editor modelines - https://www.wireshark.org/tools/modelines.html
968 *
969 * Local variables:
970 * c-basic-offset: 4
971 * tab-width: 8
972 * indent-tabs-mode: nil
973 * End:
974 *
975 * vi: set shiftwidth=4 tabstop=8 expandtab:
976 * :indentSize=4:tabSize=8:noTabs=false:
977 */
978