codegen: work around firmware bug, only accept the first found tlv
[project/uqmi.git] / data / gen-header.pl
1 #!/usr/bin/env perl
2 use strict;
3
4 use FindBin '$Bin';
5 require "$Bin/gen-common.pm";
6
7 our %tlv_types;
8
9 my $data = get_json();
10
11 sub gen_tlv_type($$$) {
12 my $cname = shift;
13 my $elem = shift;
14 my $indent = shift;
15
16 my $type = $elem->{"format"};
17 my $ptype = $elem->{"public-format"};
18 my $data;
19
20 $type or return undef;
21 $ptype or $ptype = $type;
22
23 if ($type eq "guint-sized") {
24 my $size = $elem->{"guint-size"};
25
26 if ($size > 4 and $size < 8) {
27 $ptype = "guint64";
28 } elsif ($size > 2) {
29 $ptype = "guint32";
30 } else {
31 die "Invalid size for guint-sized";
32 }
33 }
34
35 if ($tlv_types{$ptype}) {
36 return $indent.$tlv_types{$ptype}." $cname;";
37 } elsif ($tlv_types{$type}) {
38 return $indent."$ptype $cname;";
39 } elsif ($type eq "string") {
40 return $indent."char *$cname;", 1;
41 } elsif ($type eq "array") {
42 if ($elem->{"fixed-size"}) {
43 my $len_f = '['.$elem->{"fixed-size"}.']';
44 return gen_tlv_type("$cname$len_f", $elem->{"array-element"}, $indent);
45 }
46 my ($type, $no_set_field) = gen_tlv_type("*$cname", $elem->{"array-element"}, $indent);
47 return undef if not defined $type;
48 return $indent."int $cname\_n;$type", 1;
49 } elsif ($type eq "sequence" or $type eq "struct") {
50 my $contents = $elem->{"contents"};
51 my $data = "struct {";
52
53 foreach my $field (@$contents) {
54 my $_cname = gen_cname($field->{name});
55 my ($_data, $no_set_field) = gen_tlv_type($_cname, $field, "$indent\t");
56 $data .= $_data;
57 }
58 return $indent.$data.$indent."} $cname;";
59 } else {
60 die "Unknown type: $ptype\n";
61 }
62 }
63
64 sub gen_tlv_struct($$) {
65 my $name = shift;
66 my $data = shift;
67 my $_set = "";
68 my $_data = "";
69
70 foreach my $field (@$data) {
71 my $cname = gen_cname($field->{name});
72 my ($data, $no_set_field) = gen_tlv_type($cname, $field, "\n\t\t");
73
74 next if not defined $data;
75 $_data .= $data;
76
77 next if $no_set_field;
78 $_set .= "\n\t\tint $cname : 1;";
79 }
80
81 $name = gen_cname($name);
82
83 $_data or return;
84
85 $_set .= "\n\t";
86 $_data .= "\n\t";
87
88 print <<EOF
89 struct qmi_$name {
90 struct {$_set} set;
91 struct {$_data} data;
92 };
93
94 EOF
95 }
96
97 sub gen_set_func_header($$)
98 {
99 my $name = shift;
100 my $data = shift;
101
102 my $func = gen_tlv_set_func($name, $data);
103 $func and print "$func;\n";
104 }
105
106 sub gen_parse_func_header($$)
107 {
108 my $name = shift;
109 my $data = shift;
110
111 my $func = gen_tlv_parse_func($name, $data);
112 $func and print "$func;\n\n";
113 }
114
115 gen_foreach_message_type($data, \&gen_tlv_struct, \&gen_tlv_struct);
116 gen_foreach_message_type($data, \&gen_set_func_header, \&gen_parse_func_header);