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