Coverage Report

Created: 2026-03-30 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-flexray.c
Line
Count
Source
1
/* packet-flexray.c
2
 * Routines for FlexRay dissection
3
 * Copyright 2016, Roman Leonhartsberger <ro.leonhartsberger@gmail.com>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include <config.h>
13
14
#include <epan/packet.h>
15
#include <epan/decode_as.h>
16
#include <epan/prefs.h>
17
#include <wiretap/wtap.h>
18
#include <epan/expert.h>
19
#include <epan/uat.h>
20
#include <epan/tfs.h>
21
22
#include "packet-flexray.h"
23
24
25
void proto_reg_handoff_flexray(void);
26
void proto_register_flexray(void);
27
28
static dissector_handle_t flexray_handle;
29
30
static bool prefvar_try_heuristic_first;
31
32
static dissector_table_t subdissector_table;
33
static dissector_table_t flexrayid_subdissector_table;
34
35
static heur_dissector_list_t heur_subdissector_list;
36
static heur_dtbl_entry_t *heur_dtbl_entry;
37
38
static int proto_flexray;
39
static int hf_flexray_measurement_header_field;
40
static int hf_flexray_error_flags_field;
41
static int hf_flexray_frame_header;
42
static int hf_flexray_frame_trailer;
43
44
static int hf_flexray_ti;
45
static int hf_flexray_ch;
46
static int hf_flexray_fcrc_err;
47
static int hf_flexray_hcrc_err;
48
static int hf_flexray_fes_err;
49
static int hf_flexray_cod_err;
50
static int hf_flexray_tss_viol;
51
static int hf_flexray_res;
52
static int hf_flexray_ppi;
53
static int hf_flexray_nfi;
54
static int hf_flexray_sfi;
55
static int hf_flexray_stfi;
56
static int hf_flexray_fid;
57
static int hf_flexray_pl;
58
static int hf_flexray_hcrc;
59
static int hf_flexray_cc;
60
static int hf_flexray_sl;
61
static int hf_flexray_flexray_id;
62
static int hf_flexray_crc;
63
64
static int ett_flexray;
65
static int ett_flexray_measurement_header;
66
static int ett_flexray_error_flags;
67
static int ett_flexray_frame;
68
static int ett_flexray_frame_trailer;
69
70
static int * const error_fields[] = {
71
    &hf_flexray_fcrc_err,
72
    &hf_flexray_hcrc_err,
73
    &hf_flexray_fes_err,
74
    &hf_flexray_cod_err,
75
    &hf_flexray_tss_viol,
76
    NULL
77
};
78
79
static expert_field ei_flexray_frame_payload_truncated;
80
static expert_field ei_flexray_symbol_frame;
81
static expert_field ei_flexray_error_flag;
82
static expert_field ei_flexray_stfi_flag;
83
84
static const value_string flexray_type_names[] = {
85
    { FLEXRAY_FRAME, "FRAME" },
86
    { FLEXRAY_SYMBOL, "SYMB" },
87
    {0, NULL}
88
};
89
90
static const true_false_string flexray_channel_tfs = {
91
    "CHB",
92
    "CHA"
93
};
94
95
static const true_false_string flexray_nfi_tfs = {
96
    "False",
97
    "True"
98
};
99
100
/* Senders and Receivers UAT */
101
typedef struct _sender_receiver_config {
102
    unsigned  bus_id;
103
    unsigned  channel;
104
    unsigned  cycle;
105
    unsigned  frame_id;
106
    char *sender_name;
107
    char *receiver_name;
108
} sender_receiver_config_t;
109
110
14
#define DATAFILE_FR_SENDER_RECEIVER "FR_senders_receivers"
111
112
static GHashTable *data_sender_receiver;
113
static sender_receiver_config_t *sender_receiver_configs;
114
static unsigned sender_receiver_config_num;
115
116
0
UAT_HEX_CB_DEF(sender_receiver_configs, bus_id, sender_receiver_config_t)
Unexecuted instantiation: packet-flexray.c:sender_receiver_configs_bus_id_set_cb
Unexecuted instantiation: packet-flexray.c:sender_receiver_configs_bus_id_tostr_cb
117
0
UAT_HEX_CB_DEF(sender_receiver_configs, channel, sender_receiver_config_t)
Unexecuted instantiation: packet-flexray.c:sender_receiver_configs_channel_set_cb
Unexecuted instantiation: packet-flexray.c:sender_receiver_configs_channel_tostr_cb
118
0
UAT_HEX_CB_DEF(sender_receiver_configs, cycle, sender_receiver_config_t)
Unexecuted instantiation: packet-flexray.c:sender_receiver_configs_cycle_set_cb
Unexecuted instantiation: packet-flexray.c:sender_receiver_configs_cycle_tostr_cb
119
0
UAT_HEX_CB_DEF(sender_receiver_configs, frame_id, sender_receiver_config_t)
Unexecuted instantiation: packet-flexray.c:sender_receiver_configs_frame_id_set_cb
Unexecuted instantiation: packet-flexray.c:sender_receiver_configs_frame_id_tostr_cb
120
0
UAT_CSTRING_CB_DEF(sender_receiver_configs, sender_name, sender_receiver_config_t)
121
0
UAT_CSTRING_CB_DEF(sender_receiver_configs, receiver_name, sender_receiver_config_t)
122
123
static void *
124
0
copy_sender_receiver_config_cb(void *n, const void *o, size_t size _U_) {
125
0
    sender_receiver_config_t *new_rec = (sender_receiver_config_t *)n;
126
0
    const sender_receiver_config_t *old_rec = (const sender_receiver_config_t *)o;
127
128
0
    new_rec->bus_id = old_rec->bus_id;
129
0
    new_rec->channel = old_rec->channel;
130
0
    new_rec->cycle = old_rec->cycle;
131
0
    new_rec->frame_id = old_rec->frame_id;
132
0
    new_rec->sender_name = g_strdup(old_rec->sender_name);
133
0
    new_rec->receiver_name = g_strdup(old_rec->receiver_name);
134
0
    return new_rec;
135
0
}
136
137
static bool
138
0
update_sender_receiver_config(void *r, char **err) {
139
0
    sender_receiver_config_t *rec = (sender_receiver_config_t *)r;
140
141
0
    if (rec->channel > 0x1) {
142
0
        *err = ws_strdup_printf("We currently only support 0 and 1 for Channels (Channel: %i  Frame ID: %i)", rec->channel, rec->frame_id);
143
0
        return false;
144
0
    }
145
146
0
    if (rec->cycle > 0xff) {
147
0
        *err = ws_strdup_printf("We currently only support 8 bit Cycles (Cycle: %i  Frame ID: %i)", rec->cycle, rec->frame_id);
148
0
        return false;
149
0
    }
150
151
0
    if (rec->frame_id > 0xffff) {
152
0
        *err = ws_strdup_printf("We currently only support 16 bit Frame IDs (Cycle: %i  Frame ID: %i)", rec->cycle, rec->frame_id);
153
0
        return false;
154
0
    }
155
156
0
    if (rec->bus_id > 0xffff) {
157
0
        *err = ws_strdup_printf("We currently only support 16 bit bus identifiers (Bus ID: 0x%x)", rec->bus_id);
158
0
        return false;
159
0
    }
160
161
0
    return true;
162
0
}
163
164
static void
165
0
free_sender_receiver_config_cb(void *r) {
166
0
    sender_receiver_config_t *rec = (sender_receiver_config_t *)r;
167
    /* freeing result of g_strdup */
168
0
    g_free(rec->sender_name);
169
0
    rec->sender_name = NULL;
170
0
    g_free(rec->receiver_name);
171
0
    rec->receiver_name = NULL;
172
0
}
173
174
static uint64_t
175
0
sender_receiver_key(uint16_t bus_id, uint8_t channel, uint8_t cycle, uint16_t frame_id) {
176
0
    return ((uint64_t)bus_id << 32) | ((uint64_t)channel << 24) | ((uint64_t)cycle << 16) | frame_id;
177
0
}
178
179
static sender_receiver_config_t *
180
2
ht_lookup_sender_receiver_config(flexray_info_t *flexray_info) {
181
2
    sender_receiver_config_t *tmp;
182
2
    uint64_t                  key;
183
184
2
    if (sender_receiver_configs == NULL || data_sender_receiver == NULL) {
185
2
        return NULL;
186
2
    }
187
188
0
    key = sender_receiver_key(flexray_info->bus_id, flexray_info->ch, flexray_info->cc, flexray_info->id);
189
0
    tmp = (sender_receiver_config_t *)g_hash_table_lookup(data_sender_receiver, &key);
190
191
0
    if (tmp == NULL) {
192
0
        key = sender_receiver_key(0, flexray_info->ch, flexray_info->cc, flexray_info->id);
193
0
        tmp = (sender_receiver_config_t *)g_hash_table_lookup(data_sender_receiver, &key);
194
0
    }
195
196
0
    return tmp;
197
2
}
198
199
static void
200
14
post_update_sender_receiver_cb(void) {
201
    /* destroy old hash table, if it exist */
202
14
    if (data_sender_receiver) {
203
0
        g_hash_table_destroy(data_sender_receiver);
204
0
    }
205
206
    /* create new hash table */
207
14
    data_sender_receiver = g_hash_table_new_full(g_int64_hash, g_int64_equal, g_free, NULL);
208
209
14
    for (unsigned i = 0; i < sender_receiver_config_num; i++) {
210
0
        uint64_t *key = g_new(uint64_t, 1);
211
0
        *key = sender_receiver_key(sender_receiver_configs[i].bus_id, sender_receiver_configs[i].channel,
212
0
                                   sender_receiver_configs[i].cycle, sender_receiver_configs[i].frame_id);
213
0
        g_hash_table_insert(data_sender_receiver, key, &sender_receiver_configs[i]);
214
0
    }
215
14
}
216
217
static void
218
0
reset_sender_receiver_cb(void) {
219
    /* destroy hash table, if it exists */
220
0
    if (data_sender_receiver) {
221
0
        g_hash_table_destroy(data_sender_receiver);
222
0
        data_sender_receiver = NULL;
223
0
    }
224
0
}
225
226
bool
227
2
flexray_set_source_and_destination_columns(packet_info *pinfo, flexray_info_t *flexray_info) {
228
2
    sender_receiver_config_t *tmp = ht_lookup_sender_receiver_config(flexray_info);
229
230
2
    if (tmp != NULL) {
231
        /* remove all addresses to support FlexRay as payload (e.g., TECMP) */
232
0
        clear_address(&pinfo->net_src);
233
0
        clear_address(&pinfo->dl_src);
234
0
        clear_address(&pinfo->src);
235
0
        clear_address(&pinfo->net_dst);
236
0
        clear_address(&pinfo->dl_dst);
237
0
        clear_address(&pinfo->dst);
238
239
0
        col_add_str(pinfo->cinfo, COL_DEF_SRC, tmp->sender_name);
240
0
        col_add_str(pinfo->cinfo, COL_DEF_DST, tmp->receiver_name);
241
0
        return true;
242
0
    }
243
2
    return false;
244
2
}
245
246
uint32_t
247
0
flexray_calc_flexrayid(uint16_t bus_id, uint8_t channel, uint16_t frame_id, uint8_t cycle) {
248
    /* Bus-ID 4bit->4bit | Channel 1bit->4bit | Frame ID 11bit->16bit | Cycle 6bit->8bit */
249
250
0
    return (uint32_t)(bus_id & 0xf) << 28 |
251
0
           (uint32_t)(channel & 0x0f) << 24 |
252
0
           (uint32_t)(frame_id & 0xffff) << 8 |
253
0
           (uint32_t)(cycle & 0xff);
254
0
}
255
256
uint32_t
257
0
flexray_flexrayinfo_to_flexrayid(flexray_info_t *flexray_info) {
258
0
    return flexray_calc_flexrayid(flexray_info->bus_id, flexray_info->ch, flexray_info->id, flexray_info->cc);
259
0
}
260
261
bool
262
0
flexray_call_subdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, flexray_info_t *flexray_info, const bool use_heuristics_first) {
263
0
    uint32_t flexray_id = flexray_flexrayinfo_to_flexrayid(flexray_info);
264
265
    /* lets try an exact match first */
266
0
    if (dissector_try_uint_with_data(flexrayid_subdissector_table, flexray_id, tvb, pinfo, tree, true, flexray_info)) {
267
0
        return true;
268
0
    }
269
270
    /* lets try with BUS-ID = 0 (any) */
271
0
    if (dissector_try_uint_with_data(flexrayid_subdissector_table, flexray_id & ~FLEXRAY_ID_BUS_ID_MASK, tvb, pinfo, tree, true, flexray_info)) {
272
0
        return true;
273
0
    }
274
275
    /* lets try with cycle = 0xff (any) */
276
0
    if (dissector_try_uint_with_data(flexrayid_subdissector_table, flexray_id | FLEXRAY_ID_CYCLE_MASK, tvb, pinfo, tree, true, flexray_info)) {
277
0
        return true;
278
0
    }
279
280
    /* lets try with BUS-ID = 0 (any) and cycle = 0xff (any) */
281
0
    if (dissector_try_uint_with_data(flexrayid_subdissector_table, (flexray_id & ~FLEXRAY_ID_BUS_ID_MASK) | FLEXRAY_ID_CYCLE_MASK, tvb, pinfo, tree, true, flexray_info)) {
282
0
        return true;
283
0
    }
284
285
0
    if (!use_heuristics_first) {
286
0
        if (!dissector_try_payload_with_data(subdissector_table, tvb, pinfo, tree, false, flexray_info)) {
287
0
            if (!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &heur_dtbl_entry, flexray_info)) {
288
0
                return false;
289
0
            }
290
0
        }
291
0
    } else {
292
0
        if (!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &heur_dtbl_entry, flexray_info)) {
293
0
            if (!dissector_try_payload_with_data(subdissector_table, tvb, pinfo, tree, false, flexray_info)) {
294
0
                return false;
295
0
            }
296
0
        }
297
0
    }
298
299
0
    return true;
300
0
}
301
302
void
303
dissect_flexray_frame(tvbuff_t* tvb, tvbuff_t* start_tvb, packet_info* pinfo, proto_tree* tree,
304
0
    proto_tree* flexray_tree, bool call_subdissector, bool flexray_channel_is_b) {
305
0
    proto_item* ti;
306
0
    proto_tree* flexray_frame_tree;
307
0
    uint16_t flexray_id;
308
0
    uint8_t flexray_pl, flexray_cc;
309
0
    bool payload_truncated = false;
310
311
    /* FlexRay Frame [5 Bytes + Payload]*/
312
0
    proto_item* ti_header = proto_tree_add_item(flexray_tree, hf_flexray_frame_header, tvb, 0, -1, ENC_NA);
313
0
    flexray_frame_tree = proto_item_add_subtree(ti_header, ett_flexray_frame);
314
315
0
    bool nfi, sfi, stfi;
316
0
    proto_tree_add_item(flexray_frame_tree, hf_flexray_res, tvb, 0, 1, ENC_NA);
317
0
    proto_tree_add_item(flexray_frame_tree, hf_flexray_ppi, tvb, 0, 1, ENC_NA);
318
0
    proto_tree_add_item_ret_boolean(flexray_frame_tree, hf_flexray_nfi, tvb, 0, 1, ENC_NA, &nfi);
319
0
    proto_tree_add_item_ret_boolean(flexray_frame_tree, hf_flexray_sfi, tvb, 0, 1, ENC_NA, &sfi);
320
0
    proto_tree_add_item_ret_boolean(flexray_frame_tree, hf_flexray_stfi, tvb, 0, 1, ENC_NA, &stfi);
321
322
0
    if (stfi && !sfi) {
323
0
        expert_add_info(pinfo, flexray_frame_tree, &ei_flexray_stfi_flag);
324
0
        call_subdissector = false;
325
0
    }
326
327
0
    proto_tree_add_item_ret_uint16(flexray_frame_tree, hf_flexray_fid, tvb, 0, 2, ENC_BIG_ENDIAN, &flexray_id);
328
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " ID %4d", flexray_id);
329
330
0
    if (flexray_id == 0) {
331
0
        call_subdissector = false;
332
0
    }
333
334
0
    proto_tree_add_item_ret_uint8(flexray_frame_tree, hf_flexray_pl, tvb, 2, 1, ENC_BIG_ENDIAN, &flexray_pl);
335
0
    int flexray_real_payload_length = 2 * flexray_pl;
336
0
    int flexray_current_payload_length = tvb_captured_length(tvb) - FLEXRAY_HEADER_LENGTH;
337
0
    if (flexray_real_payload_length > flexray_current_payload_length) {
338
0
        payload_truncated = true;
339
0
        flexray_real_payload_length = MAX(0, flexray_current_payload_length);
340
0
    }
341
342
0
    proto_tree_add_item(flexray_frame_tree, hf_flexray_hcrc, tvb, 2, 3, ENC_BIG_ENDIAN);
343
344
0
    proto_tree_add_item_ret_uint8(flexray_frame_tree, hf_flexray_cc, tvb, 4, 1, ENC_BIG_ENDIAN, &flexray_cc);
345
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " CC %2d", flexray_cc);
346
347
0
    if (nfi) {
348
0
        if (payload_truncated) {
349
0
            expert_add_info(pinfo, flexray_frame_tree, &ei_flexray_frame_payload_truncated);
350
0
            call_subdissector = false;
351
0
        }
352
353
0
        if (tvb != NULL && flexray_real_payload_length > 0) {
354
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "   %s", tvb_bytes_to_str_punct(pinfo->pool, tvb, 5, flexray_real_payload_length, ' '));
355
0
        }
356
357
0
    }
358
0
    else {
359
0
        call_subdissector = false;
360
0
        col_append_str(pinfo->cinfo, COL_INFO, "   NF");
361
362
        /* Payload is optional on Null Frames */
363
0
        if (payload_truncated && flexray_real_payload_length != 0) {
364
0
            expert_add_info(pinfo, flexray_frame_tree, &ei_flexray_frame_payload_truncated);
365
0
        }
366
0
    }
367
368
0
    proto_item_set_end(ti_header, tvb, FLEXRAY_HEADER_LENGTH);
369
370
0
    if (flexray_current_payload_length > flexray_real_payload_length) {
371
0
        int trailer_len = flexray_current_payload_length - flexray_real_payload_length;
372
0
        proto_item* ti_trailer = proto_tree_add_item(flexray_tree, hf_flexray_frame_trailer, tvb, FLEXRAY_HEADER_LENGTH + flexray_real_payload_length, trailer_len, ENC_NA);
373
0
        proto_tree* flexray_trailer = proto_item_add_subtree(ti_trailer, ett_flexray_frame_trailer);
374
0
        proto_tree_add_item(flexray_trailer, hf_flexray_crc, tvb, FLEXRAY_HEADER_LENGTH + flexray_real_payload_length, 3, ENC_BIG_ENDIAN);
375
0
    }
376
377
    /* Only supporting single bus id right now */
378
0
    flexray_info_t flexray_info = { .id = flexray_id,
379
0
                                    .cc = flexray_cc,
380
0
                                    .ch = flexray_channel_is_b ? 1 : 0,
381
0
                                    .bus_id = 0 };
382
383
0
    if (start_tvb) {
384
0
        ti = proto_tree_add_uint(flexray_frame_tree, hf_flexray_flexray_id, start_tvb, 0, 7, flexray_flexrayinfo_to_flexrayid(&flexray_info));
385
0
        proto_item_set_hidden(ti);
386
0
    }
387
0
    flexray_set_source_and_destination_columns(pinfo, &flexray_info);
388
389
0
    if (flexray_real_payload_length > 0) {
390
0
        tvbuff_t* next_tvb = tvb_new_subset_length(tvb, FLEXRAY_HEADER_LENGTH, flexray_real_payload_length);
391
0
        if (!call_subdissector || !flexray_call_subdissectors(next_tvb, pinfo, tree, &flexray_info, prefvar_try_heuristic_first)) {
392
0
            call_data_dissector(next_tvb, pinfo, tree);
393
0
        }
394
0
    }
395
0
}
396
397
static int
398
0
dissect_flexray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
399
0
    proto_item *ti;
400
0
    proto_tree *flexray_tree, *measurement_tree;
401
402
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FLEXRAY");
403
0
    col_clear(pinfo->cinfo, COL_INFO);
404
405
0
    ti = proto_tree_add_item(tree, proto_flexray, tvb, 0, -1, ENC_NA);
406
0
    flexray_tree = proto_item_add_subtree(ti, ett_flexray);
407
408
    /* Measurement Header [1 Byte] */
409
0
    ti = proto_tree_add_item(flexray_tree, hf_flexray_measurement_header_field, tvb, 0, 1, ENC_BIG_ENDIAN);
410
0
    measurement_tree = proto_item_add_subtree(ti, ett_flexray_measurement_header);
411
412
0
    bool flexray_channel_is_b;
413
0
    proto_tree_add_item_ret_boolean(measurement_tree, hf_flexray_ch, tvb, 0, 1, ENC_BIG_ENDIAN, &flexray_channel_is_b);
414
415
0
    uint32_t frame_type;
416
0
    proto_tree_add_item_ret_uint(measurement_tree, hf_flexray_ti, tvb, 0, 1, ENC_BIG_ENDIAN, &frame_type);
417
0
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s:", val_to_str(pinfo->pool, frame_type, flexray_type_names, "Unknown (0x%02x)"));
418
419
0
    if (frame_type == FLEXRAY_FRAME) {
420
0
        proto_tree* error_flags_tree;
421
0
        bool call_subdissector = true;
422
423
        /* Error Flags [1 Byte] */
424
0
        ti = proto_tree_add_bitmask(flexray_tree, tvb, 1, hf_flexray_error_flags_field, ett_flexray_error_flags, error_fields, ENC_BIG_ENDIAN);
425
0
        error_flags_tree = proto_item_add_subtree(ti, ett_flexray_error_flags);
426
427
0
        uint8_t error_flags = tvb_get_uint8(tvb, 1) & 0x1f;
428
0
        if (error_flags) {
429
0
            expert_add_info(pinfo, error_flags_tree, &ei_flexray_error_flag);
430
0
            call_subdissector = false;
431
0
        }
432
433
0
        dissect_flexray_frame(tvb_new_subset_remaining(tvb, 2), tvb, pinfo, tree, flexray_tree, call_subdissector, flexray_channel_is_b);
434
0
    } else if (frame_type == FLEXRAY_SYMBOL) {
435
        /* FlexRay Symbol [1 Byte] */
436
0
        expert_add_info(pinfo, flexray_tree, &ei_flexray_symbol_frame);
437
438
0
        uint32_t symbol_length;
439
0
        proto_tree_add_item_ret_uint(flexray_tree, hf_flexray_sl, tvb, 1, 1, ENC_BIG_ENDIAN, &symbol_length);
440
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " SL %3d", symbol_length);
441
0
    }
442
443
0
    return tvb_captured_length(tvb);
444
0
}
445
446
void
447
14
proto_register_flexray(void) {
448
14
    module_t *flexray_module;
449
14
    expert_module_t *expert_flexray;
450
14
    uat_t  *sender_receiver_uat = NULL;
451
452
14
    static hf_register_info hf[] = {
453
14
        { &hf_flexray_measurement_header_field, {
454
14
            "Measurement Header", "flexray.mhf", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
455
14
        { &hf_flexray_ti, {
456
14
            "Type Index", "flexray.ti", FT_UINT8, BASE_HEX, VALS(flexray_type_names), FLEXRAY_TYPE_MASK, NULL, HFILL } },
457
14
        { &hf_flexray_ch, {
458
14
            "Channel", "flexray.ch", FT_BOOLEAN, 8, TFS(&flexray_channel_tfs), FLEXRAY_CHANNEL_MASK, NULL, HFILL } },
459
14
        { &hf_flexray_error_flags_field, {
460
14
            "Error Flags", "flexray.eff", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
461
14
        { &hf_flexray_fcrc_err, {
462
14
            "Frame CRC error", "flexray.fcrc_err", FT_BOOLEAN, 8, NULL, FLEXRAY_FCRC_ERROR, NULL, HFILL } },
463
14
        { &hf_flexray_hcrc_err, {
464
14
            "Header CRC error", "flexray.hcrc_err", FT_BOOLEAN, 8, NULL, FLEXRAY_HCRC_ERROR, NULL, HFILL } },
465
14
        { &hf_flexray_fes_err, {
466
14
            "Frame End Sequence error", "flexray.fes_err", FT_BOOLEAN, 8, NULL, FLEXRAY_FES_ERROR, NULL, HFILL } },
467
14
        { &hf_flexray_cod_err, {
468
14
            "Coding error", "flexray.cod_err", FT_BOOLEAN, 8, NULL, FLEXRAY_COD_ERROR, NULL, HFILL } },
469
14
        { &hf_flexray_tss_viol, {
470
14
            "TSS violation", "flexray.tss_viol", FT_BOOLEAN, 8, NULL, FLEXRAY_TSS_ERROR, NULL, HFILL } },
471
14
        { &hf_flexray_frame_header, {
472
14
            "FlexRay Frame Header", "flexray.frame_header", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
473
14
        { &hf_flexray_res, {
474
14
            "Reserved", "flexray.res", FT_BOOLEAN, 8, NULL, FLEXRAY_RES_MASK, NULL, HFILL } },
475
14
        { &hf_flexray_ppi, {
476
14
            "Payload Preamble Indicator", "flexray.ppi", FT_BOOLEAN, 8, NULL, FLEXRAY_PPI_MASK, NULL, HFILL } },
477
14
        { &hf_flexray_nfi, {
478
14
            "Null Frame Indicator", "flexray.nfi", FT_BOOLEAN, 8, TFS(&flexray_nfi_tfs), FLEXRAY_NFI_MASK, NULL, HFILL } },
479
14
        { &hf_flexray_sfi, {
480
14
            "Sync Frame Indicator", "flexray.sfi", FT_BOOLEAN, 8, NULL, FLEXRAY_SFI_MASK, NULL, HFILL } },
481
14
        { &hf_flexray_stfi, {
482
14
            "Startup Frame Indicator", "flexray.stfi", FT_BOOLEAN, 8, NULL, FLEXRAY_STFI_MASK, NULL, HFILL } },
483
14
        { &hf_flexray_fid, {
484
14
            "Frame ID", "flexray.fid", FT_UINT16, BASE_DEC, NULL, FLEXRAY_ID_MASK, NULL, HFILL } },
485
14
        { &hf_flexray_pl, {
486
14
            "Payload length", "flexray.pl", FT_UINT8, BASE_DEC, NULL, FLEXRAY_LENGTH_MASK, NULL, HFILL } },
487
14
        { &hf_flexray_hcrc, {
488
14
            "Header CRC", "flexray.hcrc", FT_UINT24, BASE_HEX, NULL, FLEXRAY_HEADER_CRC_MASK, NULL, HFILL } },
489
14
        { &hf_flexray_cc, {
490
14
            "Cycle Counter", "flexray.cc", FT_UINT8, BASE_DEC, NULL, FLEXRAY_CC_MASK, NULL, HFILL } },
491
14
        { &hf_flexray_sl, {
492
14
            "Symbol length", "flexray.sl", FT_UINT8, BASE_DEC, NULL, 0x7f, NULL, HFILL } },
493
14
        { &hf_flexray_flexray_id, {
494
14
            "FlexRay ID (combined)", "flexray.combined_id", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
495
14
        { &hf_flexray_frame_trailer, {
496
14
            "FlexRay Frame Trailer", "flexray.frame_trailer", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
497
14
        { &hf_flexray_crc, {
498
14
            "CRC", "flexray.crc", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL } },
499
14
    };
500
501
14
    static int *ett[] = {
502
14
        &ett_flexray,
503
14
        &ett_flexray_measurement_header,
504
14
        &ett_flexray_error_flags,
505
14
        &ett_flexray_frame,
506
14
        &ett_flexray_frame_trailer
507
14
    };
508
509
14
    static ei_register_info ei[] = {
510
14
        { &ei_flexray_frame_payload_truncated, {
511
14
            "flexray.malformed_frame_payload_truncated", PI_MALFORMED, PI_ERROR, "Truncated Frame Payload", EXPFILL } },
512
14
        { &ei_flexray_symbol_frame, {
513
14
            "flexray.symbol_frame", PI_SEQUENCE, PI_CHAT, "Packet is a Symbol Frame", EXPFILL } },
514
14
        { &ei_flexray_error_flag, {
515
14
            "flexray.error_flag", PI_PROTOCOL, PI_WARN, "One or more Error Flags set", EXPFILL } },
516
14
        { &ei_flexray_stfi_flag, {
517
14
            "flexray.stfi_flag", PI_PROTOCOL, PI_WARN, "A startup frame must always be a sync frame", EXPFILL } }
518
14
    };
519
520
14
    proto_flexray = proto_register_protocol("FlexRay Protocol", "FLEXRAY", "flexray");
521
522
14
    flexray_module = prefs_register_protocol(proto_flexray, NULL);
523
524
14
    proto_register_field_array(proto_flexray, hf, array_length(hf));
525
14
    proto_register_subtree_array(ett, array_length(ett));
526
527
14
    expert_flexray = expert_register_protocol(proto_flexray);
528
14
    expert_register_field_array(expert_flexray, ei, array_length(ei));
529
530
14
    flexray_handle = register_dissector("flexray", dissect_flexray, proto_flexray);
531
532
14
    prefs_register_bool_preference(flexray_module, "try_heuristic_first", "Try heuristic sub-dissectors first",
533
14
        "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to \"decode as\"",
534
14
        &prefvar_try_heuristic_first
535
14
    );
536
537
14
    static uat_field_t sender_receiver_mapping_uat_fields[] = {
538
14
        UAT_FLD_HEX(sender_receiver_configs,     bus_id,        "Bus ID",        "Bus ID of the Interface with 0 meaning any(hex uint16 without leading 0x)."),
539
14
        UAT_FLD_HEX(sender_receiver_configs,     channel,       "Channel",       "Channel (8bit hex without leading 0x)"),
540
14
        UAT_FLD_HEX(sender_receiver_configs,     cycle,         "Cycle",         "Cycle (8bit hex without leading 0x)"),
541
14
        UAT_FLD_HEX(sender_receiver_configs,     frame_id,      "Frame ID",      "Frame ID (16bit hex without leading 0x)"),
542
14
        UAT_FLD_CSTRING(sender_receiver_configs, sender_name,   "Sender Name",   "Name of Sender(s)"),
543
14
        UAT_FLD_CSTRING(sender_receiver_configs, receiver_name, "Receiver Name", "Name of Receiver(s)"),
544
14
        UAT_END_FIELDS
545
14
    };
546
547
14
    sender_receiver_uat = uat_new("Sender Receiver Config",
548
14
        sizeof(sender_receiver_config_t),   /* record size           */
549
14
        DATAFILE_FR_SENDER_RECEIVER,        /* filename              */
550
14
        true,                               /* from profile          */
551
14
        (void**)&sender_receiver_configs,   /* data_ptr              */
552
14
        &sender_receiver_config_num,        /* numitems_ptr          */
553
14
        UAT_AFFECTS_DISSECTION,             /* but not fields        */
554
14
        NULL,                               /* help                  */
555
14
        copy_sender_receiver_config_cb,     /* copy callback         */
556
14
        update_sender_receiver_config,      /* update callback       */
557
14
        free_sender_receiver_config_cb,     /* free callback         */
558
14
        post_update_sender_receiver_cb,     /* post update callback  */
559
14
        reset_sender_receiver_cb,           /* reset callback        */
560
14
        sender_receiver_mapping_uat_fields  /* UAT field definitions */
561
14
    );
562
563
14
    prefs_register_uat_preference(flexray_module, "_sender_receiver_config", "Sender Receiver Config",
564
14
        "A table to define the mapping between Bus ID and CAN ID to Sender and Receiver.", sender_receiver_uat);
565
566
14
    subdissector_table = register_decode_as_next_proto(proto_flexray, "flexray.subdissector", "FLEXRAY next level dissector", NULL);
567
14
    flexrayid_subdissector_table = register_dissector_table("flexray.combined_id", "FlexRay ID (combined)", proto_flexray, FT_UINT32, BASE_HEX);
568
14
    heur_subdissector_list = register_heur_dissector_list_with_description("flexray", "FlexRay info", proto_flexray);
569
14
}
570
571
void
572
14
proto_reg_handoff_flexray(void) {
573
14
    dissector_add_uint("wtap_encap", WTAP_ENCAP_FLEXRAY, flexray_handle);
574
14
}
575
576
/*
577
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
578
 *
579
 * Local variables:
580
 * c-basic-offset: 4
581
 * tab-width: 8
582
 * indent-tabs-mode: nil
583
 * End:
584
 *
585
 * vi: set shiftwidth=4 tabstop=8 expandtab:
586
 * :indentSize=4:tabSize=8:noTabs=true:
587
 */