2 * Signal PDU dissector.
3 * By Dr. Lars Voelker <lars.voelker@technica-engineering.de>
4 * Copyright 2020-2023 Dr. Lars Voelker
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
12 * This dissector allows Signal PDUs (e.g. CAN or FlexRay) to be dissected into signals (automotive use case).
14 * This feature is based on typical operations of signal messages:
15 * - Scaling/Offset: Move the value by multiplying with scaler and moving by adding offset. (compu methods).
16 * - Multiplexer: A signal in the PDU determines, what signals follow.
17 * - Value names: Giving raw values names.
22 #include <epan/packet.h>
23 #include <epan/prefs.h>
24 #include <epan/expert.h>
25 #include <epan/to_str.h>
27 #include <epan/proto_data.h>
29 #include <wsutil/sign_ext.h>
31 #include "packet-someip.h"
32 #include "packet-socketcan.h"
33 #include "packet-flexray.h"
34 #include "packet-pdu-transport.h"
35 #include "packet-lin.h"
36 #include "packet-autosar-ipdu-multiplexer.h"
37 #include "packet-dlt.h"
38 #include "packet-uds.h"
39 #include "packet-isobus.h"
42 * Dissector for CAN, FlexRay, and other message payloads.
43 * This includes such PDUs being transported on top of TECMP,
44 * SOME/IP, and others.
47 #define SPDU_NAME "Signal PDU"
48 #define SPDU_NAME_LONG "Signal PDU"
49 #define SPDU_NAME_FILTER "signal_pdu"
52 /*** Configuration ***/
54 /* Define the Signal PDUs and their IDs and Names. */
55 #define DATAFILE_SPDU_MESSAGES "Signal_PDU_identifiers"
56 /* Define how to parse Signal PDUs into Signals. */
57 #define DATAFILE_SPDU_SIGNALS "Signal_PDU_signal_list"
58 /* Define enumeration for signal values. */
59 #define DATAFILE_SPDU_VALUE_NAMES "Signal_PDU_signal_values"
61 /* Using the following config files the payloads of different protocols are mapped to Signal PDU IDs: */
62 #define DATAFILE_SPDU_SOMEIP_MAPPING "Signal_PDU_Binding_SOMEIP"
63 #define DATAFILE_SPDU_CAN_MAPPING "Signal_PDU_Binding_CAN"
64 #define DATAFILE_SPDU_FLEXRAY_MAPPING "Signal_PDU_Binding_FlexRay"
65 #define DATAFILE_SPDU_LIN_MAPPING "Signal_PDU_Binding_LIN"
66 #define DATAFILE_SPDU_PDU_TRANSPORT_MAPPING "Signal_PDU_Binding_PDU_Transport"
67 #define DATAFILE_SPDU_IPDUM_MAPPING "Signal_PDU_Binding_AUTOSAR_IPduM"
68 #define DATAFILE_SPDU_DLT_MAPPING "Signal_PDU_Binding_DLT"
69 #define DATAFILE_SPDU_UDS_MAPPING "Signal_PDU_Binding_UDS"
70 #define DATAFILE_SPDU_ISOBUS_MAPPING "Signal_PDU_Binding_ISOBUS"
72 /* ID wireshark identifies the dissector by */
73 static int proto_signal_pdu
;
75 static dissector_handle_t signal_pdu_handle_someip
;
76 static dissector_handle_t signal_pdu_handle_can
;
77 static dissector_handle_t signal_pdu_handle_flexray
;
78 static dissector_handle_t signal_pdu_handle_lin
;
79 static dissector_handle_t signal_pdu_handle_pdu_transport
;
80 static dissector_handle_t signal_pdu_handle_ipdum
;
81 static dissector_handle_t signal_pdu_handle_isobus
;
83 static int hf_pdu_name
;
84 static int hf_payload_unparsed
;
86 static int ett_spdu_payload
;
87 static int ett_spdu_signal
;
88 static bool spdu_deserializer_activated
= true;
89 static bool spdu_deserializer_show_hidden
;
90 static bool spdu_deserializer_hide_raw_values
= true;
92 /*** expert info items ***/
93 static expert_field ei_spdu_payload_truncated
;
94 static expert_field ei_spdu_config_error
;
95 static expert_field ei_spdu_unaligned_data
;
97 /*** Data Structure for UAT based config ***/
98 static GHashTable
*data_spdu_messages
;
100 static GHashTable
*data_spdu_signal_list
;
101 static GHashTable
*data_spdu_signal_value_names
;
103 static GHashTable
*data_spdu_someip_mappings
;
104 static GHashTable
*data_spdu_can_mappings
;
105 static GHashTable
*data_spdu_flexray_mappings
;
106 static GHashTable
*data_spdu_lin_mappings
;
107 static GHashTable
*data_spdu_pdu_transport_mappings
;
108 static GHashTable
*data_spdu_ipdum_mappings
;
109 static GHashTable
*data_spdu_dlt_mappings
;
110 static GHashTable
*data_spdu_uds_mappings
;
111 static GHashTable
*data_spdu_isobus_mappings
;
113 static hf_register_info
*dynamic_hf_base_raw
;
114 static hf_register_info
*dynamic_hf_agg_sum
;
115 static hf_register_info
*dynamic_hf_agg_avg
;
116 static hf_register_info
*dynamic_hf_agg_int
;
117 static unsigned dynamic_hf_number_of_entries
;
118 static unsigned dynamic_hf_base_raw_number
;
119 static unsigned dynamic_hf_agg_sum_number
;
120 static unsigned dynamic_hf_agg_avg_number
;
121 static unsigned dynamic_hf_agg_int_number
;
123 #define HF_TYPE_BASE 0
124 #define HF_TYPE_RAW 1
125 #define HF_TYPE_AGG_SUM 2
126 #define HF_TYPE_AGG_AVG 3
127 #define HF_TYPE_AGG_INT 4
128 #define HF_TYPE_NONE 0xffff
130 #define HF_TYPE_COUNT_BASE_RAW_TABLE 2
133 /***********************************************
134 ********* Preferences / Configuration *********
135 ***********************************************/
137 typedef struct _generic_one_id_string
{
140 } generic_one_id_string_t
;
142 typedef enum _spdu_data_type
{
146 SPDU_DATA_TYPE_FLOAT
,
147 SPDU_DATA_TYPE_STRING
,
148 SPDU_DATA_TYPE_STRINGZ
,
149 SPDU_DATA_TYPE_UINT_STRING
,
152 typedef struct _spdu_signal_value_name_item
{
153 uint64_t value_start
;
156 } spdu_signal_value_name_item_t
;
158 #define INIT_SIGNAL_VALUE_NAME_ITEM(NAME) \
159 (NAME)->value_start = 0; \
160 (NAME)->value_end = 0; \
163 typedef struct _spdu_signal_value_name
{
165 uint32_t num_of_items
;
169 spdu_signal_value_name_item_t
* items
;
170 } spdu_signal_value_name_t
;
172 #define INIT_SIGNAL_VALUE_NAME(NAME) \
175 (NAME)->num_of_items = 0; \
177 (NAME)->items = NULL;
179 typedef struct _spdu_signal_item
{
184 uint32_t bitlength_base_type
;
185 uint32_t bitlength_encoded_type
;
186 bool scale_or_offset
;
190 int multiplex_value_only
;
198 int *hf_id_effective
;
204 spdu_signal_value_name_t
* sig_val_names
;
205 bool sig_val_names_valid
;
206 } spdu_signal_item_t
;
208 typedef struct _spdu_signal_list
{
210 uint32_t num_of_items
;
213 spdu_signal_item_t
*items
;
214 } spdu_signal_list_t
;
216 typedef struct _spdu_signal_list_uat
{
218 uint32_t num_of_params
;
225 uint32_t bitlength_base_type
;
226 uint32_t bitlength_encoded_type
;
230 int multiplex_value_only
;
235 } spdu_signal_list_uat_t
;
237 typedef struct _spdu_signal_value_name_uat
{
240 uint32_t num_of_items
;
241 uint64_t value_start
;
244 } spdu_signal_value_name_uat_t
;
247 typedef struct _spdu_someip_mapping
{
250 uint32_t major_version
;
251 uint32_t message_type
;
253 uint32_t spdu_message_id
;
254 } spdu_someip_mapping_t
;
256 #define INIT_SOMEIP_MAPPING(NAME) \
257 (NAME)->service_id = 0; \
258 (NAME)->method_id = 0; \
259 (NAME)->major_version = 0; \
260 (NAME)->message_type = 0; \
261 (NAME)->message_id = 0;
263 typedef spdu_someip_mapping_t spdu_someip_mapping_uat_t
;
266 typedef struct _spdu_can_mapping
{
270 } spdu_can_mapping_t
;
271 typedef spdu_can_mapping_t spdu_can_mapping_uat_t
;
274 typedef struct _spdu_flexray_mapping
{
279 } spdu_flexray_mapping_t
;
280 typedef spdu_flexray_mapping_t spdu_flexray_mapping_uat_t
;
283 typedef struct _spdu_lin_mapping
{
287 } spdu_lin_mapping_t
;
288 typedef spdu_lin_mapping_t spdu_lin_mapping_uat_t
;
291 typedef struct _spdu_pdu_transport_mapping
{
294 } spdu_pdu_transport_mapping_t
;
295 typedef spdu_pdu_transport_mapping_t spdu_pdu_transport_mapping_uat_t
;
298 typedef struct _spdu_ipdum_mapping
{
301 } spdu_ipdum_mapping_t
;
302 typedef spdu_ipdum_mapping_t spdu_ipdum_mapping_uat_t
;
305 typedef struct _spdu_dlt_mapping
{
307 uint32_t dlt_message_id
;
309 } spdu_dlt_mapping_t
;
310 typedef spdu_dlt_mapping_t spdu_dlt_mapping_uat_t
;
313 typedef struct _spdu_uds_mapping
{
314 uint32_t uds_address
;
319 } spdu_uds_mapping_t
;
320 typedef spdu_uds_mapping_t spdu_uds_mapping_uat_t
;
323 typedef struct _spdu_isobus_mapping
{
327 } spdu_isobus_mapping_t
;
328 typedef spdu_isobus_mapping_t spdu_isobus_mapping_uat_t
;
331 static generic_one_id_string_t
*spdu_message_ident
;
332 static unsigned spdu_message_ident_num
;
334 static spdu_signal_list_uat_t
*spdu_signal_list
;
335 static unsigned spdu_signal_list_num
;
337 static spdu_signal_value_name_uat_t
*spdu_signal_value_names
;
338 static unsigned spdu_parameter_value_names_num
;
340 static spdu_someip_mapping_t
*spdu_someip_mapping
;
341 static unsigned spdu_someip_mapping_num
;
343 static spdu_can_mapping_t
*spdu_can_mapping
;
344 static unsigned spdu_can_mapping_num
;
346 static spdu_flexray_mapping_t
*spdu_flexray_mapping
;
347 static unsigned spdu_flexray_mapping_num
;
349 static spdu_lin_mapping_t
*spdu_lin_mapping
;
350 static unsigned spdu_lin_mapping_num
;
352 static spdu_pdu_transport_mapping_t
*spdu_pdu_transport_mapping
;
353 static unsigned spdu_pdu_transport_mapping_num
;
355 static spdu_ipdum_mapping_t
*spdu_ipdum_mapping
;
356 static unsigned spdu_ipdum_mapping_num
;
358 static spdu_dlt_mapping_t
*spdu_dlt_mapping
;
359 static unsigned spdu_dlt_mapping_num
;
361 static spdu_uds_mapping_t
*spdu_uds_mapping
;
362 static unsigned spdu_uds_mapping_num
;
364 static spdu_isobus_mapping_t
*spdu_isobus_mapping
;
365 static unsigned spdu_isobus_mapping_num
;
367 void proto_register_signal_pdu(void);
368 void proto_reg_handoff_signal_pdu(void);
371 register_signal_pdu_can(void) {
372 if (signal_pdu_handle_can
== NULL
) {
376 dissector_delete_all("can.id", signal_pdu_handle_can
);
377 dissector_delete_all("can.extended_id", signal_pdu_handle_can
);
379 /* CAN: loop over all frame IDs in HT */
380 if (data_spdu_can_mappings
!= NULL
) {
381 GList
*keys
= g_hash_table_get_keys(data_spdu_can_mappings
);
384 for (tmp
= keys
; tmp
!= NULL
; tmp
= tmp
->next
) {
385 int32_t id
= (*(int32_t *)tmp
->data
);
387 if ((id
& CAN_EFF_FLAG
) == CAN_EFF_FLAG
) {
388 dissector_add_uint("can.extended_id", id
& CAN_EFF_MASK
, signal_pdu_handle_can
);
390 dissector_add_uint("can.id", id
& CAN_SFF_MASK
, signal_pdu_handle_can
);
399 register_signal_pdu_lin(void) {
400 if (signal_pdu_handle_lin
== NULL
) {
404 dissector_delete_all("lin.frame_id", signal_pdu_handle_lin
);
406 /* LIN: loop over all frame IDs in HT */
407 if (data_spdu_lin_mappings
!= NULL
) {
408 GList
*keys
= g_hash_table_get_keys(data_spdu_lin_mappings
);
411 for (tmp
= keys
; tmp
!= NULL
; tmp
= tmp
->next
) {
412 int32_t *id
= (int32_t *)tmp
->data
;
413 /* we register the combination of bus and frame id */
414 dissector_add_uint("lin.frame_id", *id
, signal_pdu_handle_lin
);
422 register_signal_pdu_someip(void) {
423 if (signal_pdu_handle_someip
== NULL
) {
427 dissector_delete_all("someip.messageid", signal_pdu_handle_someip
);
429 /* SOME/IP: loop over all messages IDs in HT */
430 if (data_spdu_someip_mappings
!= NULL
) {
431 GList
*keys
= g_hash_table_get_keys(data_spdu_someip_mappings
);
434 for (tmp
= keys
; tmp
!= NULL
; tmp
= tmp
->next
) {
435 int64_t *id
= (int64_t *)tmp
->data
;
436 uint32_t message_id
= (uint32_t)((uint64_t)(*id
)) & 0xffffffff;
437 dissector_add_uint("someip.messageid", message_id
, signal_pdu_handle_someip
);
445 register_signal_pdu_pdu_transport(void) {
446 if (signal_pdu_handle_pdu_transport
== NULL
) {
450 dissector_delete_all("pdu_transport.id", signal_pdu_handle_pdu_transport
);
452 /* PDU Transport: loop over all messages IDs in HT */
453 if (data_spdu_pdu_transport_mappings
!= NULL
) {
454 GList
*keys
= g_hash_table_get_keys(data_spdu_pdu_transport_mappings
);
457 for (tmp
= keys
; tmp
!= NULL
; tmp
= tmp
->next
) {
458 int64_t *id
= (int64_t *)tmp
->data
;
459 dissector_add_uint("pdu_transport.id", ((uint32_t)((uint64_t)(*id
)) & 0xffffffff), signal_pdu_handle_pdu_transport
);
467 register_signal_pdu_ipdum(void) {
468 if (signal_pdu_handle_ipdum
== NULL
) {
472 dissector_delete_all("ipdum.pdu.id", signal_pdu_handle_ipdum
);
474 /* IPduM: loop over all messages IDs in HT */
475 if (data_spdu_ipdum_mappings
!= NULL
) {
476 GList
*keys
= g_hash_table_get_keys(data_spdu_ipdum_mappings
);
479 for (tmp
= keys
; tmp
!= NULL
; tmp
= tmp
->next
) {
480 int64_t *id
= (int64_t *)tmp
->data
;
481 dissector_add_uint("ipdum.pdu.id", ((uint32_t)((uint64_t)(*id
)) & 0xffffffff), signal_pdu_handle_ipdum
);
489 register_signal_pdu_isobus(void) {
490 if (signal_pdu_handle_isobus
== NULL
) {
494 dissector_delete_all("isobus.pgn", signal_pdu_handle_isobus
);
496 /* ISOBUS: loop over all messages IDs in HT */
497 if (data_spdu_isobus_mappings
!= NULL
) {
498 GList
*keys
= g_hash_table_get_keys(data_spdu_isobus_mappings
);
501 for (tmp
= keys
; tmp
!= NULL
; tmp
= tmp
->next
) {
502 int64_t *id
= (int64_t *)tmp
->data
;
503 dissector_add_uint("isobus.pgn", ((uint32_t)((uint64_t)(*id
)) & 0xffffffff), signal_pdu_handle_isobus
);
510 /*** UAT Callbacks and Helpers ***/
512 spdu_payload_free_key(void *key
) {
513 wmem_free(wmem_epan_scope(), key
);
517 spdu_payload_free_generic_data(void *data _U_
) {
518 /* currently nothing to be free */
523 copy_generic_one_id_string_cb(void *n
, const void *o
, size_t size _U_
) {
524 generic_one_id_string_t
*new_rec
= (generic_one_id_string_t
*)n
;
525 const generic_one_id_string_t
*old_rec
= (const generic_one_id_string_t
*)o
;
527 if (old_rec
->name
== NULL
) {
528 new_rec
->name
= NULL
;
530 new_rec
->name
= g_strdup(old_rec
->name
);
533 new_rec
->id
= old_rec
->id
;
538 update_generic_one_identifier_32bit(void *r
, char **err
) {
539 generic_one_id_string_t
*rec
= (generic_one_id_string_t
*)r
;
541 if (rec
->id
> 0xffffffff) {
542 *err
= ws_strdup_printf("We currently only support 32 bit identifiers (ID: %i Name: %s)", rec
->id
, rec
->name
);
546 if (rec
->name
== NULL
|| rec
->name
[0] == 0) {
547 *err
= g_strdup("Name cannot be empty");
551 unsigned char c
= proto_check_field_name(rec
->name
);
554 *err
= ws_strdup_printf("Name contains illegal chars '.' (ID: 0x%08x)", rec
->id
);
555 } else if (g_ascii_isprint(c
)) {
556 *err
= ws_strdup_printf("Name contains illegal chars '%c' (ID: 0x%08x)", c
, rec
->id
);
558 *err
= ws_strdup_printf("Name contains invalid byte \\%03o (ID: 0x%08x)", c
, rec
->id
);
567 free_generic_one_id_string_cb(void *r
) {
568 generic_one_id_string_t
*rec
= (generic_one_id_string_t
*)r
;
570 /* freeing result of g_strdup */
576 post_update_one_id_string_template_cb(generic_one_id_string_t
*data
, unsigned data_num
, GHashTable
*ht
) {
578 for (i
= 0; i
< data_num
; i
++) {
579 int *key
= wmem_new(wmem_epan_scope(), int);
582 g_hash_table_insert(ht
, key
, g_strdup(data
[i
].name
));
587 /*** Signal PDU Messages ***/
588 UAT_HEX_CB_DEF(spdu_message_ident
, id
, generic_one_id_string_t
)
589 UAT_CSTRING_CB_DEF(spdu_message_ident
, name
, generic_one_id_string_t
)
592 post_update_spdu_message_cb(void) {
593 /* destroy old hash table, if it exists */
594 if (data_spdu_messages
) {
595 g_hash_table_destroy(data_spdu_messages
);
596 data_spdu_messages
= NULL
;
599 /* create new hash table */
600 data_spdu_messages
= g_hash_table_new_full(g_int_hash
, g_int_equal
, &spdu_payload_free_key
, &spdu_payload_free_generic_data
);
601 post_update_one_id_string_template_cb(spdu_message_ident
, spdu_message_ident_num
, data_spdu_messages
);
605 get_message_name(uint32_t id
) {
608 if (data_spdu_messages
== NULL
) {
612 return (char *)g_hash_table_lookup(data_spdu_messages
, &tmp
);
616 UAT_HEX_CB_DEF(spdu_signal_list
, id
, spdu_signal_list_uat_t
)
617 UAT_DEC_CB_DEF(spdu_signal_list
, num_of_params
, spdu_signal_list_uat_t
)
619 UAT_DEC_CB_DEF(spdu_signal_list
, pos
, spdu_signal_list_uat_t
)
620 UAT_CSTRING_CB_DEF(spdu_signal_list
, name
, spdu_signal_list_uat_t
)
621 UAT_CSTRING_CB_DEF(spdu_signal_list
, filter_string
, spdu_signal_list_uat_t
)
622 UAT_CSTRING_CB_DEF(spdu_signal_list
, data_type
, spdu_signal_list_uat_t
)
623 UAT_BOOL_CB_DEF(spdu_signal_list
, big_endian
, spdu_signal_list_uat_t
)
624 UAT_DEC_CB_DEF(spdu_signal_list
, bitlength_base_type
, spdu_signal_list_uat_t
)
625 UAT_DEC_CB_DEF(spdu_signal_list
, bitlength_encoded_type
, spdu_signal_list_uat_t
)
626 UAT_CSTRING_CB_DEF(spdu_signal_list
, scaler
, spdu_signal_list_uat_t
)
627 UAT_CSTRING_CB_DEF(spdu_signal_list
, offset
, spdu_signal_list_uat_t
)
628 UAT_BOOL_CB_DEF(spdu_signal_list
, multiplexer
, spdu_signal_list_uat_t
)
629 UAT_SIGNED_DEC_CB_DEF(spdu_signal_list
, multiplex_value_only
, spdu_signal_list_uat_t
)
630 UAT_BOOL_CB_DEF(spdu_signal_list
, hidden
, spdu_signal_list_uat_t
)
631 UAT_BOOL_CB_DEF(spdu_signal_list
, aggregate_sum
, spdu_signal_list_uat_t
)
632 UAT_BOOL_CB_DEF(spdu_signal_list
, aggregate_avg
, spdu_signal_list_uat_t
)
633 UAT_BOOL_CB_DEF(spdu_signal_list
, aggregate_int
, spdu_signal_list_uat_t
)
636 copy_spdu_signal_list_cb(void *n
, const void *o
, size_t size _U_
) {
637 spdu_signal_list_uat_t
*new_rec
= (spdu_signal_list_uat_t
*)n
;
638 const spdu_signal_list_uat_t
*old_rec
= (const spdu_signal_list_uat_t
*)o
;
640 new_rec
->id
= old_rec
->id
;
641 new_rec
->num_of_params
= old_rec
->num_of_params
;
642 new_rec
->pos
= old_rec
->pos
;
645 new_rec
->name
= g_strdup(old_rec
->name
);
647 new_rec
->name
= NULL
;
649 if (old_rec
->filter_string
) {
650 new_rec
->filter_string
= g_strdup(old_rec
->filter_string
);
652 new_rec
->filter_string
= NULL
;
654 if (old_rec
->data_type
) {
655 new_rec
->data_type
= g_strdup(old_rec
->data_type
);
657 new_rec
->data_type
= NULL
;
660 new_rec
->big_endian
= old_rec
->big_endian
;
661 new_rec
->bitlength_base_type
= old_rec
->bitlength_base_type
;
662 new_rec
->bitlength_encoded_type
= old_rec
->bitlength_encoded_type
;
664 if (old_rec
->scaler
) {
665 new_rec
->scaler
= g_strdup(old_rec
->scaler
);
667 new_rec
->scaler
= NULL
;
669 if (old_rec
->offset
) {
670 new_rec
->offset
= g_strdup(old_rec
->offset
);
672 new_rec
->offset
= NULL
;
675 new_rec
->multiplexer
= old_rec
->multiplexer
;
676 new_rec
->multiplex_value_only
= old_rec
->multiplex_value_only
;
678 new_rec
->hidden
= old_rec
->hidden
;
679 new_rec
->aggregate_sum
= old_rec
->aggregate_sum
;
680 new_rec
->aggregate_avg
= old_rec
->aggregate_avg
;
681 new_rec
->aggregate_int
= old_rec
->aggregate_int
;
687 update_spdu_signal_list(void *r
, char **err
) {
692 spdu_signal_list_uat_t
*rec
= (spdu_signal_list_uat_t
*)r
;
694 offset
= g_ascii_strtod(rec
->offset
, &tmp
);
695 if (!(offset
== offset
)) {
696 *err
= ws_strdup_printf("Offset not a double!");
700 scaler
= g_ascii_strtod(rec
->scaler
, &tmp
);
701 if (!(scaler
== scaler
)) {
702 *err
= ws_strdup_printf("Scaler not a double!");
706 if (rec
->pos
>= 0xffff) {
707 *err
= ws_strdup_printf("Position too big");
711 if (rec
->num_of_params
>= 0xffff) {
712 *err
= ws_strdup_printf("Number of Parameters too big");
716 if (rec
->pos
>= rec
->num_of_params
) {
717 *err
= ws_strdup_printf("Position %u >= Number of Parameters %u (ID: 0x%x)", rec
->pos
, rec
->num_of_params
, rec
->id
);
721 if (rec
->name
== NULL
|| rec
->name
[0] == 0) {
722 *err
= ws_strdup_printf("Name cannot be empty");
726 if (rec
->filter_string
== NULL
|| rec
->filter_string
[0] == 0) {
727 *err
= ws_strdup_printf("Filter String cannot be empty");
731 c
= proto_check_field_name(rec
->filter_string
);
734 *err
= ws_strdup_printf("Filter String contains illegal chars '.' (ID: 0x%08x)", rec
->id
);
735 } else if (g_ascii_isprint(c
)) {
736 *err
= ws_strdup_printf("Filter String contains illegal chars '%c' (ID: 0x%08x)", c
, rec
->id
);
738 *err
= ws_strdup_printf("Filter String contains invalid byte \\%03o (ID: 0x%08x)", c
, rec
->id
);
743 if (g_strcmp0(rec
->data_type
, "uint") != 0 &&
744 g_strcmp0(rec
->data_type
, "int") != 0 &&
745 g_strcmp0(rec
->data_type
, "float") != 0 &&
746 g_strcmp0(rec
->data_type
, "string") != 0 &&
747 g_strcmp0(rec
->data_type
, "stringz") != 0 &&
748 g_strcmp0(rec
->data_type
, "uint_string") != 0 &&
749 g_strcmp0(rec
->data_type
, "utf_string") != 0 &&
750 g_strcmp0(rec
->data_type
, "utf_stringz") != 0 &&
751 g_strcmp0(rec
->data_type
, "utf_uint_string") != 0) {
752 *err
= ws_strdup_printf("Currently the only supported data types are uint, int, float, string, stringz, uint_string, utf_string, utf_stringz, and utf_uint_string (ID: 0x%08x)", rec
->id
);
757 if (g_strcmp0(rec
->data_type
, "uint") == 0) {
758 if ((rec
->bitlength_base_type
!= 8) && (rec
->bitlength_base_type
!= 16) && (rec
->bitlength_base_type
!= 32) && (rec
->bitlength_base_type
!= 64)) {
759 *err
= ws_strdup_printf("Data type uint is only supported as 8, 16, 32, or 64 bit base type (ID: 0x%08x)", rec
->id
);
765 if (g_strcmp0(rec
->data_type
, "int") == 0) {
766 if (rec
->bitlength_base_type
!= rec
->bitlength_encoded_type
) {
767 *err
= ws_strdup_printf("Data type int is only supported in non-shortened length (ID: 0x%08x)", rec
->id
);
771 if ((rec
->bitlength_encoded_type
!= 8) && (rec
->bitlength_encoded_type
!= 16) && (rec
->bitlength_encoded_type
!= 32) && (rec
->bitlength_encoded_type
!= 64)) {
772 *err
= ws_strdup_printf("Data type int is only supported in 8, 16, 32, or 64 bit (ID: 0x%08x)", rec
->id
);
778 if (g_strcmp0(rec
->data_type
, "float") == 0) {
779 if (rec
->bitlength_base_type
!= rec
->bitlength_encoded_type
) {
780 *err
= ws_strdup_printf("Data type float is only supported in non-shortened length (ID: 0x%08x)", rec
->id
);
784 if ((rec
->bitlength_encoded_type
!= 32) && (rec
->bitlength_encoded_type
!= 64)) {
785 *err
= ws_strdup_printf("Data type float is only supported in 32 or 64 bit (ID: 0x%08x)", rec
->id
);
789 if ((scaler
!= 1.0) || (offset
!= 0.0)) {
790 *err
= ws_strdup_printf("Data type float currently does not support scaling and offset (ID: 0x%08x)", rec
->id
);
794 if (rec
->multiplexer
== true) {
795 *err
= ws_strdup_printf("Data type float currently cannot be used as multiplexer (ID: 0x%08x)", rec
->id
);
800 /* string, stringz, uint_string, utf_string, utf_stringz, utf_uint_string */
801 if (g_strcmp0(rec
->data_type
, "string") == 0 || g_strcmp0(rec
->data_type
, "stringz") == 0 || g_strcmp0(rec
->data_type
, "uint_string") == 0 ||
802 g_strcmp0(rec
->data_type
, "utf_string") == 0 || g_strcmp0(rec
->data_type
, "utf_stringz") == 0 || g_strcmp0(rec
->data_type
, "utf_uint_string") == 0) {
803 if ((scaler
!= 1.0) || (offset
!= 0.0)) {
804 *err
= ws_strdup_printf("Data types string, stringz, uint_string, utf_string, utf_stringz, and utf_uint_string currently do not support scaling and offset (ID: 0x%08x)", rec
->id
);
808 if (rec
->multiplexer
== true) {
809 *err
= ws_strdup_printf("Data types string, stringz, uint_string, utf_string, utf_stringz, and utf_uint_string currently cannot be used as multiplexer (ID: 0x%08x)", rec
->id
);
813 if ((g_strcmp0(rec
->data_type
, "string") == 0 || g_strcmp0(rec
->data_type
, "stringz") == 0 || g_strcmp0(rec
->data_type
, "uint_string") == 0) &&
814 rec
->bitlength_base_type
!= 8) {
815 *err
= ws_strdup_printf("Data types string, stringz, and uint_string only support 8 bit Bitlength base type since they are ASCII-based (ID: 0x%08x)", rec
->id
);
819 if ((g_strcmp0(rec
->data_type
, "utf_string") == 0 || g_strcmp0(rec
->data_type
, "utf_stringz") == 0 || g_strcmp0(rec
->data_type
, "utf_uint_string") == 0) &&
820 rec
->bitlength_base_type
!= 8 && rec
->bitlength_base_type
!= 16) {
821 *err
= ws_strdup_printf("Data types utf_string, utf_stringz, and utf_uint_string only support Bitlength base type with 8 bit (UTF-8) or 16 bit (UTF-16) (ID: 0x%08x)", rec
->id
);
825 if ((g_strcmp0(rec
->data_type
, "stringz") == 0 || g_strcmp0(rec
->data_type
, "utf_stringz") == 0 ) &&
826 (rec
->bitlength_encoded_type
!= 0)) {
827 *err
= ws_strdup_printf("Data types stringz and utf_stringz only support Bitlength encoded with 0 bit since the length is determined by zero-termination (ID: 0x%08x)", rec
->id
);
831 if ((g_strcmp0(rec
->data_type
, "uint_string") == 0 || g_strcmp0(rec
->data_type
, "utf_uint_string") == 0) &&
832 (rec
->bitlength_encoded_type
!= 8) && (rec
->bitlength_encoded_type
!= 16) && (rec
->bitlength_encoded_type
!= 32) && (rec
->bitlength_encoded_type
!= 64)) {
833 *err
= ws_strdup_printf("Data types uint_string and utf_uint_string only support Bitlength encoded with 8, 16, 32, or 64 bit since that defines the length of the length field (ID: 0x%08x)", rec
->id
);
838 if (g_strcmp0(rec
->data_type
, "uint") != 0 && g_strcmp0(rec
->data_type
, "int") != 0 && g_strcmp0(rec
->data_type
, "float") != 0 &&
839 (rec
->aggregate_sum
|| rec
->aggregate_avg
|| rec
->aggregate_int
)) {
840 *err
= ws_strdup_printf("Aggregation is only allowed for uint, int, and float (ID: 0x%08x)", rec
->id
);
848 free_spdu_signal_list_cb(void *r
) {
849 spdu_signal_list_uat_t
*rec
= (spdu_signal_list_uat_t
*)r
;
854 if (rec
->filter_string
) {
855 g_free(rec
->filter_string
);
856 rec
->filter_string
= NULL
;
858 if (rec
->data_type
) {
859 g_free(rec
->data_type
);
860 rec
->data_type
= NULL
;
873 deregister_user_data_hfarray(hf_register_info
**hf_array
, unsigned *number_of_entries
) {
874 if (hf_array
== NULL
|| number_of_entries
== NULL
) {
878 unsigned dynamic_hf_size
= *number_of_entries
;
879 hf_register_info
*dynamic_hf
= *hf_array
;
881 if (dynamic_hf
!= NULL
) {
882 /* Unregister all fields */
883 for (unsigned i
= 0; i
< dynamic_hf_size
; i
++) {
884 if (dynamic_hf
[i
].p_id
!= NULL
) {
885 if (*(dynamic_hf
[i
].p_id
) > 0) {
886 proto_deregister_field(proto_signal_pdu
, *(dynamic_hf
[i
].p_id
));
888 g_free(dynamic_hf
[i
].p_id
);
889 dynamic_hf
[i
].p_id
= NULL
;
891 /* workaround since the proto.c proto_free_field_strings would double free this... */
892 dynamic_hf
[i
].hfinfo
.strings
= NULL
;
896 proto_add_deregistered_data(dynamic_hf
);
898 *number_of_entries
= 0;
903 deregister_user_data(void)
905 deregister_user_data_hfarray(&dynamic_hf_base_raw
, &dynamic_hf_base_raw_number
);
906 deregister_user_data_hfarray(&dynamic_hf_agg_sum
, &dynamic_hf_agg_sum_number
);
907 deregister_user_data_hfarray(&dynamic_hf_agg_avg
, &dynamic_hf_agg_avg_number
);
908 deregister_user_data_hfarray(&dynamic_hf_agg_int
, &dynamic_hf_agg_int_number
);
909 dynamic_hf_number_of_entries
= 0;
912 static spdu_signal_value_name_t
*get_signal_value_name_config(uint32_t id
, uint16_t pos
);
915 create_hf_entry(hf_register_info
*dynamic_hf
, unsigned i
, uint32_t id
, uint32_t pos
, char *name
, char *filter_string
, spdu_dt_t data_type
, bool scale_or_offset
, uint32_t hf_type
) {
916 val64_string
*vs
= NULL
;
918 int *hf_id
= g_new(int, 1);
921 spdu_signal_value_name_t
*sig_val
= get_signal_value_name_config(id
, pos
);
922 if (sig_val
!= NULL
) {
926 dynamic_hf
[i
].p_id
= hf_id
;
927 dynamic_hf
[i
].hfinfo
.bitmask
= 0x0;
931 dynamic_hf
[i
].hfinfo
.name
= ws_strdup_printf("%s_raw", name
);
932 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("%s.%s_raw", SPDU_NAME_FILTER
, filter_string
);
935 case HF_TYPE_AGG_SUM
:
936 dynamic_hf
[i
].hfinfo
.name
= ws_strdup_printf("%s_sum", name
);
937 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("%s.%s_sum", SPDU_NAME_FILTER
, filter_string
);
940 case HF_TYPE_AGG_AVG
:
941 dynamic_hf
[i
].hfinfo
.name
= ws_strdup_printf("%s_avg", name
);
942 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("%s.%s_avg", SPDU_NAME_FILTER
, filter_string
);
945 case HF_TYPE_AGG_INT
:
946 dynamic_hf
[i
].hfinfo
.name
= ws_strdup_printf("%s_int", name
);
947 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("%s.%s_int", SPDU_NAME_FILTER
, filter_string
);
951 dynamic_hf
[i
].hfinfo
.name
= ws_strdup(name
);
952 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("%s.%s", SPDU_NAME_FILTER
, filter_string
);
957 /* we bail out but have set hf_id to 0 before */
958 dynamic_hf
[i
].hfinfo
.name
= ws_strdup_printf("%s_none", name
);
959 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("%s.%s_none", SPDU_NAME_FILTER
, filter_string
);
962 dynamic_hf
[i
].hfinfo
.bitmask
= 0;
963 dynamic_hf
[i
].hfinfo
.blurb
= NULL
;
965 if ((scale_or_offset
&& hf_type
== HF_TYPE_BASE
) || hf_type
== HF_TYPE_AGG_SUM
|| hf_type
== HF_TYPE_AGG_AVG
|| hf_type
== HF_TYPE_AGG_INT
) {
966 dynamic_hf
[i
].hfinfo
.display
= BASE_NONE
;
967 dynamic_hf
[i
].hfinfo
.type
= FT_DOUBLE
;
970 case SPDU_DATA_TYPE_UINT
:
971 dynamic_hf
[i
].hfinfo
.display
= BASE_DEC
;
972 dynamic_hf
[i
].hfinfo
.type
= FT_UINT64
;
975 case SPDU_DATA_TYPE_INT
:
976 dynamic_hf
[i
].hfinfo
.display
= BASE_DEC
;
977 dynamic_hf
[i
].hfinfo
.type
= FT_INT64
;
980 case SPDU_DATA_TYPE_FLOAT
:
981 dynamic_hf
[i
].hfinfo
.display
= BASE_NONE
;
982 dynamic_hf
[i
].hfinfo
.type
= FT_DOUBLE
;
985 case SPDU_DATA_TYPE_STRING
:
986 dynamic_hf
[i
].hfinfo
.display
= BASE_NONE
;
987 dynamic_hf
[i
].hfinfo
.type
= FT_STRING
;
990 case SPDU_DATA_TYPE_STRINGZ
:
991 dynamic_hf
[i
].hfinfo
.display
= BASE_NONE
;
992 dynamic_hf
[i
].hfinfo
.type
= FT_STRINGZ
;
995 case SPDU_DATA_TYPE_UINT_STRING
:
996 dynamic_hf
[i
].hfinfo
.display
= BASE_NONE
;
997 dynamic_hf
[i
].hfinfo
.type
= FT_UINT_STRING
;
1000 case SPDU_DATA_TYPE_NONE
:
1006 if (hf_type
== HF_TYPE_RAW
&& vs
!= NULL
) {
1007 dynamic_hf
[i
].hfinfo
.strings
= VALS64(vs
);
1008 dynamic_hf
[i
].hfinfo
.display
|= BASE_VAL64_STRING
| BASE_SPECIAL_VALS
;
1010 dynamic_hf
[i
].hfinfo
.strings
= NULL
;
1013 HFILL_INIT(dynamic_hf
[i
]);
1019 post_update_spdu_signal_list_read_in_data(spdu_signal_list_uat_t
*data
, unsigned data_num
, GHashTable
*ht
) {
1020 if (ht
== NULL
|| data
== NULL
|| data_num
== 0) {
1025 dynamic_hf_number_of_entries
= data_num
;
1026 /* lets create the dynamic_hf array (base + raw) */
1027 dynamic_hf_base_raw
= g_new0(hf_register_info
, 2 * dynamic_hf_number_of_entries
);
1028 dynamic_hf_base_raw_number
= 2 * dynamic_hf_number_of_entries
;
1030 /* lets create the other dynamic_hf arrays */
1031 dynamic_hf_agg_sum
= g_new0(hf_register_info
, dynamic_hf_number_of_entries
);
1032 dynamic_hf_agg_sum_number
= 0;
1033 dynamic_hf_agg_avg
= g_new0(hf_register_info
, dynamic_hf_number_of_entries
);
1034 dynamic_hf_agg_avg_number
= 0;
1035 dynamic_hf_agg_int
= g_new0(hf_register_info
, dynamic_hf_number_of_entries
);
1036 dynamic_hf_agg_int_number
= 0;
1040 for (i
= 0; i
< data_num
; i
++) {
1042 /* the hash table does not know about uint64, so we use int64*/
1043 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1044 *key
= (uint32_t)data
[i
].id
;
1046 spdu_signal_list_t
*list
= (spdu_signal_list_t
*)g_hash_table_lookup(ht
, key
);
1049 list
= wmem_new(wmem_epan_scope(), spdu_signal_list_t
);
1051 list
->id
= data
[i
].id
;
1052 list
->num_of_items
= data
[i
].num_of_params
;
1054 spdu_signal_item_t
*items
= (spdu_signal_item_t
*)wmem_alloc0_array(wmem_epan_scope(), spdu_signal_item_t
, data
[i
].num_of_params
);
1056 list
->items
= items
;
1058 /* create new entry ... */
1059 g_hash_table_insert(ht
, key
, list
);
1061 /* already present, deleting key */
1062 wmem_free(wmem_epan_scope(), key
);
1065 /* and now we add to item array */
1066 if (data
[i
].num_of_params
== list
->num_of_items
&& data
[i
].pos
< list
->num_of_items
) {
1067 spdu_signal_item_t
*item
= &(list
->items
[data
[i
].pos
]);
1069 /* we do not care if we overwrite param */
1070 item
->name
= g_strdup(data
[i
].name
);
1071 item
->pos
= data
[i
].pos
;
1073 item
->encoding
= ENC_ASCII
;
1074 if (g_strcmp0("utf_string", data
[i
].data_type
) == 0 ||
1075 g_strcmp0("utf_stringz", data
[i
].data_type
) == 0 ||
1076 g_strcmp0("utf_uint_string", data
[i
].data_type
) == 0) {
1077 switch (data
[i
].bitlength_base_type
) {
1079 item
->encoding
= ENC_UTF_8
;
1082 item
->encoding
= ENC_UTF_16
;
1085 /* this should never happen, since it is validated in the update callback */
1086 item
->encoding
= ENC_ASCII
;
1091 if (g_strcmp0("uint", data
[i
].data_type
) == 0) {
1092 item
->data_type
= SPDU_DATA_TYPE_UINT
;
1093 } else if (g_strcmp0("int", data
[i
].data_type
) == 0) {
1094 item
->data_type
= SPDU_DATA_TYPE_INT
;
1095 } else if (g_strcmp0("float", data
[i
].data_type
) == 0) {
1096 item
->data_type
= SPDU_DATA_TYPE_FLOAT
;
1097 } else if (g_strcmp0("string", data
[i
].data_type
) == 0 || g_strcmp0("utf_string", data
[i
].data_type
) == 0) {
1098 item
->data_type
= SPDU_DATA_TYPE_STRING
;
1099 } else if (g_strcmp0("stringz", data
[i
].data_type
) == 0 || g_strcmp0("utf_stringz", data
[i
].data_type
) == 0) {
1100 item
->data_type
= SPDU_DATA_TYPE_STRINGZ
;
1101 } else if (g_strcmp0("uint_string", data
[i
].data_type
) == 0 || g_strcmp0("utf_uint_string", data
[i
].data_type
) == 0) {
1102 item
->data_type
= SPDU_DATA_TYPE_UINT_STRING
;
1104 item
->data_type
= SPDU_DATA_TYPE_NONE
;
1107 item
->big_endian
= data
[i
].big_endian
;
1108 item
->bitlength_base_type
= data
[i
].bitlength_base_type
;
1109 item
->bitlength_encoded_type
= data
[i
].bitlength_encoded_type
;
1110 item
->scaler
= g_ascii_strtod(data
[i
].scaler
, NULL
);
1111 item
->offset
= g_ascii_strtod(data
[i
].offset
, NULL
);
1112 item
->scale_or_offset
= (item
->scaler
!= 1.0 || item
->offset
!= 0.0);
1113 item
->multiplexer
= data
[i
].multiplexer
;
1114 item
->multiplex_value_only
= data
[i
].multiplex_value_only
;
1115 item
->hidden
= data
[i
].hidden
;
1117 item
->aggregate_sum
= data
[i
].aggregate_sum
;
1118 item
->aggregate_avg
= data
[i
].aggregate_avg
;
1119 item
->aggregate_int
= data
[i
].aggregate_int
;
1121 /* if one signal needs aggregation, the messages needs to know */
1122 list
->aggregation
|= item
->aggregate_sum
| item
->aggregate_avg
| item
->aggregate_int
;
1124 item
->hf_id_effective
= create_hf_entry(dynamic_hf_base_raw
, HF_TYPE_COUNT_BASE_RAW_TABLE
* i
+ HF_TYPE_BASE
, data
[i
].id
, data
[i
].pos
, data
[i
].name
, data
[i
].filter_string
, item
->data_type
, item
->scale_or_offset
, HF_TYPE_BASE
);
1125 item
->hf_id_raw
= create_hf_entry(dynamic_hf_base_raw
, HF_TYPE_COUNT_BASE_RAW_TABLE
* i
+ HF_TYPE_RAW
, data
[i
].id
, data
[i
].pos
, data
[i
].name
, data
[i
].filter_string
, item
->data_type
, item
->scale_or_offset
, HF_TYPE_RAW
);
1126 if (data
[i
].aggregate_sum
) {
1127 item
->hf_id_agg_sum
= create_hf_entry(dynamic_hf_agg_sum
, dynamic_hf_agg_sum_number
++, data
[i
].id
, data
[i
].pos
, data
[i
].name
, data
[i
].filter_string
, item
->data_type
, item
->scale_or_offset
, HF_TYPE_AGG_SUM
);
1129 if (data
[i
].aggregate_avg
) {
1130 item
->hf_id_agg_avg
= create_hf_entry(dynamic_hf_agg_avg
, dynamic_hf_agg_avg_number
++, data
[i
].id
, data
[i
].pos
, data
[i
].name
, data
[i
].filter_string
, item
->data_type
, item
->scale_or_offset
, HF_TYPE_AGG_AVG
);
1132 if (data
[i
].aggregate_int
) {
1133 item
->hf_id_agg_int
= create_hf_entry(dynamic_hf_agg_int
, dynamic_hf_agg_int_number
++, data
[i
].id
, data
[i
].pos
, data
[i
].name
, data
[i
].filter_string
, item
->data_type
, item
->scale_or_offset
, HF_TYPE_AGG_INT
);
1138 if (dynamic_hf_base_raw_number
) {
1139 proto_register_field_array(proto_signal_pdu
, dynamic_hf_base_raw
, dynamic_hf_base_raw_number
);
1141 if (dynamic_hf_agg_sum_number
) {
1142 proto_register_field_array(proto_signal_pdu
, dynamic_hf_agg_sum
, dynamic_hf_agg_sum_number
);
1144 if (dynamic_hf_agg_avg_number
) {
1145 proto_register_field_array(proto_signal_pdu
, dynamic_hf_agg_avg
, dynamic_hf_agg_avg_number
);
1147 if (dynamic_hf_agg_int_number
) {
1148 proto_register_field_array(proto_signal_pdu
, dynamic_hf_agg_int
, dynamic_hf_agg_int_number
);
1154 post_update_spdu_signal_value_names_read_in_data(spdu_signal_value_name_uat_t
* data
, unsigned data_num
, GHashTable
* ht
) {
1155 if (ht
== NULL
|| data
== NULL
|| data_num
== 0) {
1160 for (i
= 0; i
< data_num
; i
++) {
1161 int64_t* key
= wmem_new(wmem_epan_scope(), int64_t);
1162 *key
= (uint64_t)data
[i
].id
| ((uint64_t)data
[i
].pos
<< 32);
1164 spdu_signal_value_name_t
* list
= (spdu_signal_value_name_t
*)g_hash_table_lookup(ht
, key
);
1167 list
= wmem_new(wmem_epan_scope(), spdu_signal_value_name_t
);
1168 INIT_SIGNAL_VALUE_NAME(list
)
1170 list
->id
= data
[i
].id
;
1171 list
->pos
= data
[i
].pos
;
1172 list
->num_of_items
= data
[i
].num_of_items
;
1174 list
->items
= (spdu_signal_value_name_item_t
*)wmem_alloc0_array(wmem_epan_scope(), spdu_signal_value_name_item_t
, list
->num_of_items
);
1175 list
->vs
= (val64_string
*)wmem_alloc0_array(wmem_epan_scope(), val64_string
, list
->num_of_items
+ 1);
1177 /* create new entry ... */
1178 g_hash_table_insert(ht
, key
, list
);
1181 /* do not need it anymore */
1182 wmem_free(wmem_epan_scope(), key
);
1185 /* and now we add to item array */
1186 if (list
->num_of_items
> 0 && data
[i
].num_of_items
== list
->num_of_items
) {
1188 /* find first empty slot for value */
1190 for (j
= 0; j
< list
->num_of_items
&& list
->items
[j
].name
!= NULL
; j
++);
1192 if (j
< list
->num_of_items
) {
1193 spdu_signal_value_name_item_t
* item
= &(list
->items
[j
]);
1194 INIT_SIGNAL_VALUE_NAME_ITEM(item
)
1196 item
->value_start
= data
[i
].value_start
;
1197 item
->value_end
= data
[i
].value_end
;
1198 item
->name
= g_strdup(data
[i
].value_name
);
1201 /* find first empty slot for range_value array */
1203 for (g
= 0; g
< list
->num_of_items
&& list
->vs
[g
].strptr
!= NULL
; g
++);
1205 if (g
< list
->num_of_items
) {
1206 /* Limitation: range strings currently do not support uint64_t min/max and do not support filtering using value names. */
1207 /* Therefore, we currently use only val64_string. :-( */
1208 list
->vs
[g
].value
= (uint32_t)data
[i
].value_start
;
1209 list
->vs
[g
].strptr
= g_strdup(data
[i
].value_name
);
1216 post_update_spdu_signal_list_and_value_names_cb(void) {
1217 /* destroy old hash tables, if they exist */
1218 if (data_spdu_signal_list
) {
1219 g_hash_table_destroy(data_spdu_signal_list
);
1220 data_spdu_signal_list
= NULL
;
1222 if (data_spdu_signal_value_names
) {
1223 g_hash_table_destroy(data_spdu_signal_value_names
);
1224 data_spdu_signal_value_names
= NULL
;
1227 deregister_user_data();
1229 data_spdu_signal_list
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, &spdu_payload_free_generic_data
);
1230 data_spdu_signal_value_names
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, &spdu_payload_free_generic_data
);
1231 post_update_spdu_signal_list_read_in_data(spdu_signal_list
, spdu_signal_list_num
, data_spdu_signal_list
);
1232 post_update_spdu_signal_value_names_read_in_data(spdu_signal_value_names
, spdu_parameter_value_names_num
, data_spdu_signal_value_names
);
1236 reset_spdu_signal_list(void)
1238 deregister_user_data();
1241 static spdu_signal_list_t
*
1242 get_parameter_config(uint64_t id
) {
1243 if (data_spdu_signal_list
== NULL
) {
1247 int64_t key
= (int64_t)id
;
1248 return (spdu_signal_list_t
*)g_hash_table_lookup(data_spdu_signal_list
, &key
);
1251 /* UAT: Value Names */
1252 UAT_HEX_CB_DEF(spdu_signal_value_names
, id
, spdu_signal_value_name_uat_t
)
1253 UAT_DEC_CB_DEF(spdu_signal_value_names
, pos
, spdu_signal_value_name_uat_t
)
1254 UAT_DEC_CB_DEF(spdu_signal_value_names
, num_of_items
, spdu_signal_value_name_uat_t
)
1255 UAT_HEX64_CB_DEF(spdu_signal_value_names
, value_start
, spdu_signal_value_name_uat_t
)
1256 UAT_HEX64_CB_DEF(spdu_signal_value_names
, value_end
, spdu_signal_value_name_uat_t
)
1257 UAT_CSTRING_CB_DEF(spdu_signal_value_names
, value_name
, spdu_signal_value_name_uat_t
)
1260 copy_spdu_signal_value_name_cb(void *n
, const void *o
, size_t size _U_
) {
1261 spdu_signal_value_name_uat_t
*new_rec
= (spdu_signal_value_name_uat_t
*)n
;
1262 const spdu_signal_value_name_uat_t
*old_rec
= (const spdu_signal_value_name_uat_t
*)o
;
1264 new_rec
->id
= old_rec
->id
;
1265 new_rec
->num_of_items
= old_rec
->num_of_items
;
1266 new_rec
->pos
= old_rec
->pos
;
1268 new_rec
->value_start
= old_rec
->value_start
;
1269 new_rec
->value_end
= old_rec
->value_end
;
1271 if (old_rec
->value_name
) {
1272 new_rec
->value_name
= g_strdup(old_rec
->value_name
);
1274 new_rec
->value_name
= NULL
;
1281 update_spdu_signal_value_name(void *r
, char **err
) {
1282 spdu_signal_value_name_uat_t
*rec
= (spdu_signal_value_name_uat_t
*)r
;
1284 if (rec
->value_name
== NULL
|| rec
->value_name
[0] == 0) {
1285 *err
= ws_strdup_printf("Value Name cannot be empty");
1289 if (rec
->value_end
< rec
->value_start
) {
1290 *err
= ws_strdup_printf("Value Range is defined backwards (end < start)!");
1294 if (rec
->pos
>= 0xffff) {
1295 *err
= ws_strdup_printf("Position too big");
1303 free_spdu_signal_value_name_cb(void *r
) {
1304 spdu_signal_value_name_uat_t
*rec
= (spdu_signal_value_name_uat_t
*)r
;
1305 if (rec
->value_name
) {
1306 g_free(rec
->value_name
);
1307 rec
->value_name
= NULL
;
1311 static spdu_signal_value_name_t
*
1312 get_signal_value_name_config(uint32_t id
, uint16_t pos
) {
1313 if (data_spdu_signal_list
== NULL
) {
1317 int64_t key
= (uint64_t)id
| (uint64_t)pos
<< 32;
1318 return (spdu_signal_value_name_t
*)g_hash_table_lookup(data_spdu_signal_value_names
, &key
);
1321 /* UAT: SOME/IP Mapping */
1322 UAT_HEX_CB_DEF(spdu_someip_mapping
, service_id
, spdu_someip_mapping_uat_t
)
1323 UAT_HEX_CB_DEF(spdu_someip_mapping
, method_id
, spdu_someip_mapping_uat_t
)
1324 UAT_HEX_CB_DEF(spdu_someip_mapping
, major_version
, spdu_someip_mapping_uat_t
)
1325 UAT_HEX_CB_DEF(spdu_someip_mapping
, message_type
, spdu_someip_mapping_uat_t
)
1326 UAT_HEX_CB_DEF(spdu_someip_mapping
, spdu_message_id
, spdu_someip_mapping_uat_t
)
1329 spdu_someip_key(uint16_t service_id
, uint16_t method_id
, uint8_t major_version
, uint8_t message_type
) {
1330 return (int64_t)method_id
| ((int64_t)service_id
<< 16) | ((int64_t)major_version
<< 32) | ((int64_t)message_type
<< 40);
1334 copy_spdu_someip_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1335 spdu_someip_mapping_uat_t
*new_rec
= (spdu_someip_mapping_uat_t
*)n
;
1336 const spdu_someip_mapping_uat_t
*old_rec
= (const spdu_someip_mapping_uat_t
*)o
;
1338 new_rec
->service_id
= old_rec
->service_id
;
1339 new_rec
->method_id
= old_rec
->method_id
;
1340 new_rec
->major_version
= old_rec
->major_version
;
1341 new_rec
->message_type
= old_rec
->message_type
;
1342 new_rec
->spdu_message_id
= old_rec
->spdu_message_id
;
1348 update_spdu_someip_mapping(void *r
, char **err
) {
1349 spdu_someip_mapping_uat_t
*rec
= (spdu_someip_mapping_uat_t
*)r
;
1351 if (rec
->service_id
> 0xffff) {
1352 *err
= ws_strdup_printf("We currently only support 16 bit SOME/IP Service IDs (Service-ID: %x Method-ID: %x MsgType: %x Version: %i)",
1353 rec
->service_id
, rec
->method_id
, rec
->message_type
, rec
->major_version
);
1357 if (rec
->method_id
> 0xffff) {
1358 *err
= ws_strdup_printf("We currently only support 16 bit SOME/IP Method IDs (Service-ID: %x Method-ID: %x MsgType: %x Version: %i)",
1359 rec
->service_id
, rec
->method_id
, rec
->message_type
, rec
->major_version
);
1363 if (rec
->major_version
> 0xff) {
1364 *err
= ws_strdup_printf("We currently only support 8 bit SOME/IP major versions (Service-ID: %x Method-ID: %x MsgType: %x Version: %i)",
1365 rec
->service_id
, rec
->method_id
, rec
->message_type
, rec
->major_version
);
1368 if (rec
->message_type
> 0xff) {
1369 *err
= ws_strdup_printf("We currently only support 8 bit SOME/IP message types (Service-ID: %x Method-ID: %x MsgType: %x Version: %i)",
1370 rec
->service_id
, rec
->method_id
, rec
->message_type
, rec
->major_version
);
1377 post_update_spdu_someip_mapping_cb(void) {
1378 /* destroy old hash table, if it exists */
1379 if (data_spdu_someip_mappings
) {
1380 g_hash_table_destroy(data_spdu_someip_mappings
);
1381 data_spdu_someip_mappings
= NULL
;
1384 /* we don't need to free the data as long as we don't alloc it first */
1385 data_spdu_someip_mappings
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, NULL
);
1387 if (data_spdu_someip_mappings
== NULL
|| spdu_someip_mapping
== NULL
) {
1392 if (spdu_someip_mapping_num
> 0) {
1393 for (i
= 0; i
< spdu_someip_mapping_num
; i
++) {
1394 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1395 *key
= spdu_someip_key((uint16_t)spdu_someip_mapping
[i
].service_id
,
1396 (uint16_t)spdu_someip_mapping
[i
].method_id
,
1397 (uint8_t)spdu_someip_mapping
[i
].major_version
,
1398 (uint8_t)spdu_someip_mapping
[i
].message_type
);
1400 g_hash_table_insert(data_spdu_someip_mappings
, key
, &spdu_someip_mapping
[i
]);
1404 /* we need to make sure we register again */
1405 register_signal_pdu_someip();
1408 static spdu_someip_mapping_t
*
1409 get_someip_mapping(uint16_t service_id
, uint16_t method_id
, uint8_t major_version
, uint8_t message_type
) {
1410 if (data_spdu_someip_mappings
== NULL
) {
1414 int64_t key
= spdu_someip_key(service_id
, method_id
, major_version
, message_type
);
1415 return (spdu_someip_mapping_t
*)g_hash_table_lookup(data_spdu_someip_mappings
, &key
);
1418 /* UAT: CAN Mapping */
1419 UAT_HEX_CB_DEF(spdu_can_mapping
, can_id
, spdu_can_mapping_uat_t
)
1420 UAT_HEX_CB_DEF(spdu_can_mapping
, bus_id
, spdu_can_mapping_uat_t
)
1421 UAT_HEX_CB_DEF(spdu_can_mapping
, message_id
, spdu_can_mapping_uat_t
)
1424 copy_spdu_can_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1425 spdu_can_mapping_uat_t
*new_rec
= (spdu_can_mapping_uat_t
*)n
;
1426 const spdu_can_mapping_uat_t
*old_rec
= (const spdu_can_mapping_uat_t
*)o
;
1428 new_rec
->can_id
= old_rec
->can_id
;
1429 new_rec
->bus_id
= old_rec
->bus_id
;
1430 new_rec
->message_id
= old_rec
->message_id
;
1436 update_spdu_can_mapping(void *r
, char **err
) {
1437 spdu_can_mapping_uat_t
*rec
= (spdu_can_mapping_uat_t
*)r
;
1439 if ((rec
->can_id
& (CAN_RTR_FLAG
| CAN_ERR_FLAG
)) != 0) {
1440 *err
= g_strdup_printf("We currently do not support CAN IDs with RTR or Error Flag set (CAN_ID: 0x%x)", rec
->can_id
);
1444 if ((rec
->can_id
& CAN_EFF_FLAG
) == 0 && rec
->can_id
> CAN_SFF_MASK
) {
1445 *err
= g_strdup_printf("Standard CAN ID (EFF flag not set) cannot be bigger than 0x7ff (CAN_ID: 0x%x)", rec
->can_id
);
1453 post_update_spdu_can_mapping_cb(void) {
1454 /* destroy old hash table, if it exists */
1455 if (data_spdu_can_mappings
) {
1456 g_hash_table_destroy(data_spdu_can_mappings
);
1457 data_spdu_can_mappings
= NULL
;
1460 /* we don't need to free the data as long as we don't alloc it first */
1461 data_spdu_can_mappings
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, NULL
);
1463 if (data_spdu_can_mappings
== NULL
|| spdu_can_mapping
== NULL
) {
1467 if (spdu_can_mapping_num
> 0) {
1469 for (i
= 0; i
< spdu_can_mapping_num
; i
++) {
1470 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1471 *key
= spdu_can_mapping
[i
].can_id
;
1472 *key
|= ((int64_t)(spdu_can_mapping
[i
].bus_id
& 0xffff)) << 32;
1474 g_hash_table_insert(data_spdu_can_mappings
, key
, &spdu_can_mapping
[i
]);
1478 /* we need to make sure we register again */
1479 register_signal_pdu_can();
1482 static spdu_can_mapping_t
*
1483 get_can_mapping(uint32_t id
, uint16_t bus_id
) {
1484 if (data_spdu_can_mappings
== NULL
) {
1488 /* key is Bus ID, EFF Flag, CAN-ID*/
1489 int64_t key
= ((int64_t)id
& (CAN_EFF_MASK
| CAN_EFF_FLAG
)) | ((int64_t)bus_id
<< 32);
1490 spdu_can_mapping_t
*tmp
= (spdu_can_mapping_t
*)g_hash_table_lookup(data_spdu_can_mappings
, &key
);
1492 /* try again without Bus ID set */
1493 key
= id
& (CAN_EFF_MASK
| CAN_EFF_FLAG
);
1494 tmp
= (spdu_can_mapping_t
*)g_hash_table_lookup(data_spdu_can_mappings
, &key
);
1501 /* UAT: FlexRay Mapping */
1502 UAT_HEX_CB_DEF(spdu_flexray_mapping
, channel
, spdu_flexray_mapping_uat_t
)
1503 UAT_HEX_CB_DEF(spdu_flexray_mapping
, cycle
, spdu_flexray_mapping_uat_t
)
1504 UAT_HEX_CB_DEF(spdu_flexray_mapping
, flexray_id
, spdu_flexray_mapping_uat_t
)
1505 UAT_HEX_CB_DEF(spdu_flexray_mapping
, message_id
, spdu_flexray_mapping_uat_t
)
1508 copy_spdu_flexray_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1509 spdu_flexray_mapping_uat_t
*new_rec
= (spdu_flexray_mapping_uat_t
*)n
;
1510 const spdu_flexray_mapping_uat_t
*old_rec
= (const spdu_flexray_mapping_uat_t
*)o
;
1512 new_rec
->channel
= old_rec
->channel
;
1513 new_rec
->cycle
= old_rec
->cycle
;
1514 new_rec
->flexray_id
= old_rec
->flexray_id
;
1515 new_rec
->message_id
= old_rec
->message_id
;
1521 update_spdu_flexray_mapping(void *r
, char **err
) {
1522 spdu_flexray_mapping_uat_t
*rec
= (spdu_flexray_mapping_uat_t
*)r
;
1524 if (rec
->cycle
> 0xff) {
1525 *err
= ws_strdup_printf("We currently only support 8 bit Cycles (Cycle: %i Frame ID: %i)", rec
->cycle
, rec
->flexray_id
);
1529 if (rec
->flexray_id
> 0xffff) {
1530 *err
= ws_strdup_printf("We currently only support 16 bit Frame IDs (Cycle: %i Frame ID: %i)", rec
->cycle
, rec
->flexray_id
);
1538 post_update_spdu_flexray_mapping_cb(void) {
1539 /* destroy old hash table, if it exists */
1540 if (data_spdu_flexray_mappings
) {
1541 g_hash_table_destroy(data_spdu_flexray_mappings
);
1542 data_spdu_flexray_mappings
= NULL
;
1545 /* we don't need to free the data as long as we don't alloc it first */
1546 data_spdu_flexray_mappings
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, NULL
);
1548 if (data_spdu_flexray_mappings
== NULL
|| spdu_flexray_mapping
== NULL
) {
1552 if (spdu_flexray_mapping_num
> 0) {
1554 for (i
= 0; i
< spdu_flexray_mapping_num
; i
++) {
1555 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1556 *key
= spdu_flexray_mapping
[i
].flexray_id
& 0xffff;
1557 *key
|= (int64_t)(spdu_flexray_mapping
[i
].cycle
& 0xff) << 16;
1558 *key
|= (int64_t)(spdu_flexray_mapping
[i
].channel
& 0xff) << 24;
1560 g_hash_table_insert(data_spdu_flexray_mappings
, key
, &spdu_flexray_mapping
[i
]);
1565 static spdu_flexray_mapping_t
*
1566 get_flexray_mapping(uint8_t channel
, uint8_t cycle
, uint16_t flexray_id
) {
1567 if (data_spdu_flexray_mappings
== NULL
) {
1571 int64_t key
= ((int64_t)channel
<< 24) | ((int64_t)cycle
<< 16) | (int64_t)flexray_id
;
1572 return (spdu_flexray_mapping_t
*)g_hash_table_lookup(data_spdu_flexray_mappings
, &key
);
1576 /* UAT: LIN Mapping */
1577 UAT_HEX_CB_DEF(spdu_lin_mapping
, frame_id
, spdu_lin_mapping_uat_t
)
1578 UAT_HEX_CB_DEF(spdu_lin_mapping
, bus_id
, spdu_lin_mapping_uat_t
)
1579 UAT_HEX_CB_DEF(spdu_lin_mapping
, message_id
, spdu_lin_mapping_uat_t
)
1582 copy_spdu_lin_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1583 spdu_lin_mapping_uat_t
*new_rec
= (spdu_lin_mapping_uat_t
*)n
;
1584 const spdu_lin_mapping_uat_t
*old_rec
= (const spdu_lin_mapping_uat_t
*)o
;
1586 new_rec
->frame_id
= old_rec
->frame_id
;
1587 new_rec
->bus_id
= old_rec
->bus_id
;
1588 new_rec
->message_id
= old_rec
->message_id
;
1594 update_spdu_lin_mapping(void *r
, char **err
) {
1595 spdu_lin_mapping_uat_t
*rec
= (spdu_lin_mapping_uat_t
*)r
;
1597 if (rec
->frame_id
> LIN_ID_MASK
) {
1598 *err
= ws_strdup_printf("LIN Frame IDs are only uint with 6 bits (ID: %i)", rec
->frame_id
);
1602 if (rec
->bus_id
> 0xffff) {
1603 *err
= ws_strdup_printf("LIN Bus IDs are only uint with 16 bits (ID: 0x%x, Bus ID: 0x%x)", rec
->frame_id
, rec
->bus_id
);
1611 post_update_spdu_lin_mapping_cb(void) {
1612 /* destroy old hash table, if it exists */
1613 if (data_spdu_lin_mappings
) {
1614 g_hash_table_destroy(data_spdu_lin_mappings
);
1615 data_spdu_lin_mappings
= NULL
;
1618 /* we don't need to free the data as long as we don't alloc it first */
1619 data_spdu_lin_mappings
= g_hash_table_new_full(g_int_hash
, g_int_equal
, &spdu_payload_free_key
, NULL
);
1621 if (data_spdu_lin_mappings
== NULL
|| spdu_lin_mapping
== NULL
) {
1625 if (spdu_lin_mapping_num
> 0) {
1627 for (i
= 0; i
< spdu_lin_mapping_num
; i
++) {
1628 int *key
= wmem_new(wmem_epan_scope(), int);
1629 *key
= (spdu_lin_mapping
[i
].frame_id
) & LIN_ID_MASK
;
1630 *key
|= ((spdu_lin_mapping
[i
].bus_id
) & 0xffff) << 16;
1632 g_hash_table_insert(data_spdu_lin_mappings
, key
, &spdu_lin_mapping
[i
]);
1636 /* we need to make sure we register again */
1637 register_signal_pdu_lin();
1640 static spdu_lin_mapping_t
*
1641 get_lin_mapping(lin_info_t
*lininfo
) {
1642 if (data_spdu_lin_mappings
== NULL
) {
1646 int32_t key
= ((lininfo
->id
) & LIN_ID_MASK
) | (((lininfo
->bus_id
) & 0xffff) << 16);
1648 spdu_lin_mapping_uat_t
*tmp
= (spdu_lin_mapping_uat_t
*)g_hash_table_lookup(data_spdu_lin_mappings
, &key
);
1651 /* try again without Bus ID set */
1652 key
= (lininfo
->id
) & LIN_ID_MASK
;
1653 tmp
= (spdu_lin_mapping_uat_t
*)g_hash_table_lookup(data_spdu_lin_mappings
, &key
);
1659 /* UAT: PDU Transport Mapping */
1660 UAT_HEX_CB_DEF(spdu_pdu_transport_mapping
, pdu_id
, spdu_pdu_transport_mapping_uat_t
)
1661 UAT_HEX_CB_DEF(spdu_pdu_transport_mapping
, message_id
, spdu_pdu_transport_mapping_uat_t
)
1664 copy_spdu_pdu_transport_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1665 spdu_pdu_transport_mapping_uat_t
*new_rec
= (spdu_pdu_transport_mapping_uat_t
*)n
;
1666 const spdu_pdu_transport_mapping_uat_t
*old_rec
= (const spdu_pdu_transport_mapping_uat_t
*)o
;
1668 new_rec
->pdu_id
= old_rec
->pdu_id
;
1669 new_rec
->message_id
= old_rec
->message_id
;
1675 update_spdu_pdu_transport_mapping(void *r
, char **err
) {
1676 spdu_pdu_transport_mapping_uat_t
*rec
= (spdu_pdu_transport_mapping_uat_t
*)r
;
1678 if (rec
->pdu_id
> 0xffffffff) {
1679 *err
= ws_strdup_printf("PDU-Transport IDs are only uint32 (ID: %i)", rec
->pdu_id
);
1687 post_update_spdu_pdu_transport_mapping_cb(void) {
1688 /* destroy old hash table, if it exists */
1689 if (data_spdu_pdu_transport_mappings
) {
1690 g_hash_table_destroy(data_spdu_pdu_transport_mappings
);
1691 data_spdu_pdu_transport_mappings
= NULL
;
1694 /* we don't need to free the data as long as we don't alloc it first */
1695 data_spdu_pdu_transport_mappings
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, NULL
);
1697 if (data_spdu_pdu_transport_mappings
== NULL
|| spdu_pdu_transport_mapping
== NULL
) {
1701 if (spdu_pdu_transport_mapping_num
> 0) {
1703 for (i
= 0; i
< spdu_pdu_transport_mapping_num
; i
++) {
1704 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1705 *key
= spdu_pdu_transport_mapping
[i
].pdu_id
;
1707 g_hash_table_insert(data_spdu_pdu_transport_mappings
, key
, &spdu_pdu_transport_mapping
[i
]);
1711 /* we need to make sure we register again */
1712 register_signal_pdu_pdu_transport();
1715 static spdu_pdu_transport_mapping_t
*
1716 get_pdu_transport_mapping(uint32_t pdu_transport_id
) {
1717 if (data_spdu_pdu_transport_mappings
== NULL
) {
1721 int64_t key
= pdu_transport_id
;
1722 return (spdu_pdu_transport_mapping_uat_t
*)g_hash_table_lookup(data_spdu_pdu_transport_mappings
, &key
);
1725 /* UAT: IPduM Mapping */
1726 UAT_HEX_CB_DEF(spdu_ipdum_mapping
, pdu_id
, spdu_ipdum_mapping_uat_t
)
1727 UAT_HEX_CB_DEF(spdu_ipdum_mapping
, message_id
, spdu_ipdum_mapping_uat_t
)
1730 copy_spdu_ipdum_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1731 spdu_ipdum_mapping_uat_t
*new_rec
= (spdu_ipdum_mapping_uat_t
*)n
;
1732 const spdu_ipdum_mapping_uat_t
*old_rec
= (const spdu_ipdum_mapping_uat_t
*)o
;
1734 new_rec
->pdu_id
= old_rec
->pdu_id
;
1735 new_rec
->message_id
= old_rec
->message_id
;
1741 update_spdu_ipdum_mapping(void *r
, char **err
) {
1742 spdu_ipdum_mapping_uat_t
*rec
= (spdu_ipdum_mapping_uat_t
*)r
;
1744 if (rec
->pdu_id
> 0xffffffff) {
1745 *err
= ws_strdup_printf("IPduM IDs are only uint32 (ID: %i)", rec
->pdu_id
);
1753 post_update_spdu_ipdum_mapping_cb(void) {
1754 /* destroy old hash table, if it exists */
1755 if (data_spdu_ipdum_mappings
) {
1756 g_hash_table_destroy(data_spdu_ipdum_mappings
);
1757 data_spdu_ipdum_mappings
= NULL
;
1760 /* we don't need to free the data as long as we don't alloc it first */
1761 data_spdu_ipdum_mappings
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, NULL
);
1763 if (data_spdu_ipdum_mappings
== NULL
|| spdu_ipdum_mapping
== NULL
) {
1767 if (spdu_ipdum_mapping_num
> 0) {
1769 for (i
= 0; i
< spdu_ipdum_mapping_num
; i
++) {
1770 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1771 *key
= spdu_ipdum_mapping
[i
].pdu_id
;
1773 g_hash_table_insert(data_spdu_ipdum_mappings
, key
, &spdu_ipdum_mapping
[i
]);
1777 /* we need to make sure we register again */
1778 register_signal_pdu_ipdum();
1781 static spdu_ipdum_mapping_uat_t
*
1782 get_ipdum_mapping(uint32_t pdu_id
) {
1783 if (data_spdu_ipdum_mappings
== NULL
) {
1787 int64_t key
= pdu_id
;
1788 return (spdu_ipdum_mapping_uat_t
*)g_hash_table_lookup(data_spdu_ipdum_mappings
, &key
);
1791 /* UAT: DLT Mapping */
1792 UAT_CSTRING_CB_DEF(spdu_dlt_mapping
, ecu_id
, spdu_dlt_mapping_uat_t
)
1793 UAT_HEX_CB_DEF(spdu_dlt_mapping
, dlt_message_id
, spdu_dlt_mapping_uat_t
)
1794 UAT_HEX_CB_DEF(spdu_dlt_mapping
, message_id
, spdu_dlt_mapping_uat_t
)
1797 copy_spdu_dlt_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1798 spdu_dlt_mapping_uat_t
*new_rec
= (spdu_dlt_mapping_uat_t
*)n
;
1799 const spdu_dlt_mapping_uat_t
*old_rec
= (const spdu_dlt_mapping_uat_t
*)o
;
1801 if (old_rec
->ecu_id
) {
1802 new_rec
->ecu_id
= g_strdup(old_rec
->ecu_id
);
1804 new_rec
->ecu_id
= NULL
;
1807 new_rec
->dlt_message_id
= old_rec
->dlt_message_id
;
1808 new_rec
->message_id
= old_rec
->message_id
;
1814 update_spdu_dlt_mapping(void *r
, char **err
) {
1815 spdu_dlt_mapping_uat_t
*rec
= (spdu_dlt_mapping_uat_t
*)r
;
1817 if (rec
->ecu_id
!= NULL
&& strlen(rec
->ecu_id
) > 4) {
1818 *err
= ws_strdup_printf("ECU ID can only be up to 4 characters long!");
1826 post_update_spdu_dlt_mapping_cb(void) {
1827 /* destroy old hash table, if it exists */
1828 if (data_spdu_dlt_mappings
) {
1829 g_hash_table_destroy(data_spdu_dlt_mappings
);
1830 data_spdu_dlt_mappings
= NULL
;
1833 /* we don't need to free the data as long as we don't alloc it first */
1834 data_spdu_dlt_mappings
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, NULL
);
1836 if (data_spdu_dlt_mappings
== NULL
|| spdu_dlt_mapping
== NULL
) {
1840 if (spdu_dlt_mapping_num
> 0) {
1842 for (i
= 0; i
< spdu_dlt_mapping_num
; i
++) {
1843 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1844 *key
= spdu_dlt_mapping
[i
].dlt_message_id
;
1845 *key
|= (int64_t)(dlt_ecu_id_to_int32(spdu_dlt_mapping
[i
].ecu_id
)) << 32;
1847 g_hash_table_insert(data_spdu_dlt_mappings
, key
, &spdu_dlt_mapping
[i
]);
1852 static spdu_dlt_mapping_uat_t
*
1853 get_dlt_mapping(uint32_t pdu_id
, const char *ecu_id
) {
1854 if (data_spdu_dlt_mappings
== NULL
) {
1858 int64_t key
= pdu_id
;
1859 key
|= (int64_t)dlt_ecu_id_to_int32(ecu_id
) << 32;
1861 return (spdu_dlt_mapping_uat_t
*)g_hash_table_lookup(data_spdu_dlt_mappings
, &key
);
1864 /* UAT: UDS Mapping */
1865 UAT_HEX_CB_DEF(spdu_uds_mapping
, uds_address
, spdu_uds_mapping_uat_t
)
1866 UAT_HEX_CB_DEF(spdu_uds_mapping
, service
, spdu_uds_mapping_uat_t
)
1867 UAT_BOOL_CB_DEF(spdu_uds_mapping
, reply
, spdu_uds_mapping_uat_t
)
1868 UAT_HEX_CB_DEF(spdu_uds_mapping
, id
, spdu_uds_mapping_uat_t
)
1869 UAT_HEX_CB_DEF(spdu_uds_mapping
, message_id
, spdu_uds_mapping_uat_t
)
1872 copy_spdu_uds_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1873 spdu_uds_mapping_uat_t
*new_rec
= (spdu_uds_mapping_uat_t
*)n
;
1874 const spdu_uds_mapping_uat_t
*old_rec
= (const spdu_uds_mapping_uat_t
*)o
;
1876 new_rec
->uds_address
= old_rec
->uds_address
;
1877 new_rec
->service
= old_rec
->service
;
1878 new_rec
->reply
= old_rec
->reply
;
1879 new_rec
->id
= old_rec
->id
;
1880 new_rec
->message_id
= old_rec
->message_id
;
1886 update_spdu_uds_mapping(void *r
, char **err
) {
1887 spdu_uds_mapping_uat_t
*rec
= (spdu_uds_mapping_uat_t
*)r
;
1889 if (rec
->id
> 0xffff) {
1890 *err
= g_strdup("UDS IDs are only uint16!");
1894 if (rec
->service
> 0xff) {
1895 *err
= g_strdup("UDS Services are only uint8!");
1903 post_update_spdu_uds_mapping_cb(void) {
1904 /* destroy old hash table, if it exists */
1905 if (data_spdu_uds_mappings
) {
1906 g_hash_table_destroy(data_spdu_uds_mappings
);
1907 data_spdu_uds_mappings
= NULL
;
1910 /* we don't need to free the data as long as we don't alloc it first */
1911 data_spdu_uds_mappings
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, NULL
);
1913 if (data_spdu_uds_mappings
== NULL
|| spdu_uds_mapping
== NULL
) {
1917 if (spdu_uds_mapping_num
> 0) {
1920 for (i
= 0; i
< spdu_uds_mapping_num
; i
++) {
1921 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1922 if (spdu_uds_mapping
[i
].reply
) {
1923 sid
= (0xff & spdu_uds_mapping
[i
].service
) | UDS_REPLY_MASK
;
1925 sid
= (0xff & spdu_uds_mapping
[i
].service
);
1928 *key
= (uint64_t)(spdu_uds_mapping
[i
].uds_address
) | ((uint64_t)(0xffff & spdu_uds_mapping
[i
].id
) << 32) | ((uint64_t)sid
<< 48);
1929 g_hash_table_insert(data_spdu_uds_mappings
, key
, &spdu_uds_mapping
[i
]);
1931 /* Adding with 0xffffffff (ANY) as address too */
1932 key
= wmem_new(wmem_epan_scope(), int64_t);
1933 *key
= (uint64_t)(0xffffffff) | ((uint64_t)(0xffff & spdu_uds_mapping
[i
].id
) << 32) | ((uint64_t)sid
<< 48);
1934 g_hash_table_insert(data_spdu_uds_mappings
, key
, &spdu_uds_mapping
[i
]);
1939 static spdu_uds_mapping_uat_t
*
1940 get_uds_mapping(uds_info_t
*uds_info
) {
1943 DISSECTOR_ASSERT(uds_info
);
1944 if (data_spdu_uds_mappings
== NULL
) {
1948 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
1949 if (uds_info
->reply
) {
1950 sid
= (0xff & uds_info
->service
) | UDS_REPLY_MASK
;
1952 sid
= (0xff & uds_info
->service
);
1954 *key
= (uint64_t)(uds_info
->uds_address
) | ((uint64_t)(0xffff & uds_info
->id
) << 32) | ((uint64_t)sid
<< 48);
1956 spdu_uds_mapping_uat_t
*tmp
= (spdu_uds_mapping_uat_t
*)g_hash_table_lookup(data_spdu_uds_mappings
, key
);
1958 /* if we cannot find it for the Address, lets look at MAXUINT32 */
1960 *key
= (uint64_t)(UINT32_MAX
) | ((uint64_t)(0xffff & uds_info
->id
) << 32) | ((uint64_t)sid
<< 48);
1962 tmp
= (spdu_uds_mapping_uat_t
*)g_hash_table_lookup(data_spdu_uds_mappings
, key
);
1965 wmem_free(wmem_epan_scope(), key
);
1970 /* UAT: ISOBUS Mapping */
1971 UAT_HEX_CB_DEF(spdu_isobus_mapping
, pgn
, spdu_isobus_mapping_uat_t
)
1972 UAT_HEX_CB_DEF(spdu_isobus_mapping
, bus_id
, spdu_isobus_mapping_uat_t
)
1973 UAT_HEX_CB_DEF(spdu_isobus_mapping
, message_id
, spdu_isobus_mapping_uat_t
)
1976 copy_spdu_isobus_mapping_cb(void *n
, const void *o
, size_t size _U_
) {
1977 spdu_isobus_mapping_uat_t
*new_rec
= (spdu_isobus_mapping_uat_t
*)n
;
1978 const spdu_isobus_mapping_uat_t
*old_rec
= (const spdu_isobus_mapping_uat_t
*)o
;
1980 new_rec
->pgn
= old_rec
->pgn
;
1981 new_rec
->bus_id
= old_rec
->bus_id
;
1982 new_rec
->message_id
= old_rec
->message_id
;
1988 update_spdu_isobus_mapping(void *r
, char **err
) {
1989 spdu_isobus_mapping_uat_t
*rec
= (spdu_isobus_mapping_uat_t
*)r
;
1991 if (rec
->pgn
> 0x03ffff) {
1992 *err
= g_strdup_printf("PGN %u > %u!", rec
->pgn
, 0x03ffff);
2000 post_update_spdu_isobus_mapping_cb(void) {
2001 /* destroy old hash table, if it exists */
2002 if (data_spdu_isobus_mappings
) {
2003 g_hash_table_destroy(data_spdu_isobus_mappings
);
2004 data_spdu_isobus_mappings
= NULL
;
2007 /* we don't need to free the data as long as we don't alloc it first */
2008 data_spdu_isobus_mappings
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &spdu_payload_free_key
, NULL
);
2010 if (data_spdu_isobus_mappings
== NULL
|| spdu_isobus_mapping
== NULL
) {
2014 if (spdu_isobus_mapping_num
> 0) {
2016 for (i
= 0; i
< spdu_isobus_mapping_num
; i
++) {
2017 int64_t *key
= wmem_new(wmem_epan_scope(), int64_t);
2018 *key
= spdu_isobus_mapping
[i
].pgn
;
2019 *key
|= ((int64_t)(spdu_isobus_mapping
[i
].bus_id
& 0xffff)) << 32;
2021 g_hash_table_insert(data_spdu_isobus_mappings
, key
, &spdu_isobus_mapping
[i
]);
2025 /* we need to make sure we register again */
2026 register_signal_pdu_isobus();
2029 static spdu_isobus_mapping_uat_t
*
2030 get_isobus_mapping(uint32_t pgn
, uint16_t bus_id
) {
2031 if (data_spdu_isobus_mappings
== NULL
) {
2036 int64_t key
= ((int64_t)pgn
) | ((int64_t)bus_id
<< 32);
2037 spdu_isobus_mapping_t
*tmp
= (spdu_isobus_mapping_t
*)g_hash_table_lookup(data_spdu_isobus_mappings
, &key
);
2039 /* try again without Bus ID set */
2041 tmp
= (spdu_isobus_mapping_t
*)g_hash_table_lookup(data_spdu_isobus_mappings
, &key
);
2047 /**************************************
2048 ******** Expert Infos ********
2049 **************************************/
2052 expert_spdu_payload_truncated(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, int length
) {
2053 proto_tree_add_expert(tree
, pinfo
, &ei_spdu_payload_truncated
, tvb
, offset
, length
);
2054 col_append_str(pinfo
->cinfo
, COL_INFO
, " [Signal PDU: Truncated payload!]");
2058 expert_spdu_config_error(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, int length
) {
2059 proto_tree_add_expert(tree
, pinfo
, &ei_spdu_config_error
, tvb
, offset
, length
);
2060 col_append_str(pinfo
->cinfo
, COL_INFO
, " [Signal PDU: Config Error!]");
2064 expert_spdu_unaligned_data(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, int length
) {
2065 proto_tree_add_expert(tree
, pinfo
, &ei_spdu_unaligned_data
, tvb
, offset
, length
);
2066 col_append_str(pinfo
->cinfo
, COL_INFO
, " [Signal PDU: Unaligned Data!]");
2070 /**************************************
2071 ******** Aggregation Feature ********
2072 **************************************/
2074 typedef struct _spdu_frame_data
{
2078 double sum_time_value_products
;
2079 } spdu_frame_data_t
;
2081 typedef struct _spdu_aggregation
{
2084 nstime_t start_time
;
2088 double sum_time_value_products
;
2089 } spdu_aggregation_t
;
2091 static wmem_map_t
*spdu_aggregation_data
;
2093 static spdu_aggregation_t
*
2094 get_or_create_aggregation_data(packet_info
*pinfo
, int hf_id_effective
) {
2095 DISSECTOR_ASSERT(spdu_aggregation_data
!= NULL
);
2096 DISSECTOR_ASSERT(hf_id_effective
> 0);
2098 spdu_aggregation_t
*data
= (spdu_aggregation_t
*)wmem_map_lookup(spdu_aggregation_data
, GINT_TO_POINTER(hf_id_effective
));
2102 data
= wmem_new0(wmem_file_scope(), spdu_aggregation_t
);
2105 data
->start_time
= pinfo
->abs_ts
;
2106 data
->last_time
= pinfo
->abs_ts
;
2107 data
->sum_time_value_products
= 0.0;
2108 wmem_map_insert(spdu_aggregation_data
, GINT_TO_POINTER(hf_id_effective
), data
);
2115 /**************************************
2116 ******** Dissector Helpers ********
2117 **************************************/
2119 /* There is similar code in tvbuff.c ... */
2122 spdu_ieee_double_from_64bits(uint64_t value
) {
2128 ieee_fp_union
.w
= value
;
2130 return ieee_fp_union
.d
;
2134 spdu_ieee_float_from_32bits(uint32_t value
) {
2140 ieee_fp_union
.w
= value
;
2142 return ieee_fp_union
.d
;
2146 /**************************************
2147 ******** Signal PDU Dissector ********
2148 **************************************/
2151 dissect_shifted_and_shortened_uint(tvbuff_t
*tvb
, int offset
, int offset_bits
, int offset_end
, int offset_end_bits
, bool big_endian
) {
2153 uint64_t value_uint64
= 0;
2156 /* offset and offset_end need to be included */
2157 for (i
= offset_end
; i
>= offset
; i
--) {
2159 if (i
!= offset_end
|| offset_end_bits
!= 0) {
2160 uint8_t tmp
= tvb_get_uint8(tvb
, i
);
2161 int tmp_bit_count
= 8;
2163 if (i
== offset_end
) {
2164 tmp
= tmp
& (0xff >> (8 - offset_end_bits
));
2165 /* don't need to shift value, in the first round */
2170 tmp
>>= offset_bits
;
2171 tmp_bit_count
= 8 - offset_bits
;
2174 value_uint64
<<= (unsigned)tmp_bit_count
;
2175 value_uint64
|= tmp
;
2179 /* offset_end needs to be included. */
2180 for (i
= offset
; i
<= offset_end
; i
++) {
2182 /* Do not read the last byte, if you do not need any bit of it. Else we read behind buffer! */
2183 if (i
!= offset_end
|| offset_end_bits
!= 0) {
2184 uint8_t tmp
= tvb_get_uint8(tvb
, i
);
2185 int tmp_bit_count
= 8;
2188 tmp
= tmp
& (0xff >> offset_bits
);
2189 /* don't need to shift value, in the first round */
2193 if (i
== offset_end
) {
2194 tmp
>>= 8 - offset_end_bits
;
2195 tmp_bit_count
= offset_end_bits
;
2198 value_uint64
<<= (unsigned)tmp_bit_count
;
2199 value_uint64
|= tmp
;
2203 return value_uint64
;
2207 dissect_spdu_payload_signal(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, int offset_bits
, spdu_signal_item_t
*item
, int *multiplexer
) {
2208 DISSECTOR_ASSERT(item
!= NULL
);
2209 DISSECTOR_ASSERT(item
->hf_id_effective
!= NULL
);
2211 proto_item
*ti
= NULL
;
2212 proto_tree
*subtree
= NULL
;
2214 char *value_name
= NULL
;
2215 int hf_id_effective
= 0;
2218 int offset_end
= (int)((8 * offset
+ offset_bits
+ item
->bitlength_encoded_type
) / 8);
2219 int offset_end_bits
= (int)((8 * offset
+ offset_bits
+ item
->bitlength_encoded_type
) % 8);
2221 int string_length
= 0;
2222 int signal_length
= offset_end
- offset
;
2223 if (offset_end_bits
!= 0) {
2227 if (item
->multiplex_value_only
!= -1 && item
->multiplex_value_only
!= *multiplexer
) {
2228 /* multiplexer set and we are in the wrong multiplex */
2232 if (tvb_captured_length_remaining(tvb
, offset
) < signal_length
) {
2233 expert_spdu_payload_truncated(tree
, pinfo
, tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
));
2237 if (!spdu_deserializer_show_hidden
&& item
->hidden
) {
2238 return (int)item
->bitlength_encoded_type
;
2241 if (item
!= NULL
&& item
->hf_id_effective
!= NULL
) {
2242 hf_id_effective
= *item
->hf_id_effective
;
2244 expert_spdu_config_error(tree
, pinfo
, tvb
, offset
, signal_length
);
2248 return tvb_captured_length_remaining(tvb
, offset
);
2251 if (item
->hf_id_raw
!= NULL
) {
2252 hf_id_raw
= *item
->hf_id_raw
;
2254 expert_spdu_config_error(tree
, pinfo
, tvb
, offset
, signal_length
);
2257 uint64_t value_uint64
= dissect_shifted_and_shortened_uint(tvb
, offset
, offset_bits
, offset_end
, offset_end_bits
, item
->big_endian
);
2259 /* we need to reset this because it is reused */
2262 double value_double
= 0.0;
2264 switch (item
->data_type
) {
2265 case SPDU_DATA_TYPE_UINT
: {
2266 value_double
= (double)value_uint64
;
2268 if (item
->multiplexer
) {
2269 *multiplexer
= (int)value_uint64
;
2272 /* show names for values */
2273 if (item
->sig_val_names
!= NULL
) {
2275 for (i
= 0; i
< item
->sig_val_names
->num_of_items
; i
++) {
2276 if (item
->sig_val_names
->items
[i
].value_start
<= value_uint64
&& value_uint64
<= item
->sig_val_names
->items
[i
].value_end
) {
2277 value_name
= item
->sig_val_names
->items
[i
].name
;
2282 /* scale and output */
2283 if (item
->scale_or_offset
) {
2284 value_double
= item
->scaler
* value_double
+ item
->offset
;
2285 ti
= proto_tree_add_double(tree
, hf_id_effective
, tvb
, offset
, signal_length
, value_double
);
2287 ti
= proto_tree_add_uint64(tree
, hf_id_effective
, tvb
, offset
, signal_length
, value_uint64
);
2289 if (value_name
!= NULL
) {
2290 proto_item_append_text(ti
, " [raw: 0x%" PRIx64
": %s]", value_uint64
, value_name
);
2292 proto_item_append_text(ti
, " [raw: 0x%" PRIx64
"]", value_uint64
);
2295 subtree
= proto_item_add_subtree(ti
, ett_spdu_signal
);
2296 ti
= proto_tree_add_uint64(subtree
, hf_id_raw
, tvb
, offset
, signal_length
, value_uint64
);
2297 proto_item_append_text(ti
, " (0x%" PRIx64
")", value_uint64
);
2301 case SPDU_DATA_TYPE_INT
: {
2302 int64_t value_int64
= ws_sign_ext64(value_uint64
, (int)item
->bitlength_encoded_type
);
2303 value_double
= (double)value_int64
;
2305 if (item
->multiplexer
) {
2306 *multiplexer
= (int)value_int64
;
2309 /* scale and output */
2310 if (item
->scale_or_offset
) {
2311 value_double
= item
->scaler
* value_double
+ item
->offset
;
2312 ti
= proto_tree_add_double(tree
, hf_id_effective
, tvb
, offset
, signal_length
, value_double
);
2314 ti
= proto_tree_add_int64(tree
, hf_id_effective
, tvb
, offset
, signal_length
, value_int64
);
2316 if (value_name
!= NULL
) {
2317 proto_item_append_text(ti
, " [raw: %" PRIx64
": %s]", value_int64
, value_name
);
2319 proto_item_append_text(ti
, " [raw: %" PRIx64
"]", value_int64
);
2322 subtree
= proto_item_add_subtree(ti
, ett_spdu_signal
);
2323 ti
= proto_tree_add_int64(subtree
, hf_id_raw
, tvb
, offset
, signal_length
, value_int64
);
2324 proto_item_append_text(ti
, " (0x%" PRIx64
")", value_int64
);
2328 case SPDU_DATA_TYPE_FLOAT
: {
2331 switch (item
->bitlength_base_type
) {
2333 value_double
= spdu_ieee_double_from_64bits(value_uint64
);
2336 value_double
= (double)spdu_ieee_float_from_32bits((uint32_t)value_uint64
);
2339 /* not supported and cannot occur since the config is checked! */
2343 /* scaler, offset, multiplexer not allowed by config checks */
2345 ti
= proto_tree_add_double(tree
, hf_id_effective
, tvb
, offset
, signal_length
, value_double
);
2347 if (value_name
!= NULL
) {
2348 proto_item_append_text(ti
, " [raw: 0x%" PRIx64
": %s]", value_uint64
, value_name
);
2350 proto_item_append_text(ti
, " [raw: 0x%" PRIx64
"]", value_uint64
);
2353 subtree
= proto_item_add_subtree(ti
, ett_spdu_signal
);
2354 ti
= proto_tree_add_double(subtree
, hf_id_raw
, tvb
, offset
, signal_length
, value_double
);
2355 proto_item_append_text(ti
, " [raw: 0x%" PRIx64
"]", value_uint64
);
2359 case SPDU_DATA_TYPE_STRING
:
2360 if (offset_bits
!= 0) {
2361 expert_spdu_unaligned_data(tree
, pinfo
, tvb
, offset
, 0);
2364 proto_tree_add_item(tree
, hf_id_effective
, tvb
, offset
, signal_length
, item
->encoding
);
2367 case SPDU_DATA_TYPE_STRINGZ
:
2368 if (offset_bits
!= 0) {
2369 expert_spdu_unaligned_data(tree
, pinfo
, tvb
, offset
, 0);
2371 proto_tree_add_item_ret_length(tree
, hf_id_effective
, tvb
, offset
, -1, item
->encoding
, &string_length
);
2375 case SPDU_DATA_TYPE_UINT_STRING
:
2376 if (offset_bits
!= 0) {
2377 expert_spdu_unaligned_data(tree
, pinfo
, tvb
, offset
, 0);
2380 if (item
->big_endian
) {
2381 proto_tree_add_item_ret_length(tree
, hf_id_effective
, tvb
, offset
, signal_length
, item
->encoding
| ENC_BIG_ENDIAN
, &string_length
);
2383 proto_tree_add_item_ret_length(tree
, hf_id_effective
, tvb
, offset
, signal_length
, item
->encoding
| ENC_LITTLE_ENDIAN
, &string_length
);
2385 string_length
= string_length
* 8 - (int)item
->bitlength_encoded_type
;
2388 case SPDU_DATA_TYPE_NONE
:
2393 /* hide raw value per default, if effective value is present */
2394 if (spdu_deserializer_hide_raw_values
) {
2395 proto_item_set_hidden(ti
);
2398 /* Value passed in with value_double, tree via subtree. */
2399 if (item
->aggregate_sum
|| item
->aggregate_avg
|| item
->aggregate_int
) {
2400 int hf_id_eff
= *(item
->hf_id_effective
);
2401 spdu_aggregation_t
*agg_data
= get_or_create_aggregation_data(pinfo
, hf_id_eff
);
2402 spdu_frame_data_t
*spdu_frame_data
= (spdu_frame_data_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_signal_pdu
, (uint32_t)hf_id_eff
);
2404 if (!PINFO_FD_VISITED(pinfo
)) {
2407 agg_data
->sum
+= value_double
;
2410 nstime_delta(&delta
, &(pinfo
->abs_ts
), &(agg_data
->last_time
));
2411 double delta_s
= nstime_to_sec(&delta
);
2413 if (delta_s
> 0.0) {
2414 agg_data
->sum_time_value_products
+= delta_s
* agg_data
->last_value
;
2415 agg_data
->last_time
= pinfo
->abs_ts
;
2417 agg_data
->last_value
= value_double
;
2419 if (!spdu_frame_data
) {
2420 spdu_frame_data
= wmem_new0(wmem_file_scope(), spdu_frame_data_t
);
2421 p_add_proto_data(wmem_file_scope(), pinfo
, proto_signal_pdu
, (uint32_t)hf_id_eff
, spdu_frame_data
);
2424 spdu_frame_data
->sum
= agg_data
->sum
;
2425 spdu_frame_data
->count
= agg_data
->count
;
2426 spdu_frame_data
->avg
= agg_data
->sum
/ agg_data
->count
;
2427 spdu_frame_data
->sum_time_value_products
= agg_data
->sum_time_value_products
;
2430 /* if frame data was not created on first pass, we cannot calculate it now */
2431 if (spdu_frame_data
!= NULL
) {
2432 if (item
->aggregate_sum
) {
2433 proto_tree_add_double(subtree
, *(item
->hf_id_agg_sum
), tvb
, offset
, signal_length
, spdu_frame_data
->sum
);
2435 if (item
->aggregate_avg
) {
2436 proto_tree_add_double(subtree
, *(item
->hf_id_agg_avg
), tvb
, offset
, signal_length
, spdu_frame_data
->avg
);
2438 if (item
->aggregate_int
&& (spdu_frame_data
->sum_time_value_products
== spdu_frame_data
->sum_time_value_products
)) {
2439 proto_tree_add_double(subtree
, *(item
->hf_id_agg_int
), tvb
, offset
, signal_length
, spdu_frame_data
->sum_time_value_products
);
2444 return (int)item
->bitlength_encoded_type
+ string_length
;
2448 dissect_spdu_payload(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*root_tree
, uint32_t id
, bool update_column
) {
2450 int offset_bits
= 0;
2451 int bits_parsed
= 0;
2452 int multiplexer
= -1;
2454 proto_item
*ti
= proto_tree_add_item(root_tree
, proto_signal_pdu
, tvb
, offset
, -1, ENC_NA
);
2455 proto_tree
*tree
= proto_item_add_subtree(ti
, ett_spdu_payload
);
2457 char *name
= get_message_name(id
);
2460 proto_item_append_text(ti
, ": %s", name
);
2461 if (update_column
) {
2462 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (PDU: %s)", name
);
2463 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, SPDU_NAME
);
2465 ti
= proto_tree_add_string(tree
, hf_pdu_name
, tvb
, offset
, -1, name
);
2466 proto_item_set_generated(ti
);
2467 proto_item_set_hidden(ti
);
2470 spdu_signal_list_t
*paramlist
= get_parameter_config(id
);
2472 if (name
== NULL
&& paramlist
== NULL
) {
2473 /* unknown message, lets skip */
2477 if (!spdu_deserializer_activated
) {
2478 /* we only receive a tvb with nothing behind us */
2479 proto_tree_add_text_internal(tree
, tvb
, 0, tvb_captured_length(tvb
), "Dissection of payload is disabled. It can be enabled via protocol preferences.");
2480 return tvb_captured_length(tvb
);
2483 if (tvb_captured_length(tvb
) > 0 && paramlist
== NULL
) {
2484 /* we only receive a tvb with nothing behind us */
2485 proto_tree_add_text_internal(tree
, tvb
, 0, tvb_captured_length(tvb
), "Payload of PDU is not configured. See protocol preferences.");
2486 return call_data_dissector(tvb
, pinfo
, tree
);
2489 if (root_tree
== NULL
&& !proto_field_is_referenced(root_tree
, proto_signal_pdu
) && !paramlist
->aggregation
) {
2490 /* we only receive a tvb with nothing behind us */
2491 return tvb_captured_length(tvb
);
2494 int length
= tvb_captured_length_remaining(tvb
, 0);
2497 for (i
= 0; i
< paramlist
->num_of_items
; i
++) {
2498 if (!paramlist
->items
[i
].sig_val_names_valid
) {
2499 paramlist
->items
[i
].sig_val_names
= get_signal_value_name_config(paramlist
->id
, paramlist
->items
[i
].pos
);
2500 paramlist
->items
[i
].sig_val_names_valid
= true;
2502 bits_parsed
= dissect_spdu_payload_signal(tvb
, pinfo
, tree
, offset
, offset_bits
, &(paramlist
->items
[i
]), &multiplexer
);
2503 if (bits_parsed
== -1) {
2506 offset
= (8 * offset
+ offset_bits
+ bits_parsed
) / 8;
2507 offset_bits
= (8 * offset
+ offset_bits
+ bits_parsed
) % 8;
2510 if (bits_parsed
!= -1 && length
> offset
+ 1) {
2511 if (offset_bits
== 0) {
2512 proto_tree_add_item(tree
, hf_payload_unparsed
, tvb
, offset
, length
- offset
, ENC_NA
);
2514 proto_tree_add_item(tree
, hf_payload_unparsed
, tvb
, offset
+ 1, length
- (offset
+ 1), ENC_NA
);
2522 dissect_spdu_message_someip(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2523 someip_info_t
*someip_info
= (someip_info_t
*)data
;
2525 DISSECTOR_ASSERT(someip_info
);
2527 spdu_someip_mapping_t
*someip_mapping
= get_someip_mapping(someip_info
->service_id
, someip_info
->method_id
, someip_info
->major_version
, someip_info
->message_type
);
2529 if (someip_mapping
== NULL
) {
2533 return dissect_spdu_payload(tvb
, pinfo
, tree
, someip_mapping
->spdu_message_id
, false);
2537 dissect_spdu_message_can(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2538 struct can_info
*can_info
= (struct can_info
*)data
;
2539 DISSECTOR_ASSERT(can_info
);
2541 if (can_info
->id
& (CAN_ERR_FLAG
| CAN_RTR_FLAG
)) {
2542 /* Error and RTR frames are not for us. */
2546 spdu_can_mapping_t
*can_mapping
= get_can_mapping(can_info
->id
, can_info
->bus_id
);
2547 if (can_mapping
== NULL
) {
2551 return dissect_spdu_payload(tvb
, pinfo
, tree
, can_mapping
->message_id
, true);
2555 dissect_spdu_message_can_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2556 return dissect_spdu_message_can(tvb
, pinfo
, tree
, data
) != 0;
2560 dissect_spdu_message_flexray(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2561 struct flexray_info
*flexray_data
= (struct flexray_info
*)data
;
2562 DISSECTOR_ASSERT(flexray_data
);
2564 spdu_flexray_mapping_t
*flexray_mapping
= get_flexray_mapping(flexray_data
->ch
, flexray_data
->cc
, flexray_data
->id
);
2566 if (flexray_mapping
== NULL
) {
2570 return dissect_spdu_payload(tvb
, pinfo
, tree
, flexray_mapping
->message_id
, true);
2574 dissect_spdu_message_flexray_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2575 return dissect_spdu_message_flexray(tvb
, pinfo
, tree
, data
) != 0;
2579 dissect_spdu_message_lin(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2580 lin_info_t
*lininfo
= (lin_info_t
*)data
;
2582 DISSECTOR_ASSERT(lininfo
);
2584 spdu_lin_mapping_t
*lin_mapping
= get_lin_mapping(lininfo
);
2586 if (lin_mapping
== NULL
) {
2590 return dissect_spdu_payload(tvb
, pinfo
, tree
, lin_mapping
->message_id
, true);
2594 dissect_spdu_message_pdu_transport(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2595 pdu_transport_info_t
*pdu_info
= (pdu_transport_info_t
*)data
;
2596 DISSECTOR_ASSERT(pdu_info
);
2598 spdu_pdu_transport_mapping_t
*pdu_transport_mapping
= get_pdu_transport_mapping(pdu_info
->id
);
2600 if (pdu_transport_mapping
== NULL
) {
2604 return dissect_spdu_payload(tvb
, pinfo
, tree
, pdu_transport_mapping
->message_id
, false);
2608 dissect_spdu_message_ipdum(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2609 autosar_ipdu_multiplexer_info_t
*pdu_info
= (autosar_ipdu_multiplexer_info_t
*)data
;
2610 DISSECTOR_ASSERT(pdu_info
);
2612 spdu_ipdum_mapping_uat_t
*ipdum_mapping
= get_ipdum_mapping(pdu_info
->pdu_id
);
2614 if (ipdum_mapping
== NULL
) {
2618 return dissect_spdu_payload(tvb
, pinfo
, tree
, ipdum_mapping
->message_id
, true);
2622 dissect_spdu_message_dlt_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2623 dlt_info_t
*pdu_info
= (dlt_info_t
*)data
;
2624 DISSECTOR_ASSERT(pdu_info
);
2626 spdu_dlt_mapping_uat_t
*dlt_mapping
= get_dlt_mapping(pdu_info
->message_id
, pdu_info
->ecu_id
);
2628 if (dlt_mapping
== NULL
) {
2632 return dissect_spdu_payload(tvb
, pinfo
, tree
, dlt_mapping
->message_id
, true) != 0;
2636 dissect_spdu_message_uds_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2637 uds_info_t
*uds_info
= (uds_info_t
*)data
;
2638 DISSECTOR_ASSERT(uds_info
);
2640 spdu_uds_mapping_t
*uds_mapping
= get_uds_mapping(uds_info
);
2641 if (uds_mapping
== NULL
) {
2645 return dissect_spdu_payload(tvb
, pinfo
, tree
, uds_mapping
->message_id
, false) != 0;
2649 dissect_spdu_message_isobus(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
2650 isobus_info_t
*isobus_info
= (isobus_info_t
*)data
;
2651 DISSECTOR_ASSERT(isobus_info
);
2653 spdu_isobus_mapping_t
*isobus_mapping
= get_isobus_mapping(isobus_info
->pgn
, isobus_info
->bus_id
);
2655 if (isobus_mapping
== NULL
) {
2659 return dissect_spdu_payload(tvb
, pinfo
, tree
, isobus_mapping
->message_id
, true);
2662 /**************************************
2663 ******** Register Dissector ********
2664 **************************************/
2667 proto_register_signal_pdu(void) {
2668 module_t
*spdu_module
;
2669 expert_module_t
*expert_module_lpdu
;
2671 /* UAT for naming */
2672 uat_t
*spdu_messages_uat
;
2674 /* the UATs for parsing the message*/
2675 uat_t
*spdu_signal_list_uat
;
2676 uat_t
*spdu_parameter_value_names_uat
;
2678 /* UATs for mapping different incoming payloads to messages*/
2679 uat_t
*spdu_someip_mapping_uat
;
2680 uat_t
*spdu_can_mapping_uat
;
2681 uat_t
*spdu_flexray_mapping_uat
;
2682 uat_t
*spdu_lin_mapping_uat
;
2683 uat_t
*spdu_pdu_transport_mapping_uat
;
2684 uat_t
*spdu_ipdum_mapping_uat
;
2685 uat_t
*spdu_dlt_mapping_uat
;
2686 uat_t
*spdu_uds_mapping_uat
;
2687 uat_t
*spdu_isobus_mapping_uat
;
2690 static hf_register_info hf
[] = {
2692 { "Signal PDU Name", "signal_pdu.name",
2693 FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
2694 { &hf_payload_unparsed
,
2695 { "Unparsed Payload", "signal_pdu.payload.unparsed",
2696 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
2699 static int *ett
[] = {
2704 /* UATs for user_data fields */
2705 static uat_field_t spdu_messages_uat_fields
[] = {
2706 UAT_FLD_HEX(spdu_message_ident
, id
, "Signal PDU ID", "ID of the Signal PDU"),
2707 UAT_FLD_CSTRING(spdu_message_ident
, name
, "Name", "Name of the Signal PDU"),
2711 static uat_field_t spdu_signal_list_uat_fields
[] = {
2712 UAT_FLD_HEX(spdu_signal_list
, id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2713 UAT_FLD_DEC(spdu_signal_list
, num_of_params
, "Number of Signals", "Number of signals (16bit dec)"),
2715 UAT_FLD_DEC(spdu_signal_list
, pos
, "Signal Position", "Position of signal (16bit dec, starting with 0)"),
2716 UAT_FLD_CSTRING(spdu_signal_list
, name
, "Signal Name", "Name of signal (string)"),
2717 UAT_FLD_CSTRING(spdu_signal_list
, filter_string
, "Filter String", "Unique filter string that will be prepended with signal_pdu. (string)"),
2718 UAT_FLD_CSTRING(spdu_signal_list
, data_type
, "Data Type", "Data type (string), [uint|int|float|string|stringz|uint_string|utf8_string|utf8_stringz|utf8_uint_string]"),
2719 UAT_FLD_BOOL(spdu_signal_list
, big_endian
, "Big Endian?", "Big Endian encoded [false|true]"),
2720 UAT_FLD_DEC(spdu_signal_list
, bitlength_base_type
, "Bitlength base type", "Bitlength base type (uint32 dec). The length of the original type or the length of a single character."),
2721 UAT_FLD_DEC(spdu_signal_list
, bitlength_encoded_type
, "Bitlength enc. type", "Bitlength encoded type (uint32 dec). The shortened length of uints or the total length of string/utf8_string or the length of the uint_string/utf8_uint_string length field."),
2722 UAT_FLD_CSTRING(spdu_signal_list
, scaler
, "Scaler", "Raw value is multiplied by this Scaler, e.g. 1.0 (double)"),
2723 UAT_FLD_CSTRING(spdu_signal_list
, offset
, "Offset", "Scaled raw value is shifted by this Offset, e.g. 1.0 (double)"),
2724 UAT_FLD_BOOL(spdu_signal_list
, multiplexer
, "Multiplexer?", "Is this used as multiplexer? [false|true]"),
2725 UAT_FLD_SIGNED_DEC(spdu_signal_list
, multiplex_value_only
, "Multiplexer value", "The multiplexer value for which this is relevant (-1 all)"),
2726 UAT_FLD_BOOL(spdu_signal_list
, hidden
, "Hidden?", "Should this field be hidden in the dissection? [false|true]"),
2727 UAT_FLD_BOOL(spdu_signal_list
, aggregate_sum
, "Calc Sum?", "Should this field be aggregated using sum function? [false|true]"),
2728 UAT_FLD_BOOL(spdu_signal_list
, aggregate_avg
, "Calc Avg?", "Should this field be aggregated using average function? [false|true]"),
2729 UAT_FLD_BOOL(spdu_signal_list
, aggregate_int
, "Calc Int?", "Should this field be aggregated using integrate function (sum of time value product)? [false|true]"),
2733 static uat_field_t spdu_parameter_value_name_uat_fields
[] = {
2734 UAT_FLD_HEX(spdu_signal_value_names
, id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2735 UAT_FLD_DEC(spdu_signal_value_names
, pos
, "Signal Position", "Position of signal (16bit dec, starting with 0)"),
2736 UAT_FLD_DEC(spdu_signal_value_names
, num_of_items
, "Number of Names", "Number of Value Names defined (32bit dec)"),
2737 UAT_FLD_HEX64(spdu_signal_value_names
, value_start
, "Value Range Start", "Value Range Start (64bit uint hex)"),
2738 UAT_FLD_HEX64(spdu_signal_value_names
, value_end
, "Value Range End", "Value Range End (64bit uint hex)"),
2739 UAT_FLD_CSTRING(spdu_signal_value_names
, value_name
, "Value Name", "Name for the values in this range (string)"),
2743 static uat_field_t spdu_someip_mapping_uat_fields
[] = {
2744 UAT_FLD_HEX(spdu_someip_mapping
, service_id
, "SOME/IP Service ID", "SOME/IP Service ID (16bit hex without leading 0x)"),
2745 UAT_FLD_HEX(spdu_someip_mapping
, method_id
, "SOME/IP Method ID", "SOME/IP Method ID (16bit hex without leading 0x)"),
2746 UAT_FLD_HEX(spdu_someip_mapping
, major_version
, "SOME/IP Major Version", "SOME/IP Major Version (8bit hex without leading 0x)"),
2747 UAT_FLD_HEX(spdu_someip_mapping
, message_type
, "SOME/IP Message Type", "SOME/IP Message Type (8bit hex without leading 0x)"),
2748 UAT_FLD_HEX(spdu_someip_mapping
, spdu_message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2752 static uat_field_t spdu_can_mapping_uat_fields
[] = {
2753 UAT_FLD_HEX(spdu_can_mapping
, can_id
, "CAN ID", "CAN ID (32bit hex without leading 0x, highest bit 1 for extended, 0 for standard ID)"),
2754 UAT_FLD_HEX(spdu_can_mapping
, bus_id
, "Bus ID", "Bus ID on which frame was recorded with 0=any (16bit hex without leading 0x)"),
2755 UAT_FLD_HEX(spdu_can_mapping
, message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2759 static uat_field_t spdu_flexray_mapping_uat_fields
[] = {
2760 UAT_FLD_HEX(spdu_flexray_mapping
, channel
, "Channel", "Channel (8bit hex without leading 0x)"),
2761 UAT_FLD_HEX(spdu_flexray_mapping
, cycle
, "Cycle", "Cycle (8bit hex without leading 0x)"),
2762 UAT_FLD_HEX(spdu_flexray_mapping
, flexray_id
, "Frame ID", "Frame ID (16bit hex without leading 0x)"),
2763 UAT_FLD_HEX(spdu_flexray_mapping
, message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2767 static uat_field_t spdu_lin_mapping_uat_fields
[] = {
2768 UAT_FLD_HEX(spdu_lin_mapping
, frame_id
, "Frame ID", "LIN Frame ID (6bit hex without leading 0x)"),
2769 UAT_FLD_HEX(spdu_lin_mapping
, bus_id
, "Bus ID", "Bus ID on which frame was recorded with 0=any (16bit hex without leading 0x)"),
2770 UAT_FLD_HEX(spdu_lin_mapping
, message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2774 static uat_field_t spdu_pdu_transport_mapping_uat_fields
[] = {
2775 UAT_FLD_HEX(spdu_pdu_transport_mapping
, pdu_id
, "PDU ID", "PDU ID (32bit hex without leading 0x)"),
2776 UAT_FLD_HEX(spdu_pdu_transport_mapping
, message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2780 static uat_field_t spdu_ipdum_mapping_uat_fields
[] = {
2781 UAT_FLD_HEX(spdu_ipdum_mapping
, pdu_id
, "PDU ID", "PDU ID (32bit hex without leading 0x)"),
2782 UAT_FLD_HEX(spdu_ipdum_mapping
, message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2786 static uat_field_t spdu_dlt_mapping_uat_fields
[] = {
2787 UAT_FLD_CSTRING(spdu_dlt_mapping
, ecu_id
, "ECU ID", "ECU ID (4 ASCII chars only!)"),
2788 UAT_FLD_HEX(spdu_dlt_mapping
, dlt_message_id
, "DLT Message ID", "Message ID (32bit hex without leading 0x)"),
2789 UAT_FLD_HEX(spdu_dlt_mapping
, message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2793 static uat_field_t spdu_uds_mapping_uat_fields
[] = {
2794 UAT_FLD_HEX(spdu_uds_mapping
, uds_address
, "ECU Address", "ECU Address (32bit hex without leading 0x, 0xffffffff means any)"),
2795 UAT_FLD_HEX(spdu_uds_mapping
, service
, "UDS Service", "UDS Service (8bit hex without leading 0x)"),
2796 UAT_FLD_BOOL(spdu_uds_mapping
, reply
, "Reply", "Reply [false|true]"),
2797 UAT_FLD_HEX(spdu_uds_mapping
, id
, "ID", "ID (16bit hex without leading 0x)"),
2798 UAT_FLD_HEX(spdu_uds_mapping
, message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2802 static uat_field_t spdu_isobus_mapping_uat_fields
[] = {
2803 UAT_FLD_HEX(spdu_isobus_mapping
, pgn
, "PGN", "PGN (18bit hex without leading 0x)"),
2804 UAT_FLD_HEX(spdu_isobus_mapping
, bus_id
, "Bus ID", "Bus ID on which frame was recorded with 0=any (16bit hex without leading 0x)"),
2805 UAT_FLD_HEX(spdu_isobus_mapping
, message_id
, "Signal PDU ID", "ID of the Signal PDU (32bit hex without leading 0x)"),
2809 static ei_register_info ei
[] = {
2810 { &ei_spdu_payload_truncated
, {"signal_pdu.payload.expert_truncated",
2811 PI_MALFORMED
, PI_ERROR
, "Signal PDU: Truncated payload!", EXPFILL
} },
2812 { &ei_spdu_config_error
, {"signal_pdu.payload.config_error",
2813 PI_MALFORMED
, PI_ERROR
, "Signal PDU: Config Error (missing filter, filter duplicate, ...)!", EXPFILL
} },
2814 { &ei_spdu_unaligned_data
, {"signal_pdu.payload.unaligned_data",
2815 PI_MALFORMED
, PI_ERROR
, "Signal PDU: Unaligned data! Strings etc. need to be aligned to bytes!", EXPFILL
} },
2819 proto_signal_pdu
= proto_register_protocol(SPDU_NAME_LONG
, SPDU_NAME
, SPDU_NAME_FILTER
);
2820 proto_register_field_array(proto_signal_pdu
, hf
, array_length(hf
));
2821 proto_register_subtree_array(ett
, array_length(ett
));
2822 expert_module_lpdu
= expert_register_protocol(proto_signal_pdu
);
2823 expert_register_field_array(expert_module_lpdu
, ei
, array_length(ei
));
2825 /* Register preferences */
2826 spdu_module
= prefs_register_protocol(proto_signal_pdu
, &proto_reg_handoff_signal_pdu
);
2830 spdu_messages_uat
= uat_new("Signal PDU Messages",
2831 sizeof(generic_one_id_string_t
), /* record size */
2832 DATAFILE_SPDU_MESSAGES
, /* filename */
2833 true, /* from profile */
2834 (void **)&spdu_message_ident
, /* data_ptr */
2835 &spdu_message_ident_num
, /* numitems_ptr */
2836 UAT_AFFECTS_DISSECTION
, /* but not fields */
2838 copy_generic_one_id_string_cb
, /* copy callback */
2839 update_generic_one_identifier_32bit
, /* update callback */
2840 free_generic_one_id_string_cb
, /* free callback */
2841 post_update_spdu_message_cb
, /* post update callback */
2842 NULL
, /* reset callback */
2843 spdu_messages_uat_fields
/* UAT field definitions */
2846 prefs_register_uat_preference(spdu_module
, "_spdu_signal_pdus", "Signal PDUs",
2847 "A table to define names of signal PDUs", spdu_messages_uat
);
2849 prefs_register_static_text_preference(spdu_module
, "empty1", "", NULL
);
2850 prefs_register_static_text_preference(spdu_module
, "dis", "PDU Dissection:", NULL
);
2852 prefs_register_bool_preference(spdu_module
, "payload_dissector_activated",
2854 "Should the payload dissector be active?",
2855 &spdu_deserializer_activated
);
2857 prefs_register_bool_preference(spdu_module
, "payload_dissector_show_hidden",
2858 "Show hidden entries",
2859 "Should the payload dissector show entries marked as hidden in the configuration?",
2860 &spdu_deserializer_show_hidden
);
2862 prefs_register_bool_preference(spdu_module
, "payload_dissector_hide_raw_values",
2864 "Should the payload dissector hide raw values?",
2865 &spdu_deserializer_hide_raw_values
);
2867 spdu_parameter_value_names_uat
= uat_new("Signal Value Names",
2868 sizeof(spdu_signal_value_name_uat_t
), /* record size */
2869 DATAFILE_SPDU_VALUE_NAMES
, /* filename */
2870 true, /* from profile */
2871 (void **)&spdu_signal_value_names
, /* data_ptr */
2872 &spdu_parameter_value_names_num
, /* numitems_ptr */
2873 UAT_AFFECTS_DISSECTION
, /* but not fields */
2875 copy_spdu_signal_value_name_cb
, /* copy callback */
2876 update_spdu_signal_value_name
, /* update callback */
2877 free_spdu_signal_value_name_cb
, /* free callback */
2878 post_update_spdu_signal_list_and_value_names_cb
, /* post update callback */
2879 NULL
, /* reset callback */
2880 spdu_parameter_value_name_uat_fields
/* UAT field definitions */
2883 /* value names must be for signals since we need this data for the later */
2884 prefs_register_uat_preference(spdu_module
, "_spdu_parameter_value_names", "Value Names",
2885 "A table to define names of signal values", spdu_parameter_value_names_uat
);
2888 spdu_signal_list_uat
= uat_new("Signal PDU Signal List",
2889 sizeof(spdu_signal_list_uat_t
), /* record size */
2890 DATAFILE_SPDU_SIGNALS
, /* filename */
2891 true, /* from profile */
2892 (void **)&spdu_signal_list
, /* data_ptr */
2893 &spdu_signal_list_num
, /* numitems_ptr */
2894 UAT_AFFECTS_DISSECTION
| UAT_AFFECTS_FIELDS
,
2896 copy_spdu_signal_list_cb
, /* copy callback */
2897 update_spdu_signal_list
, /* update callback */
2898 free_spdu_signal_list_cb
, /* free callback */
2899 post_update_spdu_signal_list_and_value_names_cb
, /* post update callback */
2900 reset_spdu_signal_list
, /* reset callback */
2901 spdu_signal_list_uat_fields
/* UAT field definitions */
2904 static const char *spdu_signal_list_uat_defaults_
[] = {
2905 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
2906 "FALSE", "FALSE", "FALSE" };
2907 uat_set_default_values(spdu_signal_list_uat
, spdu_signal_list_uat_defaults_
);
2909 prefs_register_uat_preference(spdu_module
, "_spdu_signal_list", "Signal List",
2910 "A table to define names of signals", spdu_signal_list_uat
);
2913 prefs_register_static_text_preference(spdu_module
, "empty2", "", NULL
);
2914 prefs_register_static_text_preference(spdu_module
, "map", "Protocol Mappings:", NULL
);
2917 spdu_someip_mapping_uat
= uat_new("SOME/IP",
2918 sizeof(spdu_someip_mapping_uat_t
), /* record size */
2919 DATAFILE_SPDU_SOMEIP_MAPPING
, /* filename */
2920 true, /* from profile */
2921 (void **)&spdu_someip_mapping
, /* data_ptr */
2922 &spdu_someip_mapping_num
, /* numitems_ptr */
2923 UAT_AFFECTS_DISSECTION
, /* but not fields */
2925 copy_spdu_someip_mapping_cb
, /* copy callback */
2926 update_spdu_someip_mapping
, /* update callback */
2927 NULL
, /* free callback */
2928 post_update_spdu_someip_mapping_cb
, /* post update callback */
2929 NULL
, /* reset callback */
2930 spdu_someip_mapping_uat_fields
/* UAT field definitions */
2933 prefs_register_uat_preference(spdu_module
, "_spdu_someip_mapping", "SOME/IP Mappings",
2934 "A table to map SOME/IP payloads to Signal PDUs", spdu_someip_mapping_uat
);
2937 spdu_can_mapping_uat
= uat_new("CAN",
2938 sizeof(spdu_can_mapping_uat_t
), /* record size */
2939 DATAFILE_SPDU_CAN_MAPPING
, /* filename */
2940 true, /* from profile */
2941 (void **)&spdu_can_mapping
, /* data_ptr */
2942 &spdu_can_mapping_num
, /* numitems_ptr */
2943 UAT_AFFECTS_DISSECTION
, /* but not fields */
2945 copy_spdu_can_mapping_cb
, /* copy callback */
2946 update_spdu_can_mapping
, /* update callback */
2947 NULL
, /* free callback */
2948 post_update_spdu_can_mapping_cb
, /* post update callback */
2949 NULL
, /* reset callback */
2950 spdu_can_mapping_uat_fields
/* UAT field definitions */
2953 prefs_register_uat_preference(spdu_module
, "_spdu_can_mapping", "CAN Mappings",
2954 "A table to map CAN payloads to Signal PDUs", spdu_can_mapping_uat
);
2957 spdu_flexray_mapping_uat
= uat_new("FlexRay",
2958 sizeof(spdu_flexray_mapping_uat_t
), /* record size */
2959 DATAFILE_SPDU_FLEXRAY_MAPPING
, /* filename */
2960 true, /* from profile */
2961 (void **)&spdu_flexray_mapping
, /* data_ptr */
2962 &spdu_flexray_mapping_num
, /* numitems_ptr */
2963 UAT_AFFECTS_DISSECTION
, /* but not fields */
2965 copy_spdu_flexray_mapping_cb
, /* copy callback */
2966 update_spdu_flexray_mapping
, /* update callback */
2967 NULL
, /* free callback */
2968 post_update_spdu_flexray_mapping_cb
, /* post update callback */
2969 NULL
, /* reset callback */
2970 spdu_flexray_mapping_uat_fields
/* UAT field definitions */
2973 prefs_register_uat_preference(spdu_module
, "_spdu_flexray_mapping", "FlexRay Mappings",
2974 "A table to map FlexRay payloads to Signal PDUs", spdu_flexray_mapping_uat
);
2977 spdu_lin_mapping_uat
= uat_new("LIN",
2978 sizeof(spdu_lin_mapping_uat_t
), /* record size */
2979 DATAFILE_SPDU_LIN_MAPPING
, /* filename */
2980 true, /* from profile */
2981 (void **)&spdu_lin_mapping
, /* data_ptr */
2982 &spdu_lin_mapping_num
, /* numitems_ptr */
2983 UAT_AFFECTS_DISSECTION
, /* but not fields */
2985 copy_spdu_lin_mapping_cb
, /* copy callback */
2986 update_spdu_lin_mapping
, /* update callback */
2987 NULL
, /* free callback */
2988 post_update_spdu_lin_mapping_cb
, /* post update callback */
2989 NULL
, /* reset callback */
2990 spdu_lin_mapping_uat_fields
/* UAT field definitions */
2993 prefs_register_uat_preference(spdu_module
, "_spdu_lin_mapping", "LIN Mappings",
2994 "A table to map LIN payloads to Signal PDUs", spdu_lin_mapping_uat
);
2997 spdu_pdu_transport_mapping_uat
= uat_new("PDU Transport",
2998 sizeof(spdu_pdu_transport_mapping_uat_t
), /* record size */
2999 DATAFILE_SPDU_PDU_TRANSPORT_MAPPING
, /* filename */
3000 true, /* from profile */
3001 (void **)&spdu_pdu_transport_mapping
, /* data_ptr */
3002 &spdu_pdu_transport_mapping_num
, /* numitems_ptr */
3003 UAT_AFFECTS_DISSECTION
, /* but not fields */
3005 copy_spdu_pdu_transport_mapping_cb
, /* copy callback */
3006 update_spdu_pdu_transport_mapping
, /* update callback */
3007 NULL
, /* free callback */
3008 post_update_spdu_pdu_transport_mapping_cb
, /* post update callback */
3009 NULL
, /* reset callback */
3010 spdu_pdu_transport_mapping_uat_fields
/* UAT field definitions */
3013 prefs_register_uat_preference(spdu_module
, "_spdu_pdu_transport_mapping", "PDU Transport Mappings",
3014 "A table to map PDU Transport payloads to Signal PDUs", spdu_pdu_transport_mapping_uat
);
3017 spdu_ipdum_mapping_uat
= uat_new("AUTOSAR I-PduM",
3018 sizeof(spdu_ipdum_mapping_uat_t
), /* record size */
3019 DATAFILE_SPDU_IPDUM_MAPPING
, /* filename */
3020 true, /* from profile */
3021 (void **)&spdu_ipdum_mapping
, /* data_ptr */
3022 &spdu_ipdum_mapping_num
, /* numitems_ptr */
3023 UAT_AFFECTS_DISSECTION
, /* but not fields */
3025 copy_spdu_ipdum_mapping_cb
, /* copy callback */
3026 update_spdu_ipdum_mapping
, /* update callback */
3027 NULL
, /* free callback */
3028 post_update_spdu_ipdum_mapping_cb
, /* post update callback */
3029 NULL
, /* reset callback */
3030 spdu_ipdum_mapping_uat_fields
/* UAT field definitions */
3033 prefs_register_uat_preference(spdu_module
, "_spdu_ipdum_mapping", "IPduM Mappings",
3034 "A table to map AUTOSAR I-PduM PDUs to Signal PDUs", spdu_ipdum_mapping_uat
);
3037 spdu_dlt_mapping_uat
= uat_new("DLT",
3038 sizeof(spdu_dlt_mapping_uat_t
), /* record size */
3039 DATAFILE_SPDU_DLT_MAPPING
, /* filename */
3040 true, /* from profile */
3041 (void **)&spdu_dlt_mapping
, /* data_ptr */
3042 &spdu_dlt_mapping_num
, /* numitems_ptr */
3043 UAT_AFFECTS_DISSECTION
, /* but not fields */
3045 copy_spdu_dlt_mapping_cb
, /* copy callback */
3046 update_spdu_dlt_mapping
, /* update callback */
3047 NULL
, /* free callback */
3048 post_update_spdu_dlt_mapping_cb
, /* post update callback */
3049 NULL
, /* reset callback */
3050 spdu_dlt_mapping_uat_fields
/* UAT field definitions */
3053 prefs_register_uat_preference(spdu_module
, "_spdu_dlt_mapping", "DLT Mappings",
3054 "A table to map DLT non-verbose Payloads to Signal PDUs", spdu_dlt_mapping_uat
);
3057 spdu_uds_mapping_uat
= uat_new("UDS",
3058 sizeof(spdu_uds_mapping_uat_t
), /* record size */
3059 DATAFILE_SPDU_UDS_MAPPING
, /* filename */
3060 true, /* from profile */
3061 (void **)&spdu_uds_mapping
, /* data_ptr */
3062 &spdu_uds_mapping_num
, /* numitems_ptr */
3063 UAT_AFFECTS_DISSECTION
, /* but not fields */
3065 copy_spdu_uds_mapping_cb
, /* copy callback */
3066 update_spdu_uds_mapping
, /* update callback */
3067 NULL
, /* free callback */
3068 post_update_spdu_uds_mapping_cb
, /* post update callback */
3069 NULL
, /* reset callback */
3070 spdu_uds_mapping_uat_fields
/* UAT field definitions */
3073 prefs_register_uat_preference(spdu_module
, "_spdu_uds_mapping", "UDS Mappings",
3074 "A table to map UDS payloads to Signal PDUs", spdu_uds_mapping_uat
);
3077 spdu_isobus_mapping_uat
= uat_new("ISOBUS",
3078 sizeof(spdu_isobus_mapping_uat_t
), /* record size */
3079 DATAFILE_SPDU_ISOBUS_MAPPING
, /* filename */
3080 true, /* from profile */
3081 (void **)&spdu_isobus_mapping
, /* data_ptr */
3082 &spdu_isobus_mapping_num
, /* numitems_ptr */
3083 UAT_AFFECTS_DISSECTION
, /* but not fields */
3085 copy_spdu_isobus_mapping_cb
, /* copy callback */
3086 update_spdu_isobus_mapping
, /* update callback */
3087 NULL
, /* free callback */
3088 post_update_spdu_isobus_mapping_cb
, /* post update callback */
3089 NULL
, /* reset callback */
3090 spdu_isobus_mapping_uat_fields
/* UAT field definitions */
3093 prefs_register_uat_preference(spdu_module
, "_spdu_isobus_mapping", "ISOBUS Mappings",
3094 "A table to map ISOBUS payloads to Signal PDUs", spdu_isobus_mapping_uat
);
3097 /* Aggregation Feature */
3098 spdu_aggregation_data
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash
, g_direct_equal
);
3102 proto_reg_handoff_signal_pdu(void) {
3103 static bool initialized
= false;
3106 signal_pdu_handle_someip
= register_dissector("signal_pdu_over_someip", dissect_spdu_message_someip
, proto_signal_pdu
);
3108 signal_pdu_handle_can
= register_dissector("signal_pdu_over_can", dissect_spdu_message_can
, proto_signal_pdu
);
3109 dissector_add_for_decode_as("can.subdissector", signal_pdu_handle_can
);
3110 heur_dissector_add("can", dissect_spdu_message_can_heur
, "Signal PDU over CAN", "signal_pdu_can_heur", proto_signal_pdu
, HEURISTIC_ENABLE
);
3112 signal_pdu_handle_flexray
= register_dissector("signal_pdu_over_flexray", dissect_spdu_message_flexray
, proto_signal_pdu
);
3113 dissector_add_for_decode_as("flexray.subdissector", signal_pdu_handle_flexray
);
3114 heur_dissector_add("flexray", dissect_spdu_message_flexray_heur
, "Signal PDU over FlexRay", "signal_pdu_flexray_heur", proto_signal_pdu
, HEURISTIC_ENABLE
);
3116 signal_pdu_handle_lin
= register_dissector("signal_pdu_over_lin", dissect_spdu_message_lin
, proto_signal_pdu
);
3118 signal_pdu_handle_pdu_transport
= register_dissector("signal_pdu_over_pdu_transport", dissect_spdu_message_pdu_transport
, proto_signal_pdu
);
3120 signal_pdu_handle_ipdum
= register_dissector("signal_pdu_over_IPduM", dissect_spdu_message_ipdum
, proto_signal_pdu
);
3122 heur_dissector_add("dlt", dissect_spdu_message_dlt_heur
, "Signal PDU over DLT", "signal_pdu_dlt_heur", proto_signal_pdu
, HEURISTIC_ENABLE
);
3124 heur_dissector_add("uds", dissect_spdu_message_uds_heur
, "Signal PDU over UDS", "signal_pdu_uds_heur", proto_signal_pdu
, HEURISTIC_ENABLE
);
3126 signal_pdu_handle_isobus
= register_dissector("signal_pdu_over_ISOBUS", dissect_spdu_message_isobus
, proto_signal_pdu
);
3138 * indent-tabs-mode: nil
3141 * ex: set shiftwidth=4 tabstop=8 expandtab:
3142 * :indentSize=4:tabSize=8:noTabs=true: