diff options
-rw-r--r-- | build-aux/mbim-codegen/Container.py | 93 | ||||
-rw-r--r-- | build-aux/mbim-codegen/Makefile.am | 9 | ||||
-rw-r--r-- | build-aux/mbim-codegen/Message.py | 695 | ||||
-rw-r--r-- | build-aux/mbim-codegen/Struct.py | 270 | ||||
-rw-r--r-- | build-aux/mbim-codegen/Value.py | 70 | ||||
-rw-r--r-- | build-aux/mbim-codegen/ValueString.py | 55 | ||||
-rw-r--r-- | build-aux/mbim-codegen/ValueStringArray.py | 60 | ||||
-rw-r--r-- | build-aux/mbim-codegen/ValueStruct.py | 60 | ||||
-rw-r--r-- | build-aux/mbim-codegen/ValueStructArray.py | 63 | ||||
-rw-r--r-- | build-aux/mbim-codegen/ValueUint32.py | 55 | ||||
-rw-r--r-- | build-aux/mbim-codegen/ValueUint32Array.py | 57 | ||||
-rw-r--r-- | build-aux/mbim-codegen/ValueUint64.py | 55 | ||||
-rw-r--r-- | build-aux/mbim-codegen/ValueUuid.py | 55 | ||||
-rw-r--r-- | data/mbim-service-basic-connect.json | 139 | ||||
-rw-r--r-- | libmbim-glib/mbim-enums.h | 21 | ||||
-rw-r--r-- | libmbim-glib/mbim-message.c | 300 | ||||
-rw-r--r-- | libmbim-glib/mbim-message.h | 150 | ||||
-rw-r--r-- | libmbim-glib/test/test-message-contents.c | 139 |
18 files changed, 1447 insertions, 899 deletions
diff --git a/build-aux/mbim-codegen/Container.py b/build-aux/mbim-codegen/Container.py deleted file mode 100644 index 974eef5..0000000 --- a/build-aux/mbim-codegen/Container.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -import string -import utils -from ValueUuid import ValueUuid -from ValueUint32 import ValueUint32 -from ValueUint32Array import ValueUint32Array -from ValueUint64 import ValueUint64 -from ValueString import ValueString -from ValueStringArray import ValueStringArray -from ValueStruct import ValueStruct -from ValueStructArray import ValueStructArray - -""" -The Container class takes care of handling collections of Input or -Output fields -""" -class Container: - - """ - Constructor - """ - def __init__(self, message_type, dictionary): - # We may have 'Query', 'Set' or 'Notify' message types - if message_type == 'query': - self.message_type_enum = 'MBIM_MESSAGE_TYPE_COMMAND' - elif message_type == 'set': - self.message_type_enum = 'MBIM_MESSAGE_TYPE_COMMAND' - elif message_type == 'response': - self.message_type_enum = 'MBIM_MESSAGE_TYPE_COMMAND_DONE' - elif message_type == 'notification': - self.message_type_enum = 'MBIM_MESSAGE_TYPE_INDICATE_STATUS' - else: - raise ValueError('Cannot handle message type \'%s\'' % message_type) - - self.fields = [] - for field in dictionary: - if field['format'] == 'uuid': - self.fields.append(ValueUuid(field)) - elif field['format'] == 'guint32': - self.fields.append(ValueUint32(field)) - elif field['format'] == 'guint32-array': - new_field = ValueUint32Array(field) - self.mark_array_length(new_field.array_size_field) - self.fields.append(new_field) - elif field['format'] == 'guint64': - self.fields.append(ValueUint64(field)) - elif field['format'] == 'string': - self.fields.append(ValueString(field)) - elif field['format'] == 'string-array': - new_field = ValueStringArray(field) - self.mark_array_length(new_field.array_size_field) - self.fields.append(new_field) - elif field['format'] == 'struct': - self.fields.append(ValueStruct(field)) - elif field['format'] == 'struct-array': - new_field = ValueStructArray(field) - self.mark_array_length(new_field.array_size_field) - self.fields.append(new_field) - else: - raise ValueError('Cannot handle field type \'%s\'' % field['format']) - - - """ - Flag the values which are used as length of arrays - """ - def mark_array_length(self, array_size_field): - found = False - for field in self.fields: - if field.name == array_size_field: - field.is_array_size = True - found = True - break - if found == False: - raise ValueError('Couldn\'t find array size field \'%s\'' % array_size_field) diff --git a/build-aux/mbim-codegen/Makefile.am b/build-aux/mbim-codegen/Makefile.am index 1e9336a..9dc56aa 100644 --- a/build-aux/mbim-codegen/Makefile.am +++ b/build-aux/mbim-codegen/Makefile.am @@ -2,15 +2,6 @@ EXTRA_DIST = \ utils.py \ Struct.py \ - Value.py \ - ValueString.py \ - ValueStringArray.py \ - ValueStruct.py \ - ValueStructArray.py \ - ValueUint32.py \ - ValueUint32Array.py \ - ValueUuid.py \ - Container.py \ Message.py \ ObjectList.py \ mbim-codegen diff --git a/build-aux/mbim-codegen/Message.py b/build-aux/mbim-codegen/Message.py index d1f6a08..aae6784 100644 --- a/build-aux/mbim-codegen/Message.py +++ b/build-aux/mbim-codegen/Message.py @@ -19,10 +19,66 @@ # import string - -from Container import Container import utils + +""" +Flag the values which are used as length of arrays +""" +def flag_array_length_field(fields, field_name): + for field in fields: + if field['name'] == field_name: + field['is-array-size'] = True + return + raise ValueError('Couldn\'t find array size field \'%s\'' % array_size_field) + + +""" +Validate fields in the dictionary +""" +def validate_fields(fields): + for field in fields: + if field['format'] == 'uuid': + pass + elif field['format'] == 'guint32': + pass + elif field['format'] == 'guint32-array': + flag_array_length_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']) + elif field['format'] == 'string': + pass + elif field['format'] == 'string-array': + flag_array_length_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']) + 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']) + if 'struct-type' not in field: + raise ValueError('Field type \'struct\' requires \'struct-type\' field') + elif field['format'] == 'ipv4': + pass + elif field['format'] == 'ref-ipv4': + pass + elif field['format'] == 'ipv4-array': + flag_array_length_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']) + else: + raise ValueError('Cannot handle field type \'%s\'' % field['format']) + + """ The Message class takes care of all message handling """ @@ -34,14 +90,46 @@ class Message: def __init__(self, dictionary): # The message service, e.g. "Basic Connect" self.service = dictionary['service'] + # The name of the specific message, e.g. "Something" self.name = dictionary['name'] - # Gather types of command - self.query = True if 'query' in dictionary else False - self.set = True if 'set' in dictionary else False - self.response = True if 'response' in dictionary else False - self.notification = True if 'notification' in dictionary else False + # Query + if 'query' in dictionary: + self.has_query = True + self.query = dictionary['query'] + validate_fields(self.query) + else: + self.has_query = False + self.query = [] + + # Set + if 'set' in dictionary: + self.has_set = True + self.set = dictionary['set'] + validate_fields(self.set) + else: + self.has_set = False + self.set = [] + + + # Response + if 'response' in dictionary: + self.has_response = True + self.response = dictionary['response'] + validate_fields(self.response) + else: + self.has_response = False + self.response = [] + + # Notification + if 'notification' in dictionary: + self.has_notification = True + self.notification = dictionary['notification'] + validate_fields(self.notification) + else: + self.has_notification = False + self.notification = [] # Build Fullname self.fullname = 'MBIM Message ' + self.name @@ -49,29 +137,37 @@ class Message: # Build CID enum self.cid_enum_name = utils.build_underscore_name('MBIM CID' + self.service + ' ' + self.name).upper() - # Build input containers - self.query_container = None - if self.query: - self.query_container = Container('query', dictionary['query']) - self.set_container = None - if self.set: - self.set_container = Container('set', dictionary['set']) - self.notify_container = None - # Build output containers - self.response_container = None - if self.response: - self.response_container = Container('response', dictionary['response']) - self.notification_container = None - if self.notification: - self.notification_container = Container('notification', dictionary['notification']) + """ + Emit the message handling implementation + """ + def emit(self, hfile, cfile): + if self.has_query: + utils.add_separator(hfile, 'Message (Query)', self.fullname); + utils.add_separator(cfile, 'Message (Query)', self.fullname); + self._emit_message_creator(hfile, cfile, 'query', self.query) + + if self.has_set: + utils.add_separator(hfile, 'Message (Set)', self.fullname); + utils.add_separator(cfile, 'Message (Set)', self.fullname); + self._emit_message_creator(hfile, cfile, 'set', self.set) + + if self.has_response: + utils.add_separator(hfile, 'Message (Response)', self.fullname); + utils.add_separator(cfile, 'Message (Response)', self.fullname); + self._emit_message_parser(hfile, cfile, 'response', self.response) + + if self.has_notification: + utils.add_separator(hfile, 'Message (Notification)', self.fullname); + utils.add_separator(cfile, 'Message (Notification)', self.fullname); + self._emit_message_parser(hfile, cfile, 'notification', self.notification) """ Emit message creator """ - def _emit_message_creator(self, hfile, cfile, message_type, container): - translations = { 'name' : self.name, + def _emit_message_creator(self, hfile, cfile, message_type, fields): + translations = { 'message' : self.name, 'service' : self.service, 'underscore' : utils.build_underscore_name (self.fullname), 'message_type' : message_type, @@ -82,13 +178,45 @@ class Message: '\n' 'MbimMessage *${underscore}_${message_type}_new (\n') - if container != None: - for field in container.fields: - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase (field.name) - translations['field_in_format'] = field.in_format - inner_template = ( - ' ${field_in_format}${field_name_underscore},\n') - template += (string.Template(inner_template).substitute(translations)) + for field in fields: + translations['field'] = utils.build_underscore_name_from_camelcase (field['name']) + translations['struct'] = field['struct-type'] if 'struct-type' in field else '' + translations['public'] = field['public-format'] if 'public-format' in field else field['format'] + + if field['format'] == 'uuid': + inner_template = (' const MbimUuid *${field},\n') + elif field['format'] == 'guint32': + inner_template = (' ${public} ${field},\n') + elif field['format'] == 'guint32-array': + inner_template = (' const ${public} *${field},\n') + elif field['format'] == 'guint64': + inner_template = (' ${public} ${field},\n') + elif field['format'] == 'guint64-array': + inner_template = (' const ${public} *${field},\n') + elif field['format'] == 'string': + inner_template = (' const gchar *${field},\n') + elif field['format'] == 'string-array': + inner_template = (' const gchar *const *${field},\n') + elif field['format'] == 'struct': + inner_template = (' const ${struct} *${field},\n') + elif field['format'] == 'struct-array': + inner_template = (' const ${struct} *const *${field},\n') + elif field['format'] == 'ref-struct-array': + inner_template = (' const ${struct} *const *${field},\n') + elif field['format'] == 'ipv4': + inner_template = (' const MbimIPv4 *${field},\n') + elif field['format'] == 'ref-ipv4': + inner_template = (' const MbimIPv4 *${field},\n') + elif field['format'] == 'ipv4-array': + inner_template = (' const MbimIPv4 *${field},\n') + elif field['format'] == 'ipv6': + inner_template = (' const MbimIPv6 *${field},\n') + elif field['format'] == 'ref-ipv6': + inner_template = (' const MbimIPv6 *${field},\n') + elif field['format'] == 'ipv6-array': + inner_template = (' const MbimIPv6 *${field},\n') + + template += (string.Template(inner_template).substitute(translations)) template += ( ' GError **error);\n') @@ -99,32 +227,96 @@ class Message: '/**\n' ' * ${underscore}_${message_type}_new:\n') - if container != None: - for field in container.fields: - translations['field_name'] = field.name - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase (field.name) - translations['field_in_description'] = field.in_description - inner_template = ( - ' * @${field_name_underscore}: the \'${field_name}\' field, given as ${field_in_description}\n') - template += (string.Template(inner_template).substitute(translations)) + for field in fields: + translations['name'] = field['name'] + translations['field'] = utils.build_underscore_name_from_camelcase (field['name']) + translations['struct'] = field['struct-type'] if 'struct-type' in field else '' + translations['public'] = field['public-format'] if 'public-format' in field else field['format'] + + if field['format'] == 'uuid': + inner_template = (' * @${field}: the \'${name}\' field, given as a #MbimUuid.\n') + elif field['format'] == 'guint32': + inner_template = (' * @${field}: the \'${name}\' field, given as a #${public}.\n') + elif field['format'] == 'guint32-array': + inner_template = (' * @${field}: the \'${name}\' field, given as an array of #${public}.\n') + elif field['format'] == 'guint64': + inner_template = (' * @${field}: the \'${name}\' field, given as a #${public}.\n') + elif field['format'] == 'guint64-array': + inner_template = (' * @${field}: the \'${name}\' field, given as an array of #${public}.\n') + elif field['format'] == 'string': + inner_template = (' * @${field}: the \'${name}\' field, given as a string.\n') + elif field['format'] == 'string-array': + inner_template = (' * @${field}: the \'${name}\' field, given as an array of strings.\n') + elif field['format'] == 'struct': + inner_template = (' * @${field}: the \'${name}\' field, given as a #${struct}.\n') + elif field['format'] == 'struct-array': + inner_template = (' * @${field}: the \'${name}\' field, given as an array of #${struct}s.\n') + elif field['format'] == 'ref-struct-array': + inner_template = (' * @${field}: the \'${name}\' field, given as an array of #${struct}s.\n') + elif field['format'] == 'ipv4': + inner_template = (' * @${field}: the \'${name}\' field, given as a #MbimIPv4.\n') + elif field['format'] == 'ref-ipv4': + inner_template = (' * @${field}: the \'${name}\' field, given as a #MbimIPv4.\n') + elif field['format'] == 'ipv4-array': + inner_template = (' * @${field}: the \'${name}\' field, given as an array of #MbimIPv4.\n') + elif field['format'] == 'ipv6': + inner_template = (' * @${field}: the \'${name}\' field, given as a #MbimIPv6.\n') + elif field['format'] == 'ref-ipv6': + inner_template = (' * @${field}: the \'${name}\' field, given as a #MbimIPv6.\n') + elif field['format'] == 'ipv6-array': + inner_template = (' * @${field}: the \'${name}\' field, given as an array of #MbimIPv6.\n') + + template += (string.Template(inner_template).substitute(translations)) template += ( ' * @error: return location for error or %NULL.\n' ' *\n' - ' * Create a new request for the \'${name}\' ${message_type} command in the \'${service}\' service.\n' + ' * Create a new request for the \'${message}\' ${message_type} command in the \'${service}\' service.\n' ' *\n' ' * Returns: a newly allocated #MbimMessage, which should be freed with mbim_message_unref().\n' ' */\n' 'MbimMessage *\n' '${underscore}_${message_type}_new (\n') - if container != None: - for field in container.fields: - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase (field.name) - translations['field_in_format'] = field.in_format - inner_template = ( - ' ${field_in_format}${field_name_underscore},\n') - template += (string.Template(inner_template).substitute(translations)) + for field in fields: + translations['field'] = utils.build_underscore_name_from_camelcase (field['name']) + translations['struct'] = field['struct-type'] if 'struct-type' in field else '' + translations['public'] = field['public-format'] if 'public-format' in field else field['format'] + + if field['format'] == 'uuid': + inner_template = (' const MbimUuid *${field},\n') + elif field['format'] == 'guint32': + inner_template = (' ${public} ${field},\n') + elif field['format'] == 'guint32-array': + inner_template = (' const ${public} *${field},\n') + elif field['format'] == 'guint64': + inner_template = (' ${public} ${field},\n') + elif field['format'] == 'guint64-array': + inner_template = (' const ${public} *${field},\n') + elif field['format'] == 'string': + inner_template = (' const gchar *${field},\n') + elif field['format'] == 'string-array': + inner_template = (' const gchar *const *${field},\n') + elif field['format'] == 'struct': + inner_template = (' const ${struct} *${field},\n') + elif field['format'] == 'struct-array': + inner_template = (' const ${struct} *const *${field},\n') + elif field['format'] == 'ref-struct-array': + inner_template = (' const ${struct} *const *${field},\n') + elif field['format'] == 'ipv4': + inner_template = (' const MbimIPv4 *${field},\n') + elif field['format'] == 'ref-ipv4': + inner_template = (' const MbimIPv4 *${field},\n') + elif field['format'] == 'ipv4-array': + inner_template = (' const MbimIPv4 *${field},\n') + elif field['format'] == 'ipv6': + inner_template = (' const MbimIPv6 *${field},\n') + elif field['format'] == 'ref-ipv6': + inner_template = (' const MbimIPv6 *${field},\n') + elif field['format'] == 'ipv6-array': + inner_template = (' const MbimIPv6 *${field},\n') + + template += (string.Template(inner_template).substitute(translations)) template += ( ' GError **error)\n' @@ -136,14 +328,45 @@ class Message: ' MBIM_CID_${service_underscore_upper}_${name_underscore_upper},\n' ' MBIM_MESSAGE_COMMAND_TYPE_${message_type_upper});\n') - if container != None: - template += ('\n') - for field in container.fields: - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field.name) - translations['field_format_underscore'] = utils.build_underscore_name(field.format) - inner_template = ( - ' _mbim_message_command_builder_append_${field_format_underscore} (builder, ${field_name_underscore});\n') - template += (string.Template(inner_template).substitute(translations)) + for field in fields: + translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) + translations['array_size_field'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) if 'array-size-field' in field else '' + translations['struct'] = field['struct-type'] if 'struct-type' in field else '' + translations['struct_underscore'] = utils.build_underscore_name_from_camelcase (translations['struct']) + + inner_template = (' ') + if field['format'] == 'uuid': + inner_template = (' _mbim_message_command_builder_append_uuid (builder, ${field});\n') + elif field['format'] == 'guint32': + inner_template = (' _mbim_message_command_builder_append_guint32 (builder, ${field});\n') + elif field['format'] == 'guint32-array': + inner_template = (' _mbim_message_command_builder_append_guint32_array (builder, ${field}, ${array_size_field});\n') + elif field['format'] == 'guint64': + inner_template = (' _mbim_message_command_builder_append_guint64 (builder, ${field});\n') + elif field['format'] == 'string': + inner_template = (' _mbim_message_command_builder_append_string (builder, ${field});\n') + elif field['format'] == 'string-array': + inner_template = (' _mbim_message_command_builder_append_string_array (builder, ${field}, ${array_size_field});\n') + elif field['format'] == 'struct': + inner_template = (' _mbim_message_command_builder_append_${struct_underscore}_struct (builder, ${field});\n') + elif field['format'] == 'struct-array': + inner_template = (' _mbim_message_command_builder_append_${struct_underscore}_struct_array (builder, ${field}, ${array_size_field}, FALSE);\n') + elif field['format'] == 'ref-struct-array': + inner_template = (' _mbim_message_command_builder_append_${struct_underscore}_struct_array (builder, ${field}, ${array_size_field}, TRUE);\n') + elif field['format'] == 'ipv4': + inner_template = (' _mbim_message_command_builder_append_ipv4 (builder, ${field}, FALSE);\n') + elif field['format'] == 'ref-ipv4': + inner_template = (' _mbim_message_command_builder_append_ipv4 (builder, ${field}, TRUE);\n') + elif field['format'] == 'ipv4-array': + inner_template = (' _mbim_message_command_builder_append_ipv4_array (builder, ${field}, ${array_size_field});\n') + elif field['format'] == 'ipv6': + inner_template = (' _mbim_message_command_builder_append_ipv6 (builder, ${field}, FALSE);\n') + elif field['format'] == 'ref-ipv6': + inner_template = (' _mbim_message_command_builder_append_ipv6 (builder, ${field}, TRUE);\n') + elif field['format'] == 'ipv6-array': + inner_template = (' _mbim_message_command_builder_append_ipv6_array (builder, ${field}, ${array_size_field});\n') + + template += (string.Template(inner_template).substitute(translations)) template += ( '\n' @@ -155,7 +378,7 @@ class Message: """ Emit message parser """ - def _emit_message_parser(self, hfile, cfile, message_type, container): + def _emit_message_parser(self, hfile, cfile, message_type, fields): translations = { 'name' : self.name, 'service' : self.service, 'underscore' : utils.build_underscore_name (self.fullname), @@ -168,13 +391,45 @@ class Message: 'gboolean ${underscore}_${message_type}_parse (\n' ' const MbimMessage *message,\n') - if container != None: - for field in container.fields: - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field.name) - translations['field_out_format'] = field.out_format - inner_template = ( - ' ${field_out_format}${field_name_underscore},\n') - template += (string.Template(inner_template).substitute(translations)) + for field in fields: + translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) + translations['public'] = field['public-format'] if 'public-format' in field else field['format'] + translations['struct'] = field['struct-type'] if 'struct-type' in field else '' + + if field['format'] == 'uuid': + inner_template = (' const MbimUuid **${field},\n') + elif field['format'] == 'guint32': + inner_template = (' ${public} *${field},\n') + elif field['format'] == 'guint32-array': + inner_template = (' ${public} **${field},\n') + elif field['format'] == 'guint64': + inner_template = (' ${public} *${field},\n') + elif field['format'] == 'guint64-array': + inner_template = (' ${public} **${field},\n') + elif field['format'] == 'string': + inner_template = (' gchar **${field},\n') + elif field['format'] == 'string-array': + inner_template = (' gchar ***${field},\n') + elif field['format'] == 'struct': + inner_template = (' ${struct} **${field},\n') + elif field['format'] == 'struct-array': + inner_template = (' ${struct} ***${field},\n') + elif field['format'] == 'ref-struct-array': + inner_template = (' ${struct} ***${field},\n') + elif field['format'] == 'ipv4': + inner_template = (' const MbimIPv4 **${field},\n') + elif field['format'] == 'ref-ipv4': + inner_template = (' const MbimIPv4 **${field},\n') + elif field['format'] == 'ipv4-array': + inner_template = (' MbimIPv4 **${field},\n') + elif field['format'] == 'ipv6': + inner_template = (' const MbimIPv6 **${field},\n') + elif field['format'] == 'ref-ipv6': + inner_template = (' const MbimIPv6 **${field},\n') + elif field['format'] == 'ipv6-array': + inner_template = (' MbimIPv6 **${field},\n') + + template += (string.Template(inner_template).substitute(translations)) template += ( ' GError **error);\n') @@ -186,14 +441,47 @@ class Message: ' * ${underscore}_${message_type}_parse:\n' ' * @message: the #MbimMessage.\n') - if container != None: - for field in container.fields: - translations['field_name'] = field.name - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field.name) - translations['field_out_description'] = field.out_description - inner_template = ( - ' * @${field_name_underscore}: ${field_out_description}\n') - template += (string.Template(inner_template).substitute(translations)) + for field in fields: + translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) + translations['name'] = field['name'] + translations['public'] = field['public-format'] if 'public-format' in field else field['format'] + translations['struct'] = field['struct-type'] if 'struct-type' in field else '' + translations['struct_underscore'] = utils.build_underscore_name_from_camelcase (translations['struct']) + + if field['format'] == 'uuid': + inner_template = (' * @${field}: return location for a #MbimUuid, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n') + elif field['format'] == 'guint32': + inner_template = (' * @${field}: return location for a #${public}, or %NULL if the \'${name}\' field is not needed.\n') + elif field['format'] == 'guint32-array': + inner_template = (' * @${field}: return location for a newly allocated array of #${public}s, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n') + elif field['format'] == 'guint64': + inner_template = (' * @${field}: return location for a #guint64, or %NULL if the \'${name}\' field is not needed.\n') + elif field['format'] == 'guint64-array': + inner_template = (' * @${field}: return location for a newly allocated array of #guint64s, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n') + elif field['format'] == 'string': + inner_template = (' * @${field}: return location for a newly allocated string, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n') + elif field['format'] == 'string-array': + inner_template = (' * @${field}: return location for a newly allocated array of strings, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_strfreev().\n') + elif field['format'] == 'struct': + inner_template = (' * @${field}: return location for a newly allocated #${struct}, or %NULL if the \'${name}\' field is not needed. Free the returned value with ${struct_underscore}_free().\n') + elif field['format'] == 'struct-array': + inner_template = (' * @${field}: return location for a newly allocated array of #${struct}s, or %NULL if the \'${name}\' field is not needed. Free the returned value with ${struct_underscore}_array_free().\n') + elif field['format'] == 'ref-struct-array': + inner_template = (' * @${field}: return location for a newly allocated array of #${struct}s, or %NULL if the \'${name}\' field is not needed. Free the returned value with ${struct_underscore}_array_free().\n') + elif field['format'] == 'ipv4': + inner_template = (' * @${field}: return location for a #MbimIPv4, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n') + elif field['format'] == 'ref-ipv4': + inner_template = (' * @${field}: return location for a #MbimIPv4, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n') + elif field['format'] == 'ipv4-array': + inner_template = (' * @${field}: return location for a newly allocated array of #MbimIPv4s, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n') + elif field['format'] == 'ipv6': + inner_template = (' * @${field}: return location for a #MbimIPv6, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n') + elif field['format'] == 'ref-ipv6': + inner_template = (' * @${field}: return location for a #MbimIPv6, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n') + elif field['format'] == 'ipv6-array': + inner_template = (' * @${field}: return location for a newly allocated array of #MbimIPv6s, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n') + + template += (string.Template(inner_template).substitute(translations)) template += ( ' * @error: return location for error or %NULL.\n' @@ -206,107 +494,161 @@ class Message: '${underscore}_${message_type}_parse (\n' ' const MbimMessage *message,\n') - if container != None: - for field in container.fields: - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field.name) - translations['field_out_format'] = field.out_format - inner_template = ( - ' ${field_out_format}${field_name_underscore},\n') - template += (string.Template(inner_template).substitute(translations)) + for field in fields: + translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) + translations['public'] = field['public-format'] if 'public-format' in field else field['format'] + translations['struct'] = field['struct-type'] if 'struct-type' in field else '' + + if field['format'] == 'uuid': + inner_template = (' const MbimUuid **${field},\n') + elif field['format'] == 'guint32': + inner_template = (' ${public} *${field},\n') + elif field['format'] == 'guint32-array': + inner_template = (' ${public} **${field},\n') + elif field['format'] == 'guint64': + inner_template = (' ${public} *${field},\n') + elif field['format'] == 'guint64-array': + inner_template = (' ${public} **${field},\n') + elif field['format'] == 'string': + inner_template = (' gchar **${field},\n') + elif field['format'] == 'string-array': + inner_template = (' gchar ***${field},\n') + elif field['format'] == 'struct': + inner_template = (' ${struct} **${field},\n') + elif field['format'] == 'struct-array': + inner_template = (' ${struct} ***${field},\n') + elif field['format'] == 'ref-struct-array': + inner_template = (' ${struct} ***${field},\n') + elif field['format'] == 'ipv4': + inner_template = (' const MbimIPv4 **${field},\n') + elif field['format'] == 'ref-ipv4': + inner_template = (' const MbimIPv4 **${field},\n') + elif field['format'] == 'ipv4-array': + inner_template = (' MbimIPv4 **${field},\n') + elif field['format'] == 'ipv6': + inner_template = (' const MbimIPv6 **${field},\n') + elif field['format'] == 'ref-ipv6': + inner_template = (' const MbimIPv6 **${field},\n') + elif field['format'] == 'ipv6-array': + inner_template = (' MbimIPv6 **${field},\n') + + template += (string.Template(inner_template).substitute(translations)) template += ( ' GError **error)\n' '{\n' ' guint32 offset = 0;\n') - if container != None: - for field in container.fields: - if field.is_array_size: - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field.name) - inner_template = ( - ' guint32 _${field_name_underscore};\n') - template += (string.Template(inner_template).substitute(translations)) - - if container != None: - for field in container.fields: - translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field.name) - translations['field_format_underscore'] = utils.build_underscore_name(field.format) - translations['field_size'] = field.size - translations['field_size_string'] = field.size_string - translations['field_name'] = field.name - - inner_template = ( - '\n' - ' /* Read the \'${field_name}\' variable */\n' - ' {\n') - - if field.is_array_size: - inner_template += ( - ' _${field_name_underscore} = _mbim_message_read_guint32 (message, offset);\n' - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = _${field_name_underscore};\n' - ' offset += 4;\n') - elif field.format == 'uuid': - inner_template += ( - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = _mbim_message_read_uuid (message, offset);\n' - ' offset += 16;\n') - elif field.format == 'guint32': - inner_template += ( - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = _mbim_message_read_guint32 (message, offset);\n' - ' offset += 4;\n') - elif field.format == 'guint32-array': - translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase(field.array_size_field) - inner_template += ( - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = _mbim_message_read_guint32_array (message, _{array_size_field_name_underscore}, offset);\n' - ' offset += (4 * _${array_size_field_name_underscore});\n') - elif field.format == 'guint64': - inner_template += ( - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = _mbim_message_read_guint64 (message, offset);\n' - ' offset += 8;\n') - elif field.format == 'string': - inner_template += ( - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = _mbim_message_read_string (message, offset);\n' - ' offset += 8;\n') - elif field.format == 'string-array': - translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase(field.array_size_field) - inner_template += ( - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = _mbim_message_read_string_array (message, _${array_size_field_name_underscore}, offset);\n' - ' offset += (8 * _${array_size_field_name_underscore});\n') - elif field.format == 'struct': - translations['struct_name'] = field.struct_type_underscore - translations['struct_type'] = field.struct_type - - inner_template += ( - ' ${struct_type} *tmp;\n' - ' guint32 bytes_read = 0;\n' - '\n' - ' tmp = _mbim_message_read_${struct_name}_struct (message, offset, &bytes_read);\n' - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = tmp;\n' - ' else\n' - ' ${struct_name}_free (tmp);\n' - ' offset += bytes_read;\n') - elif field.format == 'struct-array': - translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase (field.array_size_field) - translations['array_member_size'] = str(field.array_member_size) - translations['struct_name'] = field.struct_type_underscore - - inner_template += ( - ' if (${field_name_underscore} != NULL)\n' - ' *${field_name_underscore} = _mbim_message_read_${struct_name}_struct_array (message, _${array_size_field_name_underscore}, offset);\n' - ' offset += (${array_member_size} * _${array_size_field_name_underscore});\n') - else: - raise ValueError('Cannot handle format \'%s\' as a field' % field.format) + for field in fields: + if 'is-array-size' in field: + translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) + inner_template = (' guint32 _${field};\n') + template += (string.Template(inner_template).substitute(translations)) + for field in fields: + translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) + translations['field_format_underscore'] = utils.build_underscore_name_from_camelcase(field['format']) + translations['field_name'] = field['name'] + translations['array_size_field'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) if 'array-size-field' in field else '' + translations['struct_name'] = utils.build_underscore_name_from_camelcase(field['struct-type']) if 'struct-type' in field else '' + translations['struct_type'] = field['struct-type'] if 'struct-type' in field else '' + + inner_template = ( + '\n' + ' /* Read the \'${field_name}\' variable */\n' + ' {\n') + + if 'is-array-size' in field: + inner_template += ( + ' _${field} = _mbim_message_read_guint32 (message, offset);\n' + ' if (${field} != NULL)\n' + ' *${field} = _${field};\n' + ' offset += 4;\n') + elif field['format'] == 'uuid': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_uuid (message, offset);\n' + ' offset += 16;\n') + elif field['format'] == 'guint32': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_guint32 (message, offset);\n' + ' offset += 4;\n') + elif field['format'] == 'guint32-array': inner_template += ( - ' }\n') + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_guint32_array (message, _{array_size_field}, offset);\n' + ' offset += (4 * _${array_size_field});\n') + elif field['format'] == 'guint64': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_guint64 (message, offset);\n' + ' offset += 8;\n') + elif field['format'] == 'string': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_string (message, offset);\n' + ' offset += 8;\n') + elif field['format'] == 'string-array': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_string_array (message, _${array_size_field}, offset);\n' + ' offset += (8 * _${array_size_field});\n') + elif field['format'] == 'struct': + inner_template += ( + ' ${struct_type} *tmp;\n' + ' guint32 bytes_read = 0;\n' + '\n' + ' tmp = _mbim_message_read_${struct_name}_struct (message, offset, &bytes_read);\n' + ' if (${field} != NULL)\n' + ' *${field} = tmp;\n' + ' else\n' + ' ${struct_name}_free (tmp);\n' + ' offset += bytes_read;\n') + elif field['format'] == 'struct-array': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_${struct_name}_struct_array (message, _${array_size_field}, offset, FALSE);\n' + ' offset += 4;\n') + elif field['format'] == 'ref-struct-array': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_${struct_name}_struct_array (message, _${array_size_field}, offset, TRUE);\n' + ' offset += (8 * _${array_size_field});\n') + elif field['format'] == 'ipv4': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_ipv4 (message, offset, FALSE);\n' + ' offset += 4;\n') + elif field['format'] == 'ref-ipv4': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_ipv4 (message, offset, TRUE);\n' + ' offset += 4;\n') + elif field['format'] == 'ipv4-array': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_ipv4_array (message, _${array_size_field}, offset);\n' + ' offset += 4;\n') + elif field['format'] == 'ipv6': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_ipv6 (message, offset, FALSE);\n' + ' offset += 4;\n') + elif field['format'] == 'ref-ipv6': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_ipv6 (message, offset, TRUE);\n' + ' offset += 4;\n') + elif field['format'] == 'ipv6-array': + inner_template += ( + ' if (${field} != NULL)\n' + ' *${field} = _mbim_message_read_ipv6_array (message, _${array_size_field}, offset);\n' + ' offset += 4;\n') - template += (string.Template(inner_template).substitute(translations)) + inner_template += ( + ' }\n') + + template += (string.Template(inner_template).substitute(translations)) template += ( '\n' @@ -316,31 +658,6 @@ class Message: """ - Emit the message handling implementation - """ - def emit(self, hfile, cfile): - if self.query: - utils.add_separator(hfile, 'Message (Query)', self.fullname); - utils.add_separator(cfile, 'Message (Query)', self.fullname); - self._emit_message_creator(hfile, cfile, 'query', self.query_container) - - if self.set: - utils.add_separator(hfile, 'Message (Set)', self.fullname); - utils.add_separator(cfile, 'Message (Set)', self.fullname); - self._emit_message_creator(hfile, cfile, 'set', self.set_container) - - if self.response: - utils.add_separator(hfile, 'Message (Response)', self.fullname); - utils.add_separator(cfile, 'Message (Response)', self.fullname); - self._emit_message_parser(hfile, cfile, 'response', self.response_container) - - if self.notification: - utils.add_separator(hfile, 'Message (Notification)', self.fullname); - utils.add_separator(cfile, 'Message (Notification)', self.fullname); - self._emit_message_parser(hfile, cfile, 'notification', self.notification_container) - - - """ Emit the sections """ def emit_sections(self, sfile): diff --git a/build-aux/mbim-codegen/Struct.py b/build-aux/mbim-codegen/Struct.py index a01858a..30a3a90 100644 --- a/build-aux/mbim-codegen/Struct.py +++ b/build-aux/mbim-codegen/Struct.py @@ -34,6 +34,24 @@ class Struct: self.name = dictionary['name'] self.contents = dictionary['contents'] + # Check whether the struct is composed of fixed-sized fields + self.size = 0 + for field in self.contents: + if field['format'] == 'guint32': + self.size += 4 + elif field['format'] == 'guint64': + self.size += 8 + elif field['format'] == 'uuid': + self.size += 16 + elif field['format'] == 'ipv4': + self.size += 4 + elif field['format'] == 'ipv6': + self.size += 16 + else: + self.size = 0 + break + + """ Emit the new struct type """ @@ -62,6 +80,24 @@ class Struct: elif field['format'] == 'string-array': inner_template = ( ' gchar **${field_name_underscore};\n') + elif field['format'] == 'ipv4': + inner_template = ( + ' MbimIPv4 ${field_name_underscore};\n') + elif field['format'] == 'ref-ipv4': + inner_template = ( + ' MbimIPv4 ${field_name_underscore};\n') + elif field['format'] == 'ipv4-array': + inner_template = ( + ' MbimIPv4 *${field_name_underscore};\n') + elif field['format'] == 'ipv6': + inner_template = ( + ' MbimIPv6 ${field_name_underscore};\n') + elif field['format'] == 'ref-ipv6': + inner_template = ( + ' MbimIPv6 ${field_name_underscore};\n') + elif field['format'] == 'ipv6-array': + inner_template = ( + ' MbimIPv6 *${field_name_underscore};\n') else: raise ValueError('Cannot handle format \'%s\' in struct' % field['format']) template += string.Template(inner_template).substitute(translations) @@ -92,7 +128,10 @@ class Struct: ' */\n' 'void\n' '${name_underscore}_free (${name} *var)\n' - '{\n') + '{\n' + ' if (!var)\n' + ' return;\n' + '\n') for field in self.contents: translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['name']) @@ -112,6 +151,20 @@ class Struct: elif field['format'] == 'string-array': inner_template += ( ' g_strfreev (var->${field_name_underscore});\n') + elif field['format'] == 'ipv4': + pass + elif field['format'] == 'ref-ipv4': + pass + elif field['format'] == 'ipv4-array': + inner_template += ( + ' g_free (var->${field_name_underscore});\n') + elif field['format'] == 'ipv6': + pass + elif field['format'] == 'ref-ipv6': + pass + elif field['format'] == 'ipv6-array': + inner_template += ( + ' g_free (var->${field_name_underscore});\n') else: raise ValueError('Cannot handle format \'%s\' in struct clear' % field['format']) template += string.Template(inner_template).substitute(translations) @@ -131,6 +184,9 @@ class Struct: '{\n' ' guint32 i;\n' '\n' + ' if (!array)\n' + ' return;\n' + '\n' ' for (i = 0; array[i]; i++)\n' ' ${name_underscore}_free (array[i]);\n' ' g_free (array);\n' @@ -142,13 +198,9 @@ class Struct: Emit the type's read methods """ def _emit_read(self, cfile): - # Setup offset for reading fields - offset = 0 - # Additional offset string computation - additional_offset_str = '' - translations = { 'name' : self.name, - 'name_underscore' : utils.build_underscore_name_from_camelcase(self.name) } + 'name_underscore' : utils.build_underscore_name_from_camelcase(self.name), + 'struct_size' : self.size } template = ( '\n' @@ -167,14 +219,12 @@ class Struct: for field in self.contents: translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['name']) - translations['format_underscore'] = utils.build_underscore_name(field['format']) - translations['offset'] = offset inner_template = '' if field['format'] == 'uuid': inner_template += ( '\n' - ' memcpy (&out->${field_name_underscore}, _mbim_message_read_uuid (self, offset), 16);\n' + ' memcpy (&(out->${field_name_underscore}), _mbim_message_read_uuid (self, offset), 16);\n' ' offset += 16;\n') elif field['format'] == 'guint32': inner_template += ( @@ -203,6 +253,36 @@ class Struct: '\n' ' out->${field_name_underscore} = _mbim_message_read_string_array (self, out->${array_size_field_name_underscore}, offset);\n' ' offset += (8 * out->${array_size_field_name_underscore});\n') + elif field['format'] == 'ipv4': + inner_template += ( + '\n' + ' memcpy (&(out->${field_name_underscore}), _mbim_message_read_ipv4 (self, offset, FALSE), 4);\n' + ' offset += 4;\n') + elif field['format'] == 'ref-ipv4': + inner_template += ( + '\n' + ' memcpy (&(out->${field_name_underscore}), _mbim_message_read_ipv4 (self, offset, TRUE), 4);\n' + ' offset += 4;\n') + elif field['format'] == 'ipv4-array': + inner_template += ( + '\n' + ' out->${field_name_underscore} =_mbim_message_read_ipv4_array (self, out->${array_size_field_name_underscore}, offset);\n' + ' offset += 4;\n') + elif field['format'] == 'ipv6': + inner_template += ( + '\n' + ' memcpy (&(out->${field_name_underscore}), _mbim_message_read_ipv6 (self, offset, FALSE), 16);\n' + ' offset += 4;\n') + elif field['format'] == 'ref-ipv6': + inner_template += ( + '\n' + ' memcpy (&(out->${field_name_underscore}), _mbim_message_read_ipv6 (self, offset, TRUE), 16);\n' + ' offset += 4;\n') + elif field['format'] == 'ipv6-array': + inner_template += ( + '\n' + ' out->${field_name_underscore} =_mbim_message_read_ipv6_array (self, out->${array_size_field_name_underscore}, offset);\n' + ' offset += 4;\n') else: raise ValueError('Cannot handle format \'%s\' in struct' % field['format']) @@ -217,23 +297,33 @@ class Struct: '}\n') cfile.write(string.Template(template).substitute(translations)) - template = ( '\n' 'static ${name} **\n' '_mbim_message_read_${name_underscore}_struct_array (\n' ' const MbimMessage *self,\n' ' guint32 array_size,\n' - ' guint32 relative_offset_array_start)\n' + ' guint32 relative_offset_array_start,\n' + ' gboolean refs)\n' '{\n' ' ${name} **out;\n' ' guint32 i;\n' ' guint32 offset;\n' '\n' + ' if (!array_size)\n' + ' return NULL;\n' + '\n' ' out = g_new (${name} *, array_size + 1);\n' - ' offset = relative_offset_array_start;\n' - ' for (i = 0; i < array_size; i++, offset += 8)\n' - ' out[i] = _mbim_message_read_${name_underscore}_struct (self, _mbim_message_read_guint32 (self, offset), NULL);\n' + '\n' + ' if (!refs) {\n' + ' offset = _mbim_message_read_guint32 (self, relative_offset_array_start);\n' + ' for (i = 0; i < array_size; i++, offset += ${struct_size})\n' + ' out[i] = _mbim_message_read_${name_underscore}_struct (self, offset, NULL);\n' + ' } else {\n' + ' offset = relative_offset_array_start;\n' + ' for (i = 0; i < array_size; i++, offset += 8)\n' + ' out[i] = _mbim_message_read_${name_underscore}_struct (self, _mbim_message_read_guint32 (self, offset), NULL);\n' + ' }\n' ' out[array_size] = NULL;\n' '\n' ' return out;\n' @@ -242,6 +332,154 @@ class Struct: """ + Emit the type's append methods + """ + def _emit_append(self, cfile): + translations = { 'name' : self.name, + 'name_underscore' : utils.build_underscore_name_from_camelcase(self.name), + 'struct_size' : self.size } + + template = ( + '\n' + 'static GByteArray *\n' + '_${name_underscore}_struct_new (const ${name} *value)\n' + '{\n' + ' MbimStructBuilder *builder;\n' + '\n' + ' g_assert (value != NULL);\n' + '\n' + ' builder = _mbim_struct_builder_new ();\n') + + for field in self.contents: + translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) + translations['array_size_field'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) if 'array-size-field' in field else '' + + if field['format'] == 'uuid': + inner_template = (' _mbim_struct_builder_append_uuid (builder, &value->${field});\n') + elif field['format'] == 'guint32': + inner_template = (' _mbim_struct_builder_append_guint32 (builder, value->${field});\n') + elif field['format'] == 'guint32-array': + inner_template = (' _mbim_struct_builder_append_guint32_array (builder, value->${field}, value->${array_size_field});\n') + elif field['format'] == 'guint64': + inner_template = (' _mbim_struct_builder_append_guint64 (builder, value->${field});\n') + elif field['format'] == 'guint64-array': + inner_template = (' _mbim_struct_builder_append_guint64_array (builder, value->${field}, value->${array_size_field});\n') + elif field['format'] == 'string': + inner_template = (' _mbim_struct_builder_append_string (builder, value->${field});\n') + elif field['format'] == 'string-array': + inner_template = (' _mbim_struct_builder_append_string_array (builder, value->${field}, value->${array_size_field});\n') + elif field['format'] == 'ipv4': + inner_template = (' _mbim_struct_builder_append_ipv4 (builder, &value->${field}, FALSE);\n') + elif field['format'] == 'ref-ipv4': + inner_template = (' _mbim_struct_builder_append_ipv4 (builder, &value->${field}, TRUE);\n') + elif field['format'] == 'ipv4-array': + inner_template = (' _mbim_struct_builder_append_ipv4_array (builder, value->${field}, value->${array_size_field});\n') + elif field['format'] == 'ipv6': + inner_template = (' _mbim_struct_builder_append_ipv6 (builder, &value->${field}, FALSE);\n') + elif field['format'] == 'ref-ipv6': + inner_template = (' _mbim_struct_builder_append_ipv6 (builder, &value->${field}, TRUE);\n') + elif field['format'] == 'ipv6-array': + inner_template = (' _mbim_struct_builder_append_ipv6_array (builder, value->${field}, value->${array_size_field});\n') + else: + raise ValueError('Cannot handle format \'%s\' in struct' % field['format']) + + template += string.Template(inner_template).substitute(translations) + + template += ( + '\n' + ' return _mbim_struct_builder_complete (builder);\n' + '}\n') + cfile.write(string.Template(template).substitute(translations)) + + template = ( + '\n' + 'static void\n' + '_mbim_struct_builder_append_${name_underscore}_struct (\n' + ' MbimStructBuilder *builder,\n' + ' const ${name} *value)\n' + '{\n' + ' GByteArray *raw;\n' + '\n' + ' raw = _${name_underscore}_struct_new (value);\n' + ' g_byte_array_append (builder->fixed_buffer, raw->data, raw->len);\n' + ' g_byte_array_unref (raw);\n' + '}\n' + '\n' + 'static void\n' + '_mbim_message_command_builder_append_${name_underscore}_struct (\n' + ' MbimMessageCommandBuilder *builder,\n' + ' const ${name} *value)\n' + '{\n' + ' _mbim_struct_builder_append_${name_underscore}_struct (builder->contents_builder, value);\n' + '}\n') + cfile.write(string.Template(template).substitute(translations)) + + template = ( + '\n' + 'static void\n' + '_mbim_struct_builder_append_${name_underscore}_struct_array (\n' + ' MbimStructBuilder *builder,\n' + ' const ${name} *const *values,\n' + ' guint32 n_values,\n' + ' gboolean refs)\n' + '{\n' + ' guint32 offset;\n' + ' guint32 i;\n' + ' GByteArray *raw_all = NULL;\n' + '\n' + ' if (!refs) {\n' + ' for (i = 0; i < n_values; i++) {\n' + ' GByteArray *raw;\n' + '\n' + ' raw = _${name_underscore}_struct_new (values[i]);\n' + ' if (!raw_all)\n' + ' raw_all = raw;\n' + ' else {\n' + ' g_byte_array_append (raw_all, raw->data, raw->len);\n' + ' g_byte_array_unref (raw);\n' + ' }\n' + ' }\n' + '\n' + ' if (!raw_all) {\n' + ' offset = 0;\n' + ' g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset));\n' + ' } else {\n' + ' guint32 offset_offset;\n' + '\n' + ' /* Offset of the offset */\n' + ' offset_offset = builder->fixed_buffer->len;\n' + ' /* Length *not* in LE yet */\n' + ' offset = builder->variable_buffer->len;\n' + ' /* Add the offset value */\n' + ' g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset));\n' + ' /* Configure the value to get updated */\n' + ' g_array_append_val (builder->offsets, offset_offset);\n' + ' /* Add the final array itself */\n' + ' g_byte_array_append (builder->variable_buffer, raw_all->data, raw_all->len);\n' + ' g_byte_array_unref (raw_all);\n' + ' }\n' + ' } else {\n' + ' /* TODO */\n' + ' g_assert_not_reached ();\n' + ' }\n' + '}\n') + cfile.write(string.Template(template).substitute(translations)) + + template = ( + '\n' + 'static void\n' + '_mbim_message_command_builder_append_${name_underscore}_struct_array (\n' + ' MbimMessageCommandBuilder *builder,\n' + ' const ${name} *const *values,\n' + ' guint32 n_values,\n' + ' gboolean refs)\n' + '{\n' + ' _mbim_struct_builder_append_${name_underscore}_struct_array (builder->contents_builder, values, n_values, refs);\n' + '}\n') + cfile.write(string.Template(template).substitute(translations)) + + + """ Emit the struct handling implementation """ def emit(self, hfile, cfile): @@ -254,3 +492,5 @@ class Struct: self._emit_free(hfile, cfile) # Emit type's read self._emit_read(cfile) + # Emit type's append + self._emit_append(cfile) diff --git a/build-aux/mbim-codegen/Value.py b/build-aux/mbim-codegen/Value.py deleted file mode 100644 index 389a9ba..0000000 --- a/build-aux/mbim-codegen/Value.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -""" -The Value class takes care of all kind of variables -""" -class Value: - - """ - Constructor - """ - def __init__(self, dictionary): - - self.dictionary = dictionary - - """ The name of the variable """ - self.name = dictionary['name'] - - """ The type of the variable """ - self.format = dictionary['format'] - - """ Whether this field is visible or not """ - self.visible = False if 'visibility' in dictionary and dictionary['visibility'] == 'private' else True - - """ The public format of the value """ - self.public_format = '' - - """ Type of the value when used as input parameter """ - self.in_format = '' - self.in_description = '' - - """ Type of the value when used as output parameter """ - self.out_format = '' - self.out_description = '' - - """ Flag to identify this value as being used as an array size """ - self.is_array_size = False - - """ The name of the method used to read the value """ - self.reader_method_name = '' - - """ The size of this variable """ - self.size = 0 - self.size_string = '' - - """ Whether this value is an array """ - self.is_array = False - - """ The size of a member of the array """ - self.array_member_size = 0 - - """ The field giving the size of the array """ - self.array_size_field = '' diff --git a/build-aux/mbim-codegen/ValueString.py b/build-aux/mbim-codegen/ValueString.py deleted file mode 100644 index b1578a5..0000000 --- a/build-aux/mbim-codegen/ValueString.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -from Value import Value - -""" -The ValueString class takes care of STRING variables -""" -class ValueString(Value): - - """ - Constructor - """ - def __init__(self, dictionary): - - # Call the parent constructor - Value.__init__(self, dictionary) - - """ The public format of the value """ - self.public_format = 'gchar *' - - """ Type of the value when used as input parameter """ - self.in_format = 'const gchar *' - self.in_description = 'The \'' + self.name + '\' field, given as a constant string.' - - """ Type of the value when used as output parameter """ - self.out_format = 'gchar **' - self.out_description = 'Return location for a newly allocated string, or %NULL if the \'' + self.name + '\' field is not needed. Free the returned value with g_free().' - - """ The name of the method used to read the value """ - self.reader_method_name = '_mbim_message_read_string' - - """ The size of this variable """ - self.size = 8 - self.size_string = '' - - """ Whether this value is an array """ - self.is_array = False diff --git a/build-aux/mbim-codegen/ValueStringArray.py b/build-aux/mbim-codegen/ValueStringArray.py deleted file mode 100644 index d6650a8..0000000 --- a/build-aux/mbim-codegen/ValueStringArray.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -from Value import Value - -""" -The ValueStringArray class takes care of string array variables -""" -class ValueStringArray(Value): - - """ - Constructor - """ - def __init__(self, dictionary): - - # Call the parent constructor - Value.__init__(self, dictionary) - - """ The type of the variable """ - self.type = 'string_array' - - """ The public format of the value """ - self.public_format = 'gchar **' - - """ Type of the value when used as input parameter """ - self.in_format = 'const gchar *const *' - self.in_description = 'The \'' + self.name + '\' field, given as an array of strings.' - - """ Type of the value when used as output parameter """ - self.out_format = 'gchar ***' - self.out_description = 'Return location for a newly allocated array of strings, or %NULL if the \'' + self.name + '\' field is not needed. Free the returned value with g_strfreev().' - - """ The name of the method used to read the value """ - self.reader_method_name = '_mbim_message_read_string_array' - - """ Whether this value is an array """ - self.is_array = True - - """ The size of a member of the array """ - self.array_member_size = 8 - - """ The field giving the size of the array """ - self.array_size_field = dictionary['array-size-field'] diff --git a/build-aux/mbim-codegen/ValueStruct.py b/build-aux/mbim-codegen/ValueStruct.py deleted file mode 100644 index 55e081c..0000000 --- a/build-aux/mbim-codegen/ValueStruct.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -import utils -from Value import Value - -""" -The ValueStruct class takes care of STRUCT variables -""" -class ValueStruct(Value): - - """ - Constructor - """ - def __init__(self, dictionary): - - # Call the parent constructor - Value.__init__(self, dictionary) - - """ The struct type """ - self.struct_type = dictionary['struct-type'] - self.struct_type_underscore = utils.build_underscore_name_from_camelcase (self.struct_type) - - """ The public format of the value """ - self.public_format = self.struct_type - - """ Type of the value when used as input parameter """ - self.in_format = 'const ' + self.struct_type + ' *' - self.in_description = 'The \'' + self.name + '\' field, given as a #' + self.struct_type + '.' - - """ Type of the value when used as output parameter """ - self.out_format = self.struct_type + ' **' - self.out_description = 'Return location for a newly allocated #' + self.struct_type + ', or %NULL if the \'' + self.name + '\' field is not needed. Free the returned value with ' + self.struct_type_underscore + '_free().' - - """ The name of the method used to read the value """ - self.reader_method_name = '_mbim_message_read_' + self.struct_type_underscore + '_struct' - - """ The size of this variable """ - self.size = 0 - self.size_string = '(_' + self.struct_type_underscore + '_size (message, offset))' - - """ Whether this value is an array """ - self.is_array = False diff --git a/build-aux/mbim-codegen/ValueStructArray.py b/build-aux/mbim-codegen/ValueStructArray.py deleted file mode 100644 index 2ff19be..0000000 --- a/build-aux/mbim-codegen/ValueStructArray.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -import utils - -from Value import Value - -""" -The ValueStructArray class takes care of struct array variables -""" -class ValueStructArray(Value): - - """ - Constructor - """ - def __init__(self, dictionary): - - # Call the parent constructor - Value.__init__(self, dictionary) - - """ The struct type """ - self.struct_type = dictionary['struct-type'] - self.struct_type_underscore = utils.build_underscore_name_from_camelcase (self.struct_type) - - """ The public format of the value """ - self.public_format = self.struct_type + ' **' - - """ Type of the value when used as input parameter """ - self.in_format = 'const ' + self.struct_type + ' * const *' - self.in_description = 'The \'' + self.name + '\' field, given as an array of #' + self.struct_type + 's.' - - """ Type of the value when used as output parameter """ - self.out_format = self.struct_type + ' ***' - self.out_description = 'Return location for a newly allocated array of #' + self.struct_type + 's, or %NULL if the \'' + self.name + '\' field is not needed. Free the returned value with ' + self.struct_type_underscore + '_free_array().' - - """ The name of the method used to read the value """ - self.reader_method_name = '_' + self.struct_type_underscore + '_read_array' - - """ Whether this value is an array """ - self.is_array = True - - """ The size of a member of the array """ - self.array_member_size = 8 - - """ The field giving the size of the array """ - self.array_size_field = dictionary['array-size-field'] diff --git a/build-aux/mbim-codegen/ValueUint32.py b/build-aux/mbim-codegen/ValueUint32.py deleted file mode 100644 index cabb29d..0000000 --- a/build-aux/mbim-codegen/ValueUint32.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -from Value import Value - -""" -The ValueUint32 class takes care of UINT32 variables -""" -class ValueUint32(Value): - - """ - Constructor - """ - def __init__(self, dictionary): - - # Call the parent constructor - Value.__init__(self, dictionary) - - """ The public format of the value """ - self.public_format = dictionary['public-format'] if 'public-format' in dictionary else 'guint32' - - """ Type of the value when used as input parameter """ - self.in_format = self.public_format + ' ' - self.in_description = 'The \'' + self.name + '\' field, given as a #' + self.public_format + '.' - - """ Type of the value when used as output parameter """ - self.out_format = self.public_format + ' *' - self.out_description = 'Return location for a #' + self.public_format + ', or %NULL if the \'' + self.name + '\' field is not needed.' - - """ The name of the method used to read the value """ - self.reader_method_name = '_mbim_message_read_guint32' - - """ The size of this variable """ - self.size = 4 - self.size_string = '' - - """ Whether this value is an array """ - self.is_array = False diff --git a/build-aux/mbim-codegen/ValueUint32Array.py b/build-aux/mbim-codegen/ValueUint32Array.py deleted file mode 100644 index 615ba62..0000000 --- a/build-aux/mbim-codegen/ValueUint32Array.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -from Value import Value - -""" -The ValueUint32Array class takes care of uint32 array variables -""" -class ValueUint32Array(Value): - - """ - Constructor - """ - def __init__(self, dictionary): - - # Call the parent constructor - Value.__init__(self, dictionary) - - """ The public format of the value """ - self.public_format = dictionary['public-format'] if 'public-format' in dictionary else 'guint32' - - """ Type of the value when used as input parameter """ - self.in_format = 'const ' + self.public_format + ' *' - self.in_description = 'The \'' + self.name + '\' field, given as an array of #' + self.public_format + 's.' - - """ Type of the value when used as output parameter """ - self.out_format = self.public_format + ' **' - self.out_description = 'Return location for a newly allocated array of #' + self.public_format + 's, or %NULL if the \'' + self.name + '\' field is not needed. Free the returned value with g_free().' - - """ The name of the method used to read the value """ - self.reader_method_name = '_mbim_message_read_guint32_array' - - """ Whether this value is an array """ - self.is_array = True - - """ The size of a member of the array """ - self.array_member_size = 0 - - """ The field giving the size of the array """ - self.array_size_field = dictionary['array-size-field'] diff --git a/build-aux/mbim-codegen/ValueUint64.py b/build-aux/mbim-codegen/ValueUint64.py deleted file mode 100644 index 989c003..0000000 --- a/build-aux/mbim-codegen/ValueUint64.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -from Value import Value - -""" -The ValueUint64 class takes care of UINT64 variables -""" -class ValueUint64(Value): - - """ - Constructor - """ - def __init__(self, dictionary): - - # Call the parent constructor - Value.__init__(self, dictionary) - - """ The public format of the value """ - self.public_format = dictionary['public-format'] if 'public-format' in dictionary else 'guint64' - - """ Type of the value when used as input parameter """ - self.in_format = self.public_format + ' ' - self.in_description = 'The \'' + self.name + '\' field, given as a #' + self.public_format + '.' - - """ Type of the value when used as output parameter """ - self.out_format = self.public_format + ' *' - self.out_description = 'Return location for a #' + self.public_format + ', or %NULL if the \'' + self.name + '\' field is not needed.' - - """ The name of the method used to read the value """ - self.reader_method_name = '_mbim_message_read_guint64' - - """ The size of this variable """ - self.size = 4 - self.size_string = '' - - """ Whether this value is an array """ - self.is_array = False diff --git a/build-aux/mbim-codegen/ValueUuid.py b/build-aux/mbim-codegen/ValueUuid.py deleted file mode 100644 index 92e4e9e..0000000 --- a/build-aux/mbim-codegen/ValueUuid.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> -# - -from Value import Value - -""" -The ValueUuid class takes care of UUID variables -""" -class ValueUuid(Value): - - """ - Constructor - """ - def __init__(self, dictionary): - - # Call the parent constructor - Value.__init__(self, dictionary) - - """ The public format of the value """ - self.public_format = 'MbimUuid' - - """ Type of the value when used as input parameter """ - self.in_format = 'const MbimUuid *' - self.in_description = 'The \'' + self.name + '\' field, given as a #MbimUuid.' - - """ Type of the value when used as output parameter """ - self.out_format = 'const MbimUuid **' - self.out_description = 'Return location for a #MbimUuid, or %NULL if the \'' + self.name + '\' field is not needed. Do not free the returned value.' - - """ The name of the method used to read the value """ - self.reader_method_name = '_mbim_message_read_uuid' - - """ The size of this variable """ - self.size = 16 - self.size_string = '' - - """ Whether this value is an array """ - self.is_array = False diff --git a/data/mbim-service-basic-connect.json b/data/mbim-service-basic-connect.json index b58b1fa..eb5a8b4 100644 --- a/data/mbim-service-basic-connect.json +++ b/data/mbim-service-basic-connect.json @@ -401,17 +401,150 @@ "response" : [ { "name" : "ProvisionedContextsCount", "format" : "guint32" }, { "name" : "ProvisionedContexts", - "format" : "struct-array", + "format" : "ref-struct-array", "struct-type" : "MbimProvisionedContextElement", "array-size-field" : "ProvisionedContextsCount" } ], "notification" : [ { "name" : "ProvisionedContextsCount", "format" : "guint32" }, { "name" : "ProvisionedContexts", - "format" : "struct-array", + "format" : "ref-struct-array", "struct-type" : "MbimProvisionedContextElement", "array-size-field" : "ProvisionedContextsCount" } ] }, // ********************************************************************************* + { "name" : "MbimIPv4Element", + "type" : "Struct", + "contents" : [ { "name" : "OnLinkPrefixLength", + "format" : "guint32" }, + { "name" : "IPv4Address", + "format" : "ipv4" } ] }, + + { "name" : "MbimIPv6Element", + "type" : "Struct", + "contents" : [ { "name" : "OnLinkPrefixLength", + "format" : "guint32" }, + { "name" : "IPv6Address", + "format" : "ipv6" } ] }, + + { "name" : "IP Configuration", + "service" : "Basic Connect", + "type" : "Command", + "query" : [ { "name" : "SessionId", + "format" : "guint32" }, + { "name" : "IPv4ConfigurationAvailable", + "format" : "guint32", + "public-format" : "MbimIPConfigurationAvailableFlag" }, + { "name" : "IPv6ConfigurationAvailable", + "format" : "guint32", + "public-format" : "MbimIPConfigurationAvailableFlag" }, + { "name" : "IPv4AddressCount", + "format" : "guint32" }, + { "name" : "IPv4Address", + "format" : "struct-array", + "struct-type" : "MbimIPv4Element", + "array-size-field" : "IPv4AddressCount" }, + { "name" : "IPv6AddressCount", + "format" : "guint32" }, + { "name" : "IPv6Address", + "format" : "struct-array", + "struct-type" : "MbimIPv6Element", + "array-size-field" : "IPv6AddressCount" }, + { "name" : "IPv4Gateway", + "format" : "ref-ipv4" }, + { "name" : "IPv6Gateway", + "format" : "ref-ipv6" }, + { "name" : "IPv4DnsServerCount", + "format" : "guint32" }, + { "name" : "IPv4DnsServer", + "format" : "ipv4-array", + "array-size-field" : "IPv4DnsServerCount" }, + { "name" : "IPv6DnsServerCount", + "format" : "guint32" }, + { "name" : "IPv6DnsServer", + "format" : "ipv6-array", + "array-size-field" : "IPv6DnsServerCount" }, + { "name" : "IPv4Mtu", + "format" : "guint32" }, + { "name" : "IPv6Mtu", + "format" : "guint32" } ], + "response" : [ { "name" : "SessionId", + "format" : "guint32" }, + { "name" : "IPv4ConfigurationAvailable", + "format" : "guint32", + "public-format" : "MbimIPConfigurationAvailableFlag" }, + { "name" : "IPv6ConfigurationAvailable", + "format" : "guint32", + "public-format" : "MbimIPConfigurationAvailableFlag" }, + { "name" : "IPv4AddressCount", + "format" : "guint32" }, + { "name" : "IPv4Address", + "format" : "struct-array", + "struct-type" : "MbimIPv4Element", + "array-size-field" : "IPv4AddressCount" }, + { "name" : "IPv6AddressCount", + "format" : "guint32" }, + { "name" : "IPv6Address", + "format" : "struct-array", + "struct-type" : "MbimIPv6Element", + "array-size-field" : "IPv6AddressCount" }, + { "name" : "IPv4Gateway", + "format" : "ref-ipv4" }, + { "name" : "IPv6Gateway", + "format" : "ref-ipv6" }, + { "name" : "IPv4DnsServerCount", + "format" : "guint32" }, + { "name" : "IPv4DnsServer", + "format" : "ipv4-array", + "array-size-field" : "IPv4DnsServerCount" }, + { "name" : "IPv6DnsServerCount", + "format" : "guint32" }, + { "name" : "IPv6DnsServer", + "format" : "ipv6-array", + "array-size-field" : "IPv6DnsServerCount" }, + { "name" : "IPv4Mtu", + "format" : "guint32" }, + { "name" : "IPv6Mtu", + "format" : "guint32" } ], + "notification" : [ { "name" : "SessionId", + "format" : "guint32" }, + { "name" : "IPv4ConfigurationAvailable", + "format" : "guint32", + "public-format" : "MbimIPConfigurationAvailableFlag" }, + { "name" : "IPv6ConfigurationAvailable", + "format" : "guint32", + "public-format" : "MbimIPConfigurationAvailableFlag" }, + { "name" : "IPv4AddressCount", + "format" : "guint32" }, + { "name" : "IPv4Address", + "format" : "struct-array", + "struct-type" : "MbimIPv4Element", + "array-size-field" : "IPv4AddressCount" }, + { "name" : "IPv6AddressCount", + "format" : "guint32" }, + { "name" : "IPv6Address", + "format" : "struct-array", + "struct-type" : "MbimIPv6Element", + "array-size-field" : "IPv6AddressCount" }, + { "name" : "IPv4Gateway", + "format" : "ref-ipv4" }, + { "name" : "IPv6Gateway", + "format" : "ref-ipv6" }, + { "name" : "IPv4DnsServerCount", + "format" : "guint32" }, + { "name" : "IPv4DnsServer", + "format" : "ipv4-array", + "array-size-field" : "IPv4DnsServerCount" }, + { "name" : "IPv6DnsServerCount", + "format" : "guint32" }, + { "name" : "IPv6DnsServer", + "format" : "ipv6-array", + "array-size-field" : "IPv6DnsServerCount" }, + { "name" : "IPv4Mtu", + "format" : "guint32" }, + { "name" : "IPv6Mtu", + "format" : "guint32" } ] }, + + // ********************************************************************************* { "name" : "MbimDeviceServiceElement", "type" : "Struct", "contents" : [ { "name" : "DeviceServiceId", @@ -435,7 +568,7 @@ { "name" : "MaxDssSessions", "format" : "guint32" }, { "name" : "DeviceServices", - "format" : "struct-array", + "format" : "ref-struct-array", "struct-type" : "MbimDeviceServiceElement", "array-size-field" : "DeviceServicesCount" } ] } ] diff --git a/libmbim-glib/mbim-enums.h b/libmbim-glib/mbim-enums.h index 8a3b69c..bfe4c65 100644 --- a/libmbim-glib/mbim-enums.h +++ b/libmbim-glib/mbim-enums.h @@ -534,6 +534,27 @@ typedef enum { MBIM_VOICE_CALL_STATE_HANG_UP = 2 } MbimVoiceCallState; +/*****************************************************************************/ +/* 'IP Configuration' enums */ + +/** + * MbimIPConfigurationAvailableFlag: + * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE: No info available. + * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS: Address info available. + * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY: Gateway info available. + * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS: DNS info available. + * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU: MTU info available. + * + * Mask of available information about an IP address. + */ +typedef enum { /*< underscore_name=mbim_ip_configuration_available_flag >*/ + MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE = 0, + MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS = 1 << 0, + MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY = 1 << 1, + MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS = 1 << 2, + MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU = 1 << 3, +} MbimIPConfigurationAvailableFlag; + G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_ENUMS_H_ */ diff --git a/libmbim-glib/mbim-message.c b/libmbim-glib/mbim-message.c index f7db79f..7a60da3 100644 --- a/libmbim-glib/mbim-message.c +++ b/libmbim-glib/mbim-message.c @@ -133,6 +133,9 @@ _mbim_message_read_guint32_array (const MbimMessage *self, guint32 *out; guint32 information_buffer_offset; + if (!array_size) + return NULL; + information_buffer_offset = _mbim_message_get_information_buffer_offset (self); out = g_new (guint32, array_size + 1); @@ -213,6 +216,9 @@ _mbim_message_read_string_array (const MbimMessage *self, guint32 i; guint32 information_buffer_offset; + if (!array_size) + return NULL; + information_buffer_offset = _mbim_message_get_information_buffer_offset (self); array = g_new (gchar *, array_size + 1); @@ -258,6 +264,113 @@ _mbim_message_read_uuid (const MbimMessage *self, (information_buffer_offset + relative_offset)); } +const MbimIPv4 * +_mbim_message_read_ipv4 (const MbimMessage *self, + guint32 relative_offset, + gboolean ref) +{ + guint32 information_buffer_offset; + guint32 offset; + + information_buffer_offset = _mbim_message_get_information_buffer_offset (self); + + if (ref) { + offset = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, + self->data, + (information_buffer_offset + relative_offset))); + if (!offset) + return NULL; + } else + offset = relative_offset; + + return (const MbimIPv4 *) G_STRUCT_MEMBER_P (self->data, + (information_buffer_offset + offset)); +} + +MbimIPv4 * +_mbim_message_read_ipv4_array (const MbimMessage *self, + guint32 array_size, + guint32 relative_offset_array_start) +{ + MbimIPv4 *array; + guint32 offset; + guint32 i; + guint32 information_buffer_offset; + + if (!array_size) + return NULL; + + information_buffer_offset = _mbim_message_get_information_buffer_offset (self); + + array = g_new (MbimIPv4, array_size); + offset = GUINT32_FROM_LE (G_STRUCT_MEMBER ( + guint32, + self->data, + (information_buffer_offset + relative_offset_array_start))); + + for (i = 0; i < array_size; i++, offset += 4) { + memcpy (&array[i], + G_STRUCT_MEMBER_P (self->data, + (information_buffer_offset + offset)), + 4); + } + + return array; +} + +const MbimIPv6 * +_mbim_message_read_ipv6 (const MbimMessage *self, + guint32 relative_offset, + gboolean ref) +{ + guint32 information_buffer_offset; + guint32 offset; + + information_buffer_offset = _mbim_message_get_information_buffer_offset (self); + + if (ref) { + offset = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, + self->data, + (information_buffer_offset + relative_offset))); + if (!offset) + return NULL; + } else + offset = relative_offset; + + return (const MbimIPv6 *) G_STRUCT_MEMBER_P (self->data, + (information_buffer_offset + offset)); +} + +MbimIPv6 * +_mbim_message_read_ipv6_array (const MbimMessage *self, + guint32 array_size, + guint32 relative_offset_array_start) +{ + MbimIPv6 *array; + guint32 offset; + guint32 i; + guint32 information_buffer_offset; + + if (!array_size) + return NULL; + + information_buffer_offset = _mbim_message_get_information_buffer_offset (self); + + array = g_new (MbimIPv6, array_size); + offset = GUINT32_FROM_LE (G_STRUCT_MEMBER ( + guint32, + self->data, + (information_buffer_offset + relative_offset_array_start))); + for (i = 0; i < array_size; i++, offset += 16) { + memcpy (&array[i], + G_STRUCT_MEMBER_P (self->data, + (information_buffer_offset + offset)), + 16); + } + + return array; +} + /*****************************************************************************/ /* Struct builder interface * @@ -265,12 +378,6 @@ _mbim_message_read_uuid (const MbimMessage *self, * data buffer. Items of variable size are usually given as an offset (with * respect to the start of the struct) plus a size field. */ -struct _MbimStructBuilder { - GByteArray *fixed_buffer; - GByteArray *variable_buffer; - GArray *offsets; -}; - MbimStructBuilder * _mbim_struct_builder_new (void) { @@ -320,8 +427,18 @@ void _mbim_struct_builder_append_uuid (MbimStructBuilder *builder, const MbimUuid *value) { + static const MbimUuid uuid_invalid = { + .a = { 0x00, 0x00, 0x00, 0x00 }, + .b = { 0x00, 0x00 }, + .c = { 0x00, 0x00 }, + .d = { 0x00, 0x00 }, + .e = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }; + /* uuids are added in the static buffer only */ - g_byte_array_append (builder->fixed_buffer, (guint8 *)value, sizeof (MbimUuid)); + g_byte_array_append (builder->fixed_buffer, + value ? (guint8 *)value : (guint8 *)&uuid_invalid, + sizeof (MbimUuid)); } void @@ -336,6 +453,15 @@ _mbim_struct_builder_append_guint32 (MbimStructBuilder *builder, } void +_mbim_struct_builder_append_guint32_array (MbimStructBuilder *builder, + const guint32 *values, + guint32 n_values) +{ + /* TODO */ + g_assert_not_reached (); +} + +void _mbim_struct_builder_append_guint64 (MbimStructBuilder *builder, guint64 value) { @@ -347,6 +473,15 @@ _mbim_struct_builder_append_guint64 (MbimStructBuilder *builder, } void +_mbim_struct_builder_append_guint64_array (MbimStructBuilder *builder, + const guint64 *values, + guint32 n_values) +{ + /* TODO */ + g_assert_not_reached (); +} + +void _mbim_struct_builder_append_string (MbimStructBuilder *builder, const gchar *value) { @@ -405,21 +540,99 @@ _mbim_struct_builder_append_string (MbimStructBuilder *builder, } void -_mbim_struct_builder_append_struct (MbimStructBuilder *builder, - const GByteArray *value) +_mbim_struct_builder_append_string_array (MbimStructBuilder *builder, + const gchar *const *values, + guint32 n_values) +{ + /* TODO */ + g_assert_not_reached (); +} + +void +_mbim_struct_builder_append_ipv4 (MbimStructBuilder *builder, + const MbimIPv4 *value, + gboolean ref) +{ + if (ref) + _mbim_struct_builder_append_ipv4_array (builder, value, value ? 1 : 0); + else + g_byte_array_append (builder->fixed_buffer, (guint8 *)value, sizeof (MbimIPv4)); +} + +void +_mbim_struct_builder_append_ipv4_array (MbimStructBuilder *builder, + const MbimIPv4 *values, + guint32 n_values) { - /* structs are added in the static buffer only */ - g_byte_array_append (builder->fixed_buffer, value->data, value->len); + guint32 offset; + + if (!n_values) { + offset = 0; + g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); + } else { + guint32 offset_offset; + + /* Offset of the offset */ + offset_offset = builder->fixed_buffer->len; + + /* Length *not* in LE yet */ + offset = builder->variable_buffer->len; + /* Add the offset value */ + g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); + /* Configure the value to get updated */ + g_array_append_val (builder->offsets, offset_offset); + + /* NOTE: length of the array must be given in a separate variable */ + + /* And finally, the array of IPs itself to the variable buffer */ + g_byte_array_append (builder->variable_buffer, (guint8 *)values, n_values * sizeof (MbimIPv4)); + } +} + +void +_mbim_struct_builder_append_ipv6 (MbimStructBuilder *builder, + const MbimIPv6 *value, + gboolean ref) +{ + if (ref) + _mbim_struct_builder_append_ipv6_array (builder, value, value ? 1 : 0); + else + g_byte_array_append (builder->fixed_buffer, (guint8 *)value, sizeof (MbimIPv6)); +} + +void +_mbim_struct_builder_append_ipv6_array (MbimStructBuilder *builder, + const MbimIPv6 *values, + guint32 n_values) +{ + guint32 offset; + + if (!n_values) { + offset = 0; + g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); + } else { + guint32 offset_offset; + + /* Offset of the offset */ + offset_offset = builder->fixed_buffer->len; + + /* Length *not* in LE yet */ + offset = builder->variable_buffer->len; + /* Add the offset value */ + g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); + /* Configure the value to get updated */ + g_array_append_val (builder->offsets, offset_offset); + + /* NOTE: length of the array must be given in a separate variable */ + + /* And finally, the array of IPs itself to the variable buffer */ + g_byte_array_append (builder->variable_buffer, (guint8 *)values, n_values * sizeof (MbimIPv6)); + } } /*****************************************************************************/ /* Command message builder interface */ -struct _MbimMessageCommandBuilder { - MbimMessage *message; - MbimStructBuilder *contents_builder; -}; - MbimMessageCommandBuilder * _mbim_message_command_builder_new (guint32 transaction_id, MbimService service, @@ -473,6 +686,14 @@ _mbim_message_command_builder_append_guint32 (MbimMessageCommandBuilder *builder } void +_mbim_message_command_builder_append_guint32_array (MbimMessageCommandBuilder *builder, + const guint32 *values, + guint32 n_values) +{ + _mbim_struct_builder_append_guint32_array (builder->contents_builder, values, n_values); +} + +void _mbim_message_command_builder_append_guint64 (MbimMessageCommandBuilder *builder, guint64 value) { @@ -480,6 +701,14 @@ _mbim_message_command_builder_append_guint64 (MbimMessageCommandBuilder *builder } void +_mbim_message_command_builder_append_guint64_array (MbimMessageCommandBuilder *builder, + const guint64 *values, + guint32 n_values) +{ + _mbim_struct_builder_append_guint64_array (builder->contents_builder, values, n_values); +} + +void _mbim_message_command_builder_append_string (MbimMessageCommandBuilder *builder, const gchar *value) { @@ -487,10 +716,43 @@ _mbim_message_command_builder_append_string (MbimMessageCommandBuilder *builder, } void -_mbim_message_command_builder_append_struct (MbimMessageCommandBuilder *builder, - const GByteArray *value) +_mbim_message_command_builder_append_string_array (MbimMessageCommandBuilder *builder, + const gchar *const *values, + guint32 n_values) +{ + _mbim_struct_builder_append_string_array (builder->contents_builder, values, n_values); +} + +void +_mbim_message_command_builder_append_ipv4 (MbimMessageCommandBuilder *builder, + const MbimIPv4 *value, + gboolean ref) +{ + _mbim_struct_builder_append_ipv4 (builder->contents_builder, value, ref); +} + +void +_mbim_message_command_builder_append_ipv4_array (MbimMessageCommandBuilder *builder, + const MbimIPv4 *values, + guint32 n_values) +{ + _mbim_struct_builder_append_ipv4_array (builder->contents_builder, values, n_values); +} + +void +_mbim_message_command_builder_append_ipv6 (MbimMessageCommandBuilder *builder, + const MbimIPv6 *value, + gboolean ref) +{ + _mbim_struct_builder_append_ipv6 (builder->contents_builder, value, ref); +} + +void +_mbim_message_command_builder_append_ipv6_array (MbimMessageCommandBuilder *builder, + const MbimIPv6 *values, + guint32 n_values) { - _mbim_struct_builder_append_struct (builder->contents_builder, value); + _mbim_struct_builder_append_ipv6_array (builder->contents_builder, values, n_values); } /*****************************************************************************/ diff --git a/libmbim-glib/mbim-message.h b/libmbim-glib/mbim-message.h index db44aa0..5e4f9b9 100644 --- a/libmbim-glib/mbim-message.h +++ b/libmbim-glib/mbim-message.h @@ -47,6 +47,26 @@ GType mbim_message_get_type (void) G_GNUC_CONST; #define MBIM_TYPE_MESSAGE (mbim_message_get_type ()) /** + * MbimIPv4: + * + * An IPv4 address. + */ +typedef struct _MbimIPv4 MbimIPv4; +struct _MbimIPv4 { + guint8 addr[4]; +}; + +/** + * MbimIPv6: + * + * An IPv6 address. + */ +typedef struct _MbimIPv6 MbimIPv6; +struct _MbimIPv6 { + guint8 addr[16]; +}; + +/** * MbimMessageType: * @MBIM_MESSAGE_TYPE_INVALID: Invalid MBIM message. * @MBIM_MESSAGE_TYPE_OPEN: Initialization request. @@ -114,6 +134,18 @@ gchar **_mbim_message_read_string_array (const MbimMessage *self, guint32 relative_offset_array_start); const MbimUuid *_mbim_message_read_uuid (const MbimMessage *self, guint32 relative_offset); +const MbimIPv4 *_mbim_message_read_ipv4 (const MbimMessage *self, + guint32 relative_offset, + gboolean ref); +MbimIPv4 *_mbim_message_read_ipv4_array (const MbimMessage *self, + guint32 array_size, + guint32 relative_offset_array_start); +const MbimIPv6 *_mbim_message_read_ipv6 (const MbimMessage *self, + guint32 relative_offset, + gboolean ref); +MbimIPv6 *_mbim_message_read_ipv6_array (const MbimMessage *self, + guint32 array_size, + guint32 relative_offset_array_start); #endif /*****************************************************************************/ @@ -183,48 +215,84 @@ const guint8 *mbim_message_command_get_raw_information_buffer (const M guint32 *length); #if defined (LIBMBIM_GLIB_COMPILATION) -/** - * MbimStruct: - * - * An opaque type representing a struct within a MBIM message command. - */ -typedef struct _MbimStructBuilder MbimStructBuilder; - -MbimStructBuilder *_mbim_struct_builder_new (void); -GByteArray *_mbim_struct_builder_complete (MbimStructBuilder *builder); -void _mbim_struct_builder_append_uuid (MbimStructBuilder *builder, - const MbimUuid *value); -void _mbim_struct_builder_append_guint32 (MbimStructBuilder *builder, - guint32 value); -void _mbim_struct_builder_append_guint64 (MbimStructBuilder *builder, - guint64 value); -void _mbim_struct_builder_append_string (MbimStructBuilder *builder, - const gchar *value); -void _mbim_struct_builder_append_struct (MbimStructBuilder *builder, - const GByteArray *value); -/** - * MbimMessageCommandBuilder: - * - * An opaque type representing a MBIM message command builder. - */ -typedef struct _MbimMessageCommandBuilder MbimMessageCommandBuilder; - -MbimMessageCommandBuilder *_mbim_message_command_builder_new (guint32 transaction_id, - MbimService service, - guint32 cid, - MbimMessageCommandType command_type); -MbimMessage *_mbim_message_command_builder_complete (MbimMessageCommandBuilder *builder); -void _mbim_message_command_builder_append_uuid (MbimMessageCommandBuilder *builder, - const MbimUuid *value); -void _mbim_message_command_builder_append_guint32 (MbimMessageCommandBuilder *builder, - guint32 value); -void _mbim_message_command_builder_append_guint64 (MbimMessageCommandBuilder *builder, - guint64 value); -void _mbim_message_command_builder_append_string (MbimMessageCommandBuilder *builder, - const gchar *value); -void _mbim_message_command_builder_append_struct (MbimMessageCommandBuilder *builder, - const GByteArray *value); +typedef struct { + GByteArray *fixed_buffer; + GByteArray *variable_buffer; + GArray *offsets; +} MbimStructBuilder; + +MbimStructBuilder *_mbim_struct_builder_new (void); +GByteArray *_mbim_struct_builder_complete (MbimStructBuilder *builder); +void _mbim_struct_builder_append_uuid (MbimStructBuilder *builder, + const MbimUuid *value); +void _mbim_struct_builder_append_guint32 (MbimStructBuilder *builder, + guint32 value); +void _mbim_struct_builder_append_guint32_array (MbimStructBuilder *builder, + const guint32 *values, + guint32 n_values); +void _mbim_struct_builder_append_guint64 (MbimStructBuilder *builder, + guint64 value); +void _mbim_struct_builder_append_guint64_array (MbimStructBuilder *builder, + const guint64 *values, + guint32 n_values); +void _mbim_struct_builder_append_string (MbimStructBuilder *builder, + const gchar *value); +void _mbim_struct_builder_append_string_array (MbimStructBuilder *builder, + const gchar *const *values, + guint32 n_values); +void _mbim_struct_builder_append_ipv4 (MbimStructBuilder *builder, + const MbimIPv4 *value, + gboolean ref); +void _mbim_struct_builder_append_ipv4_array (MbimStructBuilder *builder, + const MbimIPv4 *values, + guint32 n_values); +void _mbim_struct_builder_append_ipv6 (MbimStructBuilder *builder, + const MbimIPv6 *value, + gboolean ref); +void _mbim_struct_builder_append_ipv6_array (MbimStructBuilder *builder, + const MbimIPv6 *values, + guint32 n_values); + +typedef struct { + MbimMessage *message; + MbimStructBuilder *contents_builder; +} MbimMessageCommandBuilder; + +MbimMessageCommandBuilder *_mbim_message_command_builder_new (guint32 transaction_id, + MbimService service, + guint32 cid, + MbimMessageCommandType command_type); +MbimMessage *_mbim_message_command_builder_complete (MbimMessageCommandBuilder *builder); +void _mbim_message_command_builder_append_uuid (MbimMessageCommandBuilder *builder, + const MbimUuid *value); +void _mbim_message_command_builder_append_guint32 (MbimMessageCommandBuilder *builder, + guint32 value); +void _mbim_message_command_builder_append_guint32_array (MbimMessageCommandBuilder *builder, + const guint32 *values, + guint32 n_values); +void _mbim_message_command_builder_append_guint64 (MbimMessageCommandBuilder *builder, + guint64 value); +void _mbim_message_command_builder_append_guint64_array (MbimMessageCommandBuilder *builder, + const guint64 *values, + guint32 n_values); +void _mbim_message_command_builder_append_string (MbimMessageCommandBuilder *builder, + const gchar *value); +void _mbim_message_command_builder_append_string_array (MbimMessageCommandBuilder *builder, + const gchar *const *values, + guint32 n_values); +void _mbim_message_command_builder_append_ipv4 (MbimMessageCommandBuilder *builder, + const MbimIPv4 *value, + gboolean ref); +void _mbim_message_command_builder_append_ipv4_array (MbimMessageCommandBuilder *builder, + const MbimIPv4 *values, + guint32 n_values); +void _mbim_message_command_builder_append_ipv6 (MbimMessageCommandBuilder *builder, + const MbimIPv6 *value, + gboolean ref); +void _mbim_message_command_builder_append_ipv6_array (MbimMessageCommandBuilder *builder, + const MbimIPv6 *values, + guint32 n_values); #endif /*****************************************************************************/ diff --git a/libmbim-glib/test/test-message-contents.c b/libmbim-glib/test/test-message-contents.c index cb847db..63df00e 100644 --- a/libmbim-glib/test/test-message-contents.c +++ b/libmbim-glib/test/test-message-contents.c @@ -135,11 +135,150 @@ test_message_contents_basic_connect_device_caps (void) mbim_message_unref (response); } +static void +test_message_contents_basic_connect_ip_configuration (void) +{ + MbimMessage *response; + guint32 session_id; + MbimIPConfigurationAvailableFlag ipv4configurationavailable; + MbimIPConfigurationAvailableFlag ipv6configurationavailable; + guint32 ipv4addresscount; + MbimIPv4Element **ipv4address; + guint32 ipv6addresscount; + MbimIPv6Element **ipv6address; + const MbimIPv4 *ipv4gateway; + const MbimIPv6 *ipv6gateway; + guint32 ipv4dnsservercount; + MbimIPv4 *ipv4dnsserver; + guint32 ipv6dnsservercount; + MbimIPv6 *ipv6dnsserver; + guint32 ipv4mtu; + guint32 ipv6mtu; + GError *error = NULL; + const guint8 buffer [] = { + /* header */ + 0x03, 0x00, 0x00, 0x80, /* type */ + 0x80, 0x00, 0x00, 0x00, /* length */ + 0x1A, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0xA2, 0x89, 0xCC, 0x33, /* service id */ + 0xBC, 0xBB, 0x8B, 0x4F, + 0xB6, 0xB0, 0x13, 0x3E, + 0xC2, 0xAA, 0xE6, 0xDF, + 0x0F, 0x00, 0x00, 0x00, /* command id */ + 0x00, 0x00, 0x00, 0x00, /* status code */ + 0x50, 0x00, 0x00, 0x00, /* buffer length */ + /* information buffer */ + 0x00, 0x00, 0x00, 0x00, /* session id */ + 0x0F, 0x00, 0x00, 0x00, /* IPv4ConfigurationAvailable */ + 0x00, 0x00, 0x00, 0x00, /* IPv6ConfigurationAvailable */ + 0x01, 0x00, 0x00, 0x00, /* IPv4 element count */ + 0x3C, 0x00, 0x00, 0x00, /* IPv4 element offset */ + 0x00, 0x00, 0x00, 0x00, /* IPv6 element count */ + 0x00, 0x00, 0x00, 0x00, /* IPv6 element offset */ + 0x44, 0x00, 0x00, 0x00, /* IPv4 gateway offset */ + 0x00, 0x00, 0x00, 0x00, /* IPv6 gateway offset */ + 0x02, 0x00, 0x00, 0x00, /* IPv4 DNS count */ + 0x48, 0x00, 0x00, 0x00, /* IPv4 DNS offset */ + 0x00, 0x00, 0x00, 0x00, /* IPv6 DNS count */ + 0x00, 0x00, 0x00, 0x00, /* IPv6 DNS offset */ + 0xDC, 0x05, 0x00, 0x00, /* IPv4 MTU */ + 0x00, 0x00, 0x00, 0x00, /* IPv6 MTU */ + /* data buffer */ + 0x1C, 0x00, 0x00, 0x00, /* IPv4 element (netmask) */ + 0xD4, 0x49, 0x22, 0xF8, /* IPv4 element (address) */ + 0xD4, 0x49, 0x22, 0xF1, /* IPv4 gateway */ + 0xD4, 0xA6, 0xD2, 0x50, /* IPv4 DNS1 */ + 0xD4, 0x49, 0x20, 0x43 /* IPv4 DNS2 */ + }; + + response = mbim_message_new (buffer, sizeof (buffer)); + + g_assert (mbim_message_ip_configuration_response_parse ( + response, + &session_id, + &ipv4configurationavailable, + &ipv6configurationavailable, + &ipv4addresscount, + &ipv4address, + &ipv6addresscount, + &ipv6address, + &ipv4gateway, + &ipv6gateway, + &ipv4dnsservercount, + &ipv4dnsserver, + &ipv6dnsservercount, + &ipv6dnsserver, + &ipv4mtu, + &ipv6mtu, + &error)); + + /* + * IPv4 configuration available: 'address, gateway, dns, mtu' + * IP addresses (1) + * IP [0]: '212.166.228.25/28' + * Gateway: '212.166.228.26' + * DNS addresses (2) + * DNS [0]: '212.166.210.80' + * DNS [1]: '212.73.32.67' + * MTU: '1500' + */ + + g_assert_cmpuint (session_id, ==, 0); + g_assert_cmpuint (ipv4configurationavailable, ==, (MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS | + MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY | + MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS | + MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)); + g_assert_cmpuint (ipv6configurationavailable, ==, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE); + + { + MbimIPv4 addr = { .addr = { 0xD4, 0x49, 0x22, 0xF8 } }; + + g_assert_cmpuint (ipv4addresscount, ==, 1); + g_assert_cmpuint (ipv4address[0]->on_link_prefix_length, ==, 28); + g_assert (memcmp (&addr, &(ipv4address[0]->ipv4_address), 4) == 0); + } + + { + MbimIPv4 gateway_addr = { .addr = { 0xD4, 0x49, 0x22, 0xF1 } }; + + g_assert (memcmp (&gateway_addr, ipv4gateway, 4) == 0); + } + + { + MbimIPv4 dns_addr_1 = { .addr = { 0xD4, 0xA6, 0xD2, 0x50 } }; + MbimIPv4 dns_addr_2 = { .addr = { 0xD4, 0x49, 0x20, 0x43 } }; + + g_assert_cmpuint (ipv4dnsservercount, ==, 2); + g_assert (memcmp (&dns_addr_1, &ipv4dnsserver[0], 4) == 0); + g_assert (memcmp (&dns_addr_2, &ipv4dnsserver[1], 4) == 0); + } + + g_assert_cmpuint (ipv4mtu, ==, 1500); + + g_assert_cmpuint (ipv6addresscount, ==, 0); + g_assert (ipv6address == NULL); + g_assert (ipv6gateway == NULL); + g_assert_cmpuint (ipv6dnsservercount, ==, 0); + g_assert (ipv6dnsserver == NULL); + + mbim_ipv4_element_array_free (ipv4address); + mbim_ipv6_element_array_free (ipv6address); + g_free (ipv4dnsserver); + g_free (ipv6dnsserver); + + mbim_message_unref (response); +} + int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/libmbim-glib/message-contents/basic-connect/device-caps", test_message_contents_basic_connect_device_caps); + g_test_add_func ("/libmbim-glib/message-contents/basic-connect/ip-configuration", test_message_contents_basic_connect_ip_configuration); return g_test_run (); } |