Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-smpte-291-vanc.c
Warning:line 1879, column 13
Value stored to 'offset' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-smpte-291-vanc.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-09-08-100406-3660-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-smpte-291-vanc.c
1/* packet-smpte-291-vanc.c
2 * SMPTE ST 291 ancillary-data parsing and built-in VANC application dissectors.
3 *
4 * Built-in application payloads implemented in this source file:
5 * SMPTE ST 12-2, SMPTE ST 2010, SMPTE ST 2016-3, SMPTE ST 2031,
6 * SMPTE ST 334-2, and Free TV Australia OP-47 / SMPTE RDD 8.
7 *
8 * Copyright (c) 2026, Devin Heitmueller <dheitmueller@ltnglobal.com>
9 *
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
13 *
14 * SPDX-License-Identifier: GPL-2.0-or-later
15 */
16
17#include "config.h"
18
19#include <epan/expert.h>
20#include <epan/packet.h>
21#include <epan/reassemble.h>
22#include <epan/tfs.h>
23#include <wsutil/array.h>
24#include <wsutil/bitswap.h>
25
26#include "packet-smpte-291-vanc.h"
27
28/* Protocol, field, subtree, expert, and dissector declarations */
29
30/* SMPTE ST 291 common declarations */
31static int proto_st291;
32static int hf_st291_did;
33static int hf_st291_sdid;
34static int hf_st291_dbn;
35static dissector_table_t st291_did_sdid_table;
36
37/* SMPTE ST 12-2 declarations */
38static int proto_st12_2;
39static int hf_st12_2_timecode;
40static int hf_st12_2_frame_units;
41static int hf_st12_2_frame_tens;
42static int hf_st12_2_second_units;
43static int hf_st12_2_second_tens;
44static int hf_st12_2_minute_units;
45static int hf_st12_2_minute_tens;
46static int hf_st12_2_hour_units;
47static int hf_st12_2_hour_tens;
48static int hf_st12_2_binary_group_1;
49static int hf_st12_2_binary_group_2;
50static int hf_st12_2_binary_group_3;
51static int hf_st12_2_binary_group_4;
52static int hf_st12_2_binary_group_5;
53static int hf_st12_2_binary_group_6;
54static int hf_st12_2_binary_group_7;
55static int hf_st12_2_binary_group_8;
56static int hf_st12_2_flag_bit_10;
57static int hf_st12_2_flag_bit_11;
58static int hf_st12_2_flag_bit_27;
59static int hf_st12_2_flag_bit_43;
60static int hf_st12_2_flag_bit_58;
61static int hf_st12_2_flag_bit_59;
62static int hf_st12_2_payload_type;
63static int hf_st12_2_vitc;
64static int hf_st12_2_vitc_line_sel;
65static int hf_st12_2_vitc_line_dup;
66static int hf_st12_2_vitc_validity;
67static int hf_st12_2_vitc_process;
68static int ett_st12_2;
69static int ett_st12_2_timecode;
70static int ett_st12_2_vitc;
71static expert_field ei_st12_2_bad_length = EI_INIT{0, 0};
72static dissector_handle_t st12_2_handle;
73
74/* SMPTE ST 2010 declarations */
75static int proto_st2010;
76static int hf_st2010_payload_descriptor;
77static int hf_st2010_reserved;
78static int hf_st2010_version;
79static int hf_st2010_continued_pkt;
80static int hf_st2010_following_pkt;
81static int hf_st2010_duplicate_msg;
82static int hf_st2010_payload;
83static int hf_st2010_fragments;
84static int hf_st2010_fragment;
85static int hf_st2010_fragment_overlap;
86static int hf_st2010_fragment_overlap_conflict;
87static int hf_st2010_fragment_multiple_tails;
88static int hf_st2010_fragment_too_long_fragment;
89static int hf_st2010_fragment_error;
90static int hf_st2010_fragment_count;
91static int hf_st2010_reassembled_in;
92static int hf_st2010_reassembled_length;
93static int hf_st2010_reassembled_data;
94static int ett_st2010;
95static int ett_st2010_fragment;
96static int ett_st2010_fragments;
97static expert_field ei_st2010_bad_version = EI_INIT{0, 0};
98static expert_field ei_st2010_reserved_bits = EI_INIT{0, 0};
99static expert_field ei_st2010_orphan_fragment = EI_INIT{0, 0};
100static expert_field ei_st2010_overlapping_message = EI_INIT{0, 0};
101static expert_field ei_st2010_empty_payload = EI_INIT{0, 0};
102static dissector_handle_t st2010_handle;
103static dissector_table_t st2010_payload_table;
104static reassembly_table st2010_reassembly_table;
105
106/* SMPTE ST 2016-3 declarations */
107static int proto_st2016_3;
108static int hf_st2016_3_afd_byte;
109static int hf_st2016_3_afd_code;
110static int hf_st2016_3_afd_ar;
111static int hf_st2016_3_afd_reserved;
112static int hf_st2016_3_reserved_1;
113static int hf_st2016_3_reserved_2;
114static int hf_st2016_3_bar_flags;
115static int hf_st2016_3_bar_top;
116static int hf_st2016_3_bar_bottom;
117static int hf_st2016_3_bar_left;
118static int hf_st2016_3_bar_right;
119static int hf_st2016_3_bar_reserved;
120static int hf_st2016_3_bar_value_1;
121static int hf_st2016_3_bar_value_1_marker;
122static int hf_st2016_3_bar_value_1_data;
123static int hf_st2016_3_bar_value_2;
124static int hf_st2016_3_bar_value_2_marker;
125static int hf_st2016_3_bar_value_2_data;
126static int hf_st2016_3_bar_value_1_meaning;
127static int hf_st2016_3_bar_value_2_meaning;
128static int ett_st2016_3;
129static int ett_st2016_3_afd;
130static int ett_st2016_3_bar_flags;
131static int ett_st2016_3_bar_value_1;
132static int ett_st2016_3_bar_value_2;
133static expert_field ei_st2016_3_bad_length;
134static expert_field ei_st2016_3_afd_reserved;
135static expert_field ei_st2016_3_reserved_udw;
136static expert_field ei_st2016_3_bar_reserved;
137static expert_field ei_st2016_3_bar_flags_invalid;
138static expert_field ei_st2016_3_bar_marker;
139static dissector_handle_t st2016_3_handle;
140
141/* SMPTE ST 334-2 declarations */
142static int proto_st334_2;
143static int hf_st334_2_cdp_identifier;
144static int hf_st334_2_cdp_length;
145static int hf_st334_2_frame_rate;
146static int hf_st334_2_header_reserved;
147static int hf_st334_2_time_code_present;
148static int hf_st334_2_ccdata_present;
149static int hf_st334_2_svcinfo_present;
150static int hf_st334_2_svc_info_start;
151static int hf_st334_2_svc_info_change;
152static int hf_st334_2_svc_info_complete;
153static int hf_st334_2_caption_service_active;
154static int hf_st334_2_header_reserved_bit;
155static int hf_st334_2_header_sequence_counter;
156static int hf_st334_2_section_id;
157static int hf_st334_2_timecode;
158static int hf_st334_2_tc_field_flag;
159static int hf_st334_2_drop_frame_flag;
160static int hf_st334_2_cc_count;
161static int hf_st334_2_cc_marker_bits;
162static int hf_st334_2_cc_valid;
163static int hf_st334_2_cc_type;
164static int hf_st334_2_cc_data_1;
165static int hf_st334_2_cc_data_2;
166static int hf_st334_2_dtvcc_data;
167static int hf_st334_2_svc_reserved;
168static int hf_st334_2_svc_info_start_section;
169static int hf_st334_2_svc_info_change_section;
170static int hf_st334_2_svc_info_complete_section;
171static int hf_st334_2_svc_count;
172static int hf_st334_2_csn_reserved;
173static int hf_st334_2_csn_size;
174static int hf_st334_2_csn_reserved_2;
175static int hf_st334_2_caption_service_number;
176static int hf_st334_2_service_data;
177static int hf_st334_2_service_language;
178static int hf_st334_2_service_digital_cc;
179static int hf_st334_2_service_digital_reserved;
180static int hf_st334_2_service_line21_reserved;
181static int hf_st334_2_service_line21_field;
182static int hf_st334_2_service_descriptor_number;
183static int hf_st334_2_service_easy_reader;
184static int hf_st334_2_service_wide_aspect_ratio;
185static int hf_st334_2_service_reserved_14;
186static int hf_st334_2_future_length;
187static int hf_st334_2_future_data;
188static int hf_st334_2_footer_sequence_counter;
189static int hf_st334_2_packet_checksum;
190static int hf_st334_2_checksum_calculated;
191static int ett_st334_2;
192static int ett_st334_2_header;
193static int ett_st334_2_timecode;
194static int ett_st334_2_ccdata;
195static int ett_st334_2_cc_construct;
196static int ett_st334_2_svcinfo;
197static int ett_st334_2_service;
198static int ett_st334_2_service_data;
199static int ett_st334_2_future;
200static int ett_st334_2_footer;
201static expert_field ei_st334_2_bad_identifier;
202static expert_field ei_st334_2_bad_length;
203static expert_field ei_st334_2_bad_reserved;
204static expert_field ei_st334_2_bad_section_order;
205static expert_field ei_st334_2_duplicate_section;
206static expert_field ei_st334_2_missing_section;
207static expert_field ei_st334_2_cc_count;
208static expert_field ei_st334_2_bad_marker;
209static expert_field ei_st334_2_sequence_mismatch;
210static expert_field ei_st334_2_bad_checksum;
211static expert_field ei_st334_2_truncated;
212static dissector_handle_t st334_2_handle;
213
214/* SMPTE ST 2031 declarations */
215static int proto_st2031;
216static int hf_st2031_data_identifier;
217static int hf_st2031_data_unit_id;
218static int hf_st2031_data_unit_length;
219static int hf_st2031_field_parity;
220static int hf_st2031_line_offset;
221static int hf_st2031_framing_code;
222static int hf_st2031_magazine_hamming;
223static int hf_st2031_magazine;
224static int hf_st2031_packet_number_hamming;
225static int hf_st2031_packet_number;
226static int hf_st2031_page_units_hamming;
227static int hf_st2031_page_units;
228static int hf_st2031_page_tens_hamming;
229static int hf_st2031_page_tens;
230static int hf_st2031_data_string;
231static int hf_st2031_textdata_array;
232static int hf_st2031_erase_page;
233static int hf_st2031_newsflash;
234static int hf_st2031_subtitle;
235static int hf_st2031_suppress_header;
236static int hf_st2031_update_indicator;
237static int hf_st2031_interrupted_sequence;
238static int hf_st2031_inhibit_display;
239static int hf_st2031_magazine_serial;
240static int hf_st2031_character_set;
241static int hf_st2031_tt_control;
242static int ett_st2031;
243static dissector_handle_t st2031_handle;
244
245/* OP-47 / SMPTE RDD 8 declarations */
246static int proto_op47;
247static int hf_op47_sdp_identifier;
248static int hf_op47_sdp_length;
249static int hf_op47_sdp_format_code;
250static int hf_op47_sdp_adaption_header;
251static int hf_op47_sdp_pkt_desc_b;
252static int hf_op47_clock_runin;
253static int hf_op47_framing_code;
254static int hf_op47_magazine_hamming;
255static int hf_op47_magazine;
256static int hf_op47_packet_number_hamming;
257static int hf_op47_packet_number;
258static int hf_op47_page_units_hamming;
259static int hf_op47_page_units;
260static int hf_op47_page_tens_hamming;
261static int hf_op47_page_tens;
262static int hf_op47_data_string;
263static int hf_op47_textdata_array;
264static int hf_op47_erase_page;
265static int hf_op47_newsflash;
266static int hf_op47_subtitle;
267static int hf_op47_suppress_header;
268static int hf_op47_update_indicator;
269static int hf_op47_interrupted_sequence;
270static int hf_op47_inhibit_display;
271static int hf_op47_magazine_serial;
272static int hf_op47_character_set;
273static int hf_op47_tt_control;
274static int ett_op47;
275static int ett_op47_wst;
276static dissector_handle_t op47_handle;
277
278/* ST 291 Type 2 DID/SDID keys used by the built-in VANC dissectors. */
279#define ST12_2_DID_SDID_KEY0x6060 0x6060
280#define ST2010_DID_SDID_KEY0x4107 0x4107
281#define ST2016_3_DID_SDID_KEY0x4105 0x4105
282#define ST334_2_DID_SDID_KEY0x6101 0x6101
283#define ST334_2_CDP_IDENTIFIER0x9669 0x9669
284#define ST2031_DID_SDID_KEY0x4108 0x4108
285#define OP47_DID_SDID_KEY0x4302 0x4302
286
287#define ST2010_PAYLOAD_SCTE1040 0
288/*
289 * SMPTE ST 291-1 ancillary-data core and DID/SDID dispatch
290 */
291
292
293/*
294 * Registered SMPTE ST 291 DID/SDID assignments.
295 *
296 * SMPTE ST 291-1:2011, Sec. 4 assigns DID values through the SMPTE
297 * Registration Authority; Sec. 5.1 defines Type 1 versus Type 2 packets.
298 *
299 * Source: SMPTE Registration Authority, "Data Identification Word
300 * Assignments for Registered DIDs", downloaded from:
301 * https://www.smpte-ra.org/smpte-ancillary-data-smpte-st-291
302 *
303 * The register contained 81 assignments when reviewed on 2026-09-05.
304 * Keep this table synchronized with the SMPTE RA register rather than with
305 * transport-specific dissectors such as ST 2110-40 or ST 2038.
306 */
307typedef struct {
308 uint8_t did;
309 uint8_t sdid;
310 const char *description;
311} st291_did_sdid_entry_t;
312
313typedef struct {
314 uint8_t did;
315 const char *description;
316} st291_did_entry_t;
317
318/* Type 2 identities: SMPTE ST 291-1:2011, Sec. 5.1 uses DID + SDID. */
319static const st291_did_sdid_entry_t st291_did_sdid_assignments[] = {
320 { 0x08, 0x08, "SMPTE ST 353: MPEG recoding data, VANC space" },
321 { 0x08, 0x0c, "SMPTE ST 353: MPEG recoding data, HANC space" },
322 { 0x40, 0x01, "SMPTE ST 305: SDTI transport in active frame space" },
323 { 0x40, 0x02, "SMPTE ST 348: HD-SDTI transport in active frame space" },
324 { 0x40, 0x04, "SMPTE ST 427: Link Encryption Message 1" },
325 { 0x40, 0x05, "SMPTE ST 427: Link Encryption Message 2" },
326 { 0x40, 0x06, "SMPTE ST 427: Link Encryption Metadata" },
327 { 0x41, 0x01, "SMPTE ST 352: Payload Identification, HANC space" },
328 { 0x41, 0x05, "SMPTE ST 2016-3: AFD and Bar Data" },
329 { 0x41, 0x06, "SMPTE ST 2016-4: Pan-Scan Data" },
330 { 0x41, 0x07, "SMPTE ST 2010: ANSI/SCTE 104 messages" },
331 { 0x41, 0x08, "SMPTE ST 2031: DVB/SCTE VBI data" },
332 { 0x41, 0x09, "SMPTE ST 2056: MPEG TS packets in VANC" },
333 { 0x41, 0x0a, "SMPTE ST 2068: Stereoscopic 3D Frame Compatible Packing and Signaling" },
334 { 0x41, 0x0b, "SMPTE ST 2064-2: Lip Sync data as specified by ST 2064-1" },
335 { 0x41, 0x0c, "SMPTE ST 2108-1: Extended HDR/WCG for SDI" },
336 { 0x41, 0x0d, "SMPTE ST 2108-2: Vertical Ancillary Data Mapping of KLV Formatted HDR/WCG Metadata" },
337 { 0x43, 0x01, "ITU-R BT.1685: Structure of inter-station control data conveyed by ancillary data packets" },
338 { 0x43, 0x02, "SMPTE RDD 8: Subtitling Distribution packet (SDP)" },
339 { 0x43, 0x03, "SMPTE RDD 8: Transport of ANC packet in an ANC Multipacket" },
340 { 0x43, 0x04, "ARIB TR-B29: Metadata to monitor errors of audio and video signals on a broadcasting chain" },
341 { 0x43, 0x05, "SMPTE RDD 18: Acquisition Metadata Sets for Video Camera Parameters" },
342 { 0x44, 0x04, "SMPTE RP 214: KLV Metadata transport in VANC space" },
343 { 0x44, 0x14, "SMPTE RP 214: KLV Metadata transport in HANC space" },
344 { 0x44, 0x44, "SMPTE RP 223: Packing UMID and Program Identification Label Data into ST 291 ancillary data packets" },
345 { 0x45, 0x01, "SMPTE ST 2020-1: Compressed Audio Metadata" },
346 { 0x45, 0x02, "SMPTE ST 2020-1: Compressed Audio Metadata" },
347 { 0x45, 0x03, "SMPTE ST 2020-1: Compressed Audio Metadata" },
348 { 0x45, 0x04, "SMPTE ST 2020-1: Compressed Audio Metadata" },
349 { 0x45, 0x05, "SMPTE ST 2020-1: Compressed Audio Metadata" },
350 { 0x45, 0x06, "SMPTE ST 2020-1: Compressed Audio Metadata" },
351 { 0x45, 0x07, "SMPTE ST 2020-1: Compressed Audio Metadata" },
352 { 0x45, 0x08, "SMPTE ST 2020-1: Compressed Audio Metadata" },
353 { 0x45, 0x09, "SMPTE ST 2020-1: Compressed Audio Metadata" },
354 { 0x46, 0x01, "SMPTE ST 2051: Two Frame Marker in HANC" },
355 { 0x50, 0x01, "SMPTE RDD 8: WSS data" },
356 { 0x51, 0x01, "SMPTE RP 215: Film Codes in VANC space" },
357 { 0x60, 0x60, "SMPTE ST 12-2: Ancillary Time Code" },
358 { 0x60, 0x61, "SMPTE ST 12-3: Time Code for High Frame Rate Signals" },
359 { 0x60, 0x62, "SMPTE ST 2103: Generic Time Label" },
360 { 0x61, 0x01, "SMPTE ST 334-1: EIA 708B Data mapping into VANC space" },
361 { 0x61, 0x02, "SMPTE ST 334-1: EIA 608 Data mapping into VANC space" },
362 { 0x62, 0x01, "SMPTE RP 207: Program Description in VANC space" },
363 { 0x62, 0x02, "SMPTE ST 334-1: Data broadcast (DTV) in VANC space" },
364 { 0x62, 0x03, "SMPTE RP 208: VBI Data in VANC space" },
365 { 0x64, 0x64, "SMPTE RP 196 (withdrawn): Time Code in HANC space" },
366 { 0x64, 0x7f, "SMPTE RP 196 (withdrawn): VITC in HANC space" },
367};
368
369/* Type 1 identities: SMPTE ST 291-1:2011, Sec. 5.1 uses DID + DBN. */
370static const st291_did_entry_t st291_did_assignments[] = {
371 { 0x00, "SMPTE ST 291: Undefined data deleted (deprecated)" },
372 { 0x80, "SMPTE ST 291: Packet marked for deletion" },
373 { 0x84, "SMPTE ST 291: End packet deleted (deprecated)" },
374 { 0x88, "SMPTE ST 291: Start packet deleted (deprecated)" },
375 { 0xa0, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 8 Control packet" },
376 { 0xa1, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 7 Control packet" },
377 { 0xa2, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 6 Control packet" },
378 { 0xa3, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 5 Control packet" },
379 { 0xa4, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 8" },
380 { 0xa5, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 7" },
381 { 0xa6, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 6" },
382 { 0xa7, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 5" },
383 { 0xe0, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
384 { 0xe1, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
385 { 0xe2, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
386 { 0xe3, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
387 { 0xe4, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
388 { 0xe5, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
389 { 0xe6, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
390 { 0xe7, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
391 { 0xec, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
392 { 0xed, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
393 { 0xee, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
394 { 0xef, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
395 { 0xf0, "SMPTE ST 315: Camera position (HANC or VANC space)" },
396 { 0xf4, "SMPTE RP 165: Error Detection and Handling (HANC space)" },
397 { 0xf8, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
398 { 0xf9, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
399 { 0xfa, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
400 { 0xfb, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
401 { 0xfc, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
402 { 0xfd, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
403 { 0xfe, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
404 { 0xff, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
405};
406
407static const char *
408st291_lookup_did(uint8_t did)
409{
410 unsigned i;
411
412 for (i = 0; i < array_length(st291_did_assignments)(sizeof (st291_did_assignments) / sizeof (st291_did_assignments
)[0])
; i++) {
413 if (st291_did_assignments[i].did == did)
414 return st291_did_assignments[i].description;
415 }
416 return NULL((void*)0);
417}
418
419static const char *
420st291_lookup_did_sdid(uint8_t did, uint8_t sdid)
421{
422 unsigned i;
423
424 for (i = 0; i < array_length(st291_did_sdid_assignments)(sizeof (st291_did_sdid_assignments) / sizeof (st291_did_sdid_assignments
)[0])
; i++) {
425 if (st291_did_sdid_assignments[i].did == did &&
426 st291_did_sdid_assignments[i].sdid == sdid)
427 return st291_did_sdid_assignments[i].description;
428 }
429 return NULL((void*)0);
430}
431
432dissector_table_t
433st291_get_did_sdid_table(void)
434{
435 return st291_did_sdid_table;
436}
437
438/* SMPTE ST 291-1:2011, Secs. 5.1-5.2 -- DID/SDID/DBN on-wire identity fields. */
439proto_item *
440st291_tree_add_did(proto_tree *tree, tvbuff_t *tvb,
441 int offset, int length, uint8_t did)
442{
443 return proto_tree_add_uint(tree, hf_st291_did, tvb, offset, length, did);
444}
445
446proto_item *
447st291_tree_add_sdid(proto_tree *tree, tvbuff_t *tvb,
448 int offset, int length, uint8_t did _U___attribute__((unused)), uint8_t sdid)
449{
450 return proto_tree_add_uint(tree, hf_st291_sdid, tvb, offset, length, sdid);
451}
452
453/* SMPTE ST 291-1:2011, Sec. 5.1: bit b7 of the DID distinguishes the
454 * Type 1 (DBN) and Type 2 (SDID) identity forms used for the lookup. */
455void
456st291_append_packet_description(proto_item *item, uint8_t did, uint8_t sdid_or_dbn)
457{
458 const char *description;
459
460 if ((did & 0x80U) != 0)
461 description = st291_lookup_did(did);
462 else
463 description = st291_lookup_did_sdid(did, sdid_or_dbn);
464
465 if (description != NULL((void*)0))
466 proto_item_append_text(item, ": %s", description);
467}
468
469proto_item *
470st291_tree_add_dbn(proto_tree *tree, tvbuff_t *tvb,
471 int offset, int length, uint8_t dbn)
472{
473 return proto_tree_add_uint(tree, hf_st291_dbn, tvb, offset, length, dbn);
474}
475
476/* SMPTE ST 291-1:2011, Secs. 5.1-5.2 define DID, SDID and DBN.
477 * The st291.did_sdid table below is Wireshark-only dispatch metadata. */
478void
479proto_register_st291(void)
480{
481 static hf_register_info hf[] = {
482 { &hf_st291_did,
483 { "Data ID", "st291.did", FT_UINT8, BASE_HEX, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
484 { &hf_st291_sdid,
485 { "Secondary Data ID", "st291.sdid", FT_UINT8, BASE_HEX, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
486 { &hf_st291_dbn,
487 { "Data Block Number", "st291.dbn", FT_UINT8, BASE_HEX, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
488 };
489
490 proto_st291 = proto_register_protocol(
491 "SMPTE ST 291 Ancillary Data", "ST 291", "st291");
492
493 proto_register_field_array(proto_st291, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
494
495 /*
496 * Public extension point for ST 291 application payload dissectors.
497 * Native and Lua dissectors can register DID/SDID keys here for
498 * additional VANC payload formats.
499 */
500 st291_did_sdid_table = register_dissector_table(
501 "st291.did_sdid", "SMPTE ST 291 DID/SDID",
502 proto_st291, FT_UINT16, BASE_HEX);
503}
504
505/*
506 * SMPTE ST 12-2 time code in ancillary data
507 */
508
509
510/* SMPTE ST 12-2:2014, Sec. 6.2.1, Table 2 -- DBB1 payload type. */
511static const value_string st12_2_payload_type_vals[] = {
512 { 0x00, "Linear time code (ATC_LTC)" },
513 { 0x01, "Vertical interval time code #1 (ATC_VITC1)" },
514 { 0x02, "Vertical interval time code #2 (ATC_VITC2)" },
515 { 0x03, "User defined" },
516 { 0x04, "User defined" },
517 { 0x05, "User defined" },
518 { 0x06, "Film data block (transferred from reader)" },
519 { 0x07, "Production data block (transferred from reader)" },
520 { 0x7D, "Video tape data block (locally generated)" },
521 { 0x7E, "Film data block (locally generated)" },
522 { 0x7F, "Production data block (locally generated)" },
523 { 0, NULL((void*)0) }
524};
525
526/* SMPTE ST 12-2:2014, Sec. 6.2.2, Tables 3 and 5 -- DBB2 validity/process bits. */
527static const value_string st12_2_vitc_validity_vals[] = {
528 { 0, "No time code error received or locally generated time code address" },
529 { 1, "Transmitted time code interpolated from previous time code (received a time code error)" },
530 { 0, NULL((void*)0) }
531};
532
533static const value_string st12_2_vitc_process_vals[] = {
534 { 0, "Binary groups in time code data stream are processed to compensate for latency" },
535 { 1, "Binary groups in time code data stream are only retransmitted (no delay compensation)" },
536 { 0, NULL((void*)0) }
537};
538
539
540/*
541 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6 maps the 64 information bits
542 * defined by SMPTE ST 12-1 into UDW 1 through UDW 16. The time address
543 * is BCD; the intervening nibbles are the eight binary groups. The six
544 * remaining positions are ST 12-1 flag bits whose meaning depends on the
545 * television system/frame rate (ST 12-1:2014, Sec. 8.3 and Tables 1-3).
546 */
547static int
548dissect_st12_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
549{
550 const st291_vanc_dissector_data_t *st291_data =
551 (const st291_vanc_dissector_data_t *)data;
552 proto_tree *top_tree =
553 st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
554 proto_item *ti;
555 proto_tree *st12_tree;
556 proto_tree *time_tree;
557 proto_tree *vitc_tree;
558 uint8_t dbb1 = 0;
559 uint8_t dbb2 = 0;
560 uint8_t frame_units;
561 uint8_t frame_tens;
562 uint8_t second_units;
563 uint8_t second_tens;
564 uint8_t minute_units;
565 uint8_t minute_tens;
566 uint8_t hour_units;
567 uint8_t hour_tens;
568 uint8_t frames;
569 uint8_t seconds;
570 uint8_t minutes;
571 uint8_t hours;
572 bool_Bool drop_frame;
573 char time_str[16];
574 unsigned x;
575
576 ti = proto_tree_add_item(top_tree, proto_st12_2, tvb, 0,
577 tvb_captured_length(tvb), ENC_NA0x00000000);
578 st12_tree = proto_item_add_subtree(ti, ett_st12_2);
579
580 if (tvb_captured_length(tvb) < 16) {
581 expert_add_info_format(pinfo, ti, &ei_st12_2_bad_length,
582 "ST 12-2 requires at least 16 UDW bytes; packet contains %u",
583 tvb_captured_length(tvb));
584 return tvb_captured_length(tvb);
585 }
586
587 /*
588 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6 maps the 64 information
589 * bits defined by SMPTE ST 12-1 into UDW 1 through UDW 16.
590 *
591 * The time-address digits are BCD:
592 * UDW 1/3 -- frame units/tens
593 * UDW 5/7 -- second units/tens
594 * UDW 9/11 -- minute units/tens
595 * UDW 13/15 -- hour units/tens
596 *
597 * ST 12-2 Sec. 6.1.2 defines b4 as the least-significant bit of
598 * each four-bit information group.
599 */
600 frame_units = (tvb_get_uint8(tvb, 0) >> 4) & 0x0f;
601 frame_tens = (tvb_get_uint8(tvb, 2) >> 4) & 0x03;
602 second_units = (tvb_get_uint8(tvb, 4) >> 4) & 0x0f;
603 second_tens = (tvb_get_uint8(tvb, 6) >> 4) & 0x07;
604 minute_units = (tvb_get_uint8(tvb, 8) >> 4) & 0x0f;
605 minute_tens = (tvb_get_uint8(tvb, 10) >> 4) & 0x07;
606 hour_units = (tvb_get_uint8(tvb, 12) >> 4) & 0x0f;
607 hour_tens = (tvb_get_uint8(tvb, 14) >> 4) & 0x03;
608
609 frames = frame_tens * 10 + frame_units;
610 seconds = second_tens * 10 + second_units;
611 minutes = minute_tens * 10 + minute_units;
612 hours = hour_tens * 10 + hour_units;
613
614 /*
615 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6 maps ST 12-1 bit 10 to
616 * UDW 3 b6. SMPTE ST 12-1:2014, Table 3 identifies bit 10 as
617 * the drop-frame flag for the applicable 30-frame systems.
618 */
619 drop_frame = (tvb_get_uint8(tvb, 2) & 0x40) != 0;
620
621 snprintf(time_str, sizeof(time_str), "%02u:%02u:%02u%c%02u",
622 hours, minutes, seconds, drop_frame ? ';' : ':', frames);
623
624 /*
625 * This row is a human-readable representation of the 64 information
626 * bits below. It spans the actual UDW bytes rather than being marked
627 * generated, so selecting it highlights the complete ATC data block.
628 */
629 ti = proto_tree_add_string(st12_tree, hf_st12_2_timecode, tvb, 0, 16, time_str);
630 time_tree = proto_item_add_subtree(ti, ett_st12_2_timecode);
631
632 /*
633 * The BCD digit fields below are the actual on-wire nibbles from
634 * ST 12-2:2014, Sec. 6.3, Table 6. Their hf masks select the
635 * corresponding b4-b7 positions in each UDW byte.
636 */
637 /*
638 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6. Present the fields in
639 * UDW order so the protocol tree follows the packet layout directly.
640 */
641 /* UDW 1: units of frames */
642 proto_tree_add_item(time_tree, hf_st12_2_frame_units, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
643
644 /* UDW 2: binary group 1 */
645 proto_tree_add_item(time_tree, hf_st12_2_binary_group_1, tvb, 1, 1, ENC_BIG_ENDIAN0x00000000);
646
647 /* UDW 3: tens of frames, ST 12-1 flag bits 10 and 11 */
648 proto_tree_add_item(time_tree, hf_st12_2_frame_tens, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
649 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_10, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
650 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_11, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
651
652 /* UDW 4: binary group 2 */
653 proto_tree_add_item(time_tree, hf_st12_2_binary_group_2, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
654
655 /* UDW 5: units of seconds */
656 proto_tree_add_item(time_tree, hf_st12_2_second_units, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
657
658 /* UDW 6: binary group 3 */
659 proto_tree_add_item(time_tree, hf_st12_2_binary_group_3, tvb, 5, 1, ENC_BIG_ENDIAN0x00000000);
660
661 /* UDW 7: tens of seconds, ST 12-1 flag bit 27 */
662 proto_tree_add_item(time_tree, hf_st12_2_second_tens, tvb, 6, 1, ENC_BIG_ENDIAN0x00000000);
663 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_27, tvb, 6, 1, ENC_BIG_ENDIAN0x00000000);
664
665 /* UDW 8: binary group 4 */
666 proto_tree_add_item(time_tree, hf_st12_2_binary_group_4, tvb, 7, 1, ENC_BIG_ENDIAN0x00000000);
667
668 /* UDW 9: units of minutes */
669 proto_tree_add_item(time_tree, hf_st12_2_minute_units, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
670
671 /* UDW 10: binary group 5 */
672 proto_tree_add_item(time_tree, hf_st12_2_binary_group_5, tvb, 9, 1, ENC_BIG_ENDIAN0x00000000);
673
674 /* UDW 11: tens of minutes, ST 12-1 flag bit 43 */
675 proto_tree_add_item(time_tree, hf_st12_2_minute_tens, tvb, 10, 1, ENC_BIG_ENDIAN0x00000000);
676 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_43, tvb, 10, 1, ENC_BIG_ENDIAN0x00000000);
677
678 /* UDW 12: binary group 6 */
679 proto_tree_add_item(time_tree, hf_st12_2_binary_group_6, tvb, 11, 1, ENC_BIG_ENDIAN0x00000000);
680
681 /* UDW 13: units of hours */
682 proto_tree_add_item(time_tree, hf_st12_2_hour_units, tvb, 12, 1, ENC_BIG_ENDIAN0x00000000);
683
684 /* UDW 14: binary group 7 */
685 proto_tree_add_item(time_tree, hf_st12_2_binary_group_7, tvb, 13, 1, ENC_BIG_ENDIAN0x00000000);
686
687 /* UDW 15: tens of hours, ST 12-1 flag bits 58 and 59 */
688 proto_tree_add_item(time_tree, hf_st12_2_hour_tens, tvb, 14, 1, ENC_BIG_ENDIAN0x00000000);
689 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_58, tvb, 14, 1, ENC_BIG_ENDIAN0x00000000);
690 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_59, tvb, 14, 1, ENC_BIG_ENDIAN0x00000000);
691
692 /* UDW 16: binary group 8 */
693 proto_tree_add_item(time_tree, hf_st12_2_binary_group_8, tvb, 15, 1, ENC_BIG_ENDIAN0x00000000);
694
695 /*
696 * SMPTE ST 12-2:2014, Secs. 6.2.1-6.2.2, Tables 2-3.
697 * DBB1 is assembled from b4 of UDW 1-8; DBB2 from b4 of UDW 9-16.
698 * These bytes are logical fields spread across multiple UDWs, so they
699 * are shown as generated aggregate values.
700 */
701 for (x = 0; x < 8; x++) {
702 dbb1 |= tvb_get_bits8(tvb, (x) * 8 + 4, 1) << x;
703 dbb2 |= tvb_get_bits8(tvb, (8 + x) * 8 + 4, 1) << x;
704 }
705
706 ti = proto_tree_add_uint(st12_tree, hf_st12_2_payload_type, tvb, 0, 0, dbb1);
707 proto_item_set_generated(ti);
708
709 ti = proto_tree_add_uint(st12_tree, hf_st12_2_vitc, tvb, 0, 0, dbb2);
710 proto_item_set_generated(ti);
711
712 if (dbb1 == 0x01 || dbb1 == 0x02) {
713 vitc_tree = proto_item_add_subtree(ti, ett_st12_2_vitc);
714
715 ti = proto_tree_add_uint(vitc_tree, hf_st12_2_vitc_line_sel, tvb, 0, 0, dbb2);
716 proto_item_set_generated(ti);
717 ti = proto_tree_add_uint(vitc_tree, hf_st12_2_vitc_line_dup, tvb, 0, 0, dbb2);
718 proto_item_set_generated(ti);
719 ti = proto_tree_add_uint(vitc_tree, hf_st12_2_vitc_validity, tvb, 0, 0, dbb2);
720 proto_item_set_generated(ti);
721 ti = proto_tree_add_uint(vitc_tree, hf_st12_2_vitc_process, tvb, 0, 0, dbb2);
722 proto_item_set_generated(ti);
723 }
724
725 proto_item_append_text(proto_tree_get_parent(st12_tree), ": %s", time_str);
726
727 return tvb_captured_length(tvb);
728}
729
730void
731proto_register_st12_2(void)
732{
733 static hf_register_info hf[] = {
734 { &hf_st12_2_timecode,
735 { "Time Code", "st12_2.timecode", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
736
737 /* SMPTE ST 12-2:2014, Sec. 6.3, Table 6. */
738 { &hf_st12_2_frame_units,
739 { "Frame Units", "st12_2.time.frames.units", FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0),
740 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
741 { &hf_st12_2_frame_tens,
742 { "Frame Tens", "st12_2.time.frames.tens", FT_UINT8, BASE_DEC, NULL((void*)0), 0x30, NULL((void*)0),
743 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
744 { &hf_st12_2_second_units,
745 { "Second Units", "st12_2.time.seconds.units", FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0),
746 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
747 { &hf_st12_2_second_tens,
748 { "Second Tens", "st12_2.time.seconds.tens", FT_UINT8, BASE_DEC, NULL((void*)0), 0x70, NULL((void*)0),
749 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
750 { &hf_st12_2_minute_units,
751 { "Minute Units", "st12_2.time.minutes.units", FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0),
752 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
753 { &hf_st12_2_minute_tens,
754 { "Minute Tens", "st12_2.time.minutes.tens", FT_UINT8, BASE_DEC, NULL((void*)0), 0x70, NULL((void*)0),
755 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
756 { &hf_st12_2_hour_units,
757 { "Hour Units", "st12_2.time.hours.units", FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0),
758 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
759 { &hf_st12_2_hour_tens,
760 { "Hour Tens", "st12_2.time.hours.tens", FT_UINT8, BASE_DEC, NULL((void*)0), 0x30, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
761
762 /*
763 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6;
764 * SMPTE ST 12-1:2014, Table 3.
765 */
766 { &hf_st12_2_flag_bit_10,
767 { "ST 12-1 Flag Bit 10 (Drop Frame in 30-frame systems)", "st12_2.flag.bit10",
768 FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
769 { &hf_st12_2_flag_bit_11,
770 { "ST 12-1 Flag Bit 11 (Color Frame in 30/25-frame systems)", "st12_2.flag.bit11",
771 FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
772 { &hf_st12_2_flag_bit_27,
773 { "ST 12-1 Flag Bit 27", "st12_2.flag.bit27", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
774 { &hf_st12_2_flag_bit_43,
775 { "ST 12-1 Flag Bit 43", "st12_2.flag.bit43", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
776 { &hf_st12_2_flag_bit_58,
777 { "ST 12-1 Flag Bit 58", "st12_2.flag.bit58", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
778 { &hf_st12_2_flag_bit_59,
779 { "ST 12-1 Flag Bit 59", "st12_2.flag.bit59", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
780
781 /* SMPTE ST 12-2:2014, Sec. 6.3, Table 6; ST 12-1 Secs. 8.4-8.5. */
782 { &hf_st12_2_binary_group_1,
783 { "Binary Group 1", "st12_2.binary_group.1", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
784 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
785 { &hf_st12_2_binary_group_2,
786 { "Binary Group 2", "st12_2.binary_group.2", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
787 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
788 { &hf_st12_2_binary_group_3,
789 { "Binary Group 3", "st12_2.binary_group.3", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
790 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
791 { &hf_st12_2_binary_group_4,
792 { "Binary Group 4", "st12_2.binary_group.4", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
793 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
794 { &hf_st12_2_binary_group_5,
795 { "Binary Group 5", "st12_2.binary_group.5", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
796 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
797 { &hf_st12_2_binary_group_6,
798 { "Binary Group 6", "st12_2.binary_group.6", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
799 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
800 { &hf_st12_2_binary_group_7,
801 { "Binary Group 7", "st12_2.binary_group.7", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
802 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
803 { &hf_st12_2_binary_group_8,
804 { "Binary Group 8", "st12_2.binary_group.8", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
805 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
806
807 /* SMPTE ST 12-2:2014, Sec. 6.2.1, Table 2. */
808 { &hf_st12_2_payload_type,
809 { "Payload Type", "st12_2.payload_type", FT_UINT8, BASE_HEX,
810 VALS(st12_2_payload_type_vals)((0 ? (const struct _value_string*)0 : ((st12_2_payload_type_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
811
812 /* SMPTE ST 12-2:2014, Sec. 6.2.2, Tables 3-5. */
813 { &hf_st12_2_vitc,
814 { "VITC Data", "st12_2.vitc", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
815 { &hf_st12_2_vitc_line_sel,
816 { "Line Select", "st12_2.vitc.line_sel", FT_UINT8, BASE_DEC, NULL((void*)0), 0x1F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
817 { &hf_st12_2_vitc_line_dup,
818 { "Duplication", "st12_2.vitc.line_dup", FT_UINT8, BASE_DEC, NULL((void*)0), 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
819 { &hf_st12_2_vitc_validity,
820 { "TC Validity", "st12_2.vitc.validity", FT_UINT8, BASE_DEC,
821 VALS(st12_2_vitc_validity_vals)((0 ? (const struct _value_string*)0 : ((st12_2_vitc_validity_vals
))))
, 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
822 { &hf_st12_2_vitc_process,
823 { "Process Bit", "st12_2.vitc.process", FT_UINT8, BASE_DEC,
824 VALS(st12_2_vitc_process_vals)((0 ? (const struct _value_string*)0 : ((st12_2_vitc_process_vals
))))
, 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
825 };
826 static int *ett[] = {
827 &ett_st12_2,
828 &ett_st12_2_timecode,
829 &ett_st12_2_vitc,
830 };
831 static ei_register_info ei[] = {
832 { &ei_st12_2_bad_length,
833 { "st12_2.length.bad", PI_MALFORMED0x07000000, PI_WARN0x00600000,
834 "ST 12-2 payload contains fewer than 16 UDW bytes", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
835 };
836 expert_module_t *expert_st12_2;
837
838 proto_st12_2 = proto_register_protocol(
839 "SMPTE ST 12-2 Ancillary Time Code", "ST 12-2", "st12_2");
840 proto_register_field_array(proto_st12_2, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
841 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
842
843 expert_st12_2 = expert_register_protocol(proto_st12_2);
844 expert_register_field_array(expert_st12_2, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
845
846 st12_2_handle = register_dissector("st12_2", dissect_st12_2, proto_st12_2);
847}
848
849void
850proto_reg_handoff_st12_2(void)
851{
852 dissector_add_uint("st291.did_sdid", ST12_2_DID_SDID_KEY0x6060, st12_2_handle);
853}
854
855/*
856 * SMPTE ST 2010 SCTE-104 mapping
857 */
858
859static const fragment_items st2010_frag_items = {
860 &ett_st2010_fragment,
861 &ett_st2010_fragments,
862 &hf_st2010_fragments,
863 &hf_st2010_fragment,
864 &hf_st2010_fragment_overlap,
865 &hf_st2010_fragment_overlap_conflict,
866 &hf_st2010_fragment_multiple_tails,
867 &hf_st2010_fragment_too_long_fragment,
868 &hf_st2010_fragment_error,
869 &hf_st2010_fragment_count,
870 &hf_st2010_reassembled_in,
871 &hf_st2010_reassembled_length,
872 &hf_st2010_reassembled_data,
873 "ST 2010 message fragments"
874};
875
876static void
877call_st2010_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
878{
879 if (!dissector_try_uint(st2010_payload_table, ST2010_PAYLOAD_SCTE1040,
880 tvb, pinfo, tree)) {
881 call_data_dissector(tvb, pinfo, tree);
882 }
883}
884
885/* SMPTE 2010-2008, Sec. 5.2, Tables 1-3; Sec. 5.4 for multi-packet reassembly. */
886static int
887dissect_st2010(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
888{
889 const st291_vanc_dissector_data_t *st291_data =
890 (const st291_vanc_dissector_data_t *)data;
891 proto_tree *payload_tree =
892 st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
893 const unsigned len = tvb_captured_length(tvb);
894 uint8_t desc;
895 unsigned version;
896 bool_Bool continued_pkt;
897 bool_Bool following_pkt;
898 bool_Bool duplicate_msg;
899 proto_item *ti;
900 proto_tree *st2010_tree;
901 fragment_head *fd_head;
902 tvbuff_t *reassembled_tvb;
903 bool_Bool save_fragmented;
904
905 if (len < 1)
906 return 0;
907
908 desc = tvb_get_uint8(tvb, 0);
909 version = (desc & 0x18) >> 3;
910 continued_pkt = (desc & 0x04) != 0;
911 following_pkt = (desc & 0x02) != 0;
912 duplicate_msg = (desc & 0x01) != 0;
913
914 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ST2010");
915
916 ti = proto_tree_add_item(tree, proto_st2010, tvb, 0, -1, ENC_NA0x00000000);
917 st2010_tree = proto_item_add_subtree(ti, ett_st2010);
918
919 proto_tree_add_item(st2010_tree, hf_st2010_payload_descriptor, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
920 proto_tree_add_item(st2010_tree, hf_st2010_reserved, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
921 proto_tree_add_item(st2010_tree, hf_st2010_version, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
922 proto_tree_add_item(st2010_tree, hf_st2010_continued_pkt, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
923 proto_tree_add_item(st2010_tree, hf_st2010_following_pkt, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
924 proto_tree_add_item(st2010_tree, hf_st2010_duplicate_msg, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
925
926 if ((desc & 0xE0) != 0)
927 expert_add_info(pinfo, ti, &ei_st2010_reserved_bits);
928 if (version != 1)
929 expert_add_info(pinfo, ti, &ei_st2010_bad_version);
930
931 proto_item_append_text(ti, ": version %u%s%s%s",
932 version,
933 continued_pkt ? ", continued" : "",
934 following_pkt ? ", following" : "",
935 duplicate_msg ? ", duplicate" : "");
936
937 if (len <= 1) {
938 expert_add_info(pinfo, ti, &ei_st2010_empty_payload);
939 return len;
940 }
941
942 proto_tree_add_item(st2010_tree, hf_st2010_payload, tvb, 1, -1, ENC_NA0x00000000);
943
944 /* Single-packet SCTE-104 message. */
945 if (!continued_pkt && !following_pkt) {
946 tvbuff_t *msg_tvb = tvb_new_subset_remaining(tvb, 1);
947 call_st2010_payload(msg_tvb, pinfo, payload_tree);
948 return len;
949 }
950
951 /*
952 * Fragmented ST 2010 message. ST 2010 supplies no fragment number or
953 * message identifier, so fragments are appended in capture order. The
954 * reassembly key is the enclosing flow (addresses + ports) plus ID 0.
955 * ST 2010 permits only one complete SCTE-104 message per video frame,
956 * so overlapping in-progress messages on one flow are malformed.
957 */
958 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
959 fragment_head *active = fragment_get(&st2010_reassembly_table, pinfo, 0, NULL((void*)0));
960
961 if (!following_pkt) {
962 if (active != NULL((void*)0)) {
963 expert_add_info(pinfo, ti, &ei_st2010_overlapping_message);
964 return len;
965 }
966 } else if (active == NULL((void*)0)) {
967 expert_add_info(pinfo, ti, &ei_st2010_orphan_fragment);
968 return len;
969 }
970 }
971
972 save_fragmented = pinfo->fragmented;
973 pinfo->fragmented = true1;
974 fd_head = fragment_add_seq_next(&st2010_reassembly_table,
975 tvb, 1, pinfo, 0, NULL((void*)0),
976 len - 1, continued_pkt);
977
978 reassembled_tvb = process_reassembled_data(tvb, 1, pinfo,
979 "Reassembled SCTE-104 Message",
980 fd_head, &st2010_frag_items,
981 NULL((void*)0), st2010_tree);
982 pinfo->fragmented = save_fragmented;
983
984 if (reassembled_tvb != NULL((void*)0))
985 call_st2010_payload(reassembled_tvb, pinfo, payload_tree);
986
987 return len;
988}
989
990void
991proto_register_st2010(void)
992{
993 static hf_register_info hf[] = {
994 { &hf_st2010_payload_descriptor,
995 { "Payload Descriptor", "st2010.payload_descriptor", FT_UINT8, BASE_HEX, NULL((void*)0), 0x00,
996 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
997 { &hf_st2010_reserved,
998 { "Reserved", "st2010.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0xE0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
999 { &hf_st2010_version,
1000 { "Mapping Version", "st2010.version", FT_UINT8, BASE_DEC, NULL((void*)0), 0x18, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1001 { &hf_st2010_continued_pkt,
1002 { "Continued Packet", "st2010.continued_pkt", FT_BOOLEAN, 8, NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1003 { &hf_st2010_following_pkt,
1004 { "Following Packet", "st2010.following_pkt", FT_BOOLEAN, 8, NULL((void*)0), 0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1005 { &hf_st2010_duplicate_msg,
1006 { "Duplicate Message", "st2010.duplicate_msg", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0),
1007 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1008 { &hf_st2010_payload,
1009 { "SCTE-104 Message Bytes", "st2010.payload", FT_BYTES, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0),
1010 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1011
1012 { &hf_st2010_fragments,
1013
1014 { "Reassembled ST 2010 fragments", "st2010.fragments", FT_NONE, BASE_NONE, NULL((void*)0),
1015
1016 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1017 { &hf_st2010_fragment,
1018 { "ST 2010 fragment", "st2010.fragment", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0),
1019 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1020 { &hf_st2010_fragment_overlap,
1021 { "ST 2010 fragment overlap", "st2010.fragment.overlap", FT_BOOLEAN, BASE_NONE,
1022 NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1023 { &hf_st2010_fragment_overlap_conflict,
1024 { "ST 2010 fragment overlap conflict", "st2010.fragment.overlap.conflict",
1025 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1026 { &hf_st2010_fragment_multiple_tails,
1027 { "ST 2010 multiple tail fragments", "st2010.fragment.multiple_tails", FT_BOOLEAN,
1028 BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1029 { &hf_st2010_fragment_too_long_fragment,
1030 { "ST 2010 fragment too long", "st2010.fragment.too_long_fragment", FT_BOOLEAN,
1031 BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1032 { &hf_st2010_fragment_error,
1033 { "ST 2010 reassembly error in frame", "st2010.fragment.error", FT_FRAMENUM,
1034 BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1035 { &hf_st2010_fragment_count,
1036 { "ST 2010 fragment count", "st2010.fragment.count", FT_UINT32, BASE_DEC, NULL((void*)0),
1037 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1038 { &hf_st2010_reassembled_in,
1039 { "Reassembled in", "st2010.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x00,
1040 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1041 { &hf_st2010_reassembled_length,
1042 { "Reassembled length", "st2010.reassembled.length", FT_UINT32, BASE_DEC, NULL((void*)0),
1043 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1044 { &hf_st2010_reassembled_data,
1045 { "Reassembled SCTE-104 data", "st2010.reassembled.data", FT_BYTES, BASE_NONE, NULL((void*)0),
1046 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1047 };
1048
1049 static int *ett[] = {
1050 &ett_st2010,
1051 &ett_st2010_fragment,
1052 &ett_st2010_fragments,
1053 };
1054
1055 static ei_register_info ei[] = {
1056 { &ei_st2010_bad_version,
1057 { "st2010.version.invalid", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1058 "ST 2010 mapping version is not Version 1", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1059 { &ei_st2010_reserved_bits,
1060 { "st2010.reserved.nonzero", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1061 "Reserved Payload Descriptor bits are non-zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1062 { &ei_st2010_orphan_fragment,
1063 { "st2010.fragment.orphan", PI_REASSEMBLE0x06000000, PI_WARN0x00600000,
1064 "Following ST 2010 fragment seen without a preceding first fragment", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1065 { &ei_st2010_overlapping_message,
1066 { "st2010.fragment.overlap_message", PI_REASSEMBLE0x06000000, PI_WARN0x00600000,
1067 "New ST 2010 message started while another message is still being reassembled",
1068 EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1069 { &ei_st2010_empty_payload,
1070 { "st2010.payload.empty", PI_MALFORMED0x07000000, PI_WARN0x00600000,
1071 "ST 2010 packet contains a Payload Descriptor but no SCTE-104 bytes", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1072 };
1073
1074 expert_module_t *expert;
1075
1076 proto_st2010 = proto_register_protocol("SMPTE ST 2010", "ST 2010", "st2010");
1077 proto_register_field_array(proto_st2010, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1078 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1079
1080 expert = expert_register_protocol(proto_st2010);
1081 expert_register_field_array(expert, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1082
1083 reassembly_table_register(&st2010_reassembly_table,
1084 &addresses_ports_reassembly_table_functions);
1085
1086 /*
1087 * Public payload table. Key 0 is the complete SCTE-104 message. A Lua
1088 * dissector can register here after all compiled dissectors initialize.
1089 */
1090 st2010_payload_table = register_dissector_table(
1091 "st2010.payload_type", "ST 2010 Payload Type", proto_st2010, FT_UINT8, BASE_DEC);
1092
1093 st2010_handle = register_dissector("st2010", dissect_st2010, proto_st2010);
1094}
1095
1096void
1097proto_reg_handoff_st2010(void)
1098{
1099 dissector_add_uint("st291.did_sdid", ST2010_DID_SDID_KEY0x4107, st2010_handle);
1100}
1101
1102/*
1103 * SMPTE ST 2016-3 active format description and bar data
1104 */
1105
1106static const struct true_false_string st2016_3_tfs_afd_ar = {
1107 "16:9 coded frame",
1108 "4:3 coded frame"
1109};
1110
1111/* SMPTE ST 2016-1:2009, Sec. 5, Table 1 -- AFD code meaning depends on coded-frame AR. */
1112static const char *
1113st2016_3_afd_description(uint8_t afd, bool_Bool ar_16_9)
1114{
1115 static const char *const afd_4_3[16] = {
1116 "Undefined",
1117 "Reserved",
1118 "Letterbox 16:9 image, at top of coded frame",
1119 "Letterbox 14:9 image, at top of coded frame",
1120 "Letterbox image with aspect ratio greater than 16:9, vertically centered",
1121 "Reserved",
1122 "Reserved",
1123 "Reserved",
1124 "Full frame 4:3 image, same as coded frame",
1125 "Full frame 4:3 image, same as coded frame",
1126 "Letterbox 16:9 image, vertically centered, all image areas protected",
1127 "Letterbox 14:9 image, vertically centered",
1128 "Reserved",
1129 "Full frame 4:3 image, with alternative 14:9 center",
1130 "Letterbox 16:9 image, with alternative 14:9 center",
1131 "Letterbox 16:9 image, with alternative 4:3 center"
1132 };
1133 static const char *const afd_16_9[16] = {
1134 "Undefined",
1135 "Reserved",
1136 "Full frame 16:9 image, same as coded frame",
1137 "Pillarbox 14:9 image, horizontally centered",
1138 "Letterbox image with aspect ratio greater than 16:9, vertically centered",
1139 "Reserved",
1140 "Reserved",
1141 "Reserved",
1142 "Full frame 16:9 image, same as coded frame",
1143 "Pillarbox 4:3 image, horizontally centered",
1144 "Full frame 16:9 image, all image areas protected",
1145 "Pillarbox 14:9 image, horizontally centered",
1146 "Reserved",
1147 "Pillarbox 4:3 image, with alternative 14:9 center",
1148 "Full frame 16:9 image, with alternative 14:9 center",
1149 "Full frame 16:9 image, with alternative 4:3 center"
1150 };
1151
1152 return ar_16_9 ? afd_16_9[afd & 0x0f] : afd_4_3[afd & 0x0f];
1153}
1154
1155/* SMPTE ST 2016-1:2009, Secs. 6, 9.2.1-9.2.2, Tables 3, 5 and 6. */
1156static const char *
1157st2016_3_bar_value_meaning(unsigned value_index, bool_Bool top, bool_Bool bottom, bool_Bool left, bool_Bool right)
1158{
1159 if (value_index == 1) {
1160 if (top)
1161 return "Line number: end of top bar";
1162 if (bottom)
1163 return "Line number: start of bottom bar";
1164 if (left)
1165 return "Pixel number: end of left bar";
1166 if (right)
1167 return "Pixel number: start of right bar";
1168 } else {
1169 if (top && bottom)
1170 return "Line number: start of bottom bar";
1171 if (left && right)
1172 return "Pixel number: start of right bar";
1173 }
1174
1175 return "No valid Bar Data value";
1176}
1177
1178static int
1179dissect_st2016_3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1180{
1181 const st291_vanc_dissector_data_t *st291_data =
1182 (const st291_vanc_dissector_data_t *)data;
1183 proto_tree *top_tree =
1184 st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
1185 proto_item *ti;
1186 proto_item *root_ti;
1187 proto_tree *st2016_tree;
1188 proto_tree *afd_tree;
1189 proto_tree *flags_tree;
1190 proto_tree *value_tree;
1191 unsigned len = tvb_captured_length(tvb);
1192 uint8_t afd_byte;
1193 uint8_t afd;
1194 bool_Bool ar_16_9;
1195 uint8_t flags;
1196 bool_Bool top;
1197 bool_Bool bottom;
1198 bool_Bool left;
1199 bool_Bool right;
1200 uint16_t value1;
1201 uint16_t value2;
1202 const char *meaning1;
1203 const char *meaning2;
1204
1205 root_ti = proto_tree_add_item(top_tree, proto_st2016_3, tvb, 0, len, ENC_NA0x00000000);
1206 st2016_tree = proto_item_add_subtree(root_ti, ett_st2016_3);
1207
1208 if (len != 8) {
1209 expert_add_info_format(pinfo, root_ti, &ei_st2016_3_bad_length,
1210 "ST 2016-3 requires 8 UDW bytes; packet contains %u",
1211 len);
1212 return len;
1213 }
1214
1215 /* SMPTE ST 2016-3:2009, Sec. 4.1, Table 1 maps UDW1 to the
1216 * ST 2016-1 AFD byte; ST 2016-1:2009, Sec. 9.1, Table 4 defines
1217 * reserved bits, active_format and coded_frame_aspect_ratio. */
1218 afd_byte = tvb_get_uint8(tvb, 0);
1219 afd = (afd_byte >> 3) & 0x0f;
1220 ar_16_9 = (afd_byte & 0x04) != 0;
1221
1222 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_afd_byte, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1223 afd_tree = proto_item_add_subtree(ti, ett_st2016_3_afd);
1224 proto_tree_add_item(afd_tree, hf_st2016_3_afd_reserved, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1225 proto_tree_add_uint_format_value(afd_tree, hf_st2016_3_afd_code, tvb, 0, 1, afd,
1226 "%u (%s)", afd,
1227 st2016_3_afd_description(afd, ar_16_9));
1228 proto_tree_add_item(afd_tree, hf_st2016_3_afd_ar, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1229
1230 if ((afd_byte & 0x83) != 0)
1231 expert_add_info(pinfo, ti, &ei_st2016_3_afd_reserved);
1232
1233 /* SMPTE ST 2016-3:2009, Sec. 4.1, Table 1 -- UDW2 and UDW3 are reserved. */
1234 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_reserved_1, tvb, 1, 1, ENC_BIG_ENDIAN0x00000000);
1235 if (tvb_get_uint8(tvb, 1) != 0)
1236 expert_add_info(pinfo, ti, &ei_st2016_3_reserved_udw);
1237
1238 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_reserved_2, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
1239 if (tvb_get_uint8(tvb, 2) != 0)
1240 expert_add_info(pinfo, ti, &ei_st2016_3_reserved_udw);
1241
1242 /* SMPTE ST 2016-3:2009, Sec. 4.1, Table 1 maps UDW4 to Bar Data flags;
1243 * SMPTE ST 2016-1:2009, Sec. 9.2.1, Table 5 defines top/bottom/left/right. */
1244 flags = tvb_get_uint8(tvb, 3);
1245 top = (flags & 0x80) != 0;
1246 bottom = (flags & 0x40) != 0;
1247 left = (flags & 0x20) != 0;
1248 right = (flags & 0x10) != 0;
1249
1250 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_bar_flags, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1251 flags_tree = proto_item_add_subtree(ti, ett_st2016_3_bar_flags);
1252 proto_tree_add_item(flags_tree, hf_st2016_3_bar_top, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1253 proto_tree_add_item(flags_tree, hf_st2016_3_bar_bottom, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1254 proto_tree_add_item(flags_tree, hf_st2016_3_bar_left, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1255 proto_tree_add_item(flags_tree, hf_st2016_3_bar_right, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1256 proto_tree_add_item(flags_tree, hf_st2016_3_bar_reserved, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1257
1258 if ((flags & 0x0f) != 0)
1259 expert_add_info(pinfo, ti, &ei_st2016_3_bar_reserved);
1260
1261 if ((top != bottom) || (left != right) || ((top || bottom) && (left || right)))
1262 expert_add_info(pinfo, ti, &ei_st2016_3_bar_flags_invalid);
1263
1264 /* SMPTE ST 2016-3:2009, Sec. 4.1, Table 1 maps UDW5-UDW8 to
1265 * Bar Data Value 1/2; ST 2016-1:2009, Sec. 9.2.2, Table 6 defines
1266 * marker bits and the 14-bit line/pixel values. */
1267 value1 = tvb_get_ntohs(tvb, 4);
1268 value2 = tvb_get_ntohs(tvb, 6);
1269 meaning1 = st2016_3_bar_value_meaning(1, top, bottom, left, right);
1270 meaning2 = st2016_3_bar_value_meaning(2, top, bottom, left, right);
1271
1272 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_bar_value_1, tvb, 4, 2, ENC_BIG_ENDIAN0x00000000);
1273 value_tree = proto_item_add_subtree(ti, ett_st2016_3_bar_value_1);
1274 proto_tree_add_item(value_tree, hf_st2016_3_bar_value_1_marker, tvb, 4, 2, ENC_BIG_ENDIAN0x00000000);
1275 proto_tree_add_item(value_tree, hf_st2016_3_bar_value_1_data, tvb, 4, 2, ENC_BIG_ENDIAN0x00000000);
1276 ti = proto_tree_add_string(value_tree, hf_st2016_3_bar_value_1_meaning, tvb, 4, 0,
1277 meaning1);
1278 proto_item_set_generated(ti);
1279
1280 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_bar_value_2, tvb, 6, 2, ENC_BIG_ENDIAN0x00000000);
1281 value_tree = proto_item_add_subtree(ti, ett_st2016_3_bar_value_2);
1282 proto_tree_add_item(value_tree, hf_st2016_3_bar_value_2_marker, tvb, 6, 2, ENC_BIG_ENDIAN0x00000000);
1283 proto_tree_add_item(value_tree, hf_st2016_3_bar_value_2_data, tvb, 6, 2, ENC_BIG_ENDIAN0x00000000);
1284 ti = proto_tree_add_string(value_tree, hf_st2016_3_bar_value_2_meaning, tvb, 6, 0,
1285 meaning2);
1286 proto_item_set_generated(ti);
1287
1288 if (top || bottom || left || right) {
1289 if ((value1 & 0xc000) != 0xc000)
1290 expert_add_info(pinfo, ti, &ei_st2016_3_bar_marker);
1291 if ((top && bottom) || (left && right)) {
1292 if ((value2 & 0xc000) != 0xc000)
1293 expert_add_info(pinfo, ti, &ei_st2016_3_bar_marker);
1294 }
1295 }
1296
1297 proto_item_append_text(root_ti, ": AFD: %s in %s mode",
1298 st2016_3_afd_description(afd, ar_16_9),
1299 ar_16_9 ? "16:9" : "4:3");
1300
1301 return len;
1302}
1303
1304void
1305proto_register_st2016_3(void)
1306{
1307 static hf_register_info hf[] = {
1308 { &hf_st2016_3_afd_byte,
1309 { "AFD Information", "st2016_3.afd", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1310 { &hf_st2016_3_afd_code,
1311 { "AFD Code", "st2016_3.afd.code", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1312 { &hf_st2016_3_afd_ar,
1313 { "Coded Frame Aspect Ratio", "st2016_3.afd.ar", FT_BOOLEAN, 8,
1314 TFS(&st2016_3_tfs_afd_ar)((0 ? (const struct true_false_string*)0 : ((&st2016_3_tfs_afd_ar
))))
, 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1315 { &hf_st2016_3_afd_reserved,
1316 { "Reserved", "st2016_3.afd.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0x83, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1317 { &hf_st2016_3_reserved_1,
1318 { "Reserved UDW 2", "st2016_3.reserved1", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1319 { &hf_st2016_3_reserved_2,
1320 { "Reserved UDW 3", "st2016_3.reserved2", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1321 { &hf_st2016_3_bar_flags,
1322 { "Bar Data Flags", "st2016_3.bar.flags", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1323 { &hf_st2016_3_bar_top,
1324 { "Top Bar Present", "st2016_3.bar.top", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1325 { &hf_st2016_3_bar_bottom,
1326 { "Bottom Bar Present", "st2016_3.bar.bottom", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0),
1327 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1328 { &hf_st2016_3_bar_left,
1329 { "Left Bar Present", "st2016_3.bar.left", FT_BOOLEAN, 8, NULL((void*)0), 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1330 { &hf_st2016_3_bar_right,
1331 { "Right Bar Present", "st2016_3.bar.right", FT_BOOLEAN, 8, NULL((void*)0), 0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1332 { &hf_st2016_3_bar_reserved,
1333 { "Reserved", "st2016_3.bar.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0f, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1334 { &hf_st2016_3_bar_value_1,
1335 { "Bar Data Value 1", "st2016_3.bar.value1", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
1336 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1337 { &hf_st2016_3_bar_value_1_marker,
1338 { "Marker Bits", "st2016_3.bar.value1.marker", FT_UINT16, BASE_HEX, NULL((void*)0), 0xc000,
1339 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1340 { &hf_st2016_3_bar_value_1_data,
1341 { "Line/Pixel Number", "st2016_3.bar.value1.data", FT_UINT16, BASE_DEC, NULL((void*)0),
1342 0x3fff, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1343 { &hf_st2016_3_bar_value_2,
1344 { "Bar Data Value 2", "st2016_3.bar.value2", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
1345 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1346 { &hf_st2016_3_bar_value_2_marker,
1347 { "Marker Bits", "st2016_3.bar.value2.marker", FT_UINT16, BASE_HEX, NULL((void*)0), 0xc000,
1348 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1349 { &hf_st2016_3_bar_value_2_data,
1350 { "Line/Pixel Number", "st2016_3.bar.value2.data", FT_UINT16, BASE_DEC, NULL((void*)0),
1351 0x3fff, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1352 { &hf_st2016_3_bar_value_1_meaning,
1353 { "Meaning", "st2016_3.bar.value1.meaning", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0),
1354 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1355 { &hf_st2016_3_bar_value_2_meaning,
1356 { "Meaning", "st2016_3.bar.value2.meaning", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0),
1357 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1358 };
1359
1360 static int *ett[] = {
1361 &ett_st2016_3,
1362 &ett_st2016_3_afd,
1363 &ett_st2016_3_bar_flags,
1364 &ett_st2016_3_bar_value_1,
1365 &ett_st2016_3_bar_value_2,
1366 };
1367
1368 static ei_register_info ei[] = {
1369 { &ei_st2016_3_bad_length,
1370 { "st2016_3.length.bad", PI_MALFORMED0x07000000, PI_WARN0x00600000,
1371 "ST 2016-3 payload length is not 8 bytes", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1372 { &ei_st2016_3_afd_reserved,
1373 { "st2016_3.afd.reserved.bad", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1374 "Reserved AFD bits are not zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1375 { &ei_st2016_3_reserved_udw,
1376 { "st2016_3.reserved_udw.bad", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1377 "Reserved ST 2016-3 UDW is not zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1378 { &ei_st2016_3_bar_reserved,
1379 { "st2016_3.bar.reserved.bad", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1380 "Reserved Bar Data flag bits are not zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1381 { &ei_st2016_3_bar_flags_invalid,
1382 { "st2016_3.bar.flags.invalid", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1383 "Bar Data flags must specify Top+Bottom, Left+Right, or no bars", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1384 { &ei_st2016_3_bar_marker,
1385 { "st2016_3.bar.marker.bad", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1386 "Bar Data value marker bits are not binary '11'", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1387 };
1388
1389 expert_module_t *expert_st2016_3;
1390
1391 proto_st2016_3 = proto_register_protocol(
1392 "SMPTE ST 2016-3 AFD and Bar Data", "ST 2016-3", "st2016_3");
1393
1394 proto_register_field_array(proto_st2016_3, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1395 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1396
1397 expert_st2016_3 = expert_register_protocol(proto_st2016_3);
1398 expert_register_field_array(expert_st2016_3, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1399
1400 st2016_3_handle =
1401 register_dissector("st2016_3", dissect_st2016_3, proto_st2016_3);
1402}
1403
1404void
1405proto_reg_handoff_st2016_3(void)
1406{
1407 dissector_add_uint("st291.did_sdid", ST2016_3_DID_SDID_KEY0x4105, st2016_3_handle);
1408}
1409
1410/*
1411 * SMPTE ST 334-2 Caption Distribution Packet
1412 */
1413
1414
1415/* SMPTE ST 334-2:2015, Sec. 5.2, Table 3 -- cdp_frame_rate values. */
1416static const value_string st334_2_frame_rate_vals[] = {
1417 { 0x0, "Forbidden" },
1418 { 0x1, "24000/1001 (~23.976 fps)" },
1419 { 0x2, "24 fps" },
1420 { 0x3, "25 fps" },
1421 { 0x4, "30000/1001 (~29.97 fps)" },
1422 { 0x5, "30 fps" },
1423 { 0x6, "50 fps" },
1424 { 0x7, "60000/1001 (~59.94 fps)" },
1425 { 0x8, "60 fps" },
1426 { 0, NULL((void*)0) }
1427};
1428
1429/* SMPTE ST 334-2:2015, Sec. 5.1, Table 1; Secs. 5.3-5.7 -- CDP section IDs. */
1430static const value_string st334_2_section_id_vals[] = {
1431 { 0x71, "Time Code Section" },
1432 { 0x72, "CC Data Section" },
1433 { 0x73, "CC Service Information Section" },
1434 { 0x74, "CDP Footer" },
1435 { 0, NULL((void*)0) }
1436};
1437
1438/* SMPTE ST 334-2:2015, Sec. 5.4, Table 5; cc_type semantics are inherited from CEA-708. */
1439static const value_string st334_2_cc_type_vals[] = {
1440 { 0x0, "NTSC line 21 field 1 closed captions (CEA-608)" },
1441 { 0x1, "NTSC line 21 field 2 closed captions (CEA-608)" },
1442 { 0x2, "DTVCC channel packet data" },
1443 { 0x3, "DTVCC channel packet start" },
1444 { 0, NULL((void*)0) }
1445};
1446
1447static const struct true_false_string st334_2_tfs_present = {
1448 "Present", "Not present"
1449};
1450
1451static const struct true_false_string st334_2_tfs_valid = {
1452 "Valid", "Invalid"
1453};
1454
1455/* SMPTE ST 334-2:2015, Sec. 5.4, Table 5 -- required cc_count for each cdp_frame_rate. */
1456static unsigned
1457st334_2_expected_cc_count(uint8_t frame_rate)
1458{
1459 switch (frame_rate) {
1460 case 0x1:
1461 case 0x2:
1462 return 25;
1463 case 0x3:
1464 return 24;
1465 case 0x4:
1466 case 0x5:
1467 return 20;
1468 case 0x6:
1469 return 12;
1470 case 0x7:
1471 case 0x8:
1472 return 10;
1473 default:
1474 return 0;
1475 }
1476}
1477
1478/* SMPTE ST 334-2:2015, Sec. 5.6, Table 7 -- CDP checksum makes the modulo-256 packet sum zero. */
1479static uint8_t
1480st334_2_cdp_checksum(tvbuff_t *tvb, unsigned length)
1481{
1482 unsigned i;
1483 uint8_t sum = 0;
1484
1485 for (i = 0; i < length; i++)
1486 sum = (uint8_t)(sum + tvb_get_uint8(tvb, i));
1487
1488 return sum;
1489}
1490
1491/* SMPTE ST 334-2:2015, Sec. 5.1, Table 1 -- required CDP section ordering. */
1492static unsigned
1493st334_2_section_rank(uint8_t id)
1494{
1495 switch (id) {
1496 case 0x71: return 1;
1497 case 0x72: return 2;
1498 case 0x73: return 3;
1499 case 0x74: return 5;
1500 default:
1501 if (id >= 0x75 && id <= 0xef)
1502 return 4;
1503 return 0;
1504 }
1505}
1506
1507/* SMPTE ST 334-2:2015, Sec. 5, Tables 1-8 -- complete CDP syntax. */
1508static int
1509dissect_st334_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1510{
1511 const st291_vanc_dissector_data_t *st291_data =
1512 (const st291_vanc_dissector_data_t *)data;
1513 proto_tree *top_tree = st291_data && st291_data->top_tree ?
1514 st291_data->top_tree : tree;
1515 proto_item *ti;
1516 proto_item *root_ti;
1517 proto_tree *cdp_tree;
1518 proto_tree *header_tree;
1519 unsigned captured_len = tvb_captured_length(tvb);
1520 unsigned parse_len;
1521 unsigned offset;
1522 unsigned previous_rank = 0;
1523 uint16_t identifier;
1524 uint8_t declared_len;
1525 uint8_t frame_rate;
1526 uint8_t flags;
1527 uint16_t header_sequence;
1528 bool_Bool time_present;
1529 bool_Bool cc_present;
1530 bool_Bool svc_present;
1531 bool_Bool seen_time = false0;
1532 bool_Bool seen_cc = false0;
1533 bool_Bool seen_svc = false0;
1534 bool_Bool seen_footer = false0;
1535
1536 ti = proto_tree_add_item(top_tree, proto_st334_2, tvb, 0, -1, ENC_NA0x00000000);
1537 cdp_tree = proto_item_add_subtree(ti, ett_st334_2);
1538
1539 if (captured_len < 7) {
1540 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_length,
1541 "ST 334-2 requires at least 7 UDW bytes; packet contains %u",
1542 captured_len);
1543 return captured_len;
1544 }
1545
1546 identifier = tvb_get_ntohs(tvb, 0);
1547 declared_len = tvb_get_uint8(tvb, 2);
1548 frame_rate = (tvb_get_uint8(tvb, 3) >> 4) & 0x0f;
1549 flags = tvb_get_uint8(tvb, 4);
1550 header_sequence = tvb_get_ntohs(tvb, 5);
1551
1552 if (declared_len < 7 || declared_len > captured_len)
1553 parse_len = captured_len;
1554 else
1555 parse_len = declared_len;
1556
1557 root_ti = ti;
1558 proto_item_set_len(ti, parse_len);
1559 proto_item_append_text(ti, ", sequence %u", header_sequence);
1560
1561 /* SMPTE ST 334-2:2015, Sec. 5.2, Tables 2-3 -- cdp_header(). */
1562 header_tree = proto_tree_add_subtree(cdp_tree, tvb, 0, 7,
1563 ett_st334_2_header, NULL((void*)0), "CDP Header");
1564
1565 ti = proto_tree_add_item(header_tree, hf_st334_2_cdp_identifier, tvb, 0, 2, ENC_BIG_ENDIAN0x00000000);
1566 if (identifier != ST334_2_CDP_IDENTIFIER0x9669)
1567 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_identifier,
1568 "CDP identifier is 0x%04x; expected 0x%04x",
1569 identifier, ST334_2_CDP_IDENTIFIER0x9669);
1570
1571 ti = proto_tree_add_item(header_tree, hf_st334_2_cdp_length, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
1572 if (declared_len != captured_len)
1573 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_length,
1574 "CDP length is %u bytes, but ST 291 UDW payload contains %u bytes",
1575 declared_len, captured_len);
1576
1577 proto_tree_add_item(header_tree, hf_st334_2_frame_rate, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1578 ti = proto_tree_add_item(header_tree, hf_st334_2_header_reserved, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1579 if ((tvb_get_uint8(tvb, 3) & 0x0f) != 0x0f)
1580 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1581
1582 proto_tree_add_item(header_tree, hf_st334_2_time_code_present, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1583 proto_tree_add_item(header_tree, hf_st334_2_ccdata_present, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1584 proto_tree_add_item(header_tree, hf_st334_2_svcinfo_present, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1585 proto_tree_add_item(header_tree, hf_st334_2_svc_info_start, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1586 proto_tree_add_item(header_tree, hf_st334_2_svc_info_change, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1587 proto_tree_add_item(header_tree, hf_st334_2_svc_info_complete, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1588 proto_tree_add_item(header_tree, hf_st334_2_caption_service_active, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1589 ti = proto_tree_add_item(header_tree, hf_st334_2_header_reserved_bit, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1590 if ((flags & 0x01) == 0)
1591 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1592
1593 proto_tree_add_item(header_tree, hf_st334_2_header_sequence_counter, tvb, 5, 2, ENC_BIG_ENDIAN0x00000000);
1594
1595 time_present = (flags & 0x80) != 0;
1596 cc_present = (flags & 0x40) != 0;
1597 svc_present = (flags & 0x20) != 0;
1598
1599 offset = 7;
1600 while (offset < parse_len) {
1601 uint8_t id;
1602 unsigned rank;
1603 unsigned section_len = 0;
1604
1605 if (!tvb_bytes_exist(tvb, offset, 1))
1606 break;
1607
1608 id = tvb_get_uint8(tvb, offset);
1609 rank = st334_2_section_rank(id);
1610
1611 if (rank != 0 && rank < previous_rank) {
1612 ti = proto_tree_add_item(cdp_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1613 expert_add_info(pinfo, ti, &ei_st334_2_bad_section_order);
1614 }
1615 if (rank != 0 && rank > previous_rank)
1616 previous_rank = rank;
1617
1618 /* SMPTE ST 334-2:2015, Sec. 5.3, Table 4 -- time_code_section(). */
1619 if (id == 0x71) {
1620 proto_tree *section_tree;
1621 uint8_t b1, b2, b3, b4;
1622 unsigned hours, minutes, seconds, frames;
1623 char time_str[48];
1624
1625 if (!tvb_bytes_exist(tvb, offset, 5) || offset + 5 > parse_len) {
1626 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1627 "Truncated CDP time code section");
1628 break;
1629 }
1630 section_len = 5;
1631 section_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, section_len,
1632 ett_st334_2_timecode, NULL((void*)0), "Time Code Section");
1633 ti = proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1634 if (seen_time)
1635 expert_add_info(pinfo, ti, &ei_st334_2_duplicate_section);
1636 seen_time = true1;
1637
1638 b1 = tvb_get_uint8(tvb, offset + 1);
1639 b2 = tvb_get_uint8(tvb, offset + 2);
1640 b3 = tvb_get_uint8(tvb, offset + 3);
1641 b4 = tvb_get_uint8(tvb, offset + 4);
1642
1643 hours = ((b1 >> 4) & 0x03) * 10 + (b1 & 0x0f);
1644 minutes = ((b2 >> 4) & 0x07) * 10 + (b2 & 0x0f);
1645 seconds = ((b3 >> 4) & 0x07) * 10 + (b3 & 0x0f);
1646 frames = ((b4 >> 4) & 0x03) * 10 + (b4 & 0x0f);
1647 snprintf(time_str, sizeof(time_str), "%02u:%02u:%02u:%02u",
1648 hours, minutes, seconds, frames);
1649 ti = proto_tree_add_string(section_tree, hf_st334_2_timecode, tvb, offset + 1, 4, time_str);
1650 proto_item_set_generated(ti);
1651 proto_tree_add_item(section_tree, hf_st334_2_tc_field_flag, tvb, offset + 3, 1, ENC_BIG_ENDIAN0x00000000);
1652 proto_tree_add_item(section_tree, hf_st334_2_drop_frame_flag, tvb, offset + 4, 1, ENC_BIG_ENDIAN0x00000000);
1653 } else if (id == 0x72) {
1654 /* SMPTE ST 334-2:2015, Sec. 5.4, Table 5 -- ccdata_section(). */
1655 proto_tree *section_tree;
1656 unsigned count;
1657 unsigned expected;
1658 unsigned i;
1659 unsigned dtvcc_len = 0;
1660 uint8_t *dtvcc_data;
1661
1662 if (!tvb_bytes_exist(tvb, offset, 2) || offset + 2 > parse_len) {
1663 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1664 "Truncated CDP CC data section header");
1665 break;
1666 }
1667 count = tvb_get_uint8(tvb, offset + 1) & 0x1f;
1668 section_len = 2 + 3 * count;
1669 if (!tvb_bytes_exist(tvb, offset, section_len) || offset + section_len > parse_len) {
1670 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1671 "CC data section requires %u bytes but packet ends early",
1672 section_len);
1673 break;
1674 }
1675
1676 section_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, section_len,
1677 ett_st334_2_ccdata, NULL((void*)0), "CC Data Section");
1678 ti = proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1679 if (seen_cc)
1680 expert_add_info(pinfo, ti, &ei_st334_2_duplicate_section);
1681 seen_cc = true1;
1682
1683 ti = proto_tree_add_item(section_tree, hf_st334_2_cc_count, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1684 if ((tvb_get_uint8(tvb, offset + 1) & 0xe0) != 0xe0)
1685 expert_add_info(pinfo, ti, &ei_st334_2_bad_marker);
1686
1687 expected = st334_2_expected_cc_count(frame_rate);
1688 if (expected != 0 && count != expected)
1689 expert_add_info_format(pinfo, ti, &ei_st334_2_cc_count,
1690 "cc_count is %u; frame-rate code 0x%x requires %u",
1691 count, frame_rate, expected);
1692
1693 dtvcc_data = wmem_alloc(pinfo->pool, MAX(1U, count * 2)(((1U) > (count * 2)) ? (1U) : (count * 2)));
1694 for (i = 0; i < count; i++) {
1695 unsigned c_off = offset + 2 + i * 3;
1696 uint8_t type_byte = tvb_get_uint8(tvb, c_off);
1697 uint8_t cc_type = type_byte & 0x03;
1698 proto_tree *construct_tree;
1699
1700 construct_tree = proto_tree_add_subtree_format(
1701 section_tree, tvb, c_off, 3, ett_st334_2_cc_construct, NULL((void*)0),
1702 "CC Construct %u: %s", i + 1,
1703 val_to_str_const(cc_type, st334_2_cc_type_vals, "Unknown"));
1704 ti = proto_tree_add_item(construct_tree, hf_st334_2_cc_marker_bits, tvb, c_off, 1, ENC_BIG_ENDIAN0x00000000);
1705 if ((type_byte & 0xf8) != 0xf8)
1706 expert_add_info(pinfo, ti, &ei_st334_2_bad_marker);
1707 proto_tree_add_item(construct_tree, hf_st334_2_cc_valid, tvb, c_off, 1, ENC_BIG_ENDIAN0x00000000);
1708 proto_tree_add_item(construct_tree, hf_st334_2_cc_type, tvb, c_off, 1, ENC_BIG_ENDIAN0x00000000);
1709 proto_tree_add_item(construct_tree, hf_st334_2_cc_data_1, tvb, c_off + 1, 1, ENC_BIG_ENDIAN0x00000000);
1710 proto_tree_add_item(construct_tree, hf_st334_2_cc_data_2, tvb, c_off + 2, 1, ENC_BIG_ENDIAN0x00000000);
1711
1712 if ((type_byte & 0x04) != 0 && (cc_type == 2 || cc_type == 3)) {
1713 dtvcc_data[dtvcc_len++] = tvb_get_uint8(tvb, c_off + 1);
1714 dtvcc_data[dtvcc_len++] = tvb_get_uint8(tvb, c_off + 2);
1715 }
1716 }
1717 if (dtvcc_len != 0) {
1718 tvbuff_t *dtvcc_tvb;
1719
1720 dtvcc_tvb = tvb_new_child_real_data(tvb, dtvcc_data,
1721 dtvcc_len, dtvcc_len);
1722 /* ST 334-2:2015, Sec. 5.4, Table 5: concatenate valid cc_type 2/3 constructs for CEA-708 decoding. */
1723 add_new_data_source(pinfo, dtvcc_tvb, "CEA-708 DTVCC Data");
1724 ti = proto_tree_add_item(section_tree, hf_st334_2_dtvcc_data,
1725 dtvcc_tvb, 0, dtvcc_len, ENC_NA0x00000000);
1726 proto_item_set_generated(ti);
1727 }
1728 } else if (id == 0x73) {
1729 /* SMPTE ST 334-2:2015, Sec. 5.5, Table 6 -- ccsvcinfo_section(). */
1730 proto_tree *section_tree;
1731 uint8_t svc_flags;
1732 unsigned count;
1733 unsigned i;
1734
1735 if (!tvb_bytes_exist(tvb, offset, 2) || offset + 2 > parse_len) {
1736 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1737 "Truncated CDP service information section header");
1738 break;
1739 }
1740 svc_flags = tvb_get_uint8(tvb, offset + 1);
1741 count = svc_flags & 0x0f;
1742 section_len = 2 + 7 * count;
1743 if (!tvb_bytes_exist(tvb, offset, section_len) || offset + section_len > parse_len) {
1744 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1745 "Service information section requires %u bytes but packet ends early",
1746 section_len);
1747 break;
1748 }
1749
1750 section_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, section_len,
1751 ett_st334_2_svcinfo, NULL((void*)0),
1752 "CC Service Information Section");
1753 ti = proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1754 if (seen_svc)
1755 expert_add_info(pinfo, ti, &ei_st334_2_duplicate_section);
1756 seen_svc = true1;
1757
1758 ti = proto_tree_add_item(section_tree, hf_st334_2_svc_reserved, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1759 if ((svc_flags & 0x80) == 0)
1760 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1761 proto_tree_add_item(section_tree, hf_st334_2_svc_info_start_section, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1762 proto_tree_add_item(section_tree, hf_st334_2_svc_info_change_section, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1763 proto_tree_add_item(section_tree, hf_st334_2_svc_info_complete_section, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1764 proto_tree_add_item(section_tree, hf_st334_2_svc_count, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1765
1766 if (((flags >> 2) & 0x07) != ((svc_flags >> 4) & 0x07)) {
1767 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_reserved,
1768 "Service-info start/change/complete flags do not match CDP header");
1769 }
1770
1771 for (i = 0; i < count; i++) {
1772 unsigned s_off = offset + 2 + i * 7;
1773 uint8_t first = tvb_get_uint8(tvb, s_off);
1774 unsigned service_number;
1775 uint8_t type_byte;
1776 bool_Bool digital_cc;
1777 proto_tree *service_tree;
1778 proto_tree *data_tree;
1779
1780 service_tree = proto_tree_add_subtree_format(
1781 section_tree, tvb, s_off, 7, ett_st334_2_service, NULL((void*)0),
1782 "Caption Service %u", i + 1);
1783 ti = proto_tree_add_item(service_tree, hf_st334_2_csn_reserved, tvb, s_off, 1, ENC_BIG_ENDIAN0x00000000);
1784 if ((first & 0x80) == 0)
1785 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1786 proto_tree_add_item(service_tree, hf_st334_2_csn_size, tvb, s_off, 1, ENC_BIG_ENDIAN0x00000000);
1787 if ((first & 0x40) != 0) {
1788 ti = proto_tree_add_item(service_tree, hf_st334_2_csn_reserved_2, tvb, s_off, 1, ENC_BIG_ENDIAN0x00000000);
1789 if ((first & 0x20) == 0)
1790 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1791 service_number = first & 0x1f;
1792 } else {
1793 service_number = first & 0x3f;
1794 }
1795 ti = proto_tree_add_uint(service_tree, hf_st334_2_caption_service_number,
1796 tvb, s_off, 1, service_number);
1797
1798 /*
1799 * SMPTE ST 334-2:2015, Sec. 5.5, Table 6 defines
1800 * svc_data_byte_1 through svc_data_byte_6 as one service
1801 * entry encoded according to the caption service descriptor
1802 * loop in ATSC A/65:2013, Sec. 6.9.2, Table 6.26.
1803 */
1804 type_byte = tvb_get_uint8(tvb, s_off + 4);
1805 digital_cc = (type_byte & 0x80) != 0;
1806
1807 data_tree = proto_tree_add_subtree(
1808 service_tree, tvb, s_off + 1, 6,
1809 ett_st334_2_service_data, NULL((void*)0), "Service Data");
1810
1811 proto_tree_add_item(data_tree, hf_st334_2_service_language,
1812 tvb, s_off + 1, 3, ENC_ASCII0x00000000);
1813 proto_tree_add_item(data_tree, hf_st334_2_service_digital_cc,
1814 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
1815
1816 if (digital_cc) {
1817 proto_tree_add_item(data_tree, hf_st334_2_service_digital_reserved,
1818 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
1819 proto_tree_add_item(data_tree, hf_st334_2_service_descriptor_number,
1820 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
1821 } else {
1822 proto_tree_add_item(data_tree, hf_st334_2_service_line21_reserved,
1823 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
1824 proto_tree_add_item(data_tree, hf_st334_2_service_line21_field,
1825 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
1826 }
1827
1828 proto_tree_add_item(data_tree, hf_st334_2_service_easy_reader,
1829 tvb, s_off + 5, 1, ENC_BIG_ENDIAN0x00000000);
1830 proto_tree_add_item(data_tree, hf_st334_2_service_wide_aspect_ratio,
1831 tvb, s_off + 5, 1, ENC_BIG_ENDIAN0x00000000);
1832 ti = proto_tree_add_item(data_tree, hf_st334_2_service_reserved_14,
1833 tvb, s_off + 5, 2, ENC_BIG_ENDIAN0x00000000);
1834 if ((tvb_get_ntohs(tvb, s_off + 5) & 0x3fff) != 0x3fff)
1835 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1836 }
1837 } else if (id == 0x74) {
1838 /* SMPTE ST 334-2:2015, Sec. 5.6, Table 7 -- cdp_footer(). */
1839 proto_tree *section_tree;
1840 uint16_t footer_sequence;
1841 uint8_t sum;
1842 proto_item *checksum_item;
1843
1844 section_len = 4;
1845 if (!tvb_bytes_exist(tvb, offset, section_len) || offset + section_len > parse_len) {
1846 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1847 "Truncated CDP footer");
1848 break;
1849 }
1850
1851 section_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, section_len,
1852 ett_st334_2_footer, NULL((void*)0), "CDP Footer");
1853 ti = proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1854 if (seen_footer)
1855 expert_add_info(pinfo, ti, &ei_st334_2_duplicate_section);
1856 seen_footer = true1;
1857
1858 footer_sequence = tvb_get_ntohs(tvb, offset + 1);
1859 ti = proto_tree_add_item(section_tree, hf_st334_2_footer_sequence_counter,
1860 tvb, offset + 1, 2, ENC_BIG_ENDIAN0x00000000);
1861 if (footer_sequence != header_sequence)
1862 expert_add_info_format(pinfo, ti, &ei_st334_2_sequence_mismatch,
1863 "Footer sequence %u does not match header sequence %u",
1864 footer_sequence, header_sequence);
1865
1866 checksum_item = proto_tree_add_item(section_tree, hf_st334_2_packet_checksum,
1867 tvb, offset + 3, 1, ENC_BIG_ENDIAN0x00000000);
1868 if (parse_len == declared_len && offset + 4 == parse_len) {
1869 sum = st334_2_cdp_checksum(tvb, parse_len);
1870 ti = proto_tree_add_uint(section_tree, hf_st334_2_checksum_calculated,
1871 tvb, 0, 0,
1872 (uint8_t)(tvb_get_uint8(tvb, offset + 3) - sum));
1873 proto_item_set_generated(ti);
1874 if (sum != 0)
1875 expert_add_info_format(pinfo, checksum_item, &ei_st334_2_bad_checksum,
1876 "CDP checksum does not make packet sum modulo 256 equal zero (sum 0x%02x)",
1877 sum);
1878 }
1879 offset += section_len;
Value stored to 'offset' is never read
1880 break;
1881 } else if (id >= 0x75 && id <= 0xef) {
1882 /* SMPTE ST 334-2:2015, Sec. 5.7, Table 8 -- future_section(). */
1883 proto_tree *section_tree;
1884 unsigned future_len;
1885
1886 if (!tvb_bytes_exist(tvb, offset, 2) || offset + 2 > parse_len) {
1887 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1888 "Truncated future CDP section header");
1889 break;
1890 }
1891 future_len = tvb_get_uint8(tvb, offset + 1);
1892 section_len = 2 + future_len;
1893 if (!tvb_bytes_exist(tvb, offset, section_len) || offset + section_len > parse_len) {
1894 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1895 "Future CDP section requires %u bytes but packet ends early",
1896 section_len);
1897 break;
1898 }
1899 section_tree = proto_tree_add_subtree_format(
1900 cdp_tree, tvb, offset, section_len, ett_st334_2_future, NULL((void*)0),
1901 "Unknown/Future CDP Section 0x%02x", id);
1902 proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1903 proto_tree_add_item(section_tree, hf_st334_2_future_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1904 if (future_len != 0)
1905 proto_tree_add_item(section_tree, hf_st334_2_future_data, tvb, offset + 2,
1906 future_len, ENC_NA0x00000000);
1907 } else {
1908 ti = proto_tree_add_item(cdp_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1909 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_section_order,
1910 "Unknown CDP section identifier 0x%02x cannot be safely skipped",
1911 id);
1912 break;
1913 }
1914
1915 offset += section_len;
1916 }
1917
1918 if (time_present != seen_time)
1919 expert_add_info_format(pinfo, root_ti, &ei_st334_2_missing_section,
1920 "CDP header time_code_present=%u but time-code section %s",
1921 time_present, seen_time ? "is present" : "is absent");
1922 if (cc_present != seen_cc)
1923 expert_add_info_format(pinfo, root_ti, &ei_st334_2_missing_section,
1924 "CDP header ccdata_present=%u but CC-data section %s",
1925 cc_present, seen_cc ? "is present" : "is absent");
1926 if (svc_present != seen_svc)
1927 expert_add_info_format(pinfo, root_ti, &ei_st334_2_missing_section,
1928 "CDP header svcinfo_present=%u but service-info section %s",
1929 svc_present, seen_svc ? "is present" : "is absent");
1930 if (!seen_footer)
1931 expert_add_info_format(pinfo, root_ti, &ei_st334_2_missing_section,
1932 "Required CDP footer is absent");
1933
1934 return captured_len;
1935}
1936
1937void
1938proto_register_st334_2(void)
1939{
1940 static hf_register_info hf[] = {
1941 { &hf_st334_2_cdp_identifier,
1942 { "CDP Identifier", "st334_2.cdp.identifier", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
1943 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1944 { &hf_st334_2_cdp_length,
1945 { "CDP Length", "st334_2.cdp.length", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1946 { &hf_st334_2_frame_rate,
1947 { "CDP Frame Rate", "st334_2.cdp.frame_rate", FT_UINT8, BASE_HEX,
1948 VALS(st334_2_frame_rate_vals)((0 ? (const struct _value_string*)0 : ((st334_2_frame_rate_vals
))))
, 0xf0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1949 { &hf_st334_2_header_reserved,
1950 { "Reserved", "st334_2.cdp.header.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0f, NULL((void*)0),
1951 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1952 { &hf_st334_2_time_code_present,
1953 { "Time Code", "st334_2.cdp.time_code_present", FT_BOOLEAN, 8,
1954 TFS(&st334_2_tfs_present)((0 ? (const struct true_false_string*)0 : ((&st334_2_tfs_present
))))
, 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1955 { &hf_st334_2_ccdata_present,
1956 { "CC Data", "st334_2.cdp.ccdata_present", FT_BOOLEAN, 8, TFS(&st334_2_tfs_present)((0 ? (const struct true_false_string*)0 : ((&st334_2_tfs_present
))))
,
1957 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1958 { &hf_st334_2_svcinfo_present,
1959 { "Service Information", "st334_2.cdp.svcinfo_present", FT_BOOLEAN, 8,
1960 TFS(&st334_2_tfs_present)((0 ? (const struct true_false_string*)0 : ((&st334_2_tfs_present
))))
, 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1961 { &hf_st334_2_svc_info_start,
1962 { "Service Info Start", "st334_2.cdp.svc_info_start", FT_BOOLEAN, 8, NULL((void*)0), 0x10,
1963 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1964 { &hf_st334_2_svc_info_change,
1965 { "Service Info Change", "st334_2.cdp.svc_info_change", FT_BOOLEAN, 8, NULL((void*)0), 0x08,
1966 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1967 { &hf_st334_2_svc_info_complete,
1968 { "Service Info Complete", "st334_2.cdp.svc_info_complete", FT_BOOLEAN, 8, NULL((void*)0),
1969 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1970 { &hf_st334_2_caption_service_active,
1971 { "Caption Service Active", "st334_2.cdp.caption_service_active", FT_BOOLEAN, 8,
1972 NULL((void*)0), 0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1973 { &hf_st334_2_header_reserved_bit,
1974 { "Reserved", "st334_2.cdp.header.reserved_bit", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0),
1975 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1976 { &hf_st334_2_header_sequence_counter,
1977 { "Header Sequence Counter", "st334_2.cdp.header_sequence", FT_UINT16, BASE_DEC,
1978 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1979 { &hf_st334_2_section_id,
1980 { "Section ID", "st334_2.section.id", FT_UINT8, BASE_HEX,
1981 VALS(st334_2_section_id_vals)((0 ? (const struct _value_string*)0 : ((st334_2_section_id_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1982 { &hf_st334_2_timecode,
1983 { "Time Code", "st334_2.timecode", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1984 { &hf_st334_2_tc_field_flag,
1985 { "Field Flag", "st334_2.timecode.field_flag", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0),
1986 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1987 { &hf_st334_2_drop_frame_flag,
1988 { "Drop Frame", "st334_2.timecode.drop_frame", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0),
1989 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1990 { &hf_st334_2_cc_count,
1991 { "CC Count", "st334_2.ccdata.count", FT_UINT8, BASE_DEC, NULL((void*)0), 0x1f, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1992 { &hf_st334_2_cc_marker_bits,
1993 { "Marker Bits", "st334_2.ccdata.marker", FT_UINT8, BASE_HEX, NULL((void*)0), 0xf8, NULL((void*)0),
1994 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1995 { &hf_st334_2_cc_valid,
1996 { "CC Valid", "st334_2.ccdata.valid", FT_BOOLEAN, 8, TFS(&st334_2_tfs_valid)((0 ? (const struct true_false_string*)0 : ((&st334_2_tfs_valid
))))
, 0x04,
1997 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1998 { &hf_st334_2_cc_type,
1999 { "CC Type", "st334_2.ccdata.type", FT_UINT8, BASE_DEC, VALS(st334_2_cc_type_vals)((0 ? (const struct _value_string*)0 : ((st334_2_cc_type_vals
))))
,
2000 0x03, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2001 { &hf_st334_2_cc_data_1,
2002 { "CC Data 1", "st334_2.ccdata.data1", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2003 { &hf_st334_2_cc_data_2,
2004 { "CC Data 2", "st334_2.ccdata.data2", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2005 { &hf_st334_2_dtvcc_data,
2006 { "DTVCC Data", "st334_2.ccdata.dtvcc", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2007 { &hf_st334_2_svc_reserved,
2008 { "Reserved", "st334_2.svcinfo.reserved", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2009 { &hf_st334_2_svc_info_start_section,
2010 { "Service Info Start", "st334_2.svcinfo.start", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0),
2011 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2012 { &hf_st334_2_svc_info_change_section,
2013 { "Service Info Change", "st334_2.svcinfo.change", FT_BOOLEAN, 8, NULL((void*)0), 0x20, NULL((void*)0),
2014 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2015 { &hf_st334_2_svc_info_complete_section,
2016 { "Service Info Complete", "st334_2.svcinfo.complete", FT_BOOLEAN, 8, NULL((void*)0), 0x10,
2017 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2018 { &hf_st334_2_svc_count,
2019 { "Service Count", "st334_2.svcinfo.count", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0f, NULL((void*)0),
2020 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2021 { &hf_st334_2_csn_reserved,
2022 { "Reserved", "st334_2.svcinfo.service.reserved", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0),
2023 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2024 { &hf_st334_2_csn_size,
2025 { "Caption Service Number Size", "st334_2.svcinfo.service.csn_size", FT_BOOLEAN, 8,
2026 NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2027 { &hf_st334_2_csn_reserved_2,
2028 { "Reserved", "st334_2.svcinfo.service.reserved_2", FT_BOOLEAN, 8, NULL((void*)0), 0x20, NULL((void*)0),
2029 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2030 { &hf_st334_2_caption_service_number,
2031 { "Caption Service Number", "st334_2.svcinfo.service.number", FT_UINT8, BASE_DEC,
2032 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2033
2034 /*
2035 * SMPTE ST 334-2:2015, Sec. 5.5, Table 6;
2036 * ATSC A/65:2013, Sec. 6.9.2, Table 6.26.
2037 */
2038 { &hf_st334_2_service_data,
2039 { "Service Data", "st334_2.svcinfo.service.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
2040 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2041 { &hf_st334_2_service_language,
2042 { "Language", "st334_2.svcinfo.service.language", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
2043 "ISO 639.2/B language code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2044 { &hf_st334_2_service_digital_cc,
2045 { "Digital CC", "st334_2.svcinfo.service.digital_cc", FT_BOOLEAN, 8,
2046 TFS(&tfs_yes_no)((0 ? (const struct true_false_string*)0 : ((&tfs_yes_no)
)))
, 0x80, "1 = CEA-708 digital captions; 0 = CEA-608/line 21", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2047 { &hf_st334_2_service_digital_reserved,
2048 { "Reserved", "st334_2.svcinfo.service.digital_reserved", FT_BOOLEAN, 8, NULL((void*)0), 0x40,
2049 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2050 { &hf_st334_2_service_line21_reserved,
2051 { "Reserved", "st334_2.svcinfo.service.line21_reserved", FT_UINT8, BASE_HEX, NULL((void*)0),
2052 0x7e, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2053 { &hf_st334_2_service_line21_field,
2054 { "Line 21 Field", "st334_2.svcinfo.service.line21_field", FT_BOOLEAN, 8, NULL((void*)0),
2055 0x01, "0 = field 1; 1 = field 2", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2056 { &hf_st334_2_service_descriptor_number,
2057 { "Caption Service Number", "st334_2.svcinfo.service.descriptor_number", FT_UINT8,
2058 BASE_DEC, NULL((void*)0), 0x3f, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2059 { &hf_st334_2_service_easy_reader,
2060 { "Easy Reader", "st334_2.svcinfo.service.easy_reader", FT_BOOLEAN, 8,
2061 TFS(&tfs_yes_no)((0 ? (const struct true_false_string*)0 : ((&tfs_yes_no)
)))
, 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2062 { &hf_st334_2_service_wide_aspect_ratio,
2063 { "Wide Aspect Ratio", "st334_2.svcinfo.service.wide_aspect_ratio", FT_BOOLEAN, 8,
2064 TFS(&tfs_yes_no)((0 ? (const struct true_false_string*)0 : ((&tfs_yes_no)
)))
, 0x40, "1 = 16:9; 0 = 4:3", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2065 { &hf_st334_2_service_reserved_14,
2066 { "Reserved", "st334_2.svcinfo.service.reserved_14", FT_UINT16, BASE_HEX, NULL((void*)0),
2067 0x3fff, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2068 { &hf_st334_2_future_length,
2069 { "Length", "st334_2.future.length", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2070 { &hf_st334_2_future_data,
2071 { "Data", "st334_2.future.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2072 { &hf_st334_2_footer_sequence_counter,
2073 { "Footer Sequence Counter", "st334_2.cdp.footer_sequence", FT_UINT16, BASE_DEC,
2074 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2075 { &hf_st334_2_packet_checksum,
2076 { "Packet Checksum", "st334_2.cdp.checksum", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
2077 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2078 { &hf_st334_2_checksum_calculated,
2079 { "Calculated Checksum", "st334_2.cdp.checksum_calculated", FT_UINT8, BASE_HEX,
2080 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2081 };
2082 static int *ett[] = {
2083 &ett_st334_2,
2084 &ett_st334_2_header,
2085 &ett_st334_2_timecode,
2086 &ett_st334_2_ccdata,
2087 &ett_st334_2_cc_construct,
2088 &ett_st334_2_svcinfo,
2089 &ett_st334_2_service,
2090 &ett_st334_2_service_data,
2091 &ett_st334_2_future,
2092 &ett_st334_2_footer,
2093 };
2094 static ei_register_info ei[] = {
2095 { &ei_st334_2_bad_identifier, { "st334_2.bad_identifier", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid CDP identifier", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2096 { &ei_st334_2_bad_length, { "st334_2.bad_length", PI_MALFORMED0x07000000, PI_WARN0x00600000, "CDP length mismatch", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2097 { &ei_st334_2_bad_reserved, { "st334_2.bad_reserved", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid reserved bits or duplicated flags", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2098 { &ei_st334_2_bad_section_order, { "st334_2.bad_section_order", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid or unknown CDP section ordering", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2099 { &ei_st334_2_duplicate_section, { "st334_2.duplicate_section", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Duplicate CDP section", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2100 { &ei_st334_2_missing_section, { "st334_2.missing_section", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "CDP section presence mismatch", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2101 { &ei_st334_2_cc_count, { "st334_2.bad_cc_count", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "CC count does not match frame rate", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2102 { &ei_st334_2_bad_marker, { "st334_2.bad_marker", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid CEA-708 marker bits", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2103 { &ei_st334_2_sequence_mismatch, { "st334_2.sequence_mismatch", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "CDP header/footer sequence mismatch", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2104 { &ei_st334_2_bad_checksum, { "st334_2.bad_checksum", PI_CHECKSUM0x01000000, PI_WARN0x00600000, "Invalid CDP checksum", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2105 { &ei_st334_2_truncated, { "st334_2.truncated", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Truncated CDP section", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2106 };
2107 expert_module_t *expert_st334_2;
2108
2109 proto_st334_2 = proto_register_protocol(
2110 "SMPTE ST 334-2 Caption Distribution Packet", "ST 334-2", "st334_2");
2111 proto_register_field_array(proto_st334_2, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
2112 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
2113
2114 expert_st334_2 = expert_register_protocol(proto_st334_2);
2115 expert_register_field_array(expert_st334_2, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
2116
2117 st334_2_handle = register_dissector("st334_2", dissect_st334_2, proto_st334_2);
2118}
2119
2120void
2121proto_reg_handoff_st334_2(void)
2122{
2123 dissector_add_uint("st291.did_sdid", ST334_2_DID_SDID_KEY0x6101, st334_2_handle);
2124}
2125
2126/*
2127 * Common System B World System Teletext decoding used by ST 2031 and
2128 * RDD 8 / OP-47. The protocols retain separate display-filter fields; this
2129 * structure supplies the appropriate field IDs to the common parser.
2130 */
2131typedef struct {
2132 int *magazine_hamming;
2133 int *magazine;
2134 int *packet_number_hamming;
2135 int *packet_number;
2136 int *page_units_hamming;
2137 int *page_units;
2138 int *page_tens_hamming;
2139 int *page_tens;
2140 int *data_string;
2141 int *textdata_array;
2142 int *erase_page;
2143 int *newsflash;
2144 int *subtitle;
2145 int *suppress_header;
2146 int *update_indicator;
2147 int *interrupted_sequence;
2148 int *inhibit_display;
2149 int *magazine_serial;
2150 int *character_set;
2151 int *tt_control;
2152} st291_wst_fields_t;
2153
2154/* Rec. ITU-R BT.653-3, System B national-option character subsets. */
2155static const value_string st291_wst_national_subset_vals[] = {
2156 { 0x00, "English" },
2157 { 0x01, "German" },
2158 { 0x04, "Swedish/Finnish/Hungarian" },
2159 { 0x05, "Italian" },
2160 { 0x10, "French" },
2161 { 0x11, "Portuguese/Spanish" },
2162 { 0x14, "Czech/Slovak" },
2163 { 0, NULL((void*)0) }
2164};
2165
2166static void
2167st291_process_wst_packet(tvbuff_t *tvb, proto_tree *tree, const st291_wst_fields_t *fields)
2168{
2169 uint8_t text_data[40];
2170 char data_string[41];
2171 unsigned magazine, packet_number;
2172 unsigned data_start_offset = 0, number_of_data_bytes = 0;
2173 proto_item *ti;
2174 unsigned i;
2175
2176 if (tvb_captured_length(tvb) < 42)
2177 return;
2178
2179 proto_tree_add_item(tree, *fields->magazine_hamming, tvb, 0, 2, ENC_BIG_ENDIAN0x00000000);
2180 magazine = tvb_get_bits8(tvb, 1, 1)
2181 + 2 * tvb_get_bits8(tvb, 3, 1)
2182 + 4 * tvb_get_bits8(tvb, 5, 1);
2183 if (magazine == 0)
2184 magazine = 8;
2185 ti = proto_tree_add_uint(tree, *fields->magazine, tvb, 0, 0, magazine);
2186 proto_item_set_generated(ti);
2187
2188 proto_tree_add_item(tree, *fields->packet_number_hamming, tvb, 0, 2, ENC_BIG_ENDIAN0x00000000);
2189 packet_number = tvb_get_bits8(tvb, 7, 1)
2190 + 2 * tvb_get_bits8(tvb, 9, 1)
2191 + 4 * tvb_get_bits8(tvb, 11, 1)
2192 + 8 * tvb_get_bits8(tvb, 13, 1)
2193 + 16 * tvb_get_bits8(tvb, 15, 1);
2194 ti = proto_tree_add_uint(tree, *fields->packet_number, tvb, 0, 0, packet_number);
2195 proto_item_set_generated(ti);
2196
2197 if (packet_number == 0) {
2198 unsigned page_units, page_tens, tt_page;
2199
2200 data_start_offset = 10;
2201 number_of_data_bytes = 32;
2202
2203 page_units = tvb_get_bits8(tvb, 2 * 8 + 1, 1)
2204 + 2 * tvb_get_bits8(tvb, 2 * 8 + 3, 1)
2205 + 4 * tvb_get_bits8(tvb, 2 * 8 + 5, 1)
2206 + 8 * tvb_get_bits8(tvb, 2 * 8 + 7, 1);
2207 page_tens = tvb_get_bits8(tvb, 3 * 8 + 1, 1)
2208 + 2 * tvb_get_bits8(tvb, 3 * 8 + 3, 1)
2209 + 4 * tvb_get_bits8(tvb, 3 * 8 + 5, 1)
2210 + 8 * tvb_get_bits8(tvb, 3 * 8 + 7, 1);
2211
2212 proto_tree_add_item(tree, *fields->page_units_hamming, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
2213 proto_tree_add_item(tree, *fields->page_tens_hamming, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
2214 ti = proto_tree_add_uint(tree, *fields->page_units, tvb, 0, 0, page_units);
2215 proto_item_set_generated(ti);
2216 ti = proto_tree_add_uint(tree, *fields->page_tens, tvb, 0, 0, page_tens);
2217 proto_item_set_generated(ti);
2218
2219 tt_page = (magazine << 8) | (page_tens << 4) | page_units;
2220 proto_tree_add_none_format(tree, *fields->tt_control, tvb, 0, 0,
2221 "Control bits for TT Page 0x%x:", tt_page);
2222
2223 proto_tree_add_item(tree, *fields->erase_page, tvb, 5, 1, ENC_BIG_ENDIAN0x00000000);
2224 proto_tree_add_item(tree, *fields->newsflash, tvb, 7, 1, ENC_BIG_ENDIAN0x00000000);
2225 proto_tree_add_item(tree, *fields->subtitle, tvb, 7, 1, ENC_BIG_ENDIAN0x00000000);
2226 proto_tree_add_item(tree, *fields->suppress_header, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
2227 proto_tree_add_item(tree, *fields->update_indicator, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
2228 proto_tree_add_item(tree, *fields->interrupted_sequence, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
2229 proto_tree_add_item(tree, *fields->inhibit_display, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
2230 proto_tree_add_item(tree, *fields->magazine_serial, tvb, 9, 1, ENC_BIG_ENDIAN0x00000000);
2231 proto_tree_add_item(tree, *fields->character_set, tvb, 9, 1, ENC_BIG_ENDIAN0x00000000);
2232 } else if (packet_number >= 1 && packet_number <= 25) {
2233 data_start_offset = 2;
2234 number_of_data_bytes = 40;
2235 }
2236
2237 if (number_of_data_bytes == 0)
2238 return;
2239
2240 for (i = 0; i < number_of_data_bytes; i++) {
2241 uint8_t c = tvb_get_bits8(tvb, (data_start_offset + i) * 8, 7);
2242 text_data[i] = c;
2243 data_string[i] = (char)c;
2244 }
2245 data_string[number_of_data_bytes] = '\0';
2246
2247 ti = proto_tree_add_string(tree, *fields->data_string, tvb, 0, 0, data_string);
2248 proto_item_set_generated(ti);
2249 ti = proto_tree_add_bytes(tree, *fields->textdata_array, tvb, 0, 0, text_data);
2250 proto_item_set_generated(ti);
2251}
2252
2253/*
2254 * SMPTE ST 2031 DVB/SCTE VBI data in VANC
2255 */
2256
2257static const struct true_false_string st2031_tfs_field_parity = {
2258 "First field of a frame", "Second field of a frame"
2259};
2260
2261
2262static const st291_wst_fields_t st2031_wst_fields = {
2263 &hf_st2031_magazine_hamming,
2264 &hf_st2031_magazine,
2265 &hf_st2031_packet_number_hamming,
2266 &hf_st2031_packet_number,
2267 &hf_st2031_page_units_hamming,
2268 &hf_st2031_page_units,
2269 &hf_st2031_page_tens_hamming,
2270 &hf_st2031_page_tens,
2271 &hf_st2031_data_string,
2272 &hf_st2031_textdata_array,
2273 &hf_st2031_erase_page,
2274 &hf_st2031_newsflash,
2275 &hf_st2031_subtitle,
2276 &hf_st2031_suppress_header,
2277 &hf_st2031_update_indicator,
2278 &hf_st2031_interrupted_sequence,
2279 &hf_st2031_inhibit_display,
2280 &hf_st2031_magazine_serial,
2281 &hf_st2031_character_set,
2282 &hf_st2031_tt_control,
2283};
2284
2285/* Rec. ITU-R BT.653-3, System B national-option character subsets used by Teletext data units. */
2286/* SMPTE ST 2031:2015, Sec. 6, Table 2; values originate in ETSI EN 301 775, Sec. 4.4. */
2287static const range_string st2031_data_identifier_vals[] = {
2288 { 0x10, 0x1F, "EBU Teletext/VPS/WSS/CC/VBI sample data" },
2289 { 0x80, 0x98, "User defined" },
2290 { 0x99, 0x9B, "EBU Teletext/VPS/WSS/CC/VBI sample data" },
2291 { 0x9C, 0xFF, "User defined" },
2292 { 0x00, 0xFF, "Reserved for future use" },
2293 { 0, 0, NULL((void*)0) }
2294};
2295
2296/* SMPTE ST 2031:2015, Sec. 6, Table 2; data_unit_id values originate in ETSI EN 301 775, Sec. 4.5. */
2297static const range_string st2031_data_unit_id_vals[] = {
2298 { 0x00, 0x01, "DVB reserved" },
2299 { 0x02, 0x02, "EBU Teletext non-subtitle data" },
2300 { 0x03, 0x03, "EBU Teletext subtitle data" },
2301 { 0x04, 0x7F, "DVB reserved" },
2302 { 0x80, 0xBF, "User defined" },
2303 { 0xC0, 0xC0, "Inverted Teletext" },
2304 { 0xC1, 0xC2, "DVB reserved" },
2305 { 0xC3, 0xC3, "VPS" },
2306 { 0xC4, 0xC4, "WSS" },
2307 { 0xC5, 0xC5, "CEA-608 Closed Captioning" },
2308 { 0xC6, 0xC6, "monochrome 4:2:2 samples" },
2309 { 0xC7, 0xCF, "User defined" },
2310 { 0xD0, 0xD0, "AMOL48" },
2311 { 0xD1, 0xD1, "AMOL96" },
2312 { 0xDA, 0xE5, "SCTE reserved" },
2313 { 0xE6, 0xFE, "SCTE user defined" },
2314 { 0xFF, 0xFF, "MPEG stuffing" },
2315 { 0x00, 0xFF, "Reserved or user defined" },
2316 { 0, 0, NULL((void*)0) }
2317};
2318
2319/* ETSI EN 301 775, Sec. 4.5.2 carries a 42-byte Teletext data block;
2320 * packet addressing, page/control bits and character data follow Rec. ITU-R BT.653-3 System B. */
2321/* SMPTE ST 2031:2015, Secs. 5-6, Tables 1-2; ETSI EN 301 775 Sec. 4.5 for Teletext fields. */
2322static int
2323dissect_st2031(tvbuff_t *tvb, packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, void *data)
2324{
2325 const st291_vanc_dissector_data_t *st291_data = (const st291_vanc_dissector_data_t *)data;
2326 proto_tree *top_tree = st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
2327 proto_item *ti;
2328 proto_tree *st2031_tree;
2329 uint8_t unit_id;
2330 tvbuff_t *wst_tvb;
2331
2332 if (tvb_captured_length(tvb) < 2)
2333 return 0;
2334
2335 ti = proto_tree_add_item(top_tree, proto_st2031, tvb, 0, -1, ENC_NA0x00000000);
2336 st2031_tree = proto_item_add_subtree(ti, ett_st2031);
2337
2338 /* SMPTE ST 2031:2015, Sec. 6, Table 2 -- data_identifier,
2339 * data_unit_id and data_unit_length. */
2340 proto_tree_add_item(st2031_tree, hf_st2031_data_identifier, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
2341 proto_tree_add_item(st2031_tree, hf_st2031_data_unit_id, tvb, 1, 1, ENC_BIG_ENDIAN0x00000000);
2342 unit_id = tvb_get_uint8(tvb, 1);
2343
2344 if ((unit_id == 0x02 || unit_id == 0x03) && tvb_captured_length(tvb) >= 47) {
2345 proto_tree_add_item(st2031_tree, hf_st2031_data_unit_length, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
2346 /* ETSI EN 301 775, Secs. 4.5.1-4.5.2, Tables 4-5 --
2347 * field_parity, line_offset, framing_code and Teletext data block. */
2348 proto_tree_add_item(st2031_tree, hf_st2031_field_parity, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
2349 proto_tree_add_item(st2031_tree, hf_st2031_line_offset, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
2350 proto_tree_add_item(st2031_tree, hf_st2031_framing_code, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
2351 wst_tvb = tvb_new_subset_length(tvb, 5, 42);
2352 st291_process_wst_packet(wst_tvb, st2031_tree, &st2031_wst_fields);
2353 }
2354
2355 return tvb_captured_length(tvb);
2356}
2357
2358void
2359proto_register_st2031(void)
2360{
2361 static hf_register_info hf[] = {
2362 { &hf_st2031_data_identifier,
2363 { "Data Identifier", "st2031.data_identifier", FT_UINT8,
2364 BASE_HEX | BASE_RANGE_STRING0x00000100, RVALS(st2031_data_identifier_vals)((0 ? (const struct _range_string*)0 : ((st2031_data_identifier_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2365 { &hf_st2031_data_unit_id,
2366 { "Data Unit ID", "st2031.data_unit_id", FT_UINT8, BASE_HEX | BASE_RANGE_STRING0x00000100,
2367 RVALS(st2031_data_unit_id_vals)((0 ? (const struct _range_string*)0 : ((st2031_data_unit_id_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2368 { &hf_st2031_data_unit_length,
2369 { "Data Unit Length", "st2031.data_unit_length", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
2370 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2371 { &hf_st2031_field_parity,
2372 { "Field Parity", "st2031.field_parity", FT_BOOLEAN, 8,
2373 TFS(&st2031_tfs_field_parity)((0 ? (const struct true_false_string*)0 : ((&st2031_tfs_field_parity
))))
, 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2374 { &hf_st2031_line_offset,
2375 { "Line Offset", "st2031.line_offset", FT_UINT8, BASE_DEC, NULL((void*)0), 0x1F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2376 { &hf_st2031_framing_code,
2377 { "Framing Code", "st2031.framing_code", FT_UINT8, BASE_HEX, NULL((void*)0), 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2378 { &hf_st2031_magazine_hamming,
2379 { "Magazine (Hamming 8/4)", "st2031.teletext.magazine_hamming", FT_UINT16, BASE_DEC,
2380 NULL((void*)0), 0xFC00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2381 { &hf_st2031_magazine,
2382 { "Magazine", "st2031.teletext.magazine", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2383 { &hf_st2031_packet_number_hamming,
2384 { "Packet Number (Hamming 8/4)", "st2031.teletext.packet_number_hamming", FT_UINT16,
2385 BASE_DEC, NULL((void*)0), 0x03FF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2386 { &hf_st2031_packet_number,
2387 { "Packet Number", "st2031.teletext.packet_number", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
2388 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2389 { &hf_st2031_page_units_hamming,
2390 { "Page Units (Hamming 8/4)", "st2031.teletext.page_units_hamming", FT_UINT8,
2391 BASE_HEX, NULL((void*)0), 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2392 { &hf_st2031_page_units,
2393 { "Page Units", "st2031.teletext.page_units", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
2394 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2395 { &hf_st2031_page_tens_hamming,
2396 { "Page Tens (Hamming 8/4)", "st2031.teletext.page_tens_hamming", FT_UINT8,
2397 BASE_HEX, NULL((void*)0), 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2398 { &hf_st2031_page_tens,
2399 { "Page Tens", "st2031.teletext.page_tens", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
2400 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2401 { &hf_st2031_data_string,
2402 { "Data String", "st2031.teletext.data_string", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
2403 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2404 { &hf_st2031_textdata_array,
2405 { "Text Data", "st2031.teletext.text_data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0),
2406 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2407 { &hf_st2031_erase_page,
2408 { "Erase Page", "st2031.teletext.erase_page", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2409 { &hf_st2031_newsflash,
2410 { "Newsflash", "st2031.teletext.newsflash", FT_BOOLEAN, 8, NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2411 { &hf_st2031_subtitle,
2412 { "Subtitle", "st2031.teletext.subtitle", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2413 { &hf_st2031_suppress_header,
2414 { "Suppress Header", "st2031.teletext.suppress_header", FT_BOOLEAN, 8, NULL((void*)0), 0x40,
2415 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2416 { &hf_st2031_update_indicator,
2417 { "Update Indicator", "st2031.teletext.update_indicator", FT_BOOLEAN, 8, NULL((void*)0), 0x10,
2418 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2419 { &hf_st2031_interrupted_sequence,
2420 { "Interrupted Sequence", "st2031.teletext.interrupted_sequence", FT_BOOLEAN, 8,
2421 NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2422 { &hf_st2031_inhibit_display,
2423 { "Inhibit Display", "st2031.teletext.inhibit_display", FT_BOOLEAN, 8, NULL((void*)0), 0x01,
2424 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2425 { &hf_st2031_magazine_serial,
2426 { "Magazine Serial", "st2031.teletext.magazine_serial", FT_BOOLEAN, 8, NULL((void*)0), 0x40,
2427 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2428 { &hf_st2031_character_set,
2429 { "Character Subset", "st2031.teletext.character_set", FT_UINT8, BASE_DEC,
2430 VALS(st291_wst_national_subset_vals)((0 ? (const struct _value_string*)0 : ((st291_wst_national_subset_vals
))))
, 0x15, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2431 { &hf_st2031_tt_control,
2432 { "Teletext Control", "st2031.teletext.control", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
2433 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2434 };
2435 static int *ett[] = { &ett_st2031 };
2436
2437 proto_st2031 = proto_register_protocol(
2438 "SMPTE ST 2031 VBI Data", "ST 2031", "st2031");
2439 proto_register_field_array(proto_st2031, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
2440 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
2441
2442 st2031_handle = register_dissector("st2031", dissect_st2031, proto_st2031);
2443}
2444
2445void
2446proto_reg_handoff_st2031(void)
2447{
2448 dissector_add_uint("st291.did_sdid", ST2031_DID_SDID_KEY0x4108, st2031_handle);
2449}
2450
2451/*
2452 * Free TV Australia OP-47 / SMPTE RDD 8 teletext
2453 */
2454
2455static const st291_wst_fields_t op47_wst_fields = {
2456 &hf_op47_magazine_hamming,
2457 &hf_op47_magazine,
2458 &hf_op47_packet_number_hamming,
2459 &hf_op47_packet_number,
2460 &hf_op47_page_units_hamming,
2461 &hf_op47_page_units,
2462 &hf_op47_page_tens_hamming,
2463 &hf_op47_page_tens,
2464 &hf_op47_data_string,
2465 &hf_op47_textdata_array,
2466 &hf_op47_erase_page,
2467 &hf_op47_newsflash,
2468 &hf_op47_subtitle,
2469 &hf_op47_suppress_header,
2470 &hf_op47_update_indicator,
2471 &hf_op47_interrupted_sequence,
2472 &hf_op47_inhibit_display,
2473 &hf_op47_magazine_serial,
2474 &hf_op47_character_set,
2475 &hf_op47_tt_control,
2476};
2477
2478/* Rec. ITU-R BT.653-3, System B national-option character subsets used by OP-47 WST data. */
2479/* OP-47 Issue 6, Sec. 5.5.2 carries a System B WST packet; magazine,
2480 * packet number, page address, control bits and text follow Rec. ITU-R BT.653-3. */
2481/* Free TV Australia OP-47 Issue 6, Secs. 5.1, 5.4 and 5.5, Fig. 2. */
2482static int
2483dissect_op47(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2484{
2485 const st291_vanc_dissector_data_t *st291_data = (const st291_vanc_dissector_data_t *)data;
2486 proto_tree *top_tree = st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
2487 proto_item *ti;
2488 proto_tree *op47_tree;
2489 unsigned len = tvb_captured_length(tvb);
2490 uint8_t format_code;
2491 unsigned offset_a = 4, offset_b = 9, i;
2492
2493 if (len < 4)
2494 return 0;
2495
2496 ti = proto_tree_add_item(top_tree, proto_op47, tvb, 0, -1, ENC_NA0x00000000);
2497 op47_tree = proto_item_add_subtree(ti, ett_op47);
2498
2499 /* OP-47 Issue 6, Sec. 5.1 and Fig. 2 -- SDP identifier, length and format code. */
2500 proto_tree_add_item(op47_tree, hf_op47_sdp_identifier, tvb, 0, 2, ENC_BIG_ENDIAN0x00000000);
2501 proto_tree_add_item(op47_tree, hf_op47_sdp_length, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
2502 proto_tree_add_item(op47_tree, hf_op47_sdp_format_code, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
2503 format_code = tvb_get_uint8(tvb, 3);
2504 if (format_code != 0x02 || len < 9)
2505 return len;
2506
2507 /* OP-47 Issue 6, Sec. 5.4 -- Packet Descriptor Structure A / adaptation header. */
2508 ti = proto_tree_add_item(op47_tree, hf_op47_sdp_adaption_header, tvb, 4, 5, ENC_NA0x00000000);
2509 proto_item_set_generated(ti);
2510
2511 for (i = 0; i < 5; i++) {
2512 uint8_t pkt_desc_a;
2513 uint8_t *flipped;
2514 tvbuff_t *wst_tvb;
2515 proto_tree *wst_tree;
2516
2517 if (offset_a >= len)
2518 break;
2519 pkt_desc_a = tvb_get_uint8(tvb, offset_a);
2520 if (pkt_desc_a == 0)
2521 break;
2522 if (offset_b + 45 > len)
2523 break;
2524
2525 /* OP-47 Issue 6, Sec. 5.5 -- Packet Descriptor Structure B;
2526 * Secs. 5.5.1-5.5.2 define clock run-in, framing code and WST data. */
2527 ti = proto_tree_add_item(op47_tree, hf_op47_sdp_pkt_desc_b, tvb, offset_b, 45, ENC_NA0x00000000);
2528 proto_item_set_generated(ti);
2529 wst_tree = proto_item_add_subtree(ti, ett_op47_wst);
2530
2531 ti = proto_tree_add_item(wst_tree, hf_op47_clock_runin, tvb, offset_b, 2, ENC_BIG_ENDIAN0x00000000);
2532 proto_item_set_generated(ti);
2533 ti = proto_tree_add_item(wst_tree, hf_op47_framing_code, tvb, offset_b + 2, 1, ENC_BIG_ENDIAN0x00000000);
2534 proto_item_set_generated(ti);
2535
2536 flipped = wmem_alloc(pinfo->pool, 42);
2537 tvb_memcpy(tvb, flipped, offset_b + 3, 42);
2538 bitswap_buf_inplace(flipped, 42);
2539
2540 wst_tvb = tvb_new_child_real_data(tvb, flipped, 42, 42);
2541 add_new_data_source(pinfo, wst_tvb, "OP-47 WST data (bit reversed)");
2542 st291_process_wst_packet(wst_tvb, wst_tree, &op47_wst_fields);
2543
2544 offset_a++;
2545 offset_b += 45;
2546 }
2547
2548 return len;
2549}
2550
2551void
2552proto_register_op47(void)
2553{
2554 static hf_register_info hf[] = {
2555 { &hf_op47_sdp_identifier,
2556 { "Identifier", "op47.sdp.identifier", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2557 { &hf_op47_sdp_length,
2558 { "Length", "op47.sdp.length", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2559 { &hf_op47_sdp_format_code,
2560 { "Format Code", "op47.sdp.format_code", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2561 { &hf_op47_sdp_adaption_header,
2562 { "Adaption Header", "op47.sdp.adaption_header", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
2563 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2564 { &hf_op47_sdp_pkt_desc_b,
2565 { "Packet Descriptor B", "op47.sdp.packet_descriptor_b", FT_BYTES, BASE_NONE, NULL((void*)0),
2566 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2567 { &hf_op47_clock_runin,
2568 { "Clock Run-In", "op47.wst.clock_runin", FT_UINT16, BASE_HEX, NULL((void*)0), 0xFFFF, NULL((void*)0),
2569 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2570 { &hf_op47_framing_code,
2571 { "Framing Code", "op47.wst.framing_code", FT_UINT8, BASE_HEX, NULL((void*)0), 0xFF, NULL((void*)0),
2572 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2573 { &hf_op47_magazine_hamming,
2574 { "Magazine (Hamming 8/4)", "op47.wst.magazine_hamming", FT_UINT16, BASE_DEC, NULL((void*)0),
2575 0xFC00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2576 { &hf_op47_magazine,
2577 { "Magazine", "op47.wst.magazine", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2578 { &hf_op47_packet_number_hamming,
2579 { "Packet Number (Hamming 8/4)", "op47.wst.packet_number_hamming", FT_UINT16,
2580 BASE_DEC, NULL((void*)0), 0x03FF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2581 { &hf_op47_packet_number,
2582 { "Packet Number", "op47.wst.packet_number", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0),
2583 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2584 { &hf_op47_page_units_hamming,
2585 { "Page Units (Hamming 8/4)", "op47.wst.page_units_hamming", FT_UINT8, BASE_HEX,
2586 NULL((void*)0), 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2587 { &hf_op47_page_units,
2588 { "Page Units", "op47.wst.page_units", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2589 { &hf_op47_page_tens_hamming,
2590 { "Page Tens (Hamming 8/4)", "op47.wst.page_tens_hamming", FT_UINT8, BASE_HEX, NULL((void*)0),
2591 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2592 { &hf_op47_page_tens,
2593 { "Page Tens", "op47.wst.page_tens", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2594 { &hf_op47_data_string,
2595 { "Data String", "op47.wst.data_string", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0),
2596 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2597 { &hf_op47_textdata_array,
2598 { "Text Data", "op47.wst.text_data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2599 { &hf_op47_erase_page,
2600 { "Erase Page", "op47.wst.erase_page", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2601 { &hf_op47_newsflash,
2602 { "Newsflash", "op47.wst.newsflash", FT_BOOLEAN, 8, NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2603 { &hf_op47_subtitle,
2604 { "Subtitle", "op47.wst.subtitle", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2605 { &hf_op47_suppress_header,
2606 { "Suppress Header", "op47.wst.suppress_header", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0),
2607 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2608 { &hf_op47_update_indicator,
2609 { "Update Indicator", "op47.wst.update_indicator", FT_BOOLEAN, 8, NULL((void*)0), 0x10, NULL((void*)0),
2610 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2611 { &hf_op47_interrupted_sequence,
2612 { "Interrupted Sequence", "op47.wst.interrupted_sequence", FT_BOOLEAN, 8, NULL((void*)0),
2613 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2614 { &hf_op47_inhibit_display,
2615 { "Inhibit Display", "op47.wst.inhibit_display", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0),
2616 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2617 { &hf_op47_magazine_serial,
2618 { "Magazine Serial", "op47.wst.magazine_serial", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0),
2619 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2620 { &hf_op47_character_set,
2621 { "Character Subset", "op47.wst.character_set", FT_UINT8, BASE_DEC,
2622 VALS(st291_wst_national_subset_vals)((0 ? (const struct _value_string*)0 : ((st291_wst_national_subset_vals
))))
, 0x15, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2623 { &hf_op47_tt_control,
2624 { "Teletext Control", "op47.wst.control", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2625 };
2626 static int *ett[] = {
2627 &ett_op47,
2628 &ett_op47_wst,
2629 };
2630
2631 proto_op47 = proto_register_protocol(
2632 "RDD 8 / OP-47 Subtitle Distribution Packet", "OP-47", "op47");
2633 proto_register_field_array(proto_op47, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
2634 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
2635
2636 op47_handle = register_dissector("op47", dissect_op47, proto_op47);
2637}
2638
2639void
2640proto_reg_handoff_op47(void)
2641{
2642 dissector_add_uint("st291.did_sdid", OP47_DID_SDID_KEY0x4302, op47_handle);
2643}
2644
2645/*
2646 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2647 *
2648 * Local variables:
2649 * c-basic-offset: 4
2650 * tab-width: 8
2651 * indent-tabs-mode: nil
2652 * End:
2653 *
2654 * vi: set shiftwidth=4 tabstop=8 expandtab:
2655 * :indentSize=4:tabSize=8:noTabs=true:
2656 */