def __emit_get_printable(self, hfile, cfile): translations = { 'service' : self.service.lower() } template = ( '\n' '#if defined (LIBQMI_GLIB_COMPILATION)\n' '\n' 'G_GNUC_INTERNAL\n' 'gchar *__qmi_message_${service}_get_printable (\n' ' QmiMessage *self,\n' ' const gchar *line_prefix);\n' '\n' '#endif\n' '\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' 'gchar *\n' '__qmi_message_${service}_get_printable (\n' ' QmiMessage *self,\n' ' const gchar *line_prefix)\n' '{\n' ' if (qmi_message_is_indication (self)) {\n' ' switch (qmi_message_get_message_id (self)) {\n') for message in self.list: if message.type == 'Indication': translations['enum_name'] = message.id_enum_name translations['message_underscore'] = utils.build_underscore_name (message.name) translations['enum_value'] = message.id inner_template = ( ' case ${enum_name}:\n' ' return indication_${message_underscore}_get_printable (self, line_prefix);\n') template += string.Template(inner_template).substitute(translations) template += ( ' default:\n' ' return NULL;\n' ' }\n' ' } else {\n' ' switch (qmi_message_get_message_id (self)) {\n') for message in self.list: if message.type == 'Message': translations['enum_name'] = message.id_enum_name translations['message_underscore'] = utils.build_underscore_name (message.name) translations['enum_value'] = message.id inner_template = ( ' case ${enum_name}:\n' ' return message_${message_underscore}_get_printable (self, line_prefix);\n') template += string.Template(inner_template).substitute(translations) template += ( ' default:\n' ' return NULL;\n' ' }\n' ' }\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def emit_getter(self, hfile, cfile): input_variable_name = utils.build_underscore_name(self.name) variable_getter_dec = self.variable.build_getter_declaration(' ', input_variable_name) variable_getter_doc = self.variable.build_getter_documentation(' * ', input_variable_name) variable_getter_imp = self.variable.build_getter_implementation(' ', 'self->' + self.variable_name, input_variable_name, True) translations = { 'name' : self.name, 'variable_name' : self.variable_name, 'variable_getter_dec' : variable_getter_dec, 'variable_getter_doc' : variable_getter_doc, 'variable_getter_imp' : variable_getter_imp, 'underscore' : utils.build_underscore_name(self.name), 'prefix_camelcase' : utils.build_camelcase_name(self.prefix), 'prefix_underscore' : utils.build_underscore_name(self.prefix), 'static' : 'static ' if self.static else '' } # Emit the getter header template = ( '\n' '${static}gboolean ${prefix_underscore}_get_${underscore} (\n' ' ${prefix_camelcase} *self,\n' '${variable_getter_dec}' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) # Emit the getter source template = ( '\n' '/**\n' ' * ${prefix_underscore}_get_${underscore}:\n' ' * @self: a #${prefix_camelcase}.\n' '${variable_getter_doc}' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Get the \'${name}\' field from @self.\n' ' *\n' ' * Returns: %TRUE if the field is found, %FALSE otherwise.\n' ' */\n' '${static}gboolean\n' '${prefix_underscore}_get_${underscore} (\n' ' ${prefix_camelcase} *self,\n' '${variable_getter_dec}' ' GError **error)\n' '{\n' ' g_return_val_if_fail (self != NULL, FALSE);\n' '\n' ' if (!self->${variable_name}_set) {\n' ' g_set_error (error,\n' ' QMI_CORE_ERROR,\n' ' QMI_CORE_ERROR_TLV_NOT_FOUND,\n' ' "Field \'${name}\' was not found in the message");\n' ' return FALSE;\n' ' }\n' '\n' '${variable_getter_imp}' '\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def emit_output_tlv_get(self, f, line_prefix): tlv_out = utils.build_underscore_name (self.fullname) + '_out' error = 'error' if self.mandatory else 'NULL' translations = { 'name' : self.name, 'container_underscore' : utils.build_underscore_name (self.prefix), 'tlv_out' : tlv_out, 'tlv_id' : self.id_enum_name, 'variable_name' : self.variable_name, 'lp' : line_prefix, 'error' : error } template = ( '${lp}gsize offset = 0;\n' '${lp}gsize init_offset;\n' '\n' '${lp}if ((init_offset = qmi_message_tlv_read_init (message, ${tlv_id}, NULL, ${error})) == 0) {\n') if self.mandatory: template += ( '${lp} g_prefix_error (${error}, "Couldn\'t get the mandatory ${name} TLV: ");\n' '${lp} ${container_underscore}_unref (self);\n' '${lp} return NULL;\n') else: template += ( '${lp} goto ${tlv_out};\n') template += ( '${lp}}\n') f.write(string.Template(template).substitute(translations)) # Now, read the contents of the buffer into the variable self.variable.emit_buffer_read(f, line_prefix, tlv_out, error, 'self->' + self.variable_name) template = ( '\n' '${lp}/* The remaining size of the buffer needs to be 0 if we successfully read the TLV */\n' '${lp}if ((offset = __qmi_message_tlv_read_remaining_size (message, init_offset, offset)) > 0) {\n' '${lp} g_warning ("Left \'%" G_GSIZE_FORMAT "\' bytes unread when getting the \'${name}\' TLV", offset);\n' '${lp}}\n' '\n' '${lp}self->${variable_name}_set = TRUE;\n' '\n' '${tlv_out}:\n') if self.mandatory: template += ( '${lp}if (!self->${variable_name}_set) {\n' '${lp} ${container_underscore}_unref (self);\n' '${lp} return NULL;\n' '${lp}}\n') else: template += ( '${lp};\n') f.write(string.Template(template).substitute(translations))
def add_sections(self, sections): translations = { 'underscore' : utils.build_underscore_name(self.name), 'prefix_camelcase' : utils.build_camelcase_name(self.prefix), 'prefix_underscore' : utils.build_underscore_name(self.prefix) } # Public methods template = ( '${prefix_underscore}_get_${underscore}\n') if self.container_type == 'Input': template += ( '${prefix_underscore}_set_${underscore}\n') sections['public-methods'] += string.Template(template).substitute(translations)
def emit_setter(self, hfile, cfile): input_variable_name = utils.build_underscore_name(self.name) variable_setter_dec = self.variable.build_setter_declaration(' ', input_variable_name) variable_setter_doc = self.variable.build_setter_documentation(' * ', input_variable_name) variable_setter_imp = self.variable.build_setter_implementation(' ', input_variable_name, 'self->' + self.variable_name) translations = { 'name' : self.name, 'variable_name' : self.variable_name, 'variable_setter_dec' : variable_setter_dec, 'variable_setter_doc' : variable_setter_doc, 'variable_setter_imp' : variable_setter_imp, 'underscore' : utils.build_underscore_name(self.name), 'prefix_camelcase' : utils.build_camelcase_name(self.prefix), 'prefix_underscore' : utils.build_underscore_name(self.prefix), 'static' : 'static ' if self.static else '' } # Emit the setter header template = ( '\n' '${static}gboolean ${prefix_underscore}_set_${underscore} (\n' ' ${prefix_camelcase} *self,\n' '${variable_setter_dec}' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) # Emit the setter source template = ( '\n' '/**\n' ' * ${prefix_underscore}_set_${underscore}:\n' ' * @self: a #${prefix_camelcase}.\n' '${variable_setter_doc}' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Set the \'${name}\' field in the message.\n' ' *\n' ' * Returns: %TRUE if @value was successfully set, %FALSE otherwise.\n' ' */\n' '${static}gboolean\n' '${prefix_underscore}_set_${underscore} (\n' ' ${prefix_camelcase} *self,\n' '${variable_setter_dec}' ' GError **error)\n' '{\n' ' g_return_val_if_fail (self != NULL, FALSE);\n' '\n' '${variable_setter_imp}' ' self->${variable_name}_set = TRUE;\n' '\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def emit_section_content(self, sfile): translations = { 'name_dashed' : utils.build_dashed_name(self.name), 'underscore' : utils.build_underscore_name(self.fullname) } template = ( '\n' '<SUBSECTION ${name_dashed}>\n') sfile.write(string.Template(template).substitute(translations)) if self.has_query: template = ( '${underscore}_query_new\n') sfile.write(string.Template(template).substitute(translations)) if self.has_set: template = ( '${underscore}_set_new\n') sfile.write(string.Template(template).substitute(translations)) if self.has_response: template = ( '${underscore}_response_parse\n') sfile.write(string.Template(template).substitute(translations)) if self.has_notification: template = ( '${underscore}_notification_parse\n') sfile.write(string.Template(template).substitute(translations))
def __init__(self, dictionary, struct_type_name, container_type): # Call the parent constructor Variable.__init__(self, dictionary) # The public format of the struct is built directly from the suggested # struct type name self.public_format = utils.build_camelcase_name(struct_type_name) self.private_format = self.public_format self.container_type = container_type # Load members of this struct self.members = [] for member_dictionary in dictionary["contents"]: member = {} member["name"] = utils.build_underscore_name(member_dictionary["name"]) member["object"] = VariableFactory.create_variable( member_dictionary, struct_type_name + " " + member["name"], self.container_type ) self.members.append(member) # We'll need to dispose if at least one of the members needs it for member in self.members: if member["object"].needs_dispose == True: self.needs_dispose = True
def clear_func_name(self): # element public format might be a base type like 'gchar *' rather # than a structure name like QmiFooBar elt_name = self.array_element.public_format.replace('*', 'pointer') return utils.build_underscore_name(self.name) + \ '_' + \ utils.build_underscore_name_from_camelcase(utils.build_camelcase_name(elt_name))
def add_sections(self, sections): translations = { 'underscore' : utils.build_underscore_name(self.name), 'prefix_camelcase' : utils.build_camelcase_name(self.prefix), 'prefix_underscore' : utils.build_underscore_name(self.prefix) } if TypeFactory.is_section_emitted(self.fullname) is False: TypeFactory.set_section_emitted(self.fullname) self.variable.add_sections(sections) # Public methods template = ( '${prefix_underscore}_get_${underscore}\n') if self.container_type == 'Input': template += ( '${prefix_underscore}_set_${underscore}\n') sections['public-methods'] += string.Template(template).substitute(translations)
def emit(self, hfile, cfile): translations = { 'name' : self.name, 'camelcase' : utils.build_camelcase_name (self.fullname), 'underscore' : utils.build_underscore_name (self.fullname), 'static' : 'static ' if self.static else '' } auxfile = cfile if self.static else hfile if self.fields is None: template = ('\n' '/* Note: no fields in the ${name} container */\n') auxfile.write(string.Template(template).substitute(translations)) cfile.write(string.Template(template).substitute(translations)) return # Emit the container and field types # Emit field getter/setter if self.fields is not None: for field in self.fields: field.emit_types(auxfile, cfile) self.__emit_types(auxfile, cfile, translations) # Emit TLV enums self.__emit_tlv_ids_enum(cfile) # Emit fields if self.fields is not None: for field in self.fields: field.emit_getter(auxfile, cfile) if self.readonly == False: field.emit_setter(auxfile, cfile) # Emit the container core self.__emit_core(auxfile, cfile, translations)
def add_sections(self, sections): if self.fields is None: return translations = { 'name' : self.name, 'camelcase' : utils.build_camelcase_name (self.fullname), 'underscore' : utils.build_underscore_name (self.fullname), 'type_macro' : 'QMI_TYPE_' + utils.remove_prefix(utils.build_underscore_uppercase_name(self.fullname), 'QMI_') } # Standard template = ( '${underscore}_get_type\n' '${type_macro}\n') sections['standard'] += string.Template(template).substitute(translations) # Public types template = ( '${camelcase}\n') sections['public-types'] += string.Template(template).substitute(translations) # Public methods template = '<SUBSECTION ${camelcase}Methods>\n' if self.readonly == False: template += ( '${underscore}_new\n') template += ( '${underscore}_ref\n' '${underscore}_unref\n') sections['public-methods'] += string.Template(template).substitute(translations) for field in self.fields: field.add_sections(sections)
def __init__(self, prefix, dictionary, common_objects_dictionary, container_type, static): # The field prefix, usually the name of the Container, # e.g. "Qmi Message Ctl Something Output" self.prefix = prefix # The name of the specific field, e.g. "Result" self.name = dictionary['name'] # The specific TLV ID self.id = dictionary['id'] # Whether the field is to be considered mandatory in the message self.mandatory = True if dictionary['mandatory'] == 'yes' else False # The type, which must always be "TLV" self.type = dictionary['type'] # The container type, which must be either "Input" or "Output" self.container_type = container_type # Whether the whole field is internally used only self.static = static # Create the composed full name (prefix + name), # e.g. "Qmi Message Ctl Something Output Result" self.fullname = dictionary['fullname'] if 'fullname' in dictionary else self.prefix + ' ' + self.name # Create our variable object self.variable = VariableFactory.create_variable(dictionary, self.fullname, self.container_type) # Create the variable name within the Container self.variable_name = 'arg_' + utils.build_underscore_name(self.name).lower() # Create the ID enumeration name self.id_enum_name = utils.build_underscore_name(self.prefix + ' TLV ' + self.name).upper() # Output Fields may have prerequisites self.prerequisites = [] if 'prerequisites' in dictionary: self.prerequisites = dictionary['prerequisites'] # First, look for references to common types for prerequisite_dictionary in self.prerequisites: if 'common-ref' in prerequisite_dictionary: for common in common_objects_dictionary: if common['type'] == 'prerequisite' and \ common['common-ref'] == prerequisite_dictionary['common-ref']: # Replace the reference with a copy of the common dictionary copy = dict(common) self.prerequisites.remove(prerequisite_dictionary) self.prerequisites.append(copy) break else: raise RuntimeError('Common type \'%s\' not found' % prerequisite_dictionary['name'])
def emit_sections(self, sfile): if self.static: return translations = { 'hyphened' : utils.build_dashed_name (self.fullname), 'fullname_underscore' : utils.build_underscore_name(self.fullname), 'camelcase' : utils.build_camelcase_name (self.fullname), 'service' : utils.build_underscore_name (self.service), 'name_underscore' : utils.build_underscore_name (self.name), 'fullname' : self.service + ' ' + self.name, 'type' : 'response' if self.type == 'Message' else 'indication' } sections = { 'public-types' : '', 'public-methods' : '', 'standard' : '', 'private' : '' } if self.input: self.input.add_sections (sections) self.output.add_sections (sections) if self.type == 'Message': template = ( '<SUBSECTION ${camelcase}ClientMethods>\n' 'qmi_client_${service}_${name_underscore}\n' 'qmi_client_${service}_${name_underscore}_finish\n') sections['public-methods'] += string.Template(template).substitute(translations) translations['public_types'] = sections['public-types'] translations['public_methods'] = sections['public-methods'] translations['standard'] = sections['standard'] translations['private'] = sections['private'] template = ( '<SECTION>\n' '<FILE>${hyphened}</FILE>\n' '<TITLE>${fullname}</TITLE>\n' '${public_types}' '${public_methods}' '<SUBSECTION Private>\n' '${private}' '<SUBSECTION Standard>\n' '${standard}' '</SECTION>\n' '\n') sfile.write(string.Template(template).substitute(translations))
def emit_output_tlv_get(self, f, line_prefix): translations = { 'name' : self.name, 'container_underscore' : utils.build_underscore_name (self.prefix), 'underscore' : utils.build_underscore_name (self.fullname), 'tlv_id' : self.id_enum_name, 'variable_name' : self.variable_name, 'lp' : line_prefix, 'error' : 'error' if self.mandatory == 'yes' else 'NULL'} template = ( '${lp}const guint8 *buffer;\n' '${lp}guint16 buffer_len;\n' '\n' '${lp}buffer = qmi_message_get_raw_tlv (message,\n' '${lp} ${tlv_id},\n' '${lp} &buffer_len);\n' '${lp}if (buffer && ${underscore}_validate (buffer, buffer_len)) {\n' '${lp} self->${variable_name}_set = TRUE;\n' '\n') f.write(string.Template(template).substitute(translations)) # Now, read the contents of the buffer into the variable self.variable.emit_buffer_read(f, line_prefix + ' ', 'self->' + self.variable_name, 'buffer', 'buffer_len') template = ( '\n' '${lp} /* The remaining size of the buffer needs to be 0 if we successfully read the TLV */\n' '${lp} if (buffer_len > 0) {\n' '${lp} g_warning ("Left \'%u\' bytes unread when getting the \'${name}\' TLV", buffer_len);\n' '${lp} }\n') if self.mandatory == 'yes': template += ( '${lp}} else {\n' '${lp} g_set_error (error,\n' '${lp} QMI_CORE_ERROR,\n' '${lp} QMI_CORE_ERROR_TLV_NOT_FOUND,\n' '${lp} \"Couldn\'t get the ${name} TLV: Not found\");\n' '${lp} ${container_underscore}_unref (self);\n' '${lp} return NULL;\n' '${lp}}\n') else: template += ( '${lp}}\n') f.write(string.Template(template).substitute(translations))
def __emit_response_or_indication_parser(self, hfile, cfile): # If no output fields to parse, don't emit anything if self.output is None or self.output.fields is None: return translations = { 'name' : self.name, 'type' : 'response' if self.type == 'Message' else 'indication', 'container' : utils.build_camelcase_name (self.output.fullname), 'container_underscore' : utils.build_underscore_name (self.output.fullname), 'underscore' : utils.build_underscore_name (self.fullname), 'message_id' : self.id_enum_name } template = ( '\n' 'static ${container} *\n' '__${underscore}_${type}_parse (\n' ' QmiMessage *message,\n' ' GError **error)\n' '{\n' ' ${container} *self;\n' '\n' ' g_return_val_if_fail (qmi_message_get_message_id (message) == ${message_id}, NULL);\n' '\n' ' self = g_slice_new0 (${container});\n' ' self->ref_count = 1;\n') cfile.write(string.Template(template).substitute(translations)) for field in self.output.fields: cfile.write( '\n' ' do {\n') field.emit_output_prerequisite_check(cfile, ' ') cfile.write( '\n' ' {\n') field.emit_output_tlv_get(cfile, ' ') cfile.write( '\n' ' }\n') cfile.write( ' } while (0);\n') cfile.write( '\n' ' return self;\n' '}\n')
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'] # 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 if self.service == 'Basic Connect': self.fullname = 'MBIM Message ' + self.name elif self.name == "": self.fullname = 'MBIM Message ' + self.service else: self.fullname = 'MBIM Message ' + self.service + ' ' + self.name # Build CID enum self.cid_enum_name = 'MBIM CID ' + self.service if self.name != "": self.cid_enum_name += (' ' + self.name) self.cid_enum_name = utils.build_underscore_name(self.cid_enum_name).upper()
def emit_getter(self, hfile, cfile): translations = { 'variable_name' : self.variable_name, 'prefix_camelcase' : utils.build_camelcase_name(self.prefix), 'prefix_underscore' : utils.build_underscore_name(self.prefix) } # Emit the getter header template = ( '\n' 'gboolean ${prefix_underscore}_get_result (\n' ' ${prefix_camelcase} *self,\n' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) # Emit the getter source template = ( '\n' '/**\n' ' * ${prefix_underscore}_get_result:\n' ' * @self: a ${prefix_camelcase}.\n' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Get the result of the QMI operation.\n' ' *\n' ' * Returns: %TRUE if the QMI operation succeeded, %FALSE if @error is set.\n' ' */\n' 'gboolean\n' '${prefix_underscore}_get_result (\n' ' ${prefix_camelcase} *self,\n' ' GError **error)\n' '{\n' ' g_return_val_if_fail (self != NULL, FALSE);\n' '\n' ' /* We should always have a result set in the response message */\n' ' if (!self->${variable_name}_set) {\n' ' g_set_error (error,\n' ' QMI_CORE_ERROR,\n' ' QMI_CORE_ERROR_INVALID_MESSAGE,\n' ' "No \'Result\' field given in the message");\n' ' return FALSE;\n' ' }\n' '\n' ' if (self->${variable_name}.error_status == QMI_STATUS_SUCCESS) {\n' ' /* Operation succeeded */\n' ' return TRUE;\n' ' }\n' '\n' ' /* Report a QMI protocol error */\n' ' g_set_error (error,\n' ' QMI_PROTOCOL_ERROR,\n' ' (QmiProtocolError) self->${variable_name}.error_code,\n' ' "QMI protocol error (%u): \'%s\'",\n' ' self->${variable_name}.error_code,\n' ' qmi_protocol_error_get_string ((QmiProtocolError) self->${variable_name}.error_code));\n' ' return FALSE;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def emit_size_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'variable_name' : variable_name, 'buffer_name' : buffer_name, 'buffer_len' : buffer_len, 'common_var_prefix' : common_var_prefix } template = ( '${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size: translations['fixed_size'] = self.fixed_size template = ( '${lp} guint16 ${common_var_prefix}_n_items = ${fixed_size};\n' '\n') f.write(string.Template(template).substitute(translations)) else: translations['array_size_element_format'] = self.array_size_element.public_format if self.array_size_element.public_format == 'guint8': translations['array_size_element_size'] = '1' elif self.array_size_element.public_format == 'guint16': translations['array_size_element_size'] = '2' elif self.array_size_element.public_format == 'guint32': translations['array_size_element_size'] = '4' else: translations['array_size_element_size'] = '0' template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n' '${lp} const guint8 *${common_var_prefix}_aux_buffer = &${buffer_name}[${variable_name}];\n' '${lp} guint16 ${common_var_prefix}_aux_buffer_len = ${buffer_len} - ${variable_name};\n' '\n' '${lp} ${variable_name} += ${array_size_element_size};\n' '\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_read(f, line_prefix + ' ', common_var_prefix + '_n_items', common_var_prefix + '_aux_buffer', common_var_prefix + '_aux_buffer_len') template = ( '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${common_var_prefix}_n_items; ${common_var_prefix}_i++) {\n' '\n') f.write(string.Template(template).substitute(translations)) self.array_element.emit_size_read(f, line_prefix + ' ', variable_name, buffer_name, buffer_len) template = ( '${lp} }\n' '${lp}}\n') f.write(string.Template(template).substitute(translations))
def emit_sections(self, sfile): translations = { 'underscore' : utils.build_underscore_name(self.name), 'no_prefix_underscore_upper' : utils.build_underscore_name(self.name[4:]).upper(), 'camelcase' : utils.build_camelcase_name (self.name), 'hyphened' : utils.build_dashed_name (self.name) } template = ( '<SECTION>\n' '<FILE>${hyphened}</FILE>\n' '<TITLE>${camelcase}</TITLE>\n' '${camelcase}\n' '<SUBSECTION Standard>\n' '${camelcase}Class\n' 'QMI_TYPE_${no_prefix_underscore_upper}\n' 'QMI_${no_prefix_underscore_upper}\n' 'QMI_${no_prefix_underscore_upper}_CLASS\n' 'QMI_IS_${no_prefix_underscore_upper}\n' 'QMI_IS_${no_prefix_underscore_upper}_CLASS\n' 'QMI_${no_prefix_underscore_upper}_GET_CLASS\n' '${underscore}_get_type\n' '</SECTION>\n' '\n') sfile.write(string.Template(template).substitute(translations))
def emit_output_prerequisite_check(self, f, line_prefix): if self.prerequisites == []: f.write('%s/* No Prerequisites for field */\n' % line_prefix) return for prerequisite in self.prerequisites: translations = { 'lp' : line_prefix, 'prerequisite_field' : utils.build_underscore_name(prerequisite['field']), 'prerequisite_operation' : prerequisite['operation'], 'prerequisite_value' : prerequisite['value'] } template = ( '${lp}/* Prerequisite.... */\n' '${lp}if (!(self->arg_${prerequisite_field} ${prerequisite_operation} ${prerequisite_value}))\n' '${lp} break;\n') f.write(string.Template(template).substitute(translations))
def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'printable' : printable, 'buffer_name' : buffer_name, 'buffer_len' : buffer_len, 'common_var_prefix' : common_var_prefix } template = ( '${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size: translations['fixed_size'] = self.fixed_size template = ( '${lp} guint16 ${common_var_prefix}_n_items = ${fixed_size};\n' '\n') f.write(string.Template(template).substitute(translations)) else: translations['array_size_element_format'] = self.array_size_element.public_format template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n' '\n' '${lp} /* Read number of items in the array */\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_read(f, line_prefix + ' ', common_var_prefix + '_n_items', buffer_name, buffer_len) template = ( '\n' '${lp} g_string_append (${printable}, "{");\n' '\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${common_var_prefix}_n_items; ${common_var_prefix}_i++) {\n' '${lp} g_string_append_printf (${printable}, " [%u] = \'", ${common_var_prefix}_i);\n') f.write(string.Template(template).substitute(translations)) self.array_element.emit_get_printable(f, line_prefix + ' ', printable, buffer_name, buffer_len); template = ( '${lp} g_string_append (${printable}, " \'");\n' '${lp} }\n' '\n' '${lp} g_string_append (${printable}, "}");\n' '${lp}}') f.write(string.Template(template).substitute(translations))
def __init__(self, dictionary, common_objects_dictionary): # The message service, e.g. "Ctl" self.service = dictionary['service'] # The name of the specific message, e.g. "Something" self.name = dictionary['name'] # The specific message ID self.id = dictionary['id'] # The type, which must always be 'Message' or 'Indication' self.type = dictionary['type'] # The version info, optional self.version_info = dictionary['version'].split( '.') if 'version' in dictionary else [] self.static = True if 'scope' in dictionary and dictionary[ 'scope'] == 'library-only' else False self.abort = True if 'abort' in dictionary and dictionary[ 'abort'] == 'yes' else False # The message prefix self.prefix = 'Qmi ' + self.type # Create the composed full name (prefix + service + name), # e.g. "Qmi Message Ctl Something" self.fullname = self.prefix + ' ' + self.service + ' ' + self.name # Create the ID enumeration name self.id_enum_name = utils.build_underscore_name(self.fullname).upper() # Build output container. # Every defined message will have its own output container, which # will generate a new Output type and public getters for each output # field. This applies to both Request/Response and Indications. # Output containers are actually optional in Indications self.output = Container( self.fullname, 'Output', dictionary['output'] if 'output' in dictionary else None, common_objects_dictionary, self.static) self.input = None if self.type == 'Message': # Build input container (Request/Response only). # Every defined message will have its own input container, which # will generate a new Input type and public getters for each input # field self.input = Container( self.fullname, 'Input', dictionary['input'] if 'input' in dictionary else None, common_objects_dictionary, self.static)
def emit_tlv_helpers(self, f): if TypeFactory.helpers_emitted(self.fullname): return TypeFactory.set_helpers_emitted(self.fullname) translations = { 'name': self.name, 'tlv_id': self.id_enum_name, 'underscore': utils.build_underscore_name(self.fullname) } template = ( '\n' 'static gchar *\n' '${underscore}_get_printable (\n' ' QmiMessage *message,\n' ' const gchar *line_prefix)\n' '{\n' ' gsize offset = 0;\n' ' gsize init_offset;\n' ' GString *printable;\n' ' GError *error = NULL;\n' '\n' ' if ((init_offset = qmi_message_tlv_read_init (message, ${tlv_id}, NULL, NULL)) == 0)\n' ' return NULL;\n' '\n' ' printable = g_string_new ("");\n') f.write(string.Template(template).substitute(translations)) # Now, read the contents of the buffer into the printable representation self.variable.emit_get_printable(f, ' ') template = ( '\n' ' if ((offset = qmi_message_tlv_read_remaining_size (message, init_offset, offset)) > 0)\n' ' g_string_append_printf (printable, "Additional unexpected \'%" G_GSIZE_FORMAT "\' bytes", offset);\n' '\n' 'out:\n' ' if (error) {\n' ' g_string_append_printf (printable, " ERROR: %s", error->message);\n' ' g_error_free (error);\n' ' }\n' ' return g_string_free (printable, FALSE);\n' '}\n') f.write(string.Template(template).substitute(translations))
def __init__(self, dictionary, common_objects_dictionary): # The message service, e.g. "Ctl" self.service = dictionary['service'] # The name of the specific message, e.g. "Something" self.name = dictionary['name'] # The specific message ID self.id = dictionary['id'] # The type, which must always be 'Message' or 'Indication' self.type = dictionary['type'] # The version info, optional self.version_info = dictionary['version'].split('.') if 'version' in dictionary else [] self.static = True if 'scope' in dictionary and dictionary['scope'] == 'library-only' else False self.abort = True if 'abort' in dictionary and dictionary['abort'] == 'yes' else False # The message prefix self.prefix = 'Qmi ' + self.type # Create the composed full name (prefix + service + name), # e.g. "Qmi Message Ctl Something" self.fullname = self.prefix + ' ' + self.service + ' ' + self.name # Create the ID enumeration name self.id_enum_name = utils.build_underscore_name(self.fullname).upper() # Build output container. # Every defined message will have its own output container, which # will generate a new Output type and public getters for each output # field. This applies to both Request/Response and Indications. # Output containers are actually optional in Indications self.output = Container(self.fullname, 'Output', dictionary['output'] if 'output' in dictionary else None, common_objects_dictionary, self.static) self.input = None if self.type == 'Message': # Build input container (Request/Response only). # Every defined message will have its own input container, which # will generate a new Input type and public getters for each input # field self.input = Container(self.fullname, 'Input', dictionary['input'] if 'input' in dictionary else None, common_objects_dictionary, self.static)
def emit_buffer_write(self, f, line_prefix, tlv_name, variable_name): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp': line_prefix, 'variable_name': variable_name, 'common_var_prefix': common_var_prefix } template = ('${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size == 0: translations[ 'array_size_element_format'] = self.array_size_element.private_format template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n' '\n' '${lp} /* Write the number of items in the array first */\n' '${lp} ${common_var_prefix}_n_items = (${array_size_element_format}) ${variable_name}->len;\n' ) f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_write( f, line_prefix + ' ', tlv_name, common_var_prefix + '_n_items') if self.array_sequence_element != '': self.array_sequence_element.emit_buffer_write( f, line_prefix + ' ', tlv_name, variable_name + '_sequence') template = ( '\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${variable_name}->len; ${common_var_prefix}_i++) {\n' ) f.write(string.Template(template).substitute(translations)) self.array_element.emit_buffer_write( f, line_prefix + ' ', tlv_name, 'g_array_index (' + variable_name + ', ' + self.array_element.public_format + ',' + common_var_prefix + '_i)') template = ('${lp} }\n' '${lp}}\n') f.write(string.Template(template).substitute(translations))
def emit_tlv_helpers(self, f): if TypeFactory.helpers_emitted(self.fullname): return TypeFactory.set_helpers_emitted(self.fullname) translations = { 'name' : self.name, 'tlv_id' : self.id_enum_name, 'underscore' : utils.build_underscore_name (self.fullname) } template = ( '\n' 'static gchar *\n' '${underscore}_get_printable (\n' ' QmiMessage *message,\n' ' const gchar *line_prefix)\n' '{\n' ' gsize offset = 0;\n' ' gsize init_offset;\n' ' GString *printable;\n' ' GError *error = NULL;\n' '\n' ' if ((init_offset = qmi_message_tlv_read_init (message, ${tlv_id}, NULL, NULL)) == 0)\n' ' return NULL;\n' '\n' ' printable = g_string_new ("");\n') f.write(string.Template(template).substitute(translations)) # Now, read the contents of the buffer into the printable representation self.variable.emit_get_printable(f, ' ') template = ( '\n' ' if ((offset = __qmi_message_tlv_read_remaining_size (message, init_offset, offset)) > 0)\n' ' g_string_append_printf (printable, "Additional unexpected \'%" G_GSIZE_FORMAT "\' bytes", offset);\n' '\n' 'out:\n' ' if (error)\n' ' g_string_append_printf (printable, " ERROR: %s", error->message);\n' ' return g_string_free (printable, FALSE);\n' '}\n') f.write(string.Template(template).substitute(translations))
def __init__(self, dictionary, sequence_type_name, container_type): # Call the parent constructor Variable.__init__(self, dictionary) self.container_type = container_type # Load members of this sequence self.members = [] for member_dictionary in dictionary['contents']: member = {} member['name'] = utils.build_underscore_name(member_dictionary['name']) member['object'] = VariableFactory.create_variable(member_dictionary, sequence_type_name + ' ' + member['name'], self.container_type) self.members.append(member) # TODO: do we need this? # We'll need to dispose if at least one of the members needs it for member in self.members: if member['object'].needs_dispose == True: self.needs_dispose = True
def __init__(self, dictionary, sequence_type_name, container_type): # Call the parent constructor Variable.__init__(self, dictionary) self.container_type = container_type # Load members of this sequence self.members = [] for member_dictionary in dictionary['contents']: member = {} member['name'] = utils.build_underscore_name(member_dictionary['name']) member['object'] = VariableFactory.create_variable(member_dictionary, sequence_type_name + ' ' + member_dictionary['name'], self.container_type) self.members.append(member) # TODO: do we need this? # We'll need to dispose if at least one of the members needs it for member in self.members: if member['object'].needs_dispose == True: self.needs_dispose = True
def emit_output_prerequisite_check(self, f, line_prefix): if self.prerequisites == []: f.write('%s/* No Prerequisites for field */\n' % line_prefix) return for prerequisite in self.prerequisites: translations = { 'lp': line_prefix, 'prerequisite_field': utils.build_underscore_name(prerequisite['field']), 'prerequisite_operation': prerequisite['operation'], 'prerequisite_value': prerequisite['value'] } template = ( '${lp}/* Prerequisite.... */\n' '${lp}if (!(self->arg_${prerequisite_field} ${prerequisite_operation} ${prerequisite_value}))\n' '${lp} break;\n') f.write(string.Template(template).substitute(translations))
def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'variable_name' : variable_name, 'buffer_name' : buffer_name, 'buffer_len' : buffer_len, 'common_var_prefix' : common_var_prefix } template = ( '${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size == 0: translations['array_size_element_format'] = self.array_size_element.private_format template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n' '\n' '${lp} /* Write the number of items in the array first */\n' '${lp} ${common_var_prefix}_n_items = (${array_size_element_format}) ${variable_name}->len;\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_write(f, line_prefix + ' ', common_var_prefix + '_n_items', buffer_name, buffer_len) if self.array_sequence_element != '': self.array_sequence_element.emit_buffer_write(f, line_prefix + ' ', variable_name + '_sequence', buffer_name, buffer_len) template = ( '\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${variable_name}->len; ${common_var_prefix}_i++) {\n') f.write(string.Template(template).substitute(translations)) self.array_element.emit_buffer_write(f, line_prefix + ' ', 'g_array_index (' + variable_name + ', ' + self.array_element.public_format + ',' + common_var_prefix + '_i)', buffer_name, buffer_len) template = ( '${lp} }\n' '${lp}}\n') f.write(string.Template(template).substitute(translations))
def emit(self, hfile, cfile): translations = { 'name': self.name, 'camelcase': utils.build_camelcase_name(self.fullname), 'underscore': utils.build_underscore_name(self.fullname), 'since': self.since, 'static': 'static ' if self.static else '' } auxfile = cfile if self.static else hfile if self.fields is None: template = ('\n' '/* Note: no fields in the ${name} container */\n') auxfile.write(string.Template(template).substitute(translations)) cfile.write(string.Template(template).substitute(translations)) return # Emit the container and field types # Emit field getter/setter if self.fields is not None: for field in self.fields: field.emit_types(auxfile, cfile) self.__emit_types(auxfile, cfile, translations) # Emit TLV enums self.__emit_tlv_ids_enum(cfile) # Emit fields if self.fields is not None: for field in self.fields: field.emit_getter(auxfile, cfile) if self.readonly == False: field.emit_setter(auxfile, cfile) # Emit the container core self.__emit_core(auxfile, cfile, translations)
def emit_section_content(self, sfile): translations = { 'name_dashed': utils.build_dashed_name(self.name), 'underscore': utils.build_underscore_name(self.fullname) } template = ('\n' '<SUBSECTION ${name_dashed}>\n') sfile.write(string.Template(template).substitute(translations)) if self.has_query: template = ('${underscore}_query_new\n') sfile.write(string.Template(template).substitute(translations)) if self.has_set: template = ('${underscore}_set_new\n') sfile.write(string.Template(template).substitute(translations)) if self.has_response: template = ('${underscore}_response_parse\n') sfile.write(string.Template(template).substitute(translations)) if self.has_notification: template = ('${underscore}_notification_parse\n') sfile.write(string.Template(template).substitute(translations))
def add_sections(self, sections): if self.fields is None: return translations = { 'name': self.name, 'camelcase': utils.build_camelcase_name(self.fullname), 'underscore': utils.build_underscore_name(self.fullname), 'type_macro': 'QMI_TYPE_' + utils.remove_prefix( utils.build_underscore_uppercase_name(self.fullname), 'QMI_') } # Standard template = ('${underscore}_get_type\n' '${type_macro}\n') sections['standard'] += string.Template(template).substitute( translations) # Public types template = ('${camelcase}\n') sections['public-types'] += string.Template(template).substitute( translations) # Public methods template = '<SUBSECTION ${camelcase}Methods>\n' if self.readonly == False: template += ('${underscore}_new\n') template += ('${underscore}_ref\n' '${underscore}_unref\n') sections['public-methods'] += string.Template(template).substitute( translations) for field in self.fields: field.add_sections(sections)
def __init__(self, prefix, dictionary, common_objects_dictionary, container_type, static): # The field prefix, usually the name of the Container, # e.g. "Qmi Message Ctl Something Output" self.prefix = prefix # The name of the specific field, e.g. "Result" self.name = dictionary['name'] # The specific TLV ID self.id = dictionary['id'] # Overridden mandatory field, the default is calculated from id self._mandatory = dictionary.get('mandatory') # The type, which must always be "TLV" self.type = dictionary['type'] # The container type, which must be either "Input" or "Output" self.container_type = container_type # Whether the whole field is internally used only self.static = static # Create the composed full name (prefix + name), # e.g. "Qmi Message Ctl Something Output Result" self.fullname = dictionary[ 'fullname'] if 'fullname' in dictionary else self.prefix + ' ' + self.name # libqmi version where the message was introduced self.since = dictionary['since'] if 'since' in dictionary else None if self.since is None: raise ValueError( 'TLV ' + self.fullname + ' requires a "since" tag specifying the major version where it was introduced' ) # Create our variable object self.variable = VariableFactory.create_variable( dictionary, self.fullname, self.container_type) # Create the variable name within the Container self.variable_name = 'arg_' + utils.build_underscore_name( self.name).lower() # Create the ID enumeration name self.id_enum_name = utils.build_underscore_name(self.prefix + ' TLV ' + self.name).upper() # Output Fields may have prerequisites self.prerequisites = [] if 'prerequisites' in dictionary: self.prerequisites = dictionary['prerequisites'] # First, look for references to common types for prerequisite_dictionary in self.prerequisites: if 'common-ref' in prerequisite_dictionary: for common in common_objects_dictionary: if common['type'] == 'prerequisite' and \ common['common-ref'] == prerequisite_dictionary['common-ref']: # Replace the reference with a copy of the common dictionary copy = dict(common) self.prerequisites.remove(prerequisite_dictionary) self.prerequisites.append(copy) break else: raise RuntimeError('Common type \'%s\' not found' % prerequisite_dictionary['name'])
def __emit_helpers(self, hfile, cfile): need_tlv_printable = False if self.input is not None and self.input.fields is not None: need_tlv_printable = True for field in self.input.fields: field.emit_tlv_helpers(cfile) if self.output is not None and self.output.fields is not None: need_tlv_printable = True for field in self.output.fields: field.emit_tlv_helpers(cfile) translations = { 'name': self.name, 'service': self.service, 'id': self.id, 'type': utils.build_underscore_name(self.type), 'underscore': utils.build_underscore_name(self.name) } template = '' if need_tlv_printable: template += ('\n' 'struct ${type}_${underscore}_context {\n' ' QmiMessage *self;\n' ' const gchar *line_prefix;\n' ' GString *printable;\n' '};\n' '\n' 'static void\n' '${type}_${underscore}_get_tlv_printable (\n' ' guint8 type,\n' ' const guint8 *value,\n' ' gsize length,\n' ' struct ${type}_${underscore}_context *ctx)\n' '{\n' ' const gchar *tlv_type_str = NULL;\n' ' gchar *translated_value;\n' '\n') if self.type == 'Message': template += ( ' if (!qmi_message_is_response (ctx->self)) {\n' ' switch (type) {\n') if self.input is not None and self.input.fields is not None: for field in self.input.fields: translations[ 'underscore_field'] = utils.build_underscore_name( field.fullname) translations['field_enum'] = field.id_enum_name translations['field_name'] = field.name field_template = ( ' case ${field_enum}:\n' ' tlv_type_str = "${field_name}";\n' ' translated_value = ${underscore_field}_get_printable (\n' ' ctx->self,\n' ' ctx->line_prefix);\n' ' break;\n') template += string.Template(field_template).substitute( translations) template += (' default:\n' ' break;\n' ' }\n' ' } else {\n') else: template += (' {\n') template += (' switch (type) {\n') if self.output is not None and self.output.fields is not None: for field in self.output.fields: translations[ 'underscore_field'] = utils.build_underscore_name( field.fullname) translations['field_enum'] = field.id_enum_name translations['field_name'] = field.name field_template = ( ' case ${field_enum}:\n' ' tlv_type_str = "${field_name}";\n' ' translated_value = ${underscore_field}_get_printable (\n' ' ctx->self,\n' ' ctx->line_prefix);\n' ' break;\n') template += string.Template(field_template).substitute( translations) template += ( ' default:\n' ' break;\n' ' }\n' ' }\n' '\n' ' if (!tlv_type_str) {\n' ' gchar *value_str = NULL;\n' '\n' ' value_str = qmi_message_get_tlv_printable (ctx->self,\n' ' ctx->line_prefix,\n' ' type,\n' ' value,\n' ' length);\n' ' g_string_append (ctx->printable, value_str);\n' ' g_free (value_str);\n' ' } else {\n' ' gchar *value_hex;\n' '\n' ' value_hex = __qmi_utils_str_hex (value, length, \':\');\n' ' g_string_append_printf (ctx->printable,\n' ' "%sTLV:\\n"\n' ' "%s type = \\"%s\\" (0x%02x)\\n"\n' ' "%s length = %" G_GSIZE_FORMAT "\\n"\n' ' "%s value = %s\\n"\n' ' "%s translated = %s\\n",\n' ' ctx->line_prefix,\n' ' ctx->line_prefix, tlv_type_str, type,\n' ' ctx->line_prefix, length,\n' ' ctx->line_prefix, value_hex,\n' ' ctx->line_prefix, translated_value ? translated_value : "");\n' ' g_free (value_hex);\n' ' g_free (translated_value);\n' ' }\n' '}\n') template += ( '\n' 'static gchar *\n' '${type}_${underscore}_get_printable (\n' ' QmiMessage *self,\n' ' const gchar *line_prefix)\n' '{\n' ' GString *printable;\n' '\n' ' printable = g_string_new ("");\n' ' g_string_append_printf (printable,\n' ' "%s message = \\\"${name}\\\" (${id})\\n",\n' ' line_prefix);\n') if need_tlv_printable: template += ( '\n' ' {\n' ' struct ${type}_${underscore}_context ctx;\n' ' ctx.self = self;\n' ' ctx.line_prefix = line_prefix;\n' ' ctx.printable = printable;\n' ' qmi_message_foreach_raw_tlv (self,\n' ' (QmiMessageForeachRawTlvFn)${type}_${underscore}_get_tlv_printable,\n' ' &ctx);\n' ' }\n') template += ('\n' ' return g_string_free (printable, FALSE);\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def __init__(self, dictionary, common_objects_dictionary): # The message service, e.g. "Ctl" self.service = dictionary['service'] # The name of the specific message, e.g. "Something" self.name = dictionary['name'] # The specific message ID self.id = dictionary['id'] # The type, which must always be 'Message' or 'Indication' self.type = dictionary['type'] # The message version info is no longer supported if 'version' in dictionary: raise ValueError('The "version" tag is no longer supported') self.static = True if 'scope' in dictionary and dictionary['scope'] == 'library-only' else False self.abort = True if 'abort' in dictionary and dictionary['abort'] == 'yes' else False # libqmi version where the message was introduced self.since = dictionary['since'] if 'since' in dictionary else None if self.since is None: raise ValueError('Message ' + self.name + ' requires a "since" tag specifying the major version where it was introduced') # The vendor id if this command is vendor specific self.vendor = dictionary['vendor'] if 'vendor' in dictionary else None if self.type == 'Indication' and self.vendor is not None: raise ValueError('Vendor-specific indications unsupported') # The message prefix self.prefix = 'Qmi ' + self.type # Create the composed full name (prefix + service + name), # e.g. "Qmi Message Ctl Something" self.fullname = self.prefix + ' ' + self.service + ' ' + self.name # Create the ID enumeration name self.id_enum_name = utils.build_underscore_name(self.fullname).upper() # Create the build symbol name self.build_symbol = 'HAVE_' + self.id_enum_name # Build output container. # Every defined message will have its own output container, which # will generate a new Output type and public getters for each output # field. This applies to both Request/Response and Indications. # Output containers are actually optional in Indications self.output = Container(self.fullname, 'Output', dictionary['output'] if 'output' in dictionary else None, common_objects_dictionary, self.static, self.since) self.input = None if self.type == 'Message': # Build input container (Request/Response only). # Every defined message will have its own input container, which # will generate a new Input type and public getters for each input # field self.input = Container(self.fullname, 'Input', dictionary['input'] if 'input' in dictionary else None, common_objects_dictionary, self.static, self.since)
def emit_getter(self, hfile, cfile): translations = { 'variable_name': self.variable_name, 'prefix_camelcase': utils.build_camelcase_name(self.prefix), 'prefix_underscore': utils.build_underscore_name(self.prefix), 'since': self.since } # Emit the getter header template = '\n' if self.static == False: template += ( '\n' '/**\n' ' * ${prefix_underscore}_get_result:\n' ' * @self: a ${prefix_camelcase}.\n' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Get the result of the QMI operation.\n' ' *\n' ' * Returns: (skip): %TRUE if the QMI operation succeeded, %FALSE if @error is set.\n' ' *\n' ' * Since: ${since}\n' ' */\n') template += ('gboolean ${prefix_underscore}_get_result (\n' ' ${prefix_camelcase} *self,\n' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) # Emit the getter source template = ( '\n' 'gboolean\n' '${prefix_underscore}_get_result (\n' ' ${prefix_camelcase} *self,\n' ' GError **error)\n' '{\n' ' g_return_val_if_fail (self != NULL, FALSE);\n' '\n' ' /* We should always have a result set in the response message */\n' ' if (!self->${variable_name}_set) {\n' ' g_set_error (error,\n' ' QMI_CORE_ERROR,\n' ' QMI_CORE_ERROR_INVALID_MESSAGE,\n' ' "No \'Result\' field given in the message");\n' ' return FALSE;\n' ' }\n' '\n' ' if (self->${variable_name}.error_status == QMI_STATUS_SUCCESS) {\n' ' /* Operation succeeded */\n' ' return TRUE;\n' ' }\n' '\n' ' /* Report a QMI protocol error */\n' ' g_set_error (error,\n' ' QMI_PROTOCOL_ERROR,\n' ' (QmiProtocolError) self->${variable_name}.error_code,\n' ' "QMI protocol error (%u): \'%s\'",\n' ' self->${variable_name}.error_code,\n' ' qmi_protocol_error_get_string ((QmiProtocolError) self->${variable_name}.error_code));\n' ' return FALSE;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def __emit_class(self, hfile, cfile, message_list): # Check if we'll have indications has_indications = False for message in message_list.list: if message.type == 'Indication': has_indications = True break translations = { 'underscore': utils.build_underscore_name(self.name), 'no_prefix_underscore_upper': utils.build_underscore_name(self.name[4:]).upper(), 'camelcase': utils.build_camelcase_name(self.name), 'hyphened': utils.build_dashed_name(self.name), 'service': self.service.upper() } # Emit class header template = ( '#define QMI_TYPE_${no_prefix_underscore_upper} (${underscore}_get_type ())\n' '#define QMI_${no_prefix_underscore_upper}(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), QMI_TYPE_${no_prefix_underscore_upper}, ${camelcase}))\n' '#define QMI_${no_prefix_underscore_upper}_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), QMI_TYPE_${no_prefix_underscore_upper}, ${camelcase}Class))\n' '#define QMI_IS_${no_prefix_underscore_upper}(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), QMI_TYPE_${no_prefix_underscore_upper}))\n' '#define QMI_IS_${no_prefix_underscore_upper}_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), QMI_TYPE_${no_prefix_underscore_upper}))\n' '#define QMI_${no_prefix_underscore_upper}_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), QMI_TYPE_${no_prefix_underscore_upper}, ${camelcase}Class))\n' '\n' 'typedef struct _${camelcase} ${camelcase};\n' 'typedef struct _${camelcase}Class ${camelcase}Class;\n' '\n' '/**\n' ' * ${camelcase}:\n' ' *\n' ' * The #${camelcase} structure contains private data and should only be accessed\n' ' * using the provided API.\n' ' */\n' 'struct _${camelcase} {\n' ' /*< private >*/\n' ' QmiClient parent;\n' ' gpointer priv_unused;\n' '};\n' '\n' 'struct _${camelcase}Class {\n' ' /*< private >*/\n' ' QmiClientClass parent;\n' '};\n' '\n' 'GType ${underscore}_get_type (void);\n' '\n') hfile.write(string.Template(template).substitute(translations)) # Emit class source. Documentation skipped for the CTL service. template = '' if self.service != 'CTL': template += ( '\n' '/**\n' ' * SECTION: ${hyphened}\n' ' * @title: ${camelcase}\n' ' * @short_description: #QmiClient for the ${service} service.\n' ' *\n' ' * #QmiClient which handles operations in the ${service} service.\n' ' */\n' '\n') template += ( 'G_DEFINE_TYPE (${camelcase}, ${underscore}, QMI_TYPE_CLIENT);\n') if has_indications: template += ('\n' 'enum {\n') for message in message_list.list: if message.type == 'Indication': translations[ 'signal_id'] = utils.build_underscore_uppercase_name( message.name) inner_template = (' SIGNAL_${signal_id},\n') template += string.Template(inner_template).substitute( translations) template += (' SIGNAL_LAST\n' '};\n' '\n' 'static guint signals[SIGNAL_LAST] = { 0 };\n') template += ('\n' 'static void\n' 'process_indication (QmiClient *self,\n' ' QmiMessage *message)\n' '{\n' ' switch (qmi_message_get_message_id (message)) {\n') for message in message_list.list: if message.type == 'Indication': translations['enum_name'] = message.id_enum_name translations[ 'message_fullname_underscore'] = utils.build_underscore_name( message.fullname) translations['message_name'] = message.name translations[ 'signal_id'] = utils.build_underscore_uppercase_name( message.name) inner_template = '' if message.output is not None and message.output.fields is not None: # At least one field in the indication translations[ 'output_camelcase'] = utils.build_camelcase_name( message.output.fullname) translations[ 'output_underscore'] = utils.build_underscore_name( message.output.fullname) translations[ 'output_underscore'] = utils.build_underscore_name( message.output.fullname) inner_template += ( ' case ${enum_name}: {\n' ' ${output_camelcase} *output;\n' ' GError *error = NULL;\n' '\n' ' /* Parse indication */\n' ' output = __${message_fullname_underscore}_indication_parse (message, &error);\n' ' if (!output) {\n' ' g_warning ("Couldn\'t parse \'${message_name}\' indication: %s",\n' ' error ? error->message : "Unknown error");\n' ' if (error)\n' ' g_error_free (error);\n' ' } else {\n' ' g_signal_emit (self, signals[SIGNAL_${signal_id}], 0, output);\n' ' ${output_underscore}_unref (output);\n' ' }\n' ' break;\n' ' }\n') else: # No output field in the indication inner_template += ( ' case ${enum_name}: {\n' ' g_signal_emit (self, signals[SIGNAL_${signal_id}], 0, NULL);\n' ' break;\n' ' }\n') template += string.Template(inner_template).substitute( translations) template += ( ' default:\n' ' break;\n' ' }\n' '}\n' '\n' 'static void\n' '${underscore}_init (${camelcase} *self)\n' '{\n' '}\n' '\n' 'static void\n' '${underscore}_class_init (${camelcase}Class *klass)\n' '{\n' ' QmiClientClass *client_class = QMI_CLIENT_CLASS (klass);\n' '\n' ' client_class->process_indication = process_indication;\n') for message in message_list.list: if message.type == 'Indication': translations['signal_name'] = utils.build_dashed_name( message.name) translations[ 'signal_id'] = utils.build_underscore_uppercase_name( message.name) translations['message_name'] = message.name inner_template = '' if message.output is not None and message.output.fields is not None: # At least one field in the indication translations[ 'output_camelcase'] = utils.build_camelcase_name( message.output.fullname) translations[ 'bundle_type'] = 'QMI_TYPE_' + utils.remove_prefix( utils.build_underscore_uppercase_name( message.output.fullname), 'QMI_') translations['service'] = self.service.upper() translations['message_name_dashed'] = message.name.replace( ' ', '-') inner_template += ( '\n' ' /**\n' ' * ${camelcase}::${signal_name}:\n' ' * @object: A #${camelcase}.\n' ' * @output: A #${output_camelcase}.\n' ' *\n' ' * The ::${signal_name} signal gets emitted when a \'<link linkend=\"libqmi-glib-${service}-${message_name_dashed}.top_of_page\">${message_name}</link>\' indication is received.\n' ' */\n' ' signals[SIGNAL_${signal_id}] =\n' ' g_signal_new ("${signal_name}",\n' ' G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),\n' ' G_SIGNAL_RUN_LAST,\n' ' 0,\n' ' NULL,\n' ' NULL,\n' ' NULL,\n' ' G_TYPE_NONE,\n' ' 1,\n' ' ${bundle_type});\n') else: # No output field in the indication inner_template += ( '\n' ' /**\n' ' * ${camelcase}::${signal_name}:\n' ' * @object: A #${camelcase}.\n' ' *\n' ' * The ::${signal_name} signal gets emitted when a \'${message_name}\' indication is received.\n' ' */\n' ' signals[SIGNAL_${signal_id}] =\n' ' g_signal_new ("${signal_name}",\n' ' G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),\n' ' G_SIGNAL_RUN_LAST,\n' ' 0,\n' ' NULL,\n' ' NULL,\n' ' NULL,\n' ' G_TYPE_NONE,\n' ' 0);\n') template += string.Template(inner_template).substitute( translations) template += ('}\n' '\n') cfile.write(string.Template(template).substitute(translations))
def _emit_message_parser(self, hfile, cfile, message_type, fields): translations = { 'message' : self.name, 'service' : self.service, 'underscore' : utils.build_underscore_name (self.fullname), 'message_type' : message_type, 'message_type_upper' : message_type.upper(), 'service_underscore_upper' : utils.build_underscore_name (self.service).upper() } template = ( '\n' 'gboolean ${underscore}_${message_type}_parse (\n' ' const MbimMessage *message,\n') 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'] == 'byte-array': inner_template = (' const guint8 **${field},\n') elif field['format'] == 'unsized-byte-array' or field['format'] == 'ref-byte-array': inner_template = (' guint32 *${field}_size,\n' ' const guint8 **${field},\n') elif 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') else: raise ValueError('Cannot handle field type \'%s\'' % field['format']) template += (string.Template(inner_template).substitute(translations)) template += ( ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' '/**\n' ' * ${underscore}_${message_type}_parse:\n' ' * @message: the #MbimMessage.\n') 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']) translations['array_size'] = field['array-size'] if 'array-size' in field else '' if field['format'] == 'byte-array': inner_template = (' * @${field}: return location for an array of ${array_size} #guint8 values. Do not free the returned value, it is owned by @message.\n') elif field['format'] == 'unsized-byte-array' or field['format'] == 'ref-byte-array': inner_template = (' * @${field}_size: return location for the size of the ${field} array.\n' ' * @${field}: return location for an array of #guint8 values. Do not free the returned value, it is owned by @message.\n') elif 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' ' *\n' ' * Parses and returns parameters of the \'${message}\' ${message_type} command in the \'${service}\' service.\n' ' *\n' ' * Returns: %TRUE if the message was correctly parsed, %FALSE if @error is set.\n' ' */\n' 'gboolean\n' '${underscore}_${message_type}_parse (\n' ' const MbimMessage *message,\n') 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'] == 'byte-array': inner_template = (' const guint8 **${field},\n') elif field['format'] == 'unsized-byte-array' or field['format'] == 'ref-byte-array': inner_template = (' guint32 *${field}_size,\n' ' const guint8 **${field},\n') elif 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') if fields != []: template += ( ' guint32 offset = 0;\n') for field in fields: if 'always-read' in field: translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) inner_template = (' guint32 _${field};\n') template += (string.Template(inner_template).substitute(translations)) if message_type == 'response': template += ( '\n' ' if (mbim_message_get_message_type (message) != MBIM_MESSAGE_TYPE_COMMAND_DONE) {\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Message is not a response\");\n' ' return FALSE;\n' ' }\n') elif message_type == 'notification': template += ( '\n' ' if (mbim_message_get_message_type (message) != MBIM_MESSAGE_TYPE_INDICATE_STATUS) {\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Message is not a notification\");\n' ' return FALSE;\n' ' }\n') else: raise ValueError('Unexpected message type \'%s\'' % message_type) 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 '' translations['array_size'] = field['array-size'] if 'array-size' in field else '' inner_template = ( '\n' ' /* Read the \'${field_name}\' variable */\n') if 'available-if' in field: condition = field['available-if'] translations['condition_field'] = utils.build_underscore_name_from_camelcase(condition['field']) translations['condition_operation'] = condition['operation'] translations['condition_value'] = condition['value'] inner_template += ( ' if (!(_${condition_field} ${condition_operation} ${condition_value})) {\n') if field['format'] == 'byte-array': inner_template += ( ' if (${field})\n' ' *${field} = NULL;\n') elif field['format'] == 'unsized-byte-array' or \ field['format'] == 'ref-byte-array': inner_template += ( ' if (${field}_size)\n' ' *${field}_size = 0;\n' ' if (${field})\n' ' *${field} = NULL;\n') elif field['format'] == 'guint32-array' or \ field['format'] == 'string' or \ field['format'] == 'string-array' or \ field['format'] == 'struct' or \ field['format'] == 'struct-array' or \ field['format'] == 'ref-struct-array' or \ field['format'] == 'ipv4' or \ field['format'] == 'ref-ipv4' or \ field['format'] == 'ipv4-array' or \ field['format'] == 'ipv6' or \ field['format'] == 'ref-ipv6' or \ field['format'] == 'ipv6-array': inner_template += ( ' if (${field} != NULL)\n' ' *${field} = NULL;\n') else: raise ValueError('Field format \'%s\' unsupported as optional field' % field['format']) inner_template += ( ' } else {\n') else: inner_template += ( ' {\n') if 'always-read' 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'] == 'byte-array': inner_template += ( ' const guint8 *tmp;\n' '\n' ' tmp = _mbim_message_read_byte_array (message, 0, offset, FALSE, FALSE, NULL);\n' ' if (${field} != NULL)\n' ' *${field} = tmp;\n' ' offset += ${array_size};\n') elif field['format'] == 'unsized-byte-array': inner_template += ( ' const guint8 *tmp;\n' ' guint32 tmpsize;\n' '\n' ' tmp = _mbim_message_read_byte_array (message, 0, offset, FALSE, FALSE, &tmpsize);\n' ' if (${field} != NULL)\n' ' *${field} = tmp;\n' ' if (${field}_size != NULL)\n' ' *${field}_size = tmpsize;\n' ' offset += tmpsize;\n') elif field['format'] == 'ref-byte-array': inner_template += ( ' const guint8 *tmp;\n' ' guint32 tmpsize;\n' '\n' ' tmp = _mbim_message_read_byte_array (message, 0, offset, TRUE, TRUE, &tmpsize);\n' ' if (${field} != NULL)\n' ' *${field} = tmp;\n' ' if (${field}_size != NULL)\n' ' *${field}_size = tmpsize;\n' ' offset += 8;\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 += ( ' 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, 0, 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}, 0, 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') inner_template += ( ' }\n') template += (string.Template(inner_template).substitute(translations)) template += ( '\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def __emit_get_printable(self, hfile, cfile): translations = {'service': self.service.lower()} template = ('\n' '#if defined (LIBQMI_GLIB_COMPILATION)\n' '\n' 'G_GNUC_INTERNAL\n' 'gchar *__qmi_message_${service}_get_printable (\n' ' QmiMessage *self,\n' ' const gchar *line_prefix);\n' '\n' '#endif\n' '\n') hfile.write(string.Template(template).substitute(translations)) template = ('\n' 'gchar *\n' '__qmi_message_${service}_get_printable (\n' ' QmiMessage *self,\n' ' const gchar *line_prefix)\n' '{\n' ' if (qmi_message_is_indication (self)) {\n' ' switch (qmi_message_get_message_id (self)) {\n') for message in self.list: if message.type == 'Indication': translations['enum_name'] = message.id_enum_name translations[ 'message_underscore'] = utils.build_underscore_name( message.name) translations['enum_value'] = message.id inner_template = ( ' case ${enum_name}:\n' ' return indication_${message_underscore}_get_printable (self, line_prefix);\n' ) template += string.Template(inner_template).substitute( translations) template += (' default:\n' ' return NULL;\n' ' }\n' ' } else {\n' ' switch (qmi_message_get_message_id (self)) {\n') for message in self.list: if message.type == 'Message': translations['enum_name'] = message.id_enum_name translations[ 'message_underscore'] = utils.build_underscore_name( message.name) translations['enum_value'] = message.id inner_template = ( ' case ${enum_name}:\n' ' return message_${message_underscore}_get_printable (self, line_prefix);\n' ) template += string.Template(inner_template).substitute( translations) template += (' default:\n' ' return NULL;\n' ' }\n' ' }\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def __emit_request_creator(self, hfile, cfile): translations = { 'name' : self.name, 'service' : self.service, 'container' : utils.build_camelcase_name (self.input.fullname), 'underscore' : utils.build_underscore_name (self.fullname), 'message_id' : self.id_enum_name } input_arg_template = 'gpointer unused' if self.input.fields is None else '${container} *input' template = ( '\n' 'static QmiMessage *\n' '__${underscore}_request_create (\n' ' guint16 transaction_id,\n' ' guint8 cid,\n' ' %s,\n' ' GError **error)\n' '{\n' ' QmiMessage *self;\n' '\n' ' self = qmi_message_new (QMI_SERVICE_${service},\n' ' cid,\n' ' transaction_id,\n' ' ${message_id});\n' % input_arg_template) cfile.write(string.Template(template).substitute(translations)) if self.input.fields is not None: # Count how many mandatory fields we have n_mandatory = 0 for field in self.input.fields: if field.mandatory == 'yes': n_mandatory += 1 if n_mandatory == 0: # If we don't have mandatory fields, we do allow to have # a NULL input cfile.write( '\n' ' /* All TLVs are optional, we allow NULL input */\n' ' if (!input)\n' ' return self;\n') else: # If we do have mandatory fields, issue error if no input # given. template = ( '\n' ' /* There is at least one mandatory TLV, don\'t allow NULL input */\n' ' if (!input) {\n' ' g_set_error (error,\n' ' QMI_CORE_ERROR,\n' ' QMI_CORE_ERROR_INVALID_ARGS,\n' ' "Message \'${name}\' has mandatory TLVs");\n' ' goto error_out;\n' ' }\n') cfile.write(string.Template(template).substitute(translations)) # Now iterate fields for field in self.input.fields: translations['tlv_name'] = field.name translations['variable_name'] = field.variable_name template = ( '\n' ' /* Try to add the \'${tlv_name}\' TLV */\n' ' if (input->${variable_name}_set) {\n') cfile.write(string.Template(template).substitute(translations)) # Emit the TLV getter field.emit_input_tlv_add(cfile, ' ') if field.mandatory == 'yes': template = ( ' } else {\n' ' g_set_error (error,\n' ' QMI_CORE_ERROR,\n' ' QMI_CORE_ERROR_INVALID_ARGS,\n' ' "Missing mandatory TLV \'${tlv_name}\' in message \'${name}\'");\n' ' goto error_out;\n') cfile.write(string.Template(template).substitute(translations)) cfile.write( ' }\n') cfile.write( '\n' ' return self;\n') if self.input.fields is not None: cfile.write( '\n' 'error_out:\n' ' qmi_message_unref (self);\n' ' return NULL;\n') cfile.write( '}\n')
def __emit_methods(self, hfile, cfile, message_list): translations = { 'underscore' : utils.build_underscore_name(self.name), 'camelcase' : utils.build_camelcase_name (self.name), 'service_lowercase' : self.service.lower(), 'service_uppercase' : self.service.upper(), 'service_camelcase' : string.capwords(self.service) } for message in message_list.list: if message.type == 'Indication': continue if message.static: continue translations['message_name'] = message.name translations['message_underscore'] = utils.build_underscore_name(message.name) translations['message_fullname_underscore'] = utils.build_underscore_name(message.fullname) translations['input_camelcase'] = utils.build_camelcase_name(message.input.fullname) translations['output_camelcase'] = utils.build_camelcase_name(message.output.fullname) translations['input_underscore'] = utils.build_underscore_name(message.input.fullname) translations['output_underscore'] = utils.build_underscore_name(message.output.fullname) if message.input.fields is None: input_arg_template = 'gpointer unused' translations['input_var'] = 'NULL' translations['input_doc'] = 'unused: %NULL. This message doesn\'t have any input bundle.' else: input_arg_template = '${input_camelcase} *input' translations['input_var'] = 'input' translations['input_doc'] = 'input: a #' + translations['input_camelcase'] + '.' template = ( '\n' 'void ${underscore}_${message_underscore} (\n' ' ${camelcase} *self,\n' ' %s,\n' ' guint timeout,\n' ' GCancellable *cancellable,\n' ' GAsyncReadyCallback callback,\n' ' gpointer user_data);\n' '${output_camelcase} *${underscore}_${message_underscore}_finish (\n' ' ${camelcase} *self,\n' ' GAsyncResult *res,\n' ' GError **error);\n' % input_arg_template) hfile.write(string.Template(template).substitute(translations)) template = ( '\n' '/**\n' ' * ${underscore}_${message_underscore}_finish:\n' ' * @self: a #${camelcase}.\n' ' * @res: the #GAsyncResult obtained from the #GAsyncReadyCallback passed to ${underscore}_${message_underscore}().\n' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Finishes an async operation started with ${underscore}_${message_underscore}().\n' ' *\n' ' * Returns: a #${output_camelcase}, or %NULL if @error is set. The returned value should be freed with ${output_underscore}_unref().\n' ' */\n' '${output_camelcase} *\n' '${underscore}_${message_underscore}_finish (\n' ' ${camelcase} *self,\n' ' GAsyncResult *res,\n' ' GError **error)\n' '{\n' ' if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))\n' ' return NULL;\n' '\n' ' return ${output_underscore}_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));\n' '}\n') if message.abort: template += ( '\n' 'static void\n' '${message_underscore}_abort_ready (\n' ' QmiDevice *device,\n' ' GAsyncResult *res)\n' '{\n' ' GError *error = NULL;\n' ' QmiMessage *reply;\n' ' QmiMessage${service_camelcase}AbortOutput *output;\n' '\n' ' reply = qmi_device_command_finish (device, res, &error);\n' ' if (reply) {\n' ' output = __qmi_message_${service_lowercase}_abort_response_parse (reply, &error);\n' ' if (output)\n' ' qmi_message_${service_lowercase}_abort_output_unref (output);\n' ' qmi_message_unref (reply);\n' ' }\n' '\n' ' if (error) {\n' ' g_debug ("Operation to abort \'${message_name}\' failed: %s", error->message);\n' ' g_error_free (error);\n' ' }\n' '}\n') template += ( '\n' 'static void\n' '${message_underscore}_ready (\n' ' QmiDevice *device,\n' ' GAsyncResult *res,\n' ' GSimpleAsyncResult *simple)\n' '{\n' ' GError *error = NULL;\n' ' QmiMessage *reply;\n' ' ${output_camelcase} *output;\n' '\n' ' reply = qmi_device_command_finish (device, res, &error);\n' ' if (!reply) {\n') if message.abort: template += ( ' if (g_error_matches (error, QMI_CORE_ERROR, QMI_CORE_ERROR_TIMEOUT) ||\n' ' g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_ABORTED)) {\n' ' QmiMessage *abort;\n' ' GObject *self;\n' ' guint16 transaction_id;\n' ' QmiMessage${service_camelcase}AbortInput *input;\n' '\n' ' self = g_async_result_get_source_object (G_ASYNC_RESULT (simple));\n' ' g_assert (self != NULL);\n' '\n' ' transaction_id = (guint16) GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (simple),\n' ' "transaction-id"));\n' ' g_assert (transaction_id != 0);\n' '\n' ' input = qmi_message_${service_lowercase}_abort_input_new ();\n' ' qmi_message_${service_lowercase}_abort_input_set_transaction_id (\n' ' input,\n' ' transaction_id,\n' ' NULL);\n' ' abort = __qmi_message_${service_lowercase}_abort_request_create (\n' ' qmi_client_get_next_transaction_id (QMI_CLIENT (self)),\n' ' qmi_client_get_cid (QMI_CLIENT (self)),\n' ' input,\n' ' NULL);\n' ' g_assert (abort != NULL);\n' ' qmi_device_command (device,\n' ' abort,\n' ' 30,\n' ' NULL,\n' ' (GAsyncReadyCallback)${message_underscore}_abort_ready,\n' ' NULL);\n' ' qmi_message_${service_lowercase}_abort_input_unref (input);\n' ' qmi_message_unref (abort);\n' ' g_object_unref (self);\n' ' }\n' '\n') template += ( ' g_simple_async_result_take_error (simple, error);\n' ' g_simple_async_result_complete (simple);\n' ' g_object_unref (simple);\n' ' return;\n' ' }\n' '\n' ' /* Parse reply */\n' ' output = __${message_fullname_underscore}_response_parse (reply, &error);\n' ' if (!output)\n' ' g_simple_async_result_take_error (simple, error);\n' ' else\n' ' g_simple_async_result_set_op_res_gpointer (simple,\n' ' output,\n' ' (GDestroyNotify)${output_underscore}_unref);\n' ' g_simple_async_result_complete (simple);\n' ' g_object_unref (simple);\n' ' qmi_message_unref (reply);\n' '}\n' '\n' '/**\n' ' * ${underscore}_${message_underscore}:\n' ' * @self: a #${camelcase}.\n' ' * @${input_doc}\n' ' * @timeout: maximum time to wait for the method to complete, in seconds.\n' ' * @cancellable: a #GCancellable or %NULL.\n' ' * @callback: a #GAsyncReadyCallback to call when the request is satisfied.\n' ' * @user_data: user data to pass to @callback.\n' ' *\n' ' * Asynchronously sends a ${message_name} request to the device.\n' ' *\n' ' * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from.\n' ' *\n' ' * You can then call ${underscore}_${message_underscore}_finish() to get the result of the operation.\n' ' */\n' 'void\n' '${underscore}_${message_underscore} (\n' ' ${camelcase} *self,\n') template += ( ' %s,\n' % input_arg_template) template += ( ' guint timeout,\n' ' GCancellable *cancellable,\n' ' GAsyncReadyCallback callback,\n' ' gpointer user_data)\n' '{\n' ' GSimpleAsyncResult *result;\n' ' QmiMessage *request;\n' ' GError *error = NULL;\n' ' guint16 transaction_id;\n' '\n' ' result = g_simple_async_result_new (G_OBJECT (self),\n' ' callback,\n' ' user_data,\n' ' ${underscore}_${message_underscore});\n' '\n' ' transaction_id = qmi_client_get_next_transaction_id (QMI_CLIENT (self));\n' '\n' ' request = __${message_fullname_underscore}_request_create (\n' ' transaction_id,\n' ' qmi_client_get_cid (QMI_CLIENT (self)),\n' ' ${input_var},\n' ' &error);\n' ' if (!request) {\n' ' g_prefix_error (&error, "Couldn\'t create request message: ");\n' ' g_simple_async_result_take_error (result, error);\n' ' g_simple_async_result_complete_in_idle (result);\n' ' g_object_unref (result);\n' ' return;\n' ' }\n') if message.abort: template += ( '\n' ' g_object_set_data (G_OBJECT (result),\n' ' "transaction-id",\n' ' GUINT_TO_POINTER (transaction_id));\n') template += ( '\n' ' qmi_device_command (QMI_DEVICE (qmi_client_peek_device (QMI_CLIENT (self))),\n' ' request,\n' ' timeout,\n' ' cancellable,\n' ' (GAsyncReadyCallback)${message_underscore}_ready,\n' ' result);\n' ' qmi_message_unref (request);\n' '}\n' '\n') cfile.write(string.Template(template).substitute(translations))
def __emit_class(self, hfile, cfile, message_list): # Check if we'll have indications has_indications = False for message in message_list.list: if message.type == 'Indication': has_indications = True break translations = { 'underscore' : utils.build_underscore_name(self.name), 'no_prefix_underscore_upper' : utils.build_underscore_name(self.name[4:]).upper(), 'camelcase' : utils.build_camelcase_name(self.name), 'hyphened' : utils.build_dashed_name(self.name), 'service' : self.service.upper() } # Emit class header template = ( '#define QMI_TYPE_${no_prefix_underscore_upper} (${underscore}_get_type ())\n' '#define QMI_${no_prefix_underscore_upper}(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), QMI_TYPE_${no_prefix_underscore_upper}, ${camelcase}))\n' '#define QMI_${no_prefix_underscore_upper}_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), QMI_TYPE_${no_prefix_underscore_upper}, ${camelcase}Class))\n' '#define QMI_IS_${no_prefix_underscore_upper}(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), QMI_TYPE_${no_prefix_underscore_upper}))\n' '#define QMI_IS_${no_prefix_underscore_upper}_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), QMI_TYPE_${no_prefix_underscore_upper}))\n' '#define QMI_${no_prefix_underscore_upper}_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), QMI_TYPE_${no_prefix_underscore_upper}, ${camelcase}Class))\n' '\n' 'typedef struct _${camelcase} ${camelcase};\n' 'typedef struct _${camelcase}Class ${camelcase}Class;\n' '\n' '/**\n' ' * ${camelcase}:\n' ' *\n' ' * The #${camelcase} structure contains private data and should only be accessed\n' ' * using the provided API.\n' ' */\n' 'struct _${camelcase} {\n' ' /*< private >*/\n' ' QmiClient parent;\n' ' gpointer priv_unused;\n' '};\n' '\n' 'struct _${camelcase}Class {\n' ' /*< private >*/\n' ' QmiClientClass parent;\n' '};\n' '\n' 'GType ${underscore}_get_type (void);\n' '\n') hfile.write(string.Template(template).substitute(translations)) # Emit class source. Documentation skipped for the CTL service. template = '' if self.service != 'CTL': template += ( '\n' '/**\n' ' * SECTION: ${hyphened}\n' ' * @title: ${camelcase}\n' ' * @short_description: #QmiClient for the ${service} service.\n' ' *\n' ' * #QmiClient which handles operations in the ${service} service.\n' ' */\n' '\n') template += ( 'G_DEFINE_TYPE (${camelcase}, ${underscore}, QMI_TYPE_CLIENT);\n') if has_indications: template += ( '\n' 'enum {\n') for message in message_list.list: if message.type == 'Indication': translations['signal_id'] = utils.build_underscore_uppercase_name(message.name) inner_template = ( ' SIGNAL_${signal_id},\n') template += string.Template(inner_template).substitute(translations) template += ( ' SIGNAL_LAST\n' '};\n' '\n' 'static guint signals[SIGNAL_LAST] = { 0 };\n') template += ( '\n' 'static void\n' 'process_indication (QmiClient *self,\n' ' QmiMessage *message)\n' '{\n' ' switch (qmi_message_get_message_id (message)) {\n') for message in message_list.list: if message.type == 'Indication': translations['enum_name'] = message.id_enum_name translations['message_fullname_underscore'] = utils.build_underscore_name(message.fullname) translations['message_name'] = message.name translations['signal_id'] = utils.build_underscore_uppercase_name(message.name) inner_template = '' if message.output is not None and message.output.fields is not None: # At least one field in the indication translations['output_camelcase'] = utils.build_camelcase_name(message.output.fullname) translations['output_underscore'] = utils.build_underscore_name(message.output.fullname) translations['output_underscore'] = utils.build_underscore_name(message.output.fullname) inner_template += ( ' case ${enum_name}: {\n' ' ${output_camelcase} *output;\n' ' GError *error = NULL;\n' '\n' ' /* Parse indication */\n' ' output = __${message_fullname_underscore}_indication_parse (message, &error);\n' ' if (!output) {\n' ' g_warning ("Couldn\'t parse \'${message_name}\' indication: %s",\n' ' error ? error->message : "Unknown error");\n' ' if (error)\n' ' g_error_free (error);\n' ' } else {\n' ' g_signal_emit (self, signals[SIGNAL_${signal_id}], 0, output);\n' ' ${output_underscore}_unref (output);\n' ' }\n' ' break;\n' ' }\n') else: # No output field in the indication inner_template += ( ' case ${enum_name}: {\n' ' g_signal_emit (self, signals[SIGNAL_${signal_id}], 0, NULL);\n' ' break;\n' ' }\n') template += string.Template(inner_template).substitute(translations) template += ( ' default:\n' ' break;\n' ' }\n' '}\n' '\n' 'static void\n' '${underscore}_init (${camelcase} *self)\n' '{\n' '}\n' '\n' 'static void\n' '${underscore}_class_init (${camelcase}Class *klass)\n' '{\n' ' QmiClientClass *client_class = QMI_CLIENT_CLASS (klass);\n' '\n' ' client_class->process_indication = process_indication;\n') for message in message_list.list: if message.type == 'Indication': translations['signal_name'] = utils.build_dashed_name(message.name) translations['signal_id'] = utils.build_underscore_uppercase_name(message.name) translations['message_name'] = message.name inner_template = '' if message.output is not None and message.output.fields is not None: # At least one field in the indication translations['output_camelcase'] = utils.build_camelcase_name(message.output.fullname) translations['bundle_type'] = 'QMI_TYPE_' + utils.remove_prefix(utils.build_underscore_uppercase_name(message.output.fullname), 'QMI_') translations['service'] = self.service.upper() translations['message_name_dashed'] = message.name.replace(' ', '-') inner_template += ( '\n' ' /**\n' ' * ${camelcase}::${signal_name}:\n' ' * @object: A #${camelcase}.\n' ' * @output: A #${output_camelcase}.\n' ' *\n' ' * The ::${signal_name} signal gets emitted when a \'<link linkend=\"libqmi-glib-${service}-${message_name_dashed}.top_of_page\">${message_name}</link>\' indication is received.\n' ' */\n' ' signals[SIGNAL_${signal_id}] =\n' ' g_signal_new ("${signal_name}",\n' ' G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),\n' ' G_SIGNAL_RUN_LAST,\n' ' 0,\n' ' NULL,\n' ' NULL,\n' ' NULL,\n' ' G_TYPE_NONE,\n' ' 1,\n' ' ${bundle_type});\n') else: # No output field in the indication inner_template += ( '\n' ' /**\n' ' * ${camelcase}::${signal_name}:\n' ' * @object: A #${camelcase}.\n' ' *\n' ' * The ::${signal_name} signal gets emitted when a \'${message_name}\' indication is received.\n' ' */\n' ' signals[SIGNAL_${signal_id}] =\n' ' g_signal_new ("${signal_name}",\n' ' G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),\n' ' G_SIGNAL_RUN_LAST,\n' ' 0,\n' ' NULL,\n' ' NULL,\n' ' NULL,\n' ' G_TYPE_NONE,\n' ' 0);\n') template += string.Template(inner_template).substitute(translations) template += ( '}\n' '\n') cfile.write(string.Template(template).substitute(translations))
def emit_setter(self, hfile, cfile): input_variable_name = 'value_' + utils.build_underscore_name(self.name) variable_setter_dec = self.variable.build_setter_declaration( ' ', input_variable_name) variable_setter_doc = self.variable.build_setter_documentation( ' * ', input_variable_name) variable_setter_imp = self.variable.build_setter_implementation( ' ', input_variable_name, 'self->' + self.variable_name) translations = { 'name': self.name, 'variable_name': self.variable_name, 'variable_setter_dec': variable_setter_dec, 'variable_setter_doc': variable_setter_doc, 'variable_setter_imp': variable_setter_imp, 'underscore': utils.build_underscore_name(self.name), 'prefix_camelcase': utils.build_camelcase_name(self.prefix), 'prefix_underscore': utils.build_underscore_name(self.prefix), 'since': self.since, 'static': 'static ' if self.static else '' } # Emit the setter header template = '\n' if self.static == False: template += ( '\n' '/**\n' ' * ${prefix_underscore}_set_${underscore}:\n' ' * @self: a #${prefix_camelcase}.\n' '${variable_setter_doc}' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Set the \'${name}\' field in the message.\n' ' *\n' ' * Returns: (skip): %TRUE if @value was successfully set, %FALSE otherwise.\n' ' *\n' ' * Since: ${since}\n' ' */\n') template += ( '${static}gboolean ${prefix_underscore}_set_${underscore} (\n' ' ${prefix_camelcase} *self,\n' '${variable_setter_dec}' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) # Emit the setter source template = ('\n' '${static}gboolean\n' '${prefix_underscore}_set_${underscore} (\n' ' ${prefix_camelcase} *self,\n' '${variable_setter_dec}' ' GError **error)\n' '{\n' ' g_return_val_if_fail (self != NULL, FALSE);\n' '\n' '${variable_setter_imp}' ' self->${variable_name}_set = TRUE;\n' '\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def __emit_methods(self, hfile, cfile, message_list): translations = { 'underscore': utils.build_underscore_name(self.name), 'camelcase': utils.build_camelcase_name(self.name), 'service_lowercase': self.service.lower(), 'service_uppercase': self.service.upper(), 'service_camelcase': string.capwords(self.service) } for message in message_list.list: if message.type == 'Indication': continue if message.static: continue translations['message_name'] = message.name translations['message_underscore'] = utils.build_underscore_name( message.name) translations[ 'message_fullname_underscore'] = utils.build_underscore_name( message.fullname) translations['input_camelcase'] = utils.build_camelcase_name( message.input.fullname) translations['output_camelcase'] = utils.build_camelcase_name( message.output.fullname) translations['input_underscore'] = utils.build_underscore_name( message.input.fullname) translations['output_underscore'] = utils.build_underscore_name( message.output.fullname) if message.input.fields is None: input_arg_template = 'gpointer unused' translations['input_var'] = 'NULL' translations[ 'input_doc'] = 'unused: %NULL. This message doesn\'t have any input bundle.' else: input_arg_template = '${input_camelcase} *input' translations['input_var'] = 'input' translations['input_doc'] = 'input: a #' + translations[ 'input_camelcase'] + '.' template = ( '\n' 'void ${underscore}_${message_underscore} (\n' ' ${camelcase} *self,\n' ' %s,\n' ' guint timeout,\n' ' GCancellable *cancellable,\n' ' GAsyncReadyCallback callback,\n' ' gpointer user_data);\n' '${output_camelcase} *${underscore}_${message_underscore}_finish (\n' ' ${camelcase} *self,\n' ' GAsyncResult *res,\n' ' GError **error);\n' % input_arg_template) hfile.write(string.Template(template).substitute(translations)) template = ( '\n' '/**\n' ' * ${underscore}_${message_underscore}_finish:\n' ' * @self: a #${camelcase}.\n' ' * @res: the #GAsyncResult obtained from the #GAsyncReadyCallback passed to ${underscore}_${message_underscore}().\n' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Finishes an async operation started with ${underscore}_${message_underscore}().\n' ' *\n' ' * Returns: a #${output_camelcase}, or %NULL if @error is set. The returned value should be freed with ${output_underscore}_unref().\n' ' */\n' '${output_camelcase} *\n' '${underscore}_${message_underscore}_finish (\n' ' ${camelcase} *self,\n' ' GAsyncResult *res,\n' ' GError **error)\n' '{\n' ' if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))\n' ' return NULL;\n' '\n' ' return ${output_underscore}_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));\n' '}\n') if message.abort: template += ( '\n' 'static void\n' '${message_underscore}_abort_ready (\n' ' QmiDevice *device,\n' ' GAsyncResult *res)\n' '{\n' ' GError *error = NULL;\n' ' QmiMessage *reply;\n' ' QmiMessage${service_camelcase}AbortOutput *output;\n' '\n' ' reply = qmi_device_command_finish (device, res, &error);\n' ' if (reply) {\n' ' output = __qmi_message_${service_lowercase}_abort_response_parse (reply, &error);\n' ' if (output)\n' ' qmi_message_${service_lowercase}_abort_output_unref (output);\n' ' qmi_message_unref (reply);\n' ' }\n' '\n' ' if (error) {\n' ' g_debug ("Operation to abort \'${message_name}\' failed: %s", error->message);\n' ' g_error_free (error);\n' ' }\n' '}\n') template += ( '\n' 'static void\n' '${message_underscore}_ready (\n' ' QmiDevice *device,\n' ' GAsyncResult *res,\n' ' GSimpleAsyncResult *simple)\n' '{\n' ' GError *error = NULL;\n' ' QmiMessage *reply;\n' ' ${output_camelcase} *output;\n' '\n' ' reply = qmi_device_command_finish (device, res, &error);\n' ' if (!reply) {\n') if message.abort: template += ( ' if (g_error_matches (error, QMI_CORE_ERROR, QMI_CORE_ERROR_TIMEOUT) ||\n' ' g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_ABORTED)) {\n' ' QmiMessage *abort;\n' ' GObject *self;\n' ' guint16 transaction_id;\n' ' QmiMessage${service_camelcase}AbortInput *input;\n' '\n' ' self = g_async_result_get_source_object (G_ASYNC_RESULT (simple));\n' ' g_assert (self != NULL);\n' '\n' ' transaction_id = (guint16) GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (simple),\n' ' "transaction-id"));\n' ' g_assert (transaction_id != 0);\n' '\n' ' input = qmi_message_${service_lowercase}_abort_input_new ();\n' ' qmi_message_${service_lowercase}_abort_input_set_transaction_id (\n' ' input,\n' ' transaction_id,\n' ' NULL);\n' ' abort = __qmi_message_${service_lowercase}_abort_request_create (\n' ' qmi_client_get_next_transaction_id (QMI_CLIENT (self)),\n' ' qmi_client_get_cid (QMI_CLIENT (self)),\n' ' input,\n' ' NULL);\n' ' g_assert (abort != NULL);\n' ' qmi_device_command (device,\n' ' abort,\n' ' 30,\n' ' NULL,\n' ' (GAsyncReadyCallback)${message_underscore}_abort_ready,\n' ' NULL);\n' ' qmi_message_${service_lowercase}_abort_input_unref (input);\n' ' qmi_message_unref (abort);\n' ' g_object_unref (self);\n' ' }\n' '\n') template += ( ' g_simple_async_result_take_error (simple, error);\n' ' g_simple_async_result_complete (simple);\n' ' g_object_unref (simple);\n' ' return;\n' ' }\n' '\n' ' /* Parse reply */\n' ' output = __${message_fullname_underscore}_response_parse (reply, &error);\n' ' if (!output)\n' ' g_simple_async_result_take_error (simple, error);\n' ' else\n' ' g_simple_async_result_set_op_res_gpointer (simple,\n' ' output,\n' ' (GDestroyNotify)${output_underscore}_unref);\n' ' g_simple_async_result_complete (simple);\n' ' g_object_unref (simple);\n' ' qmi_message_unref (reply);\n' '}\n' '\n' '/**\n' ' * ${underscore}_${message_underscore}:\n' ' * @self: a #${camelcase}.\n' ' * @${input_doc}\n' ' * @timeout: maximum time to wait for the method to complete, in seconds.\n' ' * @cancellable: a #GCancellable or %NULL.\n' ' * @callback: a #GAsyncReadyCallback to call when the request is satisfied.\n' ' * @user_data: user data to pass to @callback.\n' ' *\n' ' * Asynchronously sends a ${message_name} request to the device.\n' ' *\n' ' * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from.\n' ' *\n' ' * You can then call ${underscore}_${message_underscore}_finish() to get the result of the operation.\n' ' */\n' 'void\n' '${underscore}_${message_underscore} (\n' ' ${camelcase} *self,\n') template += (' %s,\n' % input_arg_template) template += ( ' guint timeout,\n' ' GCancellable *cancellable,\n' ' GAsyncReadyCallback callback,\n' ' gpointer user_data)\n' '{\n' ' GSimpleAsyncResult *result;\n' ' QmiMessage *request;\n' ' GError *error = NULL;\n' ' guint16 transaction_id;\n' '\n' ' result = g_simple_async_result_new (G_OBJECT (self),\n' ' callback,\n' ' user_data,\n' ' ${underscore}_${message_underscore});\n' '\n' ' transaction_id = qmi_client_get_next_transaction_id (QMI_CLIENT (self));\n' '\n' ' request = __${message_fullname_underscore}_request_create (\n' ' transaction_id,\n' ' qmi_client_get_cid (QMI_CLIENT (self)),\n' ' ${input_var},\n' ' &error);\n' ' if (!request) {\n' ' g_prefix_error (&error, "Couldn\'t create request message: ");\n' ' g_simple_async_result_take_error (result, error);\n' ' g_simple_async_result_complete_in_idle (result);\n' ' g_object_unref (result);\n' ' return;\n' ' }\n') if message.abort: template += ( '\n' ' g_object_set_data (G_OBJECT (result),\n' ' "transaction-id",\n' ' GUINT_TO_POINTER (transaction_id));\n' ) template += ( '\n' ' qmi_device_command (QMI_DEVICE (qmi_client_peek_device (QMI_CLIENT (self))),\n' ' request,\n' ' timeout,\n' ' cancellable,\n' ' (GAsyncReadyCallback)${message_underscore}_ready,\n' ' result);\n' ' qmi_message_unref (request);\n' '}\n' '\n') cfile.write(string.Template(template).substitute(translations))
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, 'message_type_upper' : message_type.upper(), 'service_underscore_upper' : utils.build_underscore_name (self.service).upper(), 'cid_enum_name' : self.cid_enum_name } template = ( '\n' 'MbimMessage *${underscore}_${message_type}_new (\n') 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'] == 'byte-array': inner_template = (' const guint8 *${field},\n') elif field['format'] == 'unsized-byte-array' or \ field['format'] == 'ref-byte-array' or \ field['format'] == 'ref-byte-array-no-offset': inner_template = (' const guint32 ${field}_size,\n' ' const guint8 *${field},\n') elif 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') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' '/**\n' ' * ${underscore}_${message_type}_new:\n') 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'] translations['array_size'] = field['array-size'] if 'array-size' in field else '' if field['format'] == 'byte-array': inner_template = (' * @${field}: the \'${name}\' field, given as an array of ${array_size} #guint8 values.\n') elif field['format'] == 'unsized-byte-array' or \ field['format'] == 'ref-byte-array' or \ field['format'] == 'ref-byte-array-no-offset': inner_template = (' * @${field}_size: size of the ${field} array.\n' ' * @${field}: the \'${name}\' field, given as an array of #guint8 values.\n') elif 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 \'${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') 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'] translations['array_size'] = field['array-size'] if 'array-size' in field else '' if field['format'] == 'byte-array': inner_template = (' const guint8 *${field},\n') elif field['format'] == 'unsized-byte-array' or \ field['format'] == 'ref-byte-array' or \ field['format'] == 'ref-byte-array-no-offset': inner_template = (' const guint32 ${field}_size,\n' ' const guint8 *${field},\n') elif 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' '{\n' ' MbimMessageCommandBuilder *builder;\n' '\n' ' builder = _mbim_message_command_builder_new (0,\n' ' MBIM_SERVICE_${service_underscore_upper},\n' ' ${cid_enum_name},\n' ' MBIM_MESSAGE_COMMAND_TYPE_${message_type_upper});\n') 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']) translations['array_size'] = field['array-size'] if 'array-size' in field else '' translations['pad_array'] = field['pad-array'] if 'pad-array' in field else 'TRUE' inner_template = '' if 'available-if' in field: condition = field['available-if'] translations['condition_field'] = utils.build_underscore_name_from_camelcase(condition['field']) translations['condition_operation'] = condition['operation'] translations['condition_value'] = condition['value'] inner_template += ( ' if (${condition_field} ${condition_operation} ${condition_value}) {\n') else: inner_template += (' {\n') if field['format'] == 'byte-array': inner_template += (' _mbim_message_command_builder_append_byte_array (builder, FALSE, FALSE, ${pad_array}, ${field}, ${array_size});\n') elif field['format'] == 'unsized-byte-array': inner_template += (' _mbim_message_command_builder_append_byte_array (builder, FALSE, FALSE, ${pad_array}, ${field}, ${field}_size);\n') elif field['format'] == 'ref-byte-array': inner_template += (' _mbim_message_command_builder_append_byte_array (builder, TRUE, TRUE, ${pad_array}, ${field}, ${field}_size);\n') elif field['format'] == 'ref-byte-array-no-offset': inner_template += (' _mbim_message_command_builder_append_byte_array (builder, FALSE, TRUE, ${pad_array}, ${field}, ${field}_size);\n') elif 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') else: raise ValueError('Cannot handle field type \'%s\'' % field['format']) inner_template += (' }\n') template += (string.Template(inner_template).substitute(translations)) template += ( '\n' ' return _mbim_message_command_builder_complete (builder);\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def emit_printable(self, hfile, cfile): translations = { 'service_underscore': utils.build_underscore_name(self.service), 'service': self.service } template = ( '\n' '/*****************************************************************************/\n' '/* Service helper for printable fields */\n' '\n' '#if defined (LIBMBIM_GLIB_COMPILATION)\n' '\n' 'G_GNUC_INTERNAL\n' 'gchar *\n' '__mbim_message_${service_underscore}_get_printable_fields (\n' ' const MbimMessage *message,\n' ' const gchar *line_prefix,\n' ' GError **error);\n' '\n' '#endif\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' 'typedef struct {\n' ' gchar * (* query_cb) (const MbimMessage *message, const gchar *line_prefix, GError **error);\n' ' gchar * (* set_cb) (const MbimMessage *message, const gchar *line_prefix, GError **error);\n' ' gchar * (* response_cb) (const MbimMessage *message, const gchar *line_prefix, GError **error);\n' ' gchar * (* notification_cb) (const MbimMessage *message, const gchar *line_prefix, GError **error);\n' '} GetPrintableCallbacks;\n' '\n' 'static const GetPrintableCallbacks get_printable_callbacks[] = {\n' ) for item in self.command_list: translations['message'] = utils.build_underscore_name( item.fullname) translations['cid'] = item.cid_enum_name inner_template = (' [${cid}] = {\n') if item.has_query: inner_template += ( ' .query_cb = ${message}_query_get_printable,\n') if item.has_set: inner_template += ( ' .set_cb = ${message}_set_get_printable,\n') if item.has_response: inner_template += ( ' .response_cb = ${message}_response_get_printable,\n' ) if item.has_notification: inner_template += ( ' .notification_cb = ${message}_notification_get_printable,\n' ) inner_template += (' },\n') template += ( string.Template(inner_template).substitute(translations)) template += ( '};\n' '\n' 'gchar *\n' '__mbim_message_${service_underscore}_get_printable_fields (\n' ' const MbimMessage *message,\n' ' const gchar *line_prefix,\n' ' GError **error)\n' '{\n' ' guint32 cid;\n' '\n' ' switch (mbim_message_get_message_type (message)) {\n' ' case MBIM_MESSAGE_TYPE_COMMAND: {\n' ' cid = mbim_message_command_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (get_printable_callbacks)) {\n' ' switch (mbim_message_command_get_command_type (message)) {\n' ' case MBIM_MESSAGE_COMMAND_TYPE_QUERY:\n' ' if (get_printable_callbacks[cid].query_cb)\n' ' return get_printable_callbacks[cid].query_cb (message, line_prefix, error);\n' ' break;\n' ' case MBIM_MESSAGE_COMMAND_TYPE_SET:\n' ' if (get_printable_callbacks[cid].set_cb)\n' ' return get_printable_callbacks[cid].set_cb (message, line_prefix, error);\n' ' break;\n' ' default:\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Invalid command type\");\n' ' return NULL;\n' ' }\n' ' }\n' ' break;\n' ' }\n' '\n' ' case MBIM_MESSAGE_TYPE_COMMAND_DONE:\n' ' cid = mbim_message_command_done_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (get_printable_callbacks)) {\n' ' if (get_printable_callbacks[cid].response_cb)\n' ' return get_printable_callbacks[cid].response_cb (message, line_prefix, error);\n' ' }\n' ' break;\n' '\n' ' case MBIM_MESSAGE_TYPE_INDICATE_STATUS:\n' ' cid = mbim_message_indicate_status_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (get_printable_callbacks)) {\n' ' if (get_printable_callbacks[cid].notification_cb)\n' ' return get_printable_callbacks[cid].notification_cb (message, line_prefix, error);\n' ' }\n' ' break;\n' '\n' ' default:\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"No contents expected in this message type\");\n' ' return NULL;\n' ' }\n' '\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Unknown contents\");\n' ' return NULL;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def __emit_methods(self, hfile, cfile, message_list): translations = { 'underscore': utils.build_underscore_name(self.name), 'camelcase': utils.build_camelcase_name(self.name), 'service_lowercase': self.service.lower(), 'service_uppercase': self.service.upper(), 'service_camelcase': string.capwords(self.service) } for message in message_list.request_list: if message.static: continue translations['message_name'] = message.name translations['message_vendor_id'] = message.vendor translations['message_underscore'] = utils.build_underscore_name( message.name) translations[ 'message_fullname_underscore'] = utils.build_underscore_name( message.fullname) translations['input_camelcase'] = utils.build_camelcase_name( message.input.fullname) translations['output_camelcase'] = utils.build_camelcase_name( message.output.fullname) translations['input_underscore'] = utils.build_underscore_name( message.input.fullname) translations['output_underscore'] = utils.build_underscore_name( message.output.fullname) translations['message_since'] = message.since if message.input.fields is None: translations['input_arg'] = 'gpointer unused' translations['input_var'] = 'NULL' translations[ 'input_doc'] = 'unused: %NULL. This message doesn\'t have any input bundle.' else: translations[ 'input_arg'] = translations['input_camelcase'] + ' *input' translations['input_var'] = 'input' translations['input_doc'] = 'input: a #' + translations[ 'input_camelcase'] + '.' template = ( '\n' '/**\n' ' * ${underscore}_${message_underscore}:\n' ' * @self: a #${camelcase}.\n' ' * @${input_doc}\n' ' * @timeout: maximum time to wait for the method to complete, in seconds.\n' ' * @cancellable: a #GCancellable or %NULL.\n' ' * @callback: a #GAsyncReadyCallback to call when the request is satisfied.\n' ' * @user_data: user data to pass to @callback.\n' ' *\n' ' * Asynchronously sends a ${message_name} request to the device.\n' ) if message.abort: template += ( ' *\n' ' * This message is abortable. If @cancellable is cancelled or if @timeout expires,\n' ' * an abort request will be sent to the device, and the asynchronous operation will\n' ' * not return until the abort response is received. It is not an error if a successful\n' ' * response is returned for the asynchronous operation even after the user has cancelled\n' ' * the cancellable, because it may happen that the response is received before the\n' ' * modem had a chance to run the abort.\n') template += ( ' *\n' ' * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from.\n' ' *\n' ' * You can then call ${underscore}_${message_underscore}_finish() to get the result of the operation.\n' ' *\n' ' * Since: ${message_since}\n' ' */\n' 'void ${underscore}_${message_underscore} (\n' ' ${camelcase} *self,\n' ' ${input_arg},\n' ' guint timeout,\n' ' GCancellable *cancellable,\n' ' GAsyncReadyCallback callback,\n' ' gpointer user_data);\n' '\n' '/**\n' ' * ${underscore}_${message_underscore}_finish:\n' ' * @self: a #${camelcase}.\n' ' * @res: the #GAsyncResult obtained from the #GAsyncReadyCallback passed to ${underscore}_${message_underscore}().\n' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Finishes an async operation started with ${underscore}_${message_underscore}().\n' ' *\n' ' * Returns: a #${output_camelcase}, or %NULL if @error is set. The returned value should be freed with ${output_underscore}_unref().\n' ' *\n' ' * Since: ${message_since}\n' ' */\n' '${output_camelcase} *${underscore}_${message_underscore}_finish (\n' ' ${camelcase} *self,\n' ' GAsyncResult *res,\n' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' '${output_camelcase} *\n' '${underscore}_${message_underscore}_finish (\n' ' ${camelcase} *self,\n' ' GAsyncResult *res,\n' ' GError **error)\n' '{\n' ' return g_task_propagate_pointer (G_TASK (res), error);\n' '}\n') if message.abort: template += ( '\n' '#if defined HAVE_QMI_MESSAGE_${service_uppercase}_ABORT\n' '\n' 'static QmiMessage *\n' '__${message_fullname_underscore}_abortable_build_request (\n' ' QmiDevice *self,\n' ' QmiMessage *message,\n' ' QmiClient *client,\n' ' GError **error)\n' '{\n' ' QmiMessage *abort_request;\n' ' guint16 transaction_id;\n' ' g_autoptr(QmiMessage${service_camelcase}AbortInput) input = NULL;\n' '\n' ' transaction_id = qmi_message_get_transaction_id (message);\n' ' g_assert (transaction_id != 0);\n' '\n' ' input = qmi_message_${service_lowercase}_abort_input_new ();\n' ' qmi_message_${service_lowercase}_abort_input_set_transaction_id (\n' ' input,\n' ' transaction_id,\n' ' NULL);\n' ' abort_request = __qmi_message_${service_lowercase}_abort_request_create (\n' ' qmi_client_get_next_transaction_id (client),\n' ' qmi_client_get_cid (client),\n' ' input,\n' ' NULL);\n' ' return abort_request;\n' '}\n' '\n' 'static gboolean\n' '__${message_fullname_underscore}_abortable_parse_response (\n' ' QmiDevice *self,\n' ' QmiMessage *abort_response,\n' ' QmiClient *client,\n' ' GError **error)\n' '{\n' ' g_autoptr(QmiMessage${service_camelcase}AbortOutput) output = NULL;\n' '\n' ' output = __qmi_message_${service_lowercase}_abort_response_parse (\n' ' abort_response,\n' ' error);\n' ' return !!output;\n' '}\n' '\n' '#endif /* HAVE_QMI_MESSAGE_${service_uppercase}_ABORT */\n' '\n') template += ('\n' 'static void\n' '${message_underscore}_ready (\n' ' QmiDevice *device,\n' ' GAsyncResult *res,\n' ' GTask *task)\n' '{\n' ' GError *error = NULL;\n' ' QmiMessage *reply;\n' ' ${output_camelcase} *output;\n' '\n') if message.abort: template += ( ' reply = qmi_device_command_abortable_finish (device, res, &error);\n' ) else: template += ( ' reply = qmi_device_command_full_finish (device, res, &error);\n' ) template += (' if (!reply) {\n') template += ( ' g_task_return_error (task, error);\n' ' g_object_unref (task);\n' ' return;\n' ' }\n' '\n' ' /* Parse reply */\n' ' output = __${message_fullname_underscore}_response_parse (reply, &error);\n' ' if (!output)\n' ' g_task_return_error (task, error);\n' ' else\n' ' g_task_return_pointer (task,\n' ' output,\n' ' (GDestroyNotify)${output_underscore}_unref);\n' ' g_object_unref (task);\n' ' qmi_message_unref (reply);\n' '}\n' '\n' 'void\n' '${underscore}_${message_underscore} (\n' ' ${camelcase} *self,\n' ' ${input_arg},\n' ' guint timeout,\n' ' GCancellable *cancellable,\n' ' GAsyncReadyCallback callback,\n' ' gpointer user_data)\n' '{\n' ' GTask *task;\n' ' GError *error = NULL;\n' ' guint16 transaction_id;\n' ' g_autoptr(QmiMessage) request = NULL;\n') if message.vendor is not None: template += ( ' g_autoptr(QmiMessageContext) context = NULL;\n') template += ( '\n' ' task = g_task_new (self, cancellable, callback, user_data);\n' ' if (!qmi_client_is_valid (QMI_CLIENT (self))) {\n' ' g_task_return_new_error (task, QMI_CORE_ERROR, QMI_CORE_ERROR_WRONG_STATE, "client invalid");\n' ' g_object_unref (task);\n' ' return;\n' ' }\n' '\n' ' transaction_id = qmi_client_get_next_transaction_id (QMI_CLIENT (self));\n' '\n' ' request = __${message_fullname_underscore}_request_create (\n' ' transaction_id,\n' ' qmi_client_get_cid (QMI_CLIENT (self)),\n' ' ${input_var},\n' ' &error);\n' ' if (!request) {\n' ' g_prefix_error (&error, "Couldn\'t create request message: ");\n' ' g_task_return_error (task, error);\n' ' g_object_unref (task);\n' ' return;\n' ' }\n') if message.vendor is not None: template += ( '\n' ' context = qmi_message_context_new ();\n' ' qmi_message_context_set_vendor_id (context, ${message_vendor_id});\n' ) if message.abort: template += ( '\n' ' qmi_device_command_abortable (QMI_DEVICE (qmi_client_peek_device (QMI_CLIENT (self))),\n' ) else: template += ( '\n' ' qmi_device_command_full (QMI_DEVICE (qmi_client_peek_device (QMI_CLIENT (self))),\n' ) template += (' request,\n') if message.vendor is not None: template += (' context,\n') else: template += (' NULL,\n') template += (' timeout,\n') if message.abort: template += ( '#if defined HAVE_QMI_MESSAGE_${service_uppercase}_ABORT\n' ' (QmiDeviceCommandAbortableBuildRequestFn) __${message_fullname_underscore}_abortable_build_request,\n' ' (QmiDeviceCommandAbortableParseResponseFn) __${message_fullname_underscore}_abortable_parse_response,\n' ' g_object_ref (self),\n' ' g_object_unref,\n' '#else\n' ' NULL,\n' ' NULL,\n' ' NULL,\n' ' NULL,\n' '#endif\n') template += ( ' cancellable,\n' ' (GAsyncReadyCallback)${message_underscore}_ready,\n' ' task);\n') template += ('}\n' '\n') cfile.write(string.Template(template).substitute(translations))
def __emit_get_printable(self, hfile, cfile): translations = { 'service' : self.service.lower() } template = ( '\n' '#if defined (LIBQMI_GLIB_COMPILATION)\n' '\n' 'G_GNUC_INTERNAL\n' 'gchar *__qmi_message_${service}_get_printable (\n' ' QmiMessage *self,\n' ' QmiMessageContext *context,\n' ' const gchar *line_prefix);\n' '\n' '#endif\n' '\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' 'gchar *\n' '__qmi_message_${service}_get_printable (\n' ' QmiMessage *self,\n' ' QmiMessageContext *context,\n' ' const gchar *line_prefix)\n' '{\n' ' if (qmi_message_is_indication (self)) {\n' ' switch (qmi_message_get_message_id (self)) {\n') for message in self.list: if message.type == 'Indication': translations['enum_name'] = message.id_enum_name translations['message_underscore'] = utils.build_underscore_name (message.name) inner_template = ( ' case ${enum_name}:\n' ' return indication_${message_underscore}_get_printable (self, line_prefix);\n') template += string.Template(inner_template).substitute(translations) template += ( ' default:\n' ' return NULL;\n' ' }\n' ' } else {\n' ' guint16 vendor_id;\n' '\n' ' vendor_id = (context ? qmi_message_context_get_vendor_id (context) : QMI_MESSAGE_VENDOR_GENERIC);\n' ' if (vendor_id == QMI_MESSAGE_VENDOR_GENERIC) {\n' ' switch (qmi_message_get_message_id (self)) {\n') for message in self.list: if message.type == 'Message' and message.vendor is None: translations['enum_name'] = message.id_enum_name translations['message_underscore'] = utils.build_underscore_name (message.name) inner_template = ( ' case ${enum_name}:\n' ' return message_${message_underscore}_get_printable (self, line_prefix);\n') template += string.Template(inner_template).substitute(translations) template += ( ' default:\n' ' return NULL;\n' ' }\n' ' } else {\n') for message in self.list: if message.type == 'Message' and message.vendor is not None: translations['enum_name'] = message.id_enum_name translations['message_underscore'] = utils.build_underscore_name (message.name) translations['message_vendor'] = message.vendor inner_template = ( ' if (vendor_id == ${message_vendor} && (qmi_message_get_message_id (self) == ${enum_name}))\n' ' return message_${message_underscore}_get_printable (self, line_prefix);\n') template += string.Template(inner_template).substitute(translations) template += ( ' return NULL;\n' ' }\n' ' }\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def emit_getter(self, hfile, cfile): input_variable_name = 'value_' + utils.build_underscore_name(self.name) variable_getter_dec = self.variable.build_getter_declaration(' ', input_variable_name) variable_getter_doc = self.variable.build_getter_documentation(' * ', input_variable_name) variable_getter_imp = self.variable.build_getter_implementation(' ', 'self->' + self.variable_name, input_variable_name, True) translations = { 'name' : self.name, 'variable_name' : self.variable_name, 'variable_getter_dec' : variable_getter_dec, 'variable_getter_doc' : variable_getter_doc, 'variable_getter_imp' : variable_getter_imp, 'underscore' : utils.build_underscore_name(self.name), 'prefix_camelcase' : utils.build_camelcase_name(self.prefix), 'prefix_underscore' : utils.build_underscore_name(self.prefix), 'since' : self.since, 'static' : 'static ' if self.static else '' } # Emit the getter header template = ( '\n' '/**\n' ' * ${prefix_underscore}_get_${underscore}:\n' ' * @self: a #${prefix_camelcase}.\n' '${variable_getter_doc}' ' * @error: Return location for error or %NULL.\n' ' *\n' ' * Get the \'${name}\' field from @self.\n' ' *\n' ' * Returns: %TRUE if the field is found, %FALSE otherwise.\n' ' *\n' ' * Since: ${since}\n' ' */\n' '${static}gboolean ${prefix_underscore}_get_${underscore} (\n' ' ${prefix_camelcase} *self,\n' '${variable_getter_dec}' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) # Emit the getter source template = ( '\n' '${static}gboolean\n' '${prefix_underscore}_get_${underscore} (\n' ' ${prefix_camelcase} *self,\n' '${variable_getter_dec}' ' GError **error)\n' '{\n' ' g_return_val_if_fail (self != NULL, FALSE);\n' '\n' ' if (!self->${variable_name}_set) {\n' ' g_set_error (error,\n' ' QMI_CORE_ERROR,\n' ' QMI_CORE_ERROR_TLV_NOT_FOUND,\n' ' "Field \'${name}\' was not found in the message");\n' ' return FALSE;\n' ' }\n' '\n' '${variable_getter_imp}' '\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def emit_tlv_helpers(self, f): if TypeFactory.helpers_emitted(self.fullname): return TypeFactory.set_helpers_emitted(self.fullname) translations = { 'name': self.name, 'tlv_id': self.id_enum_name, 'underscore': utils.build_underscore_name(self.fullname) } template = ( '\n' 'static gboolean\n' '${underscore}_validate (\n' ' const guint8 *buffer,\n' ' guint16 buffer_len)\n' '{\n' ' static const guint expected_len = 4;\n' '\n' ' if (buffer_len < expected_len) {\n' ' g_warning ("Cannot read the \'${name}\' TLV: expected \'%u\' bytes, but only got \'%u\' bytes",\n' ' expected_len, buffer_len);\n' ' return FALSE;\n' ' }\n' '\n' ' return TRUE;\n' '}\n') f.write(string.Template(template).substitute(translations)) template = ( '\n' 'static gchar *\n' '${underscore}_get_printable (\n' ' QmiMessage *self,\n' ' const gchar *line_prefix)\n' '{\n' ' const guint8 *buffer;\n' ' guint16 buffer_len;\n' '\n' ' buffer = qmi_message_get_raw_tlv (self,\n' ' ${tlv_id},\n' ' &buffer_len);\n' ' if (buffer) {\n' ' GString *printable;\n' ' guint16 error_status;\n' ' guint16 error_code;\n' '\n' ' printable = g_string_new ("");\n' ' qmi_utils_read_guint16_from_buffer (\n' ' &buffer,\n' ' &buffer_len,\n' ' QMI_ENDIAN_LITTLE,\n' ' &error_status);\n' ' qmi_utils_read_guint16_from_buffer (\n' ' &buffer,\n' ' &buffer_len,\n' ' QMI_ENDIAN_LITTLE,\n' ' &error_code);\n' '\n' ' g_warn_if_fail (buffer_len == 0);\n' '\n' ' if (error_status == QMI_STATUS_SUCCESS)\n' ' g_string_append (printable, "SUCCESS");\n' ' else\n' ' g_string_append_printf (printable,\n' ' "FAILURE: %s",\n' ' qmi_protocol_error_get_string ((QmiProtocolError) error_code));\n' '\n' ' return g_string_free (printable, FALSE);\n' ' }\n' '\n' ' return NULL;\n' '}\n') f.write(string.Template(template).substitute(translations))
def emit_printable_service(self, hfile, cfile, service): translations = { 'service_underscore' : utils.build_underscore_name(service), 'service' : service } template = ( '\n' 'G_GNUC_INTERNAL\n' 'gchar *\n' '__mbim_message_${service_underscore}_get_printable_fields (\n' ' const MbimMessage *message,\n' ' const gchar *line_prefix,\n' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' 'static const GetPrintableCallbacks ${service_underscore}_get_printable_callbacks[] = {\n') for item in self.command_list: if item.service == service: translations['message'] = utils.build_underscore_name (item.fullname) translations['cid'] = item.cid_enum_name inner_template = ( ' [${cid}] = {\n') if item.has_query: inner_template += ( ' .query_cb = ${message}_query_get_printable,\n') if item.has_set: inner_template += ( ' .set_cb = ${message}_set_get_printable,\n') if item.has_response: inner_template += ( ' .response_cb = ${message}_response_get_printable,\n') if item.has_notification: inner_template += ( ' .notification_cb = ${message}_notification_get_printable,\n') inner_template += ( ' },\n') template += (string.Template(inner_template).substitute(translations)) template += ( '};\n' '\n' 'gchar *\n' '__mbim_message_${service_underscore}_get_printable_fields (\n' ' const MbimMessage *message,\n' ' const gchar *line_prefix,\n' ' GError **error)\n' '{\n' ' guint32 cid;\n' '\n' ' switch (mbim_message_get_message_type (message)) {\n' ' case MBIM_MESSAGE_TYPE_COMMAND: {\n' ' cid = mbim_message_command_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (${service_underscore}_get_printable_callbacks)) {\n' ' switch (mbim_message_command_get_command_type (message)) {\n' ' case MBIM_MESSAGE_COMMAND_TYPE_QUERY:\n' ' if (${service_underscore}_get_printable_callbacks[cid].query_cb)\n' ' return ${service_underscore}_get_printable_callbacks[cid].query_cb (message, line_prefix, error);\n' ' break;\n' ' case MBIM_MESSAGE_COMMAND_TYPE_SET:\n' ' if (${service_underscore}_get_printable_callbacks[cid].set_cb)\n' ' return ${service_underscore}_get_printable_callbacks[cid].set_cb (message, line_prefix, error);\n' ' break;\n' ' case MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN:\n' ' default:\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Invalid command type\");\n' ' return NULL;\n' ' }\n' ' }\n' ' break;\n' ' }\n' '\n' ' case MBIM_MESSAGE_TYPE_COMMAND_DONE:\n' ' cid = mbim_message_command_done_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (${service_underscore}_get_printable_callbacks)) {\n' ' if (${service_underscore}_get_printable_callbacks[cid].response_cb)\n' ' return ${service_underscore}_get_printable_callbacks[cid].response_cb (message, line_prefix, error);\n' ' }\n' ' break;\n' '\n' ' case MBIM_MESSAGE_TYPE_INDICATE_STATUS:\n' ' cid = mbim_message_indicate_status_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (${service_underscore}_get_printable_callbacks)) {\n' ' if (${service_underscore}_get_printable_callbacks[cid].notification_cb)\n' ' return ${service_underscore}_get_printable_callbacks[cid].notification_cb (message, line_prefix, error);\n' ' }\n' ' break;\n' '\n' ' case MBIM_MESSAGE_TYPE_OPEN: \n' ' case MBIM_MESSAGE_TYPE_CLOSE: \n' ' case MBIM_MESSAGE_TYPE_INVALID: \n' ' case MBIM_MESSAGE_TYPE_HOST_ERROR: \n' ' case MBIM_MESSAGE_TYPE_OPEN_DONE: \n' ' case MBIM_MESSAGE_TYPE_CLOSE_DONE: \n' ' case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: \n' ' default:\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"No contents expected in this message type\");\n' ' return NULL;\n' ' }\n' '\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_UNSUPPORTED,\n' ' \"Unsupported message\");\n' ' return NULL;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def emit_buffer_read(self, f, line_prefix, tlv_out, error, variable_name): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp': line_prefix, 'variable_name': variable_name, 'private_format': self.private_format, 'public_array_element_format': self.array_element.public_format, 'underscore': self.clear_func_name(), 'common_var_prefix': common_var_prefix } template = ('${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size: translations['fixed_size'] = self.fixed_size template = ( '${lp} guint16 ${common_var_prefix}_n_items = ${fixed_size};\n' '\n') f.write(string.Template(template).substitute(translations)) else: translations[ 'array_size_element_format'] = self.array_size_element.public_format template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n' ) if self.array_sequence_element != '': translations[ 'array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp} ${array_sequence_element_format} ${common_var_prefix}_sequence;\n' ) template += ('\n' '${lp} /* Read number of items in the array */\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_read( f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_n_items') if self.array_sequence_element != '': template = ('\n' '${lp} /* Read sequence in the array */\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_read( f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_sequence') template = ( '\n' '${lp} ${variable_name}_sequence = ${common_var_prefix}_sequence;\n' ) f.write(string.Template(template).substitute(translations)) template = ('\n' '${lp} ${variable_name} = g_array_sized_new (\n' '${lp} FALSE,\n' '${lp} FALSE,\n' '${lp} sizeof (${public_array_element_format}),\n' '${lp} (guint)${common_var_prefix}_n_items);\n' '\n') if self.array_element.needs_dispose == True: template += ( '${lp} g_array_set_clear_func (${variable_name},\n' '${lp} (GDestroyNotify)${underscore}_clear);\n' '\n') template += ( '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${common_var_prefix}_n_items; ${common_var_prefix}_i++) {\n' '${lp} ${public_array_element_format} ${common_var_prefix}_aux;\n' '\n') f.write(string.Template(template).substitute(translations)) self.array_element.emit_buffer_read(f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_aux') template = ( '${lp} g_array_insert_val (${variable_name}, ${common_var_prefix}_i, ${common_var_prefix}_aux);\n' '${lp} }\n' '${lp}}\n') f.write(string.Template(template).substitute(translations))
def emit_get_printable(self, f, line_prefix): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp': line_prefix, 'common_var_prefix': common_var_prefix } template = ('${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size: translations['fixed_size'] = self.fixed_size template = ( '${lp} guint16 ${common_var_prefix}_n_items = ${fixed_size};\n' '\n') f.write(string.Template(template).substitute(translations)) else: translations[ 'array_size_element_format'] = self.array_size_element.public_format template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n' ) if self.array_sequence_element != '': translations[ 'array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp} ${array_sequence_element_format} ${common_var_prefix}_sequence;\n' ) template += ('\n' '${lp} /* Read number of items in the array */\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_read( f, line_prefix + ' ', 'out', '&error', common_var_prefix + '_n_items') if self.array_sequence_element != '': template = ('\n' '${lp} /* Read sequence */\n') f.write(string.Template(template).substitute(translations)) self.array_sequence_element.emit_buffer_read( f, line_prefix + ' ', 'out', '&error', common_var_prefix + '_sequence') template = ( '\n' '${lp} g_string_append_printf (printable, "[[Seq:%u]] ", ${common_var_prefix}_sequence);\n' ) f.write(string.Template(template).substitute(translations)) template = ( '\n' '${lp} g_string_append (printable, "{");\n' '\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${common_var_prefix}_n_items; ${common_var_prefix}_i++) {\n' '${lp} g_string_append_printf (printable, " [%u] = \'", ${common_var_prefix}_i);\n' ) f.write(string.Template(template).substitute(translations)) self.array_element.emit_get_printable(f, line_prefix + ' ') template = ('${lp} g_string_append (printable, " \'");\n' '${lp} }\n' '\n' '${lp} g_string_append (printable, "}");\n' '${lp}}') f.write(string.Template(template).substitute(translations))
def _emit_message_parser(self, hfile, cfile, message_type, fields): translations = { 'name' : self.name, 'service' : self.service, 'underscore' : utils.build_underscore_name (self.fullname), 'message_type' : message_type, 'message_type_upper' : message_type.upper(), 'service_underscore_upper' : utils.build_underscore_name (self.service).upper() } template = ( '\n' 'gboolean ${underscore}_${message_type}_parse (\n' ' const MbimMessage *message,\n') 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'] == 'byte-array': inner_template = (' const guint8 **${field},\n') elif field['format'] == 'unsized-byte-array' or field['format'] == 'ref-byte-array': inner_template = (' guint32 *${field}_size,\n' ' const guint8 **${field},\n') elif 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') else: raise ValueError('Cannot handle field type \'%s\'' % field['format']) template += (string.Template(inner_template).substitute(translations)) template += ( ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' '/**\n' ' * ${underscore}_${message_type}_parse:\n' ' * @message: the #MbimMessage.\n') 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']) translations['array_size'] = field['array-size'] if 'array-size' in field else '' if field['format'] == 'byte-array': inner_template = (' * @${field}: return location for an array of ${array_size} #guint8 values. Do not free the returned value, it is owned by @message.\n') elif field['format'] == 'unsized-byte-array' or field['format'] == 'ref-byte-array': inner_template = (' * @${field}_size: return location for the size of the ${field} array.\n' ' * @${field}: return location for an array of #guint8 values. Do not free the returned value, it is owned by @message.\n') elif 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' ' *\n' ' * Create a new request for the \'${name}\' ${message_type} command in the \'${service}\' service.\n' ' *\n' ' * Returns: %TRUE if the message was correctly parsed, %FALSE if @error is set.\n' ' */\n' 'gboolean\n' '${underscore}_${message_type}_parse (\n' ' const MbimMessage *message,\n') 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'] == 'byte-array': inner_template = (' const guint8 **${field},\n') elif field['format'] == 'unsized-byte-array' or field['format'] == 'ref-byte-array': inner_template = (' guint32 *${field}_size,\n' ' const guint8 **${field},\n') elif 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') if fields != []: template += ( ' guint32 offset = 0;\n') for field in fields: if 'always-read' in field: translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) inner_template = (' guint32 _${field};\n') template += (string.Template(inner_template).substitute(translations)) if message_type == 'response': template += ( '\n' ' if (mbim_message_get_message_type (message) != MBIM_MESSAGE_TYPE_COMMAND_DONE) {\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Message is not a response\");\n' ' return FALSE;\n' ' }\n') elif message_type == 'notification': template += ( '\n' ' if (mbim_message_get_message_type (message) != MBIM_MESSAGE_TYPE_INDICATE_STATUS) {\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Message is not a notification\");\n' ' return FALSE;\n' ' }\n') else: raise ValueError('Unexpected message type \'%s\'' % message_type) 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 '' translations['array_size'] = field['array-size'] if 'array-size' in field else '' inner_template = ( '\n' ' /* Read the \'${field_name}\' variable */\n') if 'available-if' in field: condition = field['available-if'] translations['condition_field'] = utils.build_underscore_name_from_camelcase(condition['field']) translations['condition_operation'] = condition['operation'] translations['condition_value'] = condition['value'] inner_template += ( ' if (!(_${condition_field} ${condition_operation} ${condition_value})) {\n') if field['format'] == 'byte-array': inner_template += ( ' if (${field})\n' ' *${field} = NULL;\n') elif field['format'] == 'unsized-byte-array' or \ field['format'] == 'ref-byte-array': inner_template += ( ' if (${field}_size)\n' ' *${field}_size = 0;\n' ' if (${field})\n' ' *${field} = NULL;\n') elif field['format'] == 'guint32-array' or \ field['format'] == 'string' or \ field['format'] == 'string-array' or \ field['format'] == 'struct' or \ field['format'] == 'struct-array' or \ field['format'] == 'ref-struct-array' or \ field['format'] == 'ipv4' or \ field['format'] == 'ref-ipv4' or \ field['format'] == 'ipv4-array' or \ field['format'] == 'ipv6' or \ field['format'] == 'ref-ipv6' or \ field['format'] == 'ipv6-array': inner_template += ( ' if (${field} != NULL)\n' ' *${field} = NULL;\n') else: raise ValueError('Field format \'%s\' unsupported as optional field' % field['format']) inner_template += ( ' } else {\n') else: inner_template += ( ' {\n') if 'always-read' 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'] == 'byte-array': inner_template += ( ' const guint8 *tmp;\n' '\n' ' tmp = _mbim_message_read_byte_array (message, 0, offset, FALSE, FALSE, NULL);\n' ' if (${field} != NULL)\n' ' *${field} = tmp;\n' ' offset += ${array_size};\n') elif field['format'] == 'unsized-byte-array': inner_template += ( ' const guint8 *tmp;\n' ' guint32 tmpsize;\n' '\n' ' tmp = _mbim_message_read_byte_array (message, 0, offset, FALSE, FALSE, &tmpsize);\n' ' if (${field} != NULL)\n' ' *${field} = tmp;\n' ' if (${field}_size != NULL)\n' ' *${field}_size = tmpsize;\n' ' offset += tmpsize;\n') elif field['format'] == 'ref-byte-array': inner_template += ( ' const guint8 *tmp;\n' ' guint32 tmpsize;\n' '\n' ' tmp = _mbim_message_read_byte_array (message, 0, offset, TRUE, TRUE, &tmpsize);\n' ' if (${field} != NULL)\n' ' *${field} = tmp;\n' ' if (${field}_size != NULL)\n' ' *${field}_size = tmpsize;\n' ' offset += 8;\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 += ( ' 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, 0, 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}, 0, 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') inner_template += ( ' }\n') template += (string.Template(inner_template).substitute(translations)) template += ( '\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations))
def __emit_request_creator(self, hfile, cfile): translations = { 'name': self.name, 'service': self.service, 'container': utils.build_camelcase_name(self.input.fullname), 'underscore': utils.build_underscore_name(self.fullname), 'message_id': self.id_enum_name } input_arg_template = 'gpointer unused' if self.input.fields is None else '${container} *input' template = ('\n' 'static QmiMessage *\n' '__${underscore}_request_create (\n' ' guint16 transaction_id,\n' ' guint8 cid,\n' ' %s,\n' ' GError **error)\n' '{\n' ' QmiMessage *self;\n' '\n' ' self = qmi_message_new (QMI_SERVICE_${service},\n' ' cid,\n' ' transaction_id,\n' ' ${message_id});\n' % input_arg_template) cfile.write(string.Template(template).substitute(translations)) if self.input.fields: # Count how many mandatory fields we have n_mandatory = 0 for field in self.input.fields: if field.mandatory: n_mandatory += 1 if n_mandatory == 0: # If we don't have mandatory fields, we do allow to have # a NULL input cfile.write( '\n' ' /* All TLVs are optional, we allow NULL input */\n' ' if (!input)\n' ' return self;\n') else: # If we do have mandatory fields, issue error if no input # given. template = ( '\n' ' /* There is at least one mandatory TLV, don\'t allow NULL input */\n' ' if (!input) {\n' ' g_set_error (error,\n' ' QMI_CORE_ERROR,\n' ' QMI_CORE_ERROR_INVALID_ARGS,\n' ' "Message \'${name}\' has mandatory TLVs");\n' ' goto error_out;\n' ' }\n') cfile.write(string.Template(template).substitute(translations)) # Now iterate fields for field in self.input.fields: translations['tlv_name'] = field.name translations['variable_name'] = field.variable_name template = ('\n' ' /* Try to add the \'${tlv_name}\' TLV */\n' ' if (input->${variable_name}_set) {\n') cfile.write(string.Template(template).substitute(translations)) # Emit the TLV getter field.emit_input_tlv_add(cfile, ' ') if field.mandatory: template = ( ' } else {\n' ' g_set_error (error,\n' ' QMI_CORE_ERROR,\n' ' QMI_CORE_ERROR_INVALID_ARGS,\n' ' "Missing mandatory TLV \'${tlv_name}\' in message \'${name}\'");\n' ' goto error_out;\n') cfile.write( string.Template(template).substitute(translations)) cfile.write(' }\n') cfile.write('\n' ' return self;\n') if self.input.fields: cfile.write('\n' 'error_out:\n' ' qmi_message_unref (self);\n' ' return NULL;\n') cfile.write('}\n')
def emit_tlv_helpers(self, f): if TypeFactory.helpers_emitted(self.fullname): return TypeFactory.set_helpers_emitted(self.fullname) translations = { 'name': self.name, 'tlv_id': self.id_enum_name, 'underscore': utils.build_underscore_name(self.fullname) } template = ('\n' 'static gboolean\n' '${underscore}_validate (\n' ' const guint8 *buffer,\n' ' guint16 buffer_len)\n' '{\n' ' guint expected_len = 0;\n' '\n') f.write(string.Template(template).substitute(translations)) # Now, read the size of the expected TLV self.variable.emit_size_read(f, ' ', 'expected_len', 'buffer', 'buffer_len') template = ( '\n' ' if (buffer_len < expected_len) {\n' ' g_warning ("Cannot read the \'${name}\' TLV: expected \'%u\' bytes, but only got \'%u\' bytes",\n' ' expected_len, buffer_len);\n' ' return FALSE;\n' ' }\n' '\n' ' if (buffer_len > expected_len) {\n' ' g_debug ("Reading the \'${name}\' TLV: expected \'%u\' bytes, but got \'%u\' bytes",\n' ' expected_len, buffer_len);\n' ' return TRUE;\n' ' }\n' '\n' ' return TRUE;\n' '}\n' '\n') f.write(string.Template(template).substitute(translations)) template = ( '\n' 'static gchar *\n' '${underscore}_get_printable (\n' ' QmiMessage *message,\n' ' const gchar *line_prefix)\n' '{\n' ' const guint8 *buffer;\n' ' guint16 buffer_len;\n' '\n' ' buffer = qmi_message_get_raw_tlv (message,\n' ' ${tlv_id},\n' ' &buffer_len);\n' ' if (buffer && ${underscore}_validate (buffer, buffer_len)) {\n' ' GString *printable;\n' '\n' ' printable = g_string_new ("");\n') f.write(string.Template(template).substitute(translations)) # Now, read the contents of the buffer into the printable representation self.variable.emit_get_printable(f, ' ', 'printable', 'buffer', 'buffer_len') template = ( '\n' ' /* The remaining size of the buffer needs to be 0 if we successfully read the TLV */\n' ' if (buffer_len > 0) {\n' ' g_warning ("Left \'%u\' bytes unread when getting the \'${name}\' TLV as printable", buffer_len);\n' ' }\n' '\n' ' return g_string_free (printable, FALSE);\n' ' }\n' '\n' ' return NULL;\n' '}\n') f.write(string.Template(template).substitute(translations))