5 require "$Bin/gen-common.pm";
10 my $data = get_json
();
14 gint8
=> "*(int8_t *) get_next(1)",
15 guint8
=> "*(uint8_t *) get_next(1)",
16 gint16
=> "le16_to_cpu(*(uint16_t *) get_next(2))",
17 guint16
=> "le16_to_cpu(*(uint16_t *) get_next(2))",
18 gint32
=> "le32_to_cpu(*(uint32_t *) get_next(4))",
19 guint32
=> "le32_to_cpu(*(uint32_t *) get_next(4))",
20 gint64
=> "le64_to_cpu(*(uint64_t *) get_next(8))",
21 guint64
=> "le64_to_cpu(*(uint64_t *) get_next(8))",
22 gfloat
=> "({ uint32_t data = le32_to_cpu(*(uint32_t *) get_next(4)); float _val; memcpy(&_val, &data, sizeof(_val)); _val; })"
26 gint16
=> "be16_to_cpu(*(uint16_t *) get_next(2))",
27 guint16
=> "be16_to_cpu(*(uint16_t *) get_next(2))",
28 gint32
=> "be32_to_cpu(*(uint32_t *) get_next(4))",
29 guint32
=> "be32_to_cpu(*(uint32_t *) get_next(4))",
30 gint64
=> "be64_to_cpu(*(uint64_t *) get_next(8))",
31 guint64
=> "be64_to_cpu(*(uint64_t *) get_next(8))",
34 sub gen_tlv_parse_field
($$$$) {
41 my $indent = "\t" x
($n_indent + 3);
45 my $type = $elem->{"format"};
47 $varsize_field and die "Cannot place fields after a variable-sized field (var: $var, field: $varsize_field)\n";
50 if ($elem->{endian
} eq 'network') {
51 $val = $tlv_get_be{$type};
53 $val = $tlv_get{$type};
57 return $indent."$var = $val;\n";
58 } elsif ($type eq "array") {
60 my $cur_varsize_field;
64 if ($elem->{"fixed-size"}) {
65 $size = $elem->{"fixed-size"};
66 $data .= $indent."for ($iterator = 0; $iterator < $size; $iterator\++) {\n";
68 ($var_data, $var_iterator) =
69 gen_tlv_parse_field
($var."[$iterator]", $elem->{"array-element"}, $n_indent + 1, "i$iterator");
72 my $prefix = $elem->{"size-prefix-format"};
73 $prefix or $prefix = 'guint8';
75 $size = $tlv_get{$prefix};
76 die "Unknown size element type '$prefix'" if not defined $size;
78 my $curvar = "$var\_n";
79 if (rindex($var,"]") == length($var)-1) {
80 $curvar = substr($var, 0, index($var, "["))."\_i";
81 $data .= $indent."$curvar = 0;\n";
83 ($var_data, $var_iterator) =
84 gen_tlv_parse_field
($var."[$curvar]", $elem->{"array-element"}, $n_indent + 1, "i$iterator");
86 $var_data .= $indent."\t$curvar++;\n";
87 $data .= $indent."$iterator = $size;\n";
88 $data .= $indent."$var = __qmi_alloc_static($iterator * sizeof($var\[0]));\n";
89 $data .= $indent."while($iterator\-- > 0) {\n";
92 $var_iterator and $data .= $indent."\tunsigned int i$iterator;\n";
94 $data .= $indent."}\n";
96 $varsize_field = $cur_varsize_field;
99 } elsif ($type eq "struct" or $type eq "sequence") {
100 foreach my $field (@
{$elem->{contents
}}) {
101 my $field_cname = gen_cname
($field->{name
});
102 my ($var_data, $var_iterator) =
103 gen_tlv_parse_field
("$var.$field_cname", $field, $n_indent, $iterator);
106 $var_iterator and $use_iterator = 1;
108 return $data, $use_iterator;
109 } elsif ($type eq "string") {
110 my $size = $elem->{"fixed-size"};
112 my $prefix = $elem->{"size-prefix-format"};
114 $elem->{type
} eq 'TLV' or $prefix = 'guint8';
118 $size = $tlv_get{$prefix};
120 $size = "cur_tlv_len - ofs";
121 $varsize_field = $var;
125 $data .= $indent."$iterator = $size;\n";
126 my $maxsize = $elem->{"max-size"};
128 $data .= $indent."if ($iterator > $maxsize)\n";
129 $data .= $indent."\t$iterator = $maxsize;\n";
131 $data .= $indent.$var." = __qmi_copy_string(get_next($iterator), $iterator);\n";
133 } elsif ($type eq "guint-sized") {
134 my $size = $elem->{"guint-size"};
135 return $indent."$var = ({ uint64_t var; memcpy(&var, get_next($size), $size); le64_to_cpu(var); });\n";
137 die "Invalid type $type for variable $var";
141 sub gen_tlv_type
($$$) {
145 my $idx_word = "found[".int($idx / 32)."]";
146 my $idx_bit = "(1 << ".($idx % 32).")";
148 my $type = $elem->{"format"};
149 my $id = $elem->{"id"};
151 undef $varsize_field;
152 my $indent = "\t\t\t";
154 $type or return undef;
158 if ($idx_word & $idx_bit)
161 $idx_word |= $idx_bit;
164 my $val = $tlv_get{$type};
166 print $indent."qmi_set(res, $cname, $val);\n";
167 } elsif ($type eq "string") {
168 my ($var_data, $var_iterator) =
169 gen_tlv_parse_field
("res->data.$cname", $elem, 0, "i");
171 } elsif ($type eq "array") {
172 $elem->{"fixed-size"} and $data = $indent."res->set.$cname = 1;\n";
173 my ($var_data, $var_iterator) =
174 gen_tlv_parse_field
("res->data.$cname", $elem, 0, "i");
175 print "$data$var_data\n";
176 } elsif ($type eq "sequence" or $type eq "struct") {
177 my ($var_data, $var_iterator) =
178 gen_tlv_parse_field
("res->data.$cname", $elem, 0, "i");
180 print $indent."res->set.$cname = 1;\n".$var_data;
188 sub gen_parse_func
($$)
194 $ctl and $type = "ctl";
196 print gen_tlv_parse_func
($name, $data)."\n";
199 void *tlv_buf = &msg->$type.tlv;
200 unsigned int tlv_len = le16_to_cpu(msg->$type.tlv_len);
203 if (gen_has_types
($data)) {
204 my $n_bits = scalar @
$data;
205 my $n_words = int(($n_bits + 31) / 32);
211 uint32_t found[$n_words] = {};
213 memset(res, 0, sizeof(*res));
216 while ((tlv = tlv_get_next(&tlv_buf, &tlv_len)) != NULL) {
217 unsigned int cur_tlv_len = le16_to_cpu(tlv->len);
218 unsigned int ofs = 0;
222 foreach my $field (@
$data) {
223 $field = gen_common_ref
($field);
224 my $cname = gen_cname
($field->{name
});
225 gen_tlv_type
($cname, $field, $i++);
237 fprintf(stderr, "%s: Invalid TLV length in message, tlv=0x%02x, len=%d\\n",
238 __func__, tlv->type, le16_to_cpu(tlv->len));
239 return QMI_ERROR_INVALID_DATA;
244 return qmi_check_message_status(tlv_buf, tlv_len);
254 sub gen_parse_ind_func
($$)
260 $ctl and $type = "ctl";
262 print gen_tlv_parse_func
($name, $data)."\n";
265 void *tlv_buf = &msg->$type.tlv;
266 unsigned int tlv_len = le16_to_cpu(msg->$type.tlv_len);
269 if (gen_has_types
($data)) {
270 my $n_bits = scalar @
$data;
271 my $n_words = int(($n_bits + 31) / 32);
277 uint32_t found[$n_words] = {};
279 memset(res, 0, sizeof(*res));
282 while ((tlv = tlv_get_next(&tlv_buf, &tlv_len)) != NULL) {
283 unsigned int cur_tlv_len = le16_to_cpu(tlv->len);
284 unsigned int ofs = 0;
288 foreach my $field (@
$data) {
289 $field = gen_common_ref
($field);
290 my $cname = gen_cname
($field->{name
});
291 gen_tlv_type
($cname, $field, $i++);
303 fprintf(stderr, "%s: Invalid TLV length in message, tlv=0x%02x, len=%d\\n",
304 __func__, tlv->type, le16_to_cpu(tlv->len));
305 return QMI_ERROR_INVALID_DATA;
310 return qmi_check_message_status(tlv_buf, tlv_len);
321 guint8
=> sub { my $a = shift; my $b = shift; print "*(uint8_t *) $a = $b;\n" },
322 guint16
=> sub { my $a = shift; my $b = shift; print "*(uint16_t *) $a = cpu_to_le16($b);\n" },
323 guint32
=> sub { my $a = shift; my $b = shift; print "*(uint32_t *) $a = cpu_to_le32($b);\n" },
327 gint8
=> sub { my $a = shift; "put_tlv_var(uint8_t, $a, 1);\n" },
328 guint8
=> sub { my $a = shift; "put_tlv_var(uint8_t, $a, 1);\n" },
329 gint16
=> sub { my $a = shift; "put_tlv_var(uint16_t, cpu_to_le16($a), 2);\n" },
330 guint16
=> sub { my $a = shift; "put_tlv_var(uint16_t, cpu_to_le16($a), 2);\n" },
331 gint32
=> sub { my $a = shift; "put_tlv_var(uint32_t, cpu_to_le32($a), 4);\n" },
332 guint32
=> sub { my $a = shift; "put_tlv_var(uint32_t, cpu_to_le32($a), 4);\n" },
333 gint64
=> sub { my $a = shift; "put_tlv_var(uint64_t, cpu_to_le64($a), 8);\n" },
334 guint64
=> sub { my $a = shift; "put_tlv_var(uint64_t, cpu_to_le64($a), 8);\n" },
338 gint16
=> sub { my $a = shift; "put_tlv_var(uint16_t, cpu_to_be16($a), 2);\n" },
339 guint16
=> sub { my $a = shift; "put_tlv_var(uint16_t, cpu_to_be16($a), 2);\n" },
340 gint32
=> sub { my $a = shift; "put_tlv_var(uint32_t, cpu_to_be32($a), 4);\n" },
341 guint32
=> sub { my $a = shift; "put_tlv_var(uint32_t, cpu_to_be32($a), 4);\n" },
342 gint64
=> sub { my $a = shift; "put_tlv_var(uint64_t, cpu_to_be64($a), 8);\n" },
343 guint64
=> sub { my $a = shift; "put_tlv_var(uint64_t, cpu_to_be64($a), 8);\n" },
346 sub gen_tlv_val_set
($$$$$)
351 my $iterator = shift;
355 my $type = $elem->{format
};
359 if ($elem->{endian
} eq 'network') {
360 $put = $tlv_put_be{$type};
362 $put = $tlv_put{$type};
364 $put and return $indent.&$put($cname);
366 $type eq 'array' and do {
367 my $size = $elem->{"fixed-size"};
370 $cond and $$cond = $cname;
373 my $prefix = $elem->{"size-prefix-format"};
374 $prefix or $prefix = 'gint8';
376 $put = $tlv_put{$prefix};
377 $put or die "Unknown size prefix type $prefix\n";
379 $data .= $indent.&$put($size);
382 $data .= $indent."for ($iterator = 0; $iterator < $size; $iterator++) {\n";
383 my ($var_data, $var_iterator) =
384 gen_tlv_val_set
($cname."[$iterator]", $elem->{"array-element"}, "$indent\t", "i$iterator", undef);
386 $var_iterator and $data .= $indent."\tunsigned int i$iterator;\n";
388 $data .= $indent."}\n";
393 $type eq 'string' and do {
394 $cond and $$cond = $cname;
396 my $len = $elem->{"fixed-size"};
397 $len or $len = "strlen($cname)";
399 $data .= $indent."$iterator = $len;\n";
401 $len = $elem->{"max-size"};
403 $data .= $indent."if ($iterator > $len)\n";
404 $data .= $indent."\t$iterator = $len;\n";
407 my $prefix = $elem->{"size-prefix-format"};
409 $elem->{"type"} eq 'TLV' or $prefix = 'guint8';
413 my $put = $tlv_put{$prefix} or die "Unknown size prefix format $prefix";
414 $data .= $indent.&$put("$iterator");
417 $data .= $indent."strncpy(__qmi_alloc_static($iterator), $cname, $iterator);\n";
422 ($type eq 'sequence' or $type eq 'struct') and do {
425 foreach my $field (@
{$elem->{contents
}}) {
426 my $field_cname = gen_cname
($field->{name
});
427 my ($var_data, $var_iterator) =
428 gen_tlv_val_set
("$cname.$field_cname", $field, $indent, $iterator, undef);
430 $var_iterator and $use_iterator = 1;
433 return $data, $use_iterator;
436 die "Unknown type $type";
439 sub gen_tlv_attr_set
($$)
447 my $id = $elem->{id
};
449 my $cond = "req->set.$cname";
450 my ($var_data, $use_iterator) =
451 gen_tlv_val_set
("req->data.$cname", $elem, "\t\t", "i", \
$cond);
452 $use_iterator and $iterator = "\t\tunsigned int i;\n";
461 buf = __qmi_get_buf(&ofs);
462 tlv_new(msg, $id, ofs, buf);
476 my $service = $data->{service
};
477 my $id = $data->{id
};
479 $service eq 'CTL' and $type = 'ctl';
481 print gen_tlv_set_func
($name, $fields)."\n";
484 qmi_init_request_message(msg, QMI_SERVICE_$service);
485 msg->$type.message = cpu_to_le16($id);
488 foreach my $field (@
$fields) {
489 $field = gen_common_ref
($field);
490 my $cname = gen_cname
($field->{name
});
491 gen_tlv_attr_set
($cname, $field);
502 /* generated by uqmi gen-code.pl */
505 #include "qmi-message.h"
507 #define get_next(_size) ({ void *_buf = &tlv->data[ofs]; ofs += _size; if (ofs > cur_tlv_len) goto error_len; _buf; })
508 #define copy_tlv(_val, _size) \\
510 unsigned int __size = _size; \\
512 memcpy(__qmi_alloc_static(__size), _val, __size); \\
515 #define put_tlv_var(_type, _val, _size) \\
517 _type __var = _val; \\
518 copy_tlv(&__var, _size); \\
523 gen_foreach_message_type
($data, \
&gen_set_func
, \
&gen_parse_func
, \
&gen_parse_ind_func
);