• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/perl
2# SPDX-License-Identifier: GPL-2.0-only */
3# Copyright 2022 Collabora Ltd.
4
5my $outdir = ".";
6my %outtype = ( "common" => 1, "trace" => 1, "retrace" => 1 );
7
8while ($ARGV[0] =~ /^-/) {
9	my $arg = shift @ARGV;
10
11	($outdir = shift @ARGV) && next if $arg eq "-o";
12	(%outtype = (shift @ARGV => 1)) && next if $arg eq '-t';
13	(help() && exit 0) if $arg eq '-h';
14	last if $arg eq '--';
15
16	print stderr "invalid option $arg, use $0 -h for help\n";
17	exit 1;
18}
19
20sub help() {
21	print stderr <<EOF;
22$0 - Generate files for V4L2 tracer
23
24usage: $0 [-o dir] [-t (common|trace|retrace)] [-h] header [header2] ...
25
26	-o dir	set output directory
27	-t x	generate particular trace files, the default is to generate
28		them all
29	-h	print this help text and quit
30EOF
31}
32
33sub convert_type_to_json_type {
34	my $type = shift;
35	if ($type eq __u8 || $type eq char || $type eq __u16 || $type eq __s8 || $type eq __s16 || $type eq __s32 || $type eq 'int' ||
36		$type eq 'v4l2_av1_warp_model' || $type eq 'v4l2_av1_frame_restoration_type' || $type eq 'v4l2_av1_frame_type' ||
37		$type eq 'v4l2_av1_interpolation_filter' || $type eq 'v4l2_av1_tx_mode') {
38		return "int";
39	}
40	if ($type eq __u32 || $type eq __le32 || $type eq __s64) {
41		return "int64";
42	}
43
44	# unsigned appears just twice in videodev2.h and in both cases it is 'unsigned long'
45	if ($type eq __u64 || $type eq 'v4l2_std_id' || $type eq 'unsigned') {
46		return "uint64";
47	}
48	if ($type eq struct || $type eq union || $type eq void) {
49		return;
50	}
51	print "v4l2_tracer: error: couldn't convert \'$type\' to json_object type.\n";
52	return;
53}
54
55sub get_index_letter {
56	my $index = shift;
57	if ($index eq 0) {return "i";}
58	if ($index eq 1) {return "j";}
59	if ($index eq 2) {return "k";}
60	if ($index eq 3) {return "l";}
61	if ($index eq 4) {return "m";}
62	if ($index eq 5) {return "n";}
63	if ($index eq 6) {return "o";} # "p" is saved for pointer
64	if ($index eq 8) {return "q";}
65	return "z";
66}
67
68$flag_func_name;
69
70sub flag_gen {
71	my $flag_type = shift;
72
73	if ($flag_type =~ /fwht/) {
74		$flag_func_name = v4l2_ctrl_fwht_params_;
75	} elsif ($flag_type =~ /vp8_loop_filter/) {
76		$flag_func_name = v4l2_vp8_loop_filter_;
77	} else {
78		($flag_func_name) = ($_) =~ /#define (\w+_)FL.+/;
79		$flag_func_name = lc $flag_func_name;
80	}
81
82	printf $fh_common_info_h "constexpr flag_def %sflag_def[] = {\n", $flag_func_name;
83
84	($flag) = ($_) =~ /#define\s+(\w+)\s+.+/;
85	printf $fh_common_info_h "\t{ $flag, \"$flag\" },\n"; # get the first flag
86
87	while (<>) {
88		next if ($_ =~ /^\/?\s?\*.*/); # skip comments between flags if any
89		next if $_ =~ /^\s*$/; # skip blank lines between flags if any
90		last if ((grep {!/^#define\s+\w+_FL/} $_) && (grep {!/^#define V4L2_VP8_LF/} $_));
91		($flag) = ($_) =~ /#\s*define\s+(\w+)\s+.+/;
92
93		# don't include flags that are masks
94		next if ($flag_func_name eq v4l2_buf_) && ($flag =~ /.*TIMESTAMP.*/ || $flag =~ /.*TSTAMP.*/);
95		next if ($flag_func_name eq v4l2_ctrl_fwht_params_) && ($flag =~ /.*COMPONENTS.*/ || $flag =~ /.*PIXENC.*/);
96		next if ($flag =~ /.*MEDIA_LNK_FL_LINK_TYPE.*/);
97		next if ($flag =~ /.*MEDIA_ENT_ID_FLAG_NEXT.*/);
98
99		printf $fh_common_info_h "\t{ $flag, \"$flag\" },\n";
100	}
101	printf $fh_common_info_h "\t{ 0, \"\" }\n};\n\n";
102}
103
104sub enum_gen {
105	($enum_name) = ($_) =~ /enum (\w+) {/;
106	printf $fh_common_info_h "constexpr val_def %s_val_def[] = {\n", $enum_name;
107	while (<>) {
108		last if $_ =~ /};/;
109		($name) = ($_) =~ /\s+(\w+)\s?.*/;
110		next if ($name ne uc $name); # skip comments that don't start with *
111		next if ($_ =~ /^\s*\/?\s?\*.*/); # skip comments
112		next if $name =~ /^\s*$/;  # skip blank lines
113		printf $fh_common_info_h "\t{ %s,\t\"%s\" },\n", $name, $name;
114	}
115	printf $fh_common_info_h "\t{ -1, \"\" }\n};\n\n";
116}
117
118sub val_def_gen {
119	my $last_val = shift;
120	my $sentinel = shift;
121	if (length $sentinel == 0) {
122		$sentinel = "-1"; # _flag_def arrays end with 0, _val_def arrays end in -1
123	}
124	($val) = ($_) =~ /^#define\s*(\w+)\s*/;
125	printf $fh_common_info_h "\t{ %s,\t\"%s\" },\n", $val, $val;
126
127	# in case there is only one value e.g. flags for V4L2_DEC_CMD_START
128	if ($val eq $last_val) {
129		printf $fh_common_info_h "\t{ $sentinel, \"\" }\n};\n\n";
130		return;
131	}
132	while (<>) {
133		next if ($_ =~ /^\s*\/?\s?\*.*/); # skip comments
134		next if ($_ =~ /^\s*$/);  # skip blank lines
135		($val) = ($_) =~ /^#define\s*(\w+)\s*/;
136		next if ($val eq ""); # skip lines that don't start with define e.g. V4L2_STD_ATSC_16_VSB
137		printf $fh_common_info_h "\t{ %s,\t\"%s\" },\n", $val, $val;
138		last if ($val eq $last_val);
139	}
140	printf $fh_common_info_h "\t{ $sentinel, \"\" }\n};\n\n";
141}
142
143sub flag_def_gen {
144	my $last_flag = shift;
145	val_def_gen($last_flag, 0);
146}
147
148sub clean_up_line {
149	my $line = shift;
150	chomp($line);
151	$line =~ s/^\s+//; # remove leading whitespace
152	$line =~ s/.*\# define.*//; # zero out line if it has defines inside a structure (e.g. v4l2_jpegcompression)
153	$line =~ s/^\s*\/?\s?\*.*//; # zero out line if it has comments where the line starts with start with /* / * or just *
154	$line =~ s/\s*\/\*.*//; # remove comments /* */ at the end of a line following a member
155	$line =~ s/\s*\/\/.*//; # remove comments // at the end of a line following a member
156	$line =~ s/\*\/$//; # zero out line if it has comments that begin without any slashs or asterisks but end with */
157	# zero out lines that don't have a ; or { because they are comments but without any identifying slashes or asteriks
158	if ($line !~ /.*[\;|\{].*/) {
159		$line =~ s/.*//;
160	}
161	$line =~ s/.*reserved.*//; # zero out lines with reserved members, they will segfault on retracing
162	$line =~ s/.*raw_data.*//;
163	# don't remove semi-colon at end because some functions will look for it
164	return $line;
165}
166
167sub get_val_def_name {
168	my $member = shift;
169	my $struct_name = shift;
170	@structs_that_use_v4l2_buf_type = qw(v4l2_fmtdesc v4l2_requestbuffers v4l2_buffer v4l2_crop
171	                                     v4l2_exportbuffer v4l2_cropcap v4l2_selection
172	                                     v4l2_sliced_vbi_cap v4l2_format v4l2_streamparm);
173	@structs_that_use_v4l2_ctrl_type = qw(v4l2_queryctrl v4l2_query_ext_ctrl v4l2_event_ctrl);
174	@structs_that_use_v4l2_tuner_type = qw(v4l2_tuner v4l2_frequency);
175	if ($member eq "type") {
176		foreach (@structs_that_use_v4l2_buf_type) {
177			if ($struct_name eq $_) {
178				return "v4l2_buf_type_val_def";
179			}
180		}
181		foreach (@structs_that_use_v4l2_tuner_type) {
182			if ($struct_name eq $_) {
183				return "v4l2_tuner_type_val_def";
184			}
185		}
186		foreach (@structs_that_use_v4l2_ctrl_type) {
187			if ($struct_name eq $_) {
188				return "v4l2_ctrl_type_val_def";
189			}
190		}
191		if ($struct_name eq "v4l2_frmsizeenum") {
192			return "v4l2_frmsizetypes_val_def";
193		}
194		if ($struct_name eq "v4l2_frmivalenum") {
195			return "v4l2_frmivaltypes_val_def";
196		}
197		if ($struct_name eq "v4l2_input") {
198			return $val_def_name = "input_type_val_def";
199		}
200		if ($struct_name eq "v4l2_output") {
201			return $val_def_name = "output_type_val_def";
202		}
203		if ($struct_name eq "v4l2_event" || $struct_name eq "v4l2_event_subscription") {
204			return $val_def_name = "event_val_def";
205		}
206		return "nullptr"; # will print as hex string
207	}
208	if ($member eq "pixelformat" || $member eq "pixel_format") {
209		return "v4l2_pix_fmt_val_def";
210	}
211	if ($member =~ /cmd/) {
212		if ($struct_name =~ /v4l2_decoder_cmd/) {
213			return "decoder_cmd_val_def";
214		}
215		if ($struct_name =~ /v4l2_encoder_cmd/) {
216			return "encoder_cmd_val_def";
217		}
218	}
219	if ($member =~ /memory/) {
220		return "v4l2_memory_val_def";
221	}
222	@structs_that_use_v4l2_field = qw(v4l2_pix_format v4l2_buffer v4l2_framebuffer v4l2_window
223	                                  v4l2_pix_format_mplane v4l2_event_vsync);
224	if ($member eq "field") {
225		foreach (@structs_that_use_v4l2_field) {
226			if ($struct_name eq $_) {
227				return "v4l2_field_val_def";
228			}
229		}
230		return "nullptr"; # will print as hex string
231	}
232	if ($member =~ /^id$/) {
233		if ($struct_name =~ /.*control|query.*/) {
234			return "control_val_def";
235		}
236		return "nullptr"; # will print as hex string
237	}
238	if ($member =~ /capability|outputmode|capturemode/) {
239		if ($struct_name =~ /.*v4l2_captureparm|v4l2_outputparm.*/) {
240		return "streamparm_val_def";
241		}
242	}
243	if ($member =~ /colorspace/) {
244		return "v4l2_colorspace_val_def";
245	}
246	if ($member =~ /ycbcr_enc/) {
247		return "v4l2_ycbcr_encoding_val_def";
248	}
249	if ($member =~ /quantization/) {
250		return "v4l2_quantization_val_def";
251	}
252	if ($member =~ /xfer_func/) {
253		return "v4l2_xfer_func_val_def";
254	}
255	if (($member eq "status") && ($struct_name eq "v4l2_input")) {
256		$val_def_name = "input_field_val_def";
257	}
258	if ($member eq "audmode") {
259		return "tuner_audmode_val_def";
260	}
261	if ($member eq "target" && $struct_name eq "v4l2_selection") {
262		return "selection_target_val_def";
263	}
264}
265
266sub get_flag_def_name {
267	my $member = shift;
268	my $struct_name = shift;
269	if ($member =~ /flags/) {
270		if ($struct_name =~ /buffers$/) {
271			return "v4l2_memory_flag_def";
272		}
273		if ($struct_name =~ /.*pix_format.*/) {
274			return "v4l2_pix_fmt_flag_def";
275		}
276		if ($struct_name =~ /.*ctrl$/) {
277			return "v4l2_ctrl_flag_def";
278		}
279		if ($struct_name =~ /.*fmtdesc$/) {
280			return "v4l2_fmt_flag_def";
281		}
282		if ($struct_name =~ /.*selection$/) {
283			return "v4l2_sel_flag_def";
284		}
285		if ($struct_name eq "v4l2_event_subscription") {
286			return "v4l2_event_sub_flag_def";
287		}
288		return "nullptr";
289	}
290
291	if ($member =~ /.*cap.*/) {
292		# v4l2_requestbuffers, v4l2_create_buffers
293		if ($struct_name =~ /buffers$/) {
294			return "v4l2_buf_cap_flag_def";
295		}
296		# v4l2_capability
297		if ($struct_name =~ /capability$/) {
298			return "v4l2_cap_flag_def";
299		}
300		if ($struct_name eq "v4l2_tuner") {
301			return "tuner_cap_flag_def";
302		}
303	}
304	if ($member eq "rxsubchans") {
305		return "tuner_rxsub_flag_def";
306	}
307	if ($member eq "changes") {
308		if ($struct_name eq "v4l2_event_ctrl") {
309			return "v4l2_event_ctrl_ch_flag_def";
310		}
311	}
312	return "";
313}
314
315# trace a struct nested in another struct in videodev2.h
316sub handle_struct {
317	printf $fh_trace_cpp "\t//$line\n";
318	printf $fh_retrace_cpp "\t//$line\n";
319
320	# this is a multi-lined nested struct so iterate through it
321	if ($line !~ /.*;$/) {
322		$suppress_struct = true;
323		return;
324	}
325
326	# don't trace struct pointers
327	if ($line =~ /\*/) {
328		return;
329	}
330	# don't trace struct arrays
331	if ($line =~ /\[/) {
332		return;
333	}
334
335	my ($struct_tag) = ($line) =~ /\s*struct (\w+)\s+.*/;
336
337	# structs defined outside of videodev2.h
338	if ($struct_tag =~ /v4l2_ctrl|timeval|timespec/) {
339		return;
340	}
341
342	# e.g. $struct_tag_parent = v4l2_captureparm, $struct_tag = v4l2_fract, $struct_var = timeperframe
343	my $struct_tag_parent = $struct_name;
344	my ($struct_var) = ($line) =~ /(\w+)\;$/;
345	printf $fh_trace_cpp "\ttrace_%s_gen(&p->%s, %s_obj, \"%s\");\n", $struct_tag, $struct_var, $struct_tag_parent, $struct_var;
346
347	printf $fh_retrace_cpp "\tvoid *%s_ptr = (void *) retrace_%s_gen(%s_obj, \"%s\");\n", $struct_var, $struct_tag, $struct_tag_parent, $struct_var;
348	printf $fh_retrace_cpp "\tp->$struct_var = *static_cast<struct %s*>(%s_ptr);\n", $struct_tag, $struct_var;
349	printf $fh_retrace_cpp "\tfree(%s_ptr);\n\n", $struct_var;
350}
351
352# trace a union in videodev2.h
353sub handle_union {
354	my @params = @_;
355	my $struct_name = @params[0];
356
357	$in_union = true;
358	$suppress_union = true;
359	printf $fh_trace_cpp "\t//union\n";
360	printf $fh_retrace_cpp "\t//union\n";
361
362	if ($struct_name =~ /^v4l2_pix_format/) {
363		$suppress_union = false;
364	}
365
366	if ($struct_name =~ /^v4l2_format$/) {
367		printf $fh_trace_cpp "\tswitch (p->type) {\n";
368		printf $fh_trace_cpp "\tcase V4L2_BUF_TYPE_VIDEO_CAPTURE:\n\tcase V4L2_BUF_TYPE_VIDEO_OUTPUT:\n";
369		printf $fh_trace_cpp "\t\ttrace_v4l2_pix_format_gen(&p->fmt.pix, %s_obj);\n\t\tbreak;\n", $struct_name;
370		printf $fh_trace_cpp "\tcase V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:\n\tcase V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:\n";
371		printf $fh_trace_cpp "\t\ttrace_v4l2_pix_format_mplane_gen(&p->fmt.pix, %s_obj);\n\t\tbreak;\n", $struct_name;
372		printf $fh_trace_cpp "\tdefault:\n\t\tbreak;\n\t}\n";
373
374		printf $fh_retrace_cpp "\tswitch (p->type) {\n";
375		printf $fh_retrace_cpp "\tcase V4L2_BUF_TYPE_VIDEO_CAPTURE:\n\tcase V4L2_BUF_TYPE_VIDEO_OUTPUT: {\n";
376		printf $fh_retrace_cpp "\t\tvoid *pix_ptr = (void *) retrace_v4l2_pix_format_gen(v4l2_format_obj);\n";
377		printf $fh_retrace_cpp "\t\tp->fmt.pix = *static_cast<struct v4l2_pix_format*>(pix_ptr);\n";
378		printf $fh_retrace_cpp "\t\tfree(pix_ptr);\n\t\tbreak;\n\t}\n";
379
380		printf $fh_retrace_cpp "\tcase V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:\n\tcase V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: {\n";
381		printf $fh_retrace_cpp "\t\tvoid *pix_mp_ptr = (void *) retrace_v4l2_pix_format_mplane_gen(v4l2_format_obj);\n";
382		printf $fh_retrace_cpp "\t\tp->fmt.pix_mp = *static_cast<struct v4l2_pix_format_mplane*>(pix_mp_ptr);\n";
383		printf $fh_retrace_cpp "\t\tfree(pix_mp_ptr);\n\t\tbreak;\n\t}\n";
384
385		printf $fh_retrace_cpp "\tdefault:\n\t\tbreak;\n\t}\n";
386	}
387
388	if ($struct_name eq "v4l2_frmsizeenum") {
389		printf $fh_trace_cpp "\tswitch (p->type) {\n";
390		printf $fh_trace_cpp "\tcase V4L2_FRMSIZE_TYPE_DISCRETE:\n";
391		printf $fh_trace_cpp "\t\ttrace_v4l2_frmsize_discrete_gen(&p->discrete, %s_obj);\n\t\tbreak;\n", $struct_name;
392		printf $fh_trace_cpp "\tcase V4L2_FRMSIZE_TYPE_STEPWISE:\n\tcase V4L2_FRMSIZE_TYPE_CONTINUOUS:\n";
393		printf $fh_trace_cpp "\t\ttrace_v4l2_frmsize_stepwise_gen(&p->stepwise, %s_obj);\n\t\tbreak;\n", $struct_name;
394		printf $fh_trace_cpp "\tdefault:\n\t\tbreak;\n\t}\n";
395	}
396
397	if ($struct_name eq "v4l2_frmivalenum") {
398		printf $fh_trace_cpp "\tswitch (p->type) {\n";
399		printf $fh_trace_cpp "\tcase V4L2_FRMIVAL_TYPE_DISCRETE:\n";
400		printf $fh_trace_cpp "\t\ttrace_v4l2_fract_gen(&p->discrete, %s_obj);\n\t\tbreak;\n", $struct_name;
401		printf $fh_trace_cpp "\tcase V4L2_FRMIVAL_TYPE_STEPWISE:\n\tcase V4L2_FRMIVAL_TYPE_CONTINUOUS:\n";
402		printf $fh_trace_cpp "\t\ttrace_v4l2_frmival_stepwise_gen(&p->stepwise, %s_obj);\n\t\tbreak;\n", $struct_name;
403		printf $fh_trace_cpp "\tdefault:\n\t\tbreak;\n\t}\n";
404	}
405
406	if ($struct_name eq "v4l2_event") {
407		printf $fh_trace_cpp "\tswitch (p->type) {\n";
408		printf $fh_trace_cpp "\tcase V4L2_EVENT_VSYNC:\n";
409		printf $fh_trace_cpp "\t\ttrace_v4l2_event_vsync_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
410		printf $fh_trace_cpp "\tcase V4L2_EVENT_CTRL:\n";
411		printf $fh_trace_cpp "\t\ttrace_v4l2_event_ctrl_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
412		printf $fh_trace_cpp "\tcase V4L2_EVENT_FRAME_SYNC:\n";
413		printf $fh_trace_cpp "\t\ttrace_v4l2_event_frame_sync_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
414		printf $fh_trace_cpp "\tcase V4L2_EVENT_SOURCE_CHANGE:\n";
415		printf $fh_trace_cpp "\t\ttrace_v4l2_event_src_change_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
416		printf $fh_trace_cpp "\tcase V4L2_EVENT_MOTION_DET:\n";
417		printf $fh_trace_cpp "\t\ttrace_v4l2_event_motion_det_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
418		printf $fh_trace_cpp "\tdefault:\n\t\tbreak;\n\t}\n";
419	}
420
421	return $suppress_union;
422}
423
424# generate functions for structs in videodev2.h
425sub struct_gen {
426	($struct_name) = ($_) =~ /struct (\w+) {/;
427
428	# it's not being used and was generating a warning
429	if ($struct_name =~ /v4l2_mpeg_vbi_ITV0/) {
430		return;
431	}
432	printf $fh_trace_cpp "void trace_%s_gen(void *arg, json_object *parent_obj, std::string key_name = \"\")\n{\n", $struct_name;
433	printf $fh_trace_h "void trace_%s_gen(void *arg, json_object *parent_obj, std::string key_name = \"\");\n", $struct_name;
434	printf $fh_trace_cpp "\tjson_object *%s_obj = json_object_new_object();\n", $struct_name;
435	printf $fh_trace_cpp "\tstruct %s *p = static_cast<struct %s*>(arg);\n\n", $struct_name, $struct_name;
436
437	printf $fh_retrace_h "struct %s *retrace_%s_gen(json_object *parent_obj, std::string key_name = \"\");\n", $struct_name, $struct_name;
438	printf $fh_retrace_cpp "struct %s *retrace_%s_gen(json_object *parent_obj, std::string key_name = \"\")\n{\n", $struct_name, $struct_name;
439
440	printf $fh_retrace_cpp "\tstruct %s *p = (struct %s *) calloc(1, sizeof(%s));\n\n", $struct_name, $struct_name, $struct_name;
441	printf $fh_retrace_cpp "\tjson_object *%s_obj;\n", $struct_name;
442	printf $fh_retrace_cpp "\tif (key_name.empty())\n";
443	printf $fh_retrace_cpp "\t\tjson_object_object_get_ex(parent_obj, \"%s\", &%s_obj);\n", $struct_name, $struct_name;
444	printf $fh_retrace_cpp "\telse\n";
445	printf $fh_retrace_cpp "\t\tjson_object_object_get_ex(parent_obj, key_name.c_str(), &%s_obj);\n\n", $struct_name;
446
447	$suppress_union = false;
448	$suppress_struct = false;
449	while ($line = <>) {
450		chomp($line);
451		$member = "";
452		if ($line =~ /}.*;/) {
453			if ($suppress_struct eq true) {
454				printf $fh_trace_cpp "\t//end of struct $line\n";
455				printf $fh_retrace_cpp "\t//end of struct $line\n";
456				$suppress_struct = false;
457				next;
458			} elsif ($in_union eq true) {
459				if ($suppress_union eq true) {
460					$suppress_union = false; # end of union
461				}
462				printf $fh_trace_cpp "\t//end of union $line\n";
463				printf $fh_retrace_cpp "\t//end of union $line\n";
464				$in_union = false;
465				next;
466			} else {
467				last;
468			}
469		}
470		last if $line =~ /^} __attribute__.*/;
471
472		$line = clean_up_line($line);
473		next if $line =~ /^\s*$/; # ignore blank lines
474
475		@words = split /[\s\[]/, $line; # split on whitespace and also'[' to get char arrays
476		@words = grep  {/^\D/} @words; # remove values that start with digit from inside []
477		@words = grep  {!/\]/} @words; # remove values with brackets e.g. V4L2_H264_REF_LIST_LEN]
478
479		($type) = $words[0];
480
481		# unions inside the struct
482		if ($type eq 'union') {
483			handle_union($struct_name);
484			next;
485		}
486		# suppress anything inside a union including structs nested inside a union
487		if ($suppress_union eq true) {
488			printf $fh_trace_cpp "\t//$line\n";
489			printf $fh_retrace_cpp "\t//$line\n";
490			next;
491		}
492
493		# struct members inside the struct
494		if ($type eq 'struct') {
495			handle_struct();
496			next;
497		}
498		if ($suppress_struct eq true) {
499			printf $fh_trace_cpp "\t//$line\n";
500			printf $fh_retrace_cpp "\t//$line\n";
501			next;
502		}
503
504		$json_type = convert_type_to_json_type($type);
505
506		($member) = $words[scalar @words - 1];
507		$member =~ s/;//; # remove the ;
508
509		if ($member =~ /service_lines/) {
510			printf $fh_trace_cpp "\t//$line\n";
511			printf $fh_retrace_cpp "\t//$line\n";
512			next;
513		}
514
515		# Don't trace members that are pointers
516		if ($member =~ /\*/) {
517			printf $fh_trace_cpp "\t//$line\n";
518			printf $fh_retrace_cpp "\t//$line\n";
519			next;
520		}
521
522		if ($line =~ /dims\[V4L2_CTRL_MAX_DIMS\]/) {
523			printf $fh_trace_cpp "\t\/\* $line \*\/\n"; # add comment
524			printf $fh_trace_cpp "\tjson_object *dims_obj = json_object_new_array();\n";
525			printf $fh_trace_cpp "\tfor (int i = 0; i < (std::min((int) p->nr_of_dims, V4L2_CTRL_MAX_DIMS)); i++) {\n";
526			printf $fh_trace_cpp "\t\tjson_object_array_add(dims_obj, json_object_new_int64(p->dims[i]));\n\t}\n";
527			printf $fh_trace_cpp "\tjson_object_object_add(%s_obj, \"$member\", dims_obj);\n", $struct_name;
528
529			printf $fh_retrace_cpp "\t\/\* $line \*\/\n"; # add comment
530			printf $fh_retrace_cpp "\tjson_object *dims_obj;\n";
531			printf $fh_retrace_cpp "\tif (json_object_object_get_ex(%s_obj, \"$member\", &%s_obj)) {\n", $struct_name, $member;
532			printf $fh_retrace_cpp "\t\tfor (int i = 0; i < (std::min((int) p->nr_of_dims, V4L2_CTRL_MAX_DIMS)); i++) {\n";
533			printf $fh_retrace_cpp "\t\t\tif (json_object_array_get_idx(dims_obj, i))\n";
534			printf $fh_retrace_cpp "\t\t\t\tp->dims[i] = (__u32) json_object_get_int64(json_object_array_get_idx(dims_obj, i));\n\t\t}\n\t}\n";
535			next;
536		}
537
538		printf $fh_retrace_cpp "\tjson_object *%s_obj;\n", $member;
539
540		# struct v4l2_pix_format
541		if ($member =~ /priv/) {
542			printf $fh_trace_cpp "\tif (p->priv == V4L2_PIX_FMT_PRIV_MAGIC)\n";
543			printf $fh_trace_cpp "\t\tjson_object_object_add(%s_obj, \"%s\", json_object_new_string(\"V4L2_PIX_FMT_PRIV_MAGIC\"));\n", $struct_name, $member;
544			printf $fh_trace_cpp "\telse\n";
545			printf $fh_trace_cpp "\t\tjson_object_object_add(%s_obj, \"%s\", json_object_new_string(\"\"));\n", $struct_name, $member;
546
547			printf $fh_retrace_cpp "\tif (json_object_object_get_ex(%s_obj, \"$member\", &%s_obj)) {\n", $struct_name, $member;
548			printf $fh_retrace_cpp "\t\tif (json_object_get_string(priv_obj) == nullptr)\n\t\t\treturn p;\n";
549			printf $fh_retrace_cpp "\t\tstd::string priv_str = json_object_get_string(priv_obj);\n";
550			printf $fh_retrace_cpp "\t\tif (!priv_str.empty())\n";
551			printf $fh_retrace_cpp "\t\t\tp->priv = V4L2_PIX_FMT_PRIV_MAGIC;\n\t}\n";
552			next;
553		}
554
555		printf $fh_trace_cpp "\tjson_object_object_add(%s_obj, \"%s\", json_object_new_", $struct_name, $member;
556		printf $fh_retrace_cpp "\tif (json_object_object_get_ex(%s_obj, \"$member\", &%s_obj))\n", $struct_name, $member;
557
558		# Convert char array members to string
559		if ($line =~ /.*\[.*/) {
560			if ($member =~ /.*name|driver|card|bus_info|description|model|magic|serial|userbits|APP_data|COM_data|linemask|data|start|count|raw|.*/) {
561				printf $fh_trace_cpp "string(reinterpret_cast<const char *>(p->$member)));\n";
562
563				printf $fh_retrace_cpp "\t\tif (json_object_get_string(%s_obj) != nullptr)\n", $member;
564				my @char_array_size = ($line) =~ /\[(\w+)\]/g;
565				printf $fh_retrace_cpp "\t\t\tmemcpy(p->$member, json_object_get_string(%s_obj), @char_array_size);\n\n", $member;
566				next;
567			}
568		}
569
570		# special strings
571		if ($member =~ /version/) {
572			printf $fh_trace_cpp "string(ver2s(p->$member).c_str()));\n";
573			printf $fh_retrace_cpp "\t\tmemset(&p->$member, 0, sizeof(p->$member));\n\n"; # driver can fill in version
574			next;
575		}
576
577		printf $fh_retrace_cpp "\t\tp->$member = ";
578
579		if ($struct_name =~ /^v4l2_buffer$/) {
580			if ($member =~ /flags/) {
581				printf $fh_trace_cpp "string(fl2s_buffer(p->$member).c_str()));\n";
582				printf $fh_retrace_cpp "(%s) s2flags_buffer(json_object_get_string(%s_obj));\n\n", $type, $member, $flag_def_name;
583				next;
584			}
585		}
586
587		# strings
588		$val_def_name = get_val_def_name($member, $struct_name);
589		if ($val_def_name !~ /^\s*$/) {
590			printf $fh_trace_cpp "string(val2s(p->$member, %s).c_str()));\n", $val_def_name;
591			printf $fh_retrace_cpp "(%s) s2val(json_object_get_string(%s_obj), %s);\n", $type,  $member, $val_def_name;
592			next;
593		}
594
595		$flag_def_name = get_flag_def_name($member, $struct_name);
596		if ($flag_def_name !~ /^\s*$/) {
597			printf $fh_trace_cpp "string(fl2s(p->$member, %s).c_str()));\n", $flag_def_name;
598			printf $fh_retrace_cpp "(%s) s2flags(json_object_get_string(%s_obj), %s);\n\n", $type, $member, $flag_def_name;
599			next;
600		}
601
602		# integers
603		printf $fh_trace_cpp "$json_type(p->$member));\n";
604		printf $fh_retrace_cpp "(%s) json_object_get_%s(%s_obj);\n\n", $type, $json_type, $member;
605
606		# special treatment for v4l2_pix_format_mplane member plane_fmt[VIDEO_MAX_PLANES]
607		# it can only be traced after num_planes is known
608		if ($member =~ /num_planes/) {
609			printf $fh_trace_cpp "\tjson_object *plane_fmt_obj = json_object_new_array();\n";
610			printf $fh_trace_cpp "\tfor (int i = 0; i < (std::min((int) p->num_planes, VIDEO_MAX_PLANES)); i++) {\n";
611			printf $fh_trace_cpp "\t\tjson_object *element_obj = json_object_new_object();\n";
612			printf $fh_trace_cpp "\t\ttrace_v4l2_plane_pix_format_gen(&(p->plane_fmt[i]), element_obj);\n";
613			printf $fh_trace_cpp "\t\tjson_object *element_no_key_obj;\n";
614			printf $fh_trace_cpp "\t\tjson_object_object_get_ex(element_obj, \"v4l2_plane_pix_format\", &element_no_key_obj);\n";
615			printf $fh_trace_cpp "\t\tjson_object_array_add(plane_fmt_obj, element_no_key_obj);\n\t}\n";
616			printf $fh_trace_cpp "\tjson_object_object_add(v4l2_pix_format_mplane_obj, \"plane_fmt\", plane_fmt_obj);\n\n";
617
618			printf $fh_retrace_cpp "\tjson_object *plane_fmt_obj;\n";
619			printf $fh_retrace_cpp "\tif (json_object_object_get_ex(v4l2_pix_format_mplane_obj, \"plane_fmt\", &plane_fmt_obj)) {\n";
620			printf $fh_retrace_cpp "\t\tfor (int i = 0; i < (std::min((int) p->num_planes, VIDEO_MAX_PLANES)); i++) {\n";
621			printf $fh_retrace_cpp "\t\t\tif (json_object_array_get_idx(plane_fmt_obj, i)) {\n";
622			printf $fh_retrace_cpp "\t\t\t\tjson_object *element_obj = json_object_new_object();\n";
623			printf $fh_retrace_cpp "\t\t\t\tjson_object_object_add(element_obj, \"v4l2_plane_pix_format\", json_object_array_get_idx(plane_fmt_obj, i));\n";
624			printf $fh_retrace_cpp "\t\t\t\tvoid *ptr = (void *) retrace_v4l2_plane_pix_format_gen(element_obj);\n";
625			printf $fh_retrace_cpp "\t\t\t\tp->plane_fmt[i] = *static_cast<struct v4l2_plane_pix_format *>(ptr);\n";
626			printf $fh_retrace_cpp "\t\t\t\tfree(ptr);\n";
627			printf $fh_retrace_cpp "\t\t\t}\n\t\t}\n\t}\n\n";
628		}
629	}
630
631	# The key name option allows a struct to be traced when it is nested inside another struct.
632	printf $fh_trace_cpp "\n\tif (key_name.empty())\n";
633	printf $fh_trace_cpp "\t\tjson_object_object_add(parent_obj, \"%s\", %s_obj);\n", $struct_name, $struct_name;
634	printf $fh_trace_cpp "\telse\n";
635	printf $fh_trace_cpp "\t\tjson_object_object_add(parent_obj, key_name.c_str(), %s_obj);\n", $struct_name;
636	printf $fh_trace_cpp "}\n\n";
637
638	printf $fh_retrace_cpp "\treturn p;\n}\n";
639}
640
641# generate functions for structs in v4l2-controls.h
642sub struct_gen_ctrl {
643	($struct_name) = ($_) =~ /struct (\w+) {/;
644
645	printf $fh_trace_h "void trace_%s_gen(void *ptr, json_object *parent_obj);\n", $struct_name;
646	printf $fh_trace_cpp "void trace_%s_gen(void *ptr, json_object *parent_obj)\n{\n", $struct_name;
647	printf $fh_trace_cpp "\tjson_object *%s_obj = json_object_new_object();\n", $struct_name;
648	printf $fh_trace_cpp "\tstruct %s *p = static_cast<struct %s*>(ptr);\n", $struct_name, $struct_name;
649
650	printf $fh_retrace_h "struct %s *retrace_%s_gen(json_object *ctrl_obj);\n", $struct_name, $struct_name;
651	printf $fh_retrace_cpp "struct %s *retrace_%s_gen(json_object *ctrl_obj)\n{\n", $struct_name, $struct_name;
652	printf $fh_retrace_cpp "\tstruct %s *p = (struct %s *) calloc(1, sizeof(%s));\n", $struct_name, $struct_name, $struct_name;
653	printf $fh_retrace_cpp "\tjson_object *%s_obj;\n", $struct_name;
654	# if a key value isn't found, assume it is retracing an element of an array
655	# e.g. in struct v4l2_ctrl_h264_pred_weights
656	printf $fh_retrace_cpp "\tif (!json_object_object_get_ex(ctrl_obj, \"%s\", &%s_obj))\n", $struct_name, $struct_name;
657	printf $fh_retrace_cpp "\t\t%s_obj = ctrl_obj;\n", $struct_name;
658
659	while ($line = <>) {
660		chomp($line);
661		last if $line =~ /};/;
662		$line = clean_up_line($line);
663		next if $line =~ /^\s*$/; # ignore blank lines
664		$line =~ s/;$//; # remove semi-colon at the end
665		@words = split /[\s\[]/, $line; # also split on '[' to avoid arrays
666		@words = grep  {/^\D/} @words; # remove values that start with digit from inside []
667		@words = grep  {!/\]/} @words; # remove values with brackets e.g. V4L2_H264_REF_LIST_LEN]
668
669		($type) = $words[0];
670		if ($type eq 'enum') {
671			$type = $words[1];
672		}
673		$json_type = convert_type_to_json_type($type);
674
675		($member) = $words[scalar @words - 1];
676
677		# generate members that are arrays
678		if ($line =~ /.*\[.*/) {
679
680			# e.g. two dimensional array [x][y]
681			my @dimensions = ($line) =~ /\[(.*?)\]/g;
682
683			#for struct v4l2_av1_tile_info [V4L2_AV1_MAX_TILE_ROWS + 1]
684			if (grep {$_ =~ /\+/} @dimensions) {
685				$member = $words[scalar @words - 3];
686			}
687
688			printf $fh_trace_cpp "\t\/\* %s \*\/\n", $line; # add comment
689			printf $fh_trace_cpp "\tjson_object *%s_obj = json_object_new_array();\n", $member;
690			printf $fh_retrace_cpp "\n\t\/\* %s \*\/\n", $line; # add comment
691
692			$dimensions_count = scalar @dimensions;
693			if ($dimensions_count > 1) {
694				printf $fh_retrace_cpp "\tint count_%s = 0;\n", $member;
695			}
696			printf $fh_retrace_cpp "\tjson_object *%s_obj;\n", $member;
697			printf $fh_retrace_cpp "\tif (json_object_object_get_ex(%s_obj, \"%s\", &%s_obj)) {\n", $struct_name, $member, $member;
698
699			for (my $idx = 0; $idx < $dimensions_count; $idx = $idx + 1) {
700				$size = $dimensions[$idx];
701				$index_letter = get_index_letter($idx);
702				printf $fh_trace_cpp "\t" x ($idx + 1);
703				printf $fh_trace_cpp "for (size_t %s = 0; %s < %s\; %s++) {\n", $index_letter, $index_letter, $size, $index_letter;
704
705				printf $fh_retrace_cpp "\t" x ($idx + 1);
706				printf $fh_retrace_cpp "\t";
707				printf $fh_retrace_cpp "for (size_t %s = 0; %s < %s\; %s++) {\n", $index_letter, $index_letter, $size, $index_letter;
708			}
709			printf $fh_trace_cpp "\t" x ($dimensions_count + 1);
710			printf $fh_retrace_cpp "\t" x ($dimensions_count + 1);
711			printf $fh_retrace_cpp "\t";
712
713			# handle arrays of structs e.g. struct v4l2_ctrl_h264_pred_weights weight_factors
714			if ($type =~ /struct/) {
715				my $struct_tag = @words[1];
716				my $struct_var = $member;
717				printf $fh_trace_cpp "json_object *element_obj = json_object_new_object();\n";
718				printf $fh_trace_cpp "\t" x ($dimensions_count + 1);
719				printf $fh_trace_cpp "trace_%s_gen(&(p->%s", $struct_tag, $struct_var;
720				for (my $idx = 0; $idx < $dimensions_count; $idx = $idx + 1) {
721					printf $fh_trace_cpp "[%s]", get_index_letter($idx);
722				}
723				printf $fh_trace_cpp "), element_obj);\n";
724				printf $fh_trace_cpp "\t" x ($dimensions_count + 1);
725				printf $fh_trace_cpp "json_object *element_no_key_obj;\n";
726				printf $fh_trace_cpp "\t" x ($dimensions_count + 1);
727				printf $fh_trace_cpp "json_object_object_get_ex(element_obj, \"%s\", &element_no_key_obj);\n", $struct_tag;
728				printf $fh_trace_cpp "\t" x ($dimensions_count + 1);
729				printf $fh_trace_cpp "json_object_array_add(%s_obj, element_no_key_obj);\n", $struct_var;
730
731				printf $fh_retrace_cpp "void *%s_ptr", $struct_var;
732				printf $fh_retrace_cpp " = (void *) retrace_%s_gen(json_object_array_get_idx(%s_obj, ", $struct_tag, $struct_var;
733				if ($dimensions_count > 1) {
734					printf $fh_retrace_cpp "count_%s++", $struct_var;
735				} else {
736					printf $fh_retrace_cpp "i";
737				}
738				printf $fh_retrace_cpp "));\n";
739
740				printf $fh_retrace_cpp "\t" x ($dimensions_count + 1);
741				printf $fh_retrace_cpp "\tp->%s", $struct_var;
742				for (my $idx = 0; $idx < $dimensions_count; $idx = $idx + 1) {
743					printf $fh_retrace_cpp "[%s]", get_index_letter($idx);
744				}
745				printf $fh_retrace_cpp " = *static_cast<struct %s*>(%s_ptr);\n", $struct_tag, $struct_var;
746
747				printf $fh_retrace_cpp "\t" x ($dimensions_count + 1);
748				printf $fh_retrace_cpp "\tfree(%s_ptr);\n", $struct_var;
749			} else {
750				# handle arrays of ints
751				printf $fh_trace_cpp "json_object_array_add(%s_obj, json_object_new_%s(p->%s", $member, $json_type, $member;
752				for (my $idx = 0; $idx < $dimensions_count; $idx = $idx + 1) {
753					printf $fh_trace_cpp "[%s]", get_index_letter($idx);
754				}
755				printf $fh_trace_cpp "));\n";
756
757				# add a check to avoid accessing a null array index
758				printf $fh_retrace_cpp "if (json_object_array_get_idx(%s_obj, ", $member;
759				if ($dimensions_count > 1) {
760					printf $fh_retrace_cpp "count_%s", $member;
761				} else {
762					printf $fh_retrace_cpp "i";
763				}
764				printf $fh_retrace_cpp "))\n";
765
766				printf $fh_retrace_cpp "\t" x ($dimensions_count + 1);
767				printf $fh_retrace_cpp "\t\t";
768				printf $fh_retrace_cpp "p->%s", $member;
769				for (my $idx = 0; $idx < $dimensions_count; $idx = $idx + 1) {
770					printf $fh_retrace_cpp "[%s]", get_index_letter($idx);
771				}
772
773				printf $fh_retrace_cpp " = ($type) json_object_get_%s(json_object_array_get_idx(%s_obj, ", $json_type, $member;
774				if ($dimensions_count > 1) {
775					printf $fh_retrace_cpp "count_%s++", $member;
776				} else {
777					printf $fh_retrace_cpp "i";
778				}
779				printf $fh_retrace_cpp "));\n";
780			}
781			# closing brackets for all array types
782			for (my $idx = $dimensions_count - 1; $idx >= 0 ; $idx = $idx - 1) {
783				printf $fh_trace_cpp "\t" x ($idx + 1);
784				printf $fh_trace_cpp "}\n";
785
786				printf $fh_retrace_cpp "\t" x ($idx + 1);
787				printf $fh_retrace_cpp "\t";
788				printf $fh_retrace_cpp "}\n";
789			}
790			printf $fh_retrace_cpp "\t}\n";
791			printf $fh_trace_cpp "\tjson_object_object_add(%s_obj, \"%s\", %s_obj);\n\n", $struct_name, $member, $member;
792			next;
793		}
794
795		# member that is a struct but not an array of structs
796		# e.g. $struct_tag_parent = v4l2_ctrl_vp8_frame, $struct_tag = v4l2_vp8_segment, $struct_var = segment
797		if ($type =~ /struct/) {
798			my $struct_tag_parent = $struct_name;
799			my ($struct_tag) = ($line) =~ /\s*struct (\w+)\s+.*/;
800			my ($struct_var) = $member;
801			printf $fh_trace_cpp "\t\/\* %s \*\/\n", $line;
802			printf $fh_trace_cpp "\ttrace_%s_gen(&p->%s, %s_obj);\n", $struct_tag, $struct_var, $struct_tag_parent;
803
804			printf $fh_retrace_cpp "\n\t\/\* %s \*\/\n", $line;
805			printf $fh_retrace_cpp "\tjson_object *%s_obj;\n", $struct_var;
806			printf $fh_retrace_cpp "\tif (!json_object_object_get_ex(%s_obj, \"%s\", &%s_obj))\n", $struct_tag_parent, $struct_tag, $struct_var;
807			printf $fh_retrace_cpp "\t\treturn p;\n", $struct_tag_parent, $struct_tag, $struct_var;
808
809			printf $fh_retrace_cpp "\tvoid *%s_ptr = (void *) retrace_%s_gen(%s_obj);\n", $struct_var, $struct_tag, $struct_var;
810			printf $fh_retrace_cpp "\tp->$struct_var = *static_cast<struct %s*>(%s_ptr);\n", $struct_tag, $struct_var;
811			printf $fh_retrace_cpp "\tfree(%s_ptr);\n", $struct_var;
812			next;
813		}
814
815		printf $fh_trace_cpp "\tjson_object_object_add(%s_obj, \"%s\", json_object_new_", $struct_name, $member;
816		printf $fh_retrace_cpp "\n\tjson_object *%s_obj;\n", $member;
817		printf $fh_retrace_cpp "\tif (json_object_object_get_ex(%s_obj, \"%s\", &%s_obj))\n", $struct_name, $member, $member;
818
819		# strings
820		if ($member =~ /flags/) {
821			if ($struct_name eq "v4l2_ctrl_fwht_params") {
822				printf $fh_trace_cpp "string(fl2s_fwht(p->$member).c_str()));\n";
823				printf $fh_retrace_cpp "\t\tp->%s = ($type) s2flags_fwht(json_object_get_string(%s_obj));\n", $member, $member, $flag_func_name;
824			} else {
825				printf $fh_trace_cpp "string(fl2s(p->$member, %sflag_def).c_str()));\n", $flag_func_name;
826				printf $fh_retrace_cpp "\t\tp->%s = ($type) s2flags(json_object_get_string(%s_obj), %sflag_def);\n", $member, $member, $flag_func_name;
827			}
828			next;
829		}
830
831		# Add members with a single string value (e.g. enums, #define)
832		$val_def_name = get_val_def_name($member, $struct_name);
833		if ($val_def_name !~ /^\s*$/) {
834			printf $fh_trace_cpp "string(val2s(p->$member, %s).c_str()));\n", $val_def_name;
835			printf $fh_retrace_cpp "\t\tp->%s = ($type) s2val(json_object_get_string(%s_obj), $val_def_name);\n", $member, $member;
836			next;
837		}
838
839		# integers
840		printf $fh_trace_cpp "%s(p->%s));\n", $json_type, $member;
841		printf $fh_retrace_cpp "\t\tp->%s = ($type) json_object_get_%s(%s_obj);\n", $member, $json_type, $member;
842	}
843
844	printf $fh_trace_cpp "\tjson_object_object_add(parent_obj, \"%s\", %s_obj);\n", $struct_name, $struct_name;
845	printf $fh_trace_cpp "}\n\n";
846
847	printf $fh_retrace_cpp "\n\treturn p;\n";
848	printf $fh_retrace_cpp "}\n\n";
849}
850
851sub do_open($$) {
852	my ($type, $fname) = @_;
853	my $fh;
854
855	if (defined $outtype{$type}) {
856		$fname = "$outdir/$fname";
857	} else {
858		$fname = "/dev/null";
859	}
860
861	open($fh, "> $fname") or die "Could not open $fname for writing";
862
863	return $fh;
864}
865
866
867$fh_trace_cpp = do_open("trace", "trace-gen.cpp");
868printf $fh_trace_cpp "/* SPDX-License-Identifier: GPL-2.0-only */\n/*\n * Copyright 2022 Collabora Ltd.\n";
869printf $fh_trace_cpp " *\n * AUTOMATICALLY GENERATED BY v4l2-tracer-gen.pl DO NOT EDIT\n */\n\n";
870printf $fh_trace_cpp "#include \"v4l2-tracer-common.h\"\n\n";
871
872$fh_trace_h = do_open("trace", "trace-gen.h");
873printf $fh_trace_h "/* SPDX-License-Identifier: GPL-2.0-only */\n/*\n * Copyright 2022 Collabora Ltd.\n";
874printf $fh_trace_h " *\n * AUTOMATICALLY GENERATED BY v4l2-tracer-gen.pl DO NOT EDIT\n */\n\n";
875printf $fh_trace_h "\#ifndef TRACE_GEN_H\n";
876printf $fh_trace_h "\#define TRACE_GEN_H\n\n";
877
878$fh_retrace_cpp = do_open("retrace", "retrace-gen.cpp");
879printf $fh_retrace_cpp "/* SPDX-License-Identifier: GPL-2.0-only */\n/*\n * Copyright 2022 Collabora Ltd.\n";
880printf $fh_retrace_cpp " *\n * AUTOMATICALLY GENERATED BY v4l2-tracer-gen.pl DO NOT EDIT\n */\n\n";
881printf $fh_retrace_cpp "#include \"v4l2-tracer-common.h\"\n\n";
882
883$fh_retrace_h = do_open("retrace", "retrace-gen.h");
884printf $fh_retrace_h "/* SPDX-License-Identifier: GPL-2.0-only */\n/*\n * Copyright 2022 Collabora Ltd.\n";
885printf $fh_retrace_h " *\n * AUTOMATICALLY GENERATED BY v4l2-tracer-gen.pl DO NOT EDIT\n */\n\n";
886printf $fh_retrace_h "\#ifndef RETRACE_GEN_H\n";
887printf $fh_retrace_h "\#define RETRACE_GEN_H\n\n";
888
889$fh_common_info_h = do_open("common", "v4l2-tracer-info-gen.h");
890printf $fh_common_info_h "/* SPDX-License-Identifier: GPL-2.0-only */\n/*\n * Copyright 2022 Collabora Ltd.\n";
891printf $fh_common_info_h " *\n * AUTOMATICALLY GENERATED BY v4l2-tracer-gen.pl DO NOT EDIT\n */\n\n";
892printf $fh_common_info_h "\#ifndef V4L2_TRACER_INFO_GEN_H\n";
893printf $fh_common_info_h "\#define V4L2_TRACER_INFO_GEN_H\n\n";
894printf $fh_common_info_h "#include \"v4l2-tracer-common.h\"\n\n";
895
896$in_v4l2_controls = true;
897
898while (<>) {
899	if (grep {/#define __LINUX_VIDEODEV2_H/} $_) {
900		$in_v4l2_controls = false;
901	}
902	if (grep {/^#define.+FWHT_FL_.+/} $_) {
903		flag_gen("fwht");
904	} elsif (grep {/^#define V4L2_VP8_LF.*/} $_) {
905		flag_gen("vp8_loop_filter");
906	} elsif (grep {/^#define.+_FL_.+/} $_) {
907		flag_gen();
908	} elsif (grep {/^#define.+_FLAG_.+/} $_) {
909		flag_gen();
910	}
911	if ($in_v4l2_controls eq true) {
912		if (grep {/^struct/} $_) {
913			struct_gen_ctrl();
914		}
915	} else {
916		if (grep {/^struct/} $_) {
917			struct_gen();
918		}
919	}
920
921	if (grep {/^enum/} $_) {
922		enum_gen();
923	}
924
925	if (grep {/^#define\s+(V4L2_CID\w*)\s*.*/} $_) {
926		push (@controls, $_);
927	}
928
929	if (grep {/^#define V4L2_CTRL_CLASS_USER\s+/} $_) {
930		printf $fh_common_info_h "constexpr val_def ctrlclass_val_def[] = {\n";
931		val_def_gen("V4L2_CTRL_CLASS_COLORIMETRY");
932		next;
933	}
934	if (grep {/^#define V4L2_CAP_VIDEO_CAPTURE/} $_) {
935		printf $fh_common_info_h "constexpr flag_def v4l2_cap_flag_def[] = {\n";
936		flag_def_gen("V4L2_CAP_DEVICE_CAPS");
937		next;
938	}
939	if (grep {/^#define V4L2_PIX_FMT_RGB332\s+/} $_) {
940		printf $fh_common_info_h "constexpr val_def v4l2_pix_fmt_val_def[] = {\n";
941		val_def_gen("V4L2_PIX_FMT_IPU3_SRGGB10");
942		next;
943	}
944	if (grep {/^#define V4L2_BUF_CAP_SUPPORTS_MMAP\s+/} $_) {
945		printf $fh_common_info_h "constexpr flag_def v4l2_buf_cap_flag_def[] = {\n";
946		flag_def_gen("V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS");
947		next;
948	}
949	if (grep {/^#define V4L2_STD_PAL_B\s+/} $_) {
950		printf $fh_common_info_h "constexpr flag_def std_flag_def[] = {\n";
951		flag_def_gen("V4L2_STD_ALL");
952		next
953	}
954	if (grep {/^#define V4L2_MODE_HIGHQUALITY\s+/} $_) {
955		printf $fh_common_info_h "constexpr val_def streamparm_val_def[] = {\n";
956		val_def_gen("V4L2_CAP_TIMEPERFRAME");
957		next;
958	}
959	if (grep {/^#define V4L2_INPUT_TYPE_TUNER\s+/} $_) {
960		printf $fh_common_info_h "constexpr val_def input_type_val_def[] = {\n";
961		val_def_gen("V4L2_INPUT_TYPE_TOUCH");
962		next
963	}
964	if (grep {/^#define V4L2_IN_ST_NO_POWER\s+/} $_) {
965		printf $fh_common_info_h "constexpr val_def input_field_val_def[] = {\n";
966		val_def_gen("V4L2_IN_ST_VTR");
967		next
968	}
969	if (grep {/^#define V4L2_IN_CAP_DV_TIMINGS\s+/} $_) {
970		printf $fh_common_info_h "constexpr flag_def input_cap_flag_def[] = {\n";
971		flag_def_gen("V4L2_IN_CAP_NATIVE_SIZE");
972		next
973	}
974	if (grep {/^#define V4L2_OUTPUT_TYPE_MODULATOR\s+/} $_) {
975		printf $fh_common_info_h "constexpr val_def output_type_val_def[] = {\n";
976		val_def_gen("V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY");
977		next
978	}
979	if (grep {/^#define V4L2_OUT_CAP_DV_TIMINGS\s+/} $_) {
980		printf $fh_common_info_h "constexpr flag_def output_cap_flag_def[] = {\n";
981		flag_def_gen("V4L2_OUT_CAP_NATIVE_SIZE");
982		next
983	}
984	if (grep {/^#define V4L2_TUNER_CAP_LOW\s+/} $_) {
985		printf $fh_common_info_h "constexpr flag_def tuner_cap_flag_def[] = {\n";
986		flag_def_gen("V4L2_TUNER_CAP_1HZ");
987		next
988	}
989	if (grep {/^#define V4L2_TUNER_SUB_MONO\s+/} $_) {
990		printf $fh_common_info_h "constexpr flag_def tuner_rxsub_flag_def[] = {\n";
991		flag_def_gen("V4L2_TUNER_SUB_RDS");
992		next
993	}
994	if (grep {/^#define V4L2_TUNER_MODE_MONO\s+/} $_) {
995		printf $fh_common_info_h "constexpr val_def tuner_audmode_val_def[] = {\n";
996		val_def_gen("V4L2_TUNER_MODE_LANG1_LANG2");
997		next
998	}
999
1000	if (grep {/^#define V4L2_ENC_CMD_START\s+/} $_) {
1001		printf $fh_common_info_h "constexpr val_def encoder_cmd_val_def[] = {\n";
1002		val_def_gen("V4L2_ENC_CMD_RESUME");
1003		next;
1004	}
1005	if (grep {/^#define V4L2_DEC_CMD_START\s+/} $_) {
1006		printf $fh_common_info_h "constexpr val_def decoder_cmd_val_def[] = {\n";
1007		val_def_gen("V4L2_DEC_CMD_FLUSH");
1008		next;
1009	}
1010	if (grep {/^#define V4L2_DEC_CMD_START_MUTE_AUDIO\s+/} $_) {
1011		printf $fh_common_info_h "constexpr flag_def v4l2_decoder_cmd_start_flag_def[] = {\n";
1012		flag_def_gen("V4L2_DEC_CMD_START_MUTE_AUDIO");
1013		next;
1014	}
1015	if (grep {/^#define V4L2_DEC_CMD_PAUSE_TO_BLACK\s+/} $_) {
1016		printf $fh_common_info_h "constexpr flag_def v4l2_decoder_cmd_pause_flag_def[] = {\n";
1017		flag_def_gen("V4L2_DEC_CMD_PAUSE_TO_BLACK");
1018		next;
1019	}
1020	if (grep {/^#define V4L2_DEC_CMD_STOP_TO_BLACK\s+/} $_) {
1021		printf $fh_common_info_h "constexpr flag_def v4l2_decoder_cmd_stop_flag_def[] = {\n";
1022		flag_def_gen("V4L2_DEC_CMD_STOP_IMMEDIATELY");
1023		next;
1024	}
1025	if (grep {/^#define V4L2_EVENT_ALL\s+/} $_) {
1026		printf $fh_common_info_h "constexpr val_def event_val_def[] = {\n";
1027		val_def_gen("V4L2_EVENT_PRIVATE_START");
1028		next;
1029	}
1030	if (grep {/^#define V4L2_EVENT_CTRL_CH_VALUE\s+/} $_) {
1031		printf $fh_common_info_h "constexpr flag_def v4l2_event_ctrl_ch_flag_def[] = {\n";
1032		flag_def_gen("V4L2_EVENT_CTRL_CH_DIMENSIONS");
1033		next
1034	}
1035	if (grep {/^#define\s+(VIDIOC_\w*)\s*.*/} $_) {
1036		push (@ioctls, $_);
1037	}
1038
1039	if (grep {/^#define\s+(MEDIA_IOC\w*)\s*.*/} $_) {
1040		push (@ioctls, $_);
1041	}
1042
1043	if (grep {/^#define\s+(MEDIA_REQUEST_IOC\w*)\s*.*/} $_) {
1044		push (@ioctls, $_);
1045	}
1046	if (grep {/^#define V4L2_SEL_TGT_CROP\s+/} $_) {
1047		printf $fh_common_info_h "constexpr val_def selection_target_val_def[] = {\n";
1048		val_def_gen("V4L2_SEL_TGT_COMPOSE_PADDED");
1049		next;
1050	}
1051}
1052
1053printf $fh_common_info_h "constexpr val_def control_val_def[] = {\n";
1054foreach (@controls) {
1055	($control) = ($_) =~ /^#define\s*(\w+)\s*/;
1056	next if ($control =~ /BASE$/);
1057	printf $fh_common_info_h "\t{ %s,\t\"%s\" },\n", $control, $control;
1058}
1059printf $fh_common_info_h "\t{ -1, \"\" }\n};\n";
1060
1061printf $fh_common_info_h "constexpr val_def ioctl_val_def[] = {\n";
1062foreach (@ioctls) {
1063	($ioctl) = ($_) =~ /^#define\s*(\w+)\s*/;
1064	printf $fh_common_info_h "\t{ %s,\t\"%s\" },\n", $ioctl, $ioctl;
1065}
1066printf $fh_common_info_h "\t{ -1, \"\" }\n};\n";
1067
1068
1069printf $fh_trace_h "\n#endif\n";
1070close $fh_trace_h;
1071# Delete the last of two new lines to avoid a whitespace error
1072truncate($fh_trace_cpp, tell($fh_trace_cpp) - 1);
1073close $fh_trace_cpp;
1074
1075printf $fh_retrace_h "\n#endif\n";
1076close $fh_retrace_h;
1077close $fh_retrace_cpp;
1078
1079printf $fh_common_info_h "\n#endif\n";
1080close $fh_common_info_h;
1081