diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2013-06-16 13:37:13 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2013-06-18 18:10:23 +0200 |
commit | adfdd94e35ca79b13a58a082356604cfff00814f (patch) | |
tree | 479856eff65e6f7d881e4b453506602d617d95ae | |
parent | ae24423cfa5e738ccdffbd9171e326faa3f5f3cd (diff) | |
download | libmbim-adfdd94e35ca79b13a58a082356604cfff00814f.tar.gz |
mbim-codegen: handle optional fields flagged with 'available-if'
A given MBIM message may contain fields which can be processed in different ways
depending on the value of another field. This is the case for e.g. "SMS Read"
Query operations, where the list of messages may be formatted as either PDU or
CDMA, depending on the value of the 'Format' field.
So, we now support to have fields configured like this:
{ "name" : "Something",
"format" : "string" ,
"available-if" : { "field" : "ConditionField",
"operation" : "==",
"value" : "0" } },
{ "name" : "OtherSomething",
"format" : "string" ,
"available-if" : { "field" : "ConditionField",
"operation" : "==",
"value" : "1" } },
Meaning that:
* Field "Something" will be given if "ConditionField" == 0
* Otherwise, Field "OtherSomething" will be given if "ConditionField" == 1
Note that in the message parser, BOTH fields will be provided, but only one
will contain valid data.
-rw-r--r-- | build-aux/mbim-codegen/Message.py | 73 |
1 files changed, 58 insertions, 15 deletions
diff --git a/build-aux/mbim-codegen/Message.py b/build-aux/mbim-codegen/Message.py index 1864e44..383bdd6 100644 --- a/build-aux/mbim-codegen/Message.py +++ b/build-aux/mbim-codegen/Message.py @@ -23,14 +23,16 @@ import utils """ -Flag the values which are used as length of arrays +Flag the values which always need to be read """ -def flag_array_length_field(fields, field_name): +def flag_always_read_field(fields, field_name): for field in fields: if field['name'] == field_name: - field['is-array-size'] = True + if field['format'] != 'guint32': + raise ValueError('Fields to always read \'%s\' must be a guint32' % field_name) + field['always-read'] = True return - raise ValueError('Couldn\'t find array size field \'%s\'' % array_size_field) + raise ValueError('Couldn\'t find field to always read \'%s\'' % field_name) """ @@ -38,6 +40,12 @@ Validate fields in the dictionary """ def validate_fields(fields): for field in fields: + # Look for condition fields, which need to be always read + if 'available-if' in field: + condition = field['available-if'] + flag_always_read_field(fields, condition['field']) + + # Look for array size fields, which need to be always read if field['format'] == 'byte-array': pass elif field['format'] == 'uuid': @@ -45,24 +53,24 @@ def validate_fields(fields): elif field['format'] == 'guint32': pass elif field['format'] == 'guint32-array': - flag_array_length_field(fields, field['array-size-field']) + flag_always_read_field(fields, field['array-size-field']) elif field['format'] == 'guint64': pass elif field['format'] == 'guint64-array': - flag_array_length_field(fields, field['array-size-field']) + flag_always_read_field(fields, field['array-size-field']) elif field['format'] == 'string': pass elif field['format'] == 'string-array': - flag_array_length_field(fields, field['array-size-field']) + flag_always_read_field(fields, field['array-size-field']) elif field['format'] == 'struct': if 'struct-type' not in field: raise ValueError('Field type \'struct\' requires \'struct-type\' field') elif field['format'] == 'struct-array': - flag_array_length_field(fields, field['array-size-field']) + flag_always_read_field(fields, field['array-size-field']) if 'struct-type' not in field: raise ValueError('Field type \'struct\' requires \'struct-type\' field') elif field['format'] == 'ref-struct-array': - flag_array_length_field(fields, field['array-size-field']) + flag_always_read_field(fields, field['array-size-field']) if 'struct-type' not in field: raise ValueError('Field type \'struct\' requires \'struct-type\' field') elif field['format'] == 'ipv4': @@ -70,13 +78,13 @@ def validate_fields(fields): elif field['format'] == 'ref-ipv4': pass elif field['format'] == 'ipv4-array': - flag_array_length_field(fields, field['array-size-field']) + flag_always_read_field(fields, field['array-size-field']) elif field['format'] == 'ipv6': pass elif field['format'] == 'ref-ipv6': pass elif field['format'] == 'ipv6-array': - flag_array_length_field(fields, field['array-size-field']) + flag_always_read_field(fields, field['array-size-field']) else: raise ValueError('Cannot handle field type \'%s\'' % field['format']) @@ -565,7 +573,7 @@ class Message: ' guint32 offset = 0;\n') for field in fields: - if 'is-array-size' in field: + if 'always-read' in field: translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) inner_template = (' guint32 _${field};\n') template += (string.Template(inner_template).substitute(translations)) @@ -580,10 +588,45 @@ class Message: inner_template = ( '\n' - ' /* Read the \'${field_name}\' variable */\n' - ' {\n') + ' /* Read the \'${field_name}\' variable */\n') + if 'available-if' in field: + condition = field['available-if'] + translations['condition_field'] = utils.build_underscore_name_from_camelcase(condition['field']) + translations['condition_operation'] = condition['operation'] + translations['condition_value'] = condition['value'] + inner_template += ( + ' if (!(_${condition_field} ${condition_operation} ${condition_value})) {\n') + if field['format'] == 'byte-array': + inner_template += ( + ' if (${field}_size)\n' + ' *${field}_size = 0;\n' + ' if (${field})\n' + ' *${field} = NULL;\n') + elif field['format'] == 'guint32-array' or \ + field['format'] == 'string' or \ + field['format'] == 'string-array' or \ + field['format'] == 'struct' or \ + field['format'] == 'struct-array' or \ + field['format'] == 'ref-struct-array' or \ + field['format'] == 'ipv4' or \ + field['format'] == 'ref-ipv4' or \ + field['format'] == 'ipv4-array' or \ + field['format'] == 'ipv6' or \ + field['format'] == 'ref-ipv6' or \ + field['format'] == 'ipv6-array': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = NULL;\n') + else: + raise ValueError('Field format \'%s\' unsupported as optional field' % field['format']) + + inner_template += ( + ' } else {\n') + else: + inner_template += ( + ' {\n') - if 'is-array-size' in field: + if 'always-read' in field: inner_template += ( ' _${field} = _mbim_message_read_guint32 (message, offset);\n' ' if (${field} != NULL)\n' |