aboutsummaryrefslogtreecommitdiffstats
path: root/build-aux
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-07-05 17:17:58 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-07-23 12:51:47 +0200
commitaf6d4526b1e990a3b64c9c4d8a2905b67a1a8399 (patch)
tree2e90db87d5486b3943e9abf968fb287fa9ad3aeb /build-aux
parent5ad07e7bc714dcb66b74deed610a3b61729f7839 (diff)
qmi-codegen: convert indication messages received into `QmiClient' signals
Diffstat (limited to 'build-aux')
-rw-r--r--build-aux/qmi-codegen/Client.py110
-rw-r--r--build-aux/qmi-codegen/Message.py84
-rw-r--r--build-aux/qmi-codegen/MessageList.py105
-rw-r--r--build-aux/qmi-codegen/utils.py8
4 files changed, 239 insertions, 68 deletions
diff --git a/build-aux/qmi-codegen/Client.py b/build-aux/qmi-codegen/Client.py
index 32f5cb4..73674f6 100644
--- a/build-aux/qmi-codegen/Client.py
+++ b/build-aux/qmi-codegen/Client.py
@@ -48,7 +48,15 @@ class Client:
"""
Emits the generic GObject class implementation
"""
- def __emit_class(self, hfile, cfile):
+ 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' : string.upper(utils.build_underscore_name(self.name[4:])),
'camelcase' : utils.build_camelcase_name (self.name) }
@@ -81,7 +89,66 @@ class Client:
# Emit class source
template = (
'\n'
- 'G_DEFINE_TYPE (${camelcase}, ${underscore}, QMI_TYPE_CLIENT);\n'
+ '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['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)
+ translations['signal_id'] = utils.build_underscore_uppercase_name(message.name)
+ 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')
+ template += string.Template(inner_template).substitute(translations)
+
+ template += (
+ ' default:\n'
+ ' break;\n'
+ ' }\n'
+ '}\n'
'\n'
'static void\n'
'${underscore}_init (${camelcase} *self)\n'
@@ -91,6 +158,39 @@ class Client:
'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['output_camelcase'] = utils.build_camelcase_name(message.output.fullname)
+ translations['signal_name'] = utils.build_dashed_name(message.name)
+ translations['signal_id'] = utils.build_underscore_uppercase_name(message.name)
+ translations['bundle_type'] = 'QMI_TYPE_' + utils.remove_prefix(utils.build_underscore_uppercase_name(message.output.fullname), 'QMI_')
+ 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 \'${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'
+ ' 1,\n'
+ ' ${bundle_type});\n')
+ template += string.Template(inner_template).substitute(translations)
+
+ template += (
'}\n'
'\n')
cfile.write(string.Template(template).substitute(translations))
@@ -104,6 +204,10 @@ class Client:
'camelcase' : utils.build_camelcase_name (self.name) }
for message in message_list.list:
+
+ if message.type == 'Indication':
+ continue
+
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)
@@ -227,5 +331,5 @@ class Client:
# First, emit common class code
utils.add_separator(hfile, 'CLIENT', self.name);
utils.add_separator(cfile, 'CLIENT', self.name);
- self.__emit_class(hfile, cfile)
+ self.__emit_class(hfile, cfile, message_list)
self.__emit_methods(hfile, cfile, message_list)
diff --git a/build-aux/qmi-codegen/Message.py b/build-aux/qmi-codegen/Message.py
index bb562aa..a187193 100644
--- a/build-aux/qmi-codegen/Message.py
+++ b/build-aux/qmi-codegen/Message.py
@@ -32,19 +32,20 @@ class Message:
Constructor
"""
def __init__(self, dictionary, common_objects_dictionary):
- # The message prefix
- self.prefix = 'Qmi Message'
# 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'
+ # 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 []
+ # The message prefix
+ self.prefix = 'Qmi ' + self.type
+
# Create the composed full name (prefix + service + name),
# e.g. "Qmi Message Ctl Something Output Result"
self.fullname = self.prefix + ' ' + self.service + ' ' + self.name
@@ -55,20 +56,22 @@ class Message:
# 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
+ # field. This applies to both Request/Response and Indications.
self.output = Container(self.fullname,
'Output',
dictionary['output'],
common_objects_dictionary)
- # Build input container.
- # 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.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)
"""
@@ -176,10 +179,11 @@ class Message:
"""
- Emit method responsible for parsing a response of the given type
+ Emit method responsible for parsing a response/indication of the given type
"""
- def __emit_response_parser(self, hfile, cfile):
+ def __emit_response_or_indication_parser(self, hfile, cfile):
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),
@@ -187,7 +191,7 @@ class Message:
template = (
'\n'
- '${container} *${underscore}_response_parse (\n'
+ '${container} *${underscore}_${type}_parse (\n'
' QmiMessage *message,\n'
' GError **error);\n')
hfile.write(string.Template(template).substitute(translations))
@@ -195,16 +199,16 @@ class Message:
template = (
'\n'
'/**\n'
- ' * ${underscore}_response_parse:\n'
- ' * @message: a #QmiMessage response.\n'
+ ' * ${underscore}_${type}_parse:\n'
+ ' * @message: a #QmiMessage ${type}.\n'
' * @error: a #GError.\n'
' *\n'
- ' * Parse the \'${name}\' response.\n'
+ ' * Parse the \'${name}\' ${type}.\n'
' *\n'
' * Returns: a #${container} which should be disposed with ${container_underscore}_unref(), or #NULL if @error is set.\n'
' */\n'
'${container} *\n'
- '${underscore}_response_parse (\n'
+ '${underscore}_${type}_parse (\n'
' QmiMessage *message,\n'
' GError **error)\n'
'{\n'
@@ -242,7 +246,7 @@ class Message:
"""
def __emit_get_printable(self, hfile, cfile):
- if self.input.fields is not None:
+ if self.input is not None and self.input.fields is not None:
for field in self.input.fields:
field.emit_tlv_get_printable(cfile)
for field in self.output.fields:
@@ -251,22 +255,23 @@ class Message:
translations = { 'name' : self.name,
'service' : self.service,
'id' : self.id,
- 'underscore' : utils.build_underscore_name (self.name) }
+ 'type' : utils.build_underscore_name(self.type),
+ 'underscore' : utils.build_underscore_name(self.name) }
template = (
'\n'
- 'struct ${underscore}_context {\n'
+ 'struct ${type}_${underscore}_context {\n'
' QmiMessage *self;\n'
' const gchar *line_prefix;\n'
' GString *printable;\n'
'};\n'
'\n'
'static void\n'
- '${underscore}_get_tlv_printable (\n'
+ '${type}_${underscore}_get_tlv_printable (\n'
' guint8 type,\n'
' gsize length,\n'
' gconstpointer value,\n'
- ' struct ${underscore}_context *ctx)\n'
+ ' struct ${type}_${underscore}_context *ctx)\n'
'{\n'
' const gchar *tlv_type_str = NULL;\n'
' gchar *translated_value;\n'
@@ -274,7 +279,7 @@ class Message:
' if (!qmi_message_is_response (ctx->self)) {\n'
' switch (type) {\n')
- if self.input.fields is not None:
+ 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
@@ -345,11 +350,11 @@ class Message:
'}\n'
'\n'
'static gchar *\n'
- '${underscore}_get_printable (\n'
+ '${type}_${underscore}_get_printable (\n'
' QmiMessage *self,\n'
' const gchar *line_prefix)\n'
'{\n'
- ' struct ${underscore}_context ctx;\n'
+ ' struct ${type}_${underscore}_context ctx;\n'
' GString *printable;\n'
'\n'
' printable = g_string_new ("");\n'
@@ -361,7 +366,7 @@ class Message:
' ctx.line_prefix = line_prefix;\n'
' ctx.printable = printable;\n'
' qmi_message_tlv_foreach (self,\n'
- ' (QmiMessageForeachTlvFn)${underscore}_get_tlv_printable,\n'
+ ' (QmiMessageForeachTlvFn)${type}_${underscore}_get_tlv_printable,\n'
' &ctx);\n'
'\n'
' return g_string_free (printable, FALSE);\n'
@@ -370,21 +375,26 @@ class Message:
"""
- Emit request/response handling implementation
+ Emit request/response/indication handling implementation
"""
def emit(self, hfile, cfile):
- utils.add_separator(hfile, 'REQUEST/RESPONSE', self.fullname);
- utils.add_separator(cfile, 'REQUEST/RESPONSE', self.fullname);
-
- hfile.write('\n/* --- Input -- */\n');
- cfile.write('\n/* --- Input -- */\n');
- self.input.emit(hfile, cfile)
- self.__emit_request_creator(hfile, cfile)
+ if self.type == 'Message':
+ utils.add_separator(hfile, 'REQUEST/RESPONSE', self.fullname);
+ utils.add_separator(cfile, 'REQUEST/RESPONSE', self.fullname);
+ else:
+ utils.add_separator(hfile, 'INDICATION', self.fullname);
+ utils.add_separator(cfile, 'INDICATION', self.fullname);
+
+ if self.type == 'Message':
+ hfile.write('\n/* --- Input -- */\n');
+ cfile.write('\n/* --- Input -- */\n');
+ self.input.emit(hfile, cfile)
+ self.__emit_request_creator(hfile, cfile)
hfile.write('\n/* --- Output -- */\n');
cfile.write('\n/* --- Output -- */\n');
self.output.emit(hfile, cfile)
- self.__emit_response_parser(hfile, cfile)
+ self.__emit_response_or_indication_parser(hfile, cfile)
hfile.write('\n/* --- Printable -- */\n');
cfile.write('\n/* --- Printable -- */\n');
diff --git a/build-aux/qmi-codegen/MessageList.py b/build-aux/qmi-codegen/MessageList.py
index a610a31..9cd057c 100644
--- a/build-aux/qmi-codegen/MessageList.py
+++ b/build-aux/qmi-codegen/MessageList.py
@@ -35,16 +35,20 @@ class MessageList:
def __init__(self, objects_dictionary, common_objects_dictionary):
self.list = []
self.message_id_enum_name = None
+ self.indication_id_enum_name = None
self.service = None
# Loop items in the list, creating Message objects for the messages
# and looking for the special 'Message-ID-Enum' type
for object_dictionary in objects_dictionary:
- if object_dictionary['type'] == 'Message':
+ if object_dictionary['type'] == 'Message' or \
+ object_dictionary['type'] == 'Indication':
message = Message(object_dictionary, common_objects_dictionary)
self.list.append(message)
elif object_dictionary['type'] == 'Message-ID-Enum':
self.message_id_enum_name = object_dictionary['name']
+ elif object_dictionary['type'] == 'Indication-ID-Enum':
+ self.indication_id_enum_name = object_dictionary['name']
elif object_dictionary['type'] == 'Service':
self.service = object_dictionary['name']
@@ -66,11 +70,33 @@ class MessageList:
'\n'
'typedef enum {\n')
for message in self.list:
- translations['enum_name'] = message.id_enum_name
- translations['enum_value'] = message.id
- enum_template = (
- ' ${enum_name} = ${enum_value},\n')
- template += string.Template(enum_template).substitute(translations)
+ if message.type == 'Message':
+ translations['enum_name'] = message.id_enum_name
+ translations['enum_value'] = message.id
+ enum_template = (
+ ' ${enum_name} = ${enum_value},\n')
+ template += string.Template(enum_template).substitute(translations)
+
+ template += (
+ '} ${enum_type};\n'
+ '\n')
+ f.write(string.Template(template).substitute(translations))
+
+ """
+ Emit the enumeration of the indications found in the specific service
+ """
+ def emit_indication_ids_enum(self, f):
+ translations = { 'enum_type' : utils.build_camelcase_name (self.indication_id_enum_name) }
+ template = (
+ '\n'
+ 'typedef enum {\n')
+ for message in self.list:
+ if message.type == 'Indication':
+ translations['enum_name'] = message.id_enum_name
+ translations['enum_value'] = message.id
+ enum_template = (
+ ' ${enum_name} = ${enum_value},\n')
+ template += string.Template(enum_template).substitute(translations)
template += (
'} ${enum_type};\n'
@@ -99,20 +125,40 @@ class MessageList:
' QmiMessage *self,\n'
' const gchar *line_prefix)\n'
'{\n'
- ' switch (qmi_message_get_message_id (self)) {\n')
+ ' if (qmi_message_is_indication (self)) {\n'
+ ' switch (qmi_message_get_message_id (self)) {\n')
for message in self.list:
- 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_underscore}_get_printable (self, line_prefix);\n')
- template += string.Template(inner_template).substitute(translations)
+ 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'
+ ' 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))
@@ -144,17 +190,18 @@ class MessageList:
' switch (qmi_message_get_message_id (self)) {\n')
for message in self.list:
- # Only add if we know the version info
- if message.version_info != []:
- translations['enum_name'] = message.id_enum_name
- translations['message_major'] = message.version_info[0]
- translations['message_minor'] = message.version_info[1]
- inner_template = (
- ' case ${enum_name}:\n'
- ' *major = ${message_major};\n'
- ' *minor = ${message_minor};\n'
- ' return TRUE;\n')
- template += string.Template(inner_template).substitute(translations)
+ if message.type == 'Message':
+ # Only add if we know the version info
+ if message.version_info != []:
+ translations['enum_name'] = message.id_enum_name
+ translations['message_major'] = message.version_info[0]
+ translations['message_minor'] = message.version_info[1]
+ inner_template = (
+ ' case ${enum_name}:\n'
+ ' *major = ${message_major};\n'
+ ' *minor = ${message_minor};\n'
+ ' return TRUE;\n')
+ template += string.Template(inner_template).substitute(translations)
template += (
' default:\n'
@@ -168,8 +215,10 @@ class MessageList:
Emit the message list handling implementation
"""
def emit(self, hfile, cfile):
- # First, emit the message IDs enum
+ # First, emit the message/indication IDs enum
self.emit_message_ids_enum(cfile)
+ if self.indication_id_enum_name is not None:
+ self.emit_indication_ids_enum(cfile)
# Then, emit all message handlers
for message in self.list:
diff --git a/build-aux/qmi-codegen/utils.py b/build-aux/qmi-codegen/utils.py
index 1969d4a..ebea84b 100644
--- a/build-aux/qmi-codegen/utils.py
+++ b/build-aux/qmi-codegen/utils.py
@@ -157,6 +157,14 @@ def build_camelcase_name(name):
"""
+Build a dashed lowercase name from the given full name
+e.g.: "This is a message" --> "this-is-a-message"
+"""
+def build_dashed_name(name):
+ return string.replace(string.lower(name), ' ', '-')
+
+
+"""
Remove the given prefix from the string
"""
def remove_prefix(line, prefix):