uqmi: print radio interfaces in serving system command
[project/uqmi.git] / data / gen-code.pl
index 71b738dffec615ab1aeacf8fe02d0408ec7e6bd5..d05cc766bb6eb75c8a615dfdf31b7e4bd26d6d1b 100755 (executable)
@@ -19,6 +19,7 @@ my %tlv_get = (
        guint32 => "le32_to_cpu(*(uint32_t *) get_next(4))",
        gint64 => "le64_to_cpu(*(uint64_t *) get_next(8))",
        guint64 => "le64_to_cpu(*(uint64_t *) get_next(8))",
+       gfloat => "({ uint32_t data = le32_to_cpu(*(uint32_t *) get_next(4)); float _val; memcpy(&_val, &data, sizeof(_val)); _val; })"
 );
 
 my %tlv_get_be = (
@@ -74,16 +75,21 @@ sub gen_tlv_parse_field($$$$) {
                        $size = $tlv_get{$prefix};
                        die "Unknown size element type '$prefix'" if not defined $size;
 
+                       my $curvar = "$var\_n";
+                       if (rindex($var,"]") == length($var)-1) {
+                               $curvar = substr($var, 0, index($var, "["))."\_i";
+                               $data .= $indent."$curvar = 0;\n";
+                       }
                        ($var_data, $var_iterator) =
-                               gen_tlv_parse_field($var."[$var\_n]", $elem->{"array-element"}, $n_indent + 1, "i$iterator");
+                               gen_tlv_parse_field($var."[$curvar]", $elem->{"array-element"}, $n_indent + 1, "i$iterator");
 
-                       $var_data .= $indent."\t$var\_n++;\n";
+                       $var_data .= $indent."\t$curvar++;\n";
                        $data .= $indent."$iterator = $size;\n";
                        $data .= $indent."$var = __qmi_alloc_static($iterator * sizeof($var\[0]));\n";
                        $data .= $indent."while($iterator\-- > 0) {\n";
                }
 
-               $var_iterator and $data .= $indent."\tint i$iterator;\n";
+               $var_iterator and $data .= $indent."\tunsigned int i$iterator;\n";
                $data .= $var_data;
                $data .= $indent."}\n";
 
@@ -132,9 +138,12 @@ sub gen_tlv_parse_field($$$$) {
        }
 }
 
-sub gen_tlv_type($$) {
+sub gen_tlv_type($$$) {
        my $cname = shift;
        my $elem = shift;
+       my $idx = shift;
+       my $idx_word = "found[".int($idx / 32)."]";
+       my $idx_bit = "(1 << ".($idx % 32).")";
 
        my $type = $elem->{"format"};
        my $id = $elem->{"id"};
@@ -146,6 +155,10 @@ sub gen_tlv_type($$) {
 
        print <<EOF;
                case $id:
+                       if ($idx_word & $idx_bit)
+                               break;
+
+                       $idx_word |= $idx_bit;
 EOF
 
        my $val = $tlv_get{$type};
@@ -184,13 +197,84 @@ sub gen_parse_func($$)
        print <<EOF;
 {
        void *tlv_buf = &msg->$type.tlv;
-       int tlv_len = le16_to_cpu(msg->$type.tlv_len);
+       unsigned int tlv_len = le16_to_cpu(msg->$type.tlv_len);
 EOF
 
        if (gen_has_types($data)) {
+               my $n_bits = scalar @$data;
+               my $n_words = int(($n_bits + 31) / 32);
+               my $i = 0;
+
+               print <<EOF;
+       struct tlv *tlv;
+       int i;
+       uint32_t found[$n_words] = {};
+
+       memset(res, 0, sizeof(*res));
+
+       __qmi_alloc_reset();
+       while ((tlv = tlv_get_next(&tlv_buf, &tlv_len)) != NULL) {
+               unsigned int cur_tlv_len = le16_to_cpu(tlv->len);
+               unsigned int ofs = 0;
+
+               switch(tlv->type) {
+EOF
+               foreach my $field (@$data) {
+                       $field = gen_common_ref($field);
+                       my $cname = gen_cname($field->{name});
+                       gen_tlv_type($cname, $field, $i++);
+               }
+
+               print <<EOF;
+               default:
+                       break;
+               }
+       }
+
+       return 0;
+
+error_len:
+       fprintf(stderr, "%s: Invalid TLV length in message, tlv=0x%02x, len=%d\\n",
+               __func__, tlv->type, le16_to_cpu(tlv->len));
+       return QMI_ERROR_INVALID_DATA;
+EOF
+       } else {
+               print <<EOF;
+
+       return qmi_check_message_status(tlv_buf, tlv_len);
+EOF
+       }
+
+       print <<EOF;
+}
+
+EOF
+}
+
+sub gen_parse_ind_func($$)
+{
+       my $name = shift;
+       my $data = shift;
+
+       my $type = "svc";
+       $ctl and $type = "ctl";
+
+       print gen_tlv_parse_func($name, $data)."\n";
+       print <<EOF;
+{
+       void *tlv_buf = &msg->$type.tlv;
+       unsigned int tlv_len = le16_to_cpu(msg->$type.tlv_len);
+EOF
+
+       if (gen_has_types($data)) {
+               my $n_bits = scalar @$data;
+               my $n_words = int(($n_bits + 31) / 32);
+               my $i = 0;
+
                print <<EOF;
        struct tlv *tlv;
        int i;
+       uint32_t found[$n_words] = {};
 
        memset(res, 0, sizeof(*res));
 
@@ -202,8 +286,9 @@ EOF
                switch(tlv->type) {
 EOF
                foreach my $field (@$data) {
+                       $field = gen_common_ref($field);
                        my $cname = gen_cname($field->{name});
-                       gen_tlv_type($cname, $field);
+                       gen_tlv_type($cname, $field, $i++);
                }
 
                print <<EOF;
@@ -298,7 +383,7 @@ sub gen_tlv_val_set($$$$$)
                my ($var_data, $var_iterator) =
                        gen_tlv_val_set($cname."[$iterator]", $elem->{"array-element"}, "$indent\t", "i$iterator", undef);
 
-               $var_iterator and $data .= $indent."\tint i$iterator;\n";
+               $var_iterator and $data .= $indent."\tunsigned int i$iterator;\n";
                $data .= $var_data;
                $data .= $indent."}\n";
 
@@ -364,12 +449,12 @@ sub gen_tlv_attr_set($$)
        my $cond = "req->set.$cname";
        my ($var_data, $use_iterator) =
                gen_tlv_val_set("req->data.$cname", $elem, "\t\t", "i", \$cond);
-       $use_iterator and $iterator = "\t\tint i;\n";
+       $use_iterator and $iterator = "\t\tunsigned int i;\n";
 
        $data = <<EOF;
        if ($cond) {
                void *buf;
-               int ofs;
+               unsigned int ofs;
 $iterator$size_var
                __qmi_alloc_reset();
 $var_data
@@ -401,6 +486,7 @@ sub gen_set_func($$)
 
 EOF
        foreach my $field (@$fields) {
+               $field = gen_common_ref($field);
                my $cname = gen_cname($field->{name});
                gen_tlv_attr_set($cname, $field);
        }
@@ -421,7 +507,7 @@ print <<EOF;
 #define get_next(_size) ({ void *_buf = &tlv->data[ofs]; ofs += _size; if (ofs > cur_tlv_len) goto error_len; _buf; })
 #define copy_tlv(_val, _size) \\
        do { \\
-               int __size = _size; \\
+               unsigned int __size = _size; \\
                if (__size > 0) \\
                        memcpy(__qmi_alloc_static(__size), _val, __size); \\
        } while (0);
@@ -434,4 +520,4 @@ print <<EOF;
 
 EOF
 
-gen_foreach_message_type($data, \&gen_set_func, \&gen_parse_func);
+gen_foreach_message_type($data, \&gen_set_func, \&gen_parse_func, \&gen_parse_ind_func);