From 9bd604224f56fcf6fb0be577a646e62f59200594 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Sun, 22 Jan 2017 18:17:09 +0100 Subject: libqmi-glib: support vendor-specific request/responses We want to support non-standard messages that may be encoded with different TLVs depending on how the vendor implemented them. Anyway, right now this is really just to support the correct translation of TLVs and message contents in the get_printable() methods. The support is only included for QMI request/responses, and not for QMI indications. This is because the library knows in which moment the requests are created (and can apply the same rules to the matched response when it is received). For the indications, though, there is no such context configurable yet. --- build-aux/qmi-codegen/Client.py | 46 +++++++++++++++---- build-aux/qmi-codegen/Message.py | 5 +++ build-aux/qmi-codegen/MessageList.py | 85 ++++++++++++++++++++++++++++-------- 3 files changed, 110 insertions(+), 26 deletions(-) (limited to 'build-aux') diff --git a/build-aux/qmi-codegen/Client.py b/build-aux/qmi-codegen/Client.py index 1e342ae..32e1e0d 100644 --- a/build-aux/qmi-codegen/Client.py +++ b/build-aux/qmi-codegen/Client.py @@ -278,6 +278,7 @@ class Client: 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) @@ -370,7 +371,7 @@ class Client: ' QmiMessage *reply;\n' ' ${output_camelcase} *output;\n' '\n' - ' reply = qmi_device_command_finish (device, res, &error);\n' + ' reply = qmi_device_command_full_finish (device, res, &error);\n' ' if (!reply) {\n') if message.abort: @@ -461,7 +462,13 @@ class Client: ' GSimpleAsyncResult *result;\n' ' QmiMessage *request;\n' ' GError *error = NULL;\n' - ' guint16 transaction_id;\n' + ' guint16 transaction_id;\n') + + if message.vendor is not None: + template += ( + ' QmiMessageContext *context;\n') + + template += ( '\n' ' result = g_simple_async_result_new (G_OBJECT (self),\n' ' callback,\n' @@ -490,15 +497,36 @@ class Client: ' "transaction-id",\n' ' GUINT_TO_POINTER (transaction_id));\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') + 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' + ' qmi_device_command_full (QMI_DEVICE (qmi_client_peek_device (QMI_CLIENT (self))),\n' + ' request,\n') + + if message.vendor is not None: + template += ( + ' context,\n') + else: + template += ( + ' NULL,\n') + + template += ( + ' timeout,\n' + ' cancellable,\n' + ' (GAsyncReadyCallback)${message_underscore}_ready,\n' + ' result);\n' + ' qmi_message_unref (request);\n') + + if message.vendor is not None: + template += ( + ' qmi_message_context_unref (context);\n') + + template += ( '}\n' '\n') cfile.write(string.Template(template).substitute(translations)) diff --git a/build-aux/qmi-codegen/Message.py b/build-aux/qmi-codegen/Message.py index aae9561..9c78cf5 100644 --- a/build-aux/qmi-codegen/Message.py +++ b/build-aux/qmi-codegen/Message.py @@ -45,6 +45,11 @@ class Message: 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 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 diff --git a/build-aux/qmi-codegen/MessageList.py b/build-aux/qmi-codegen/MessageList.py index bbd020f..4331b90 100644 --- a/build-aux/qmi-codegen/MessageList.py +++ b/build-aux/qmi-codegen/MessageList.py @@ -73,8 +73,13 @@ class MessageList: if message.type == 'Message': translations['enum_name'] = message.id_enum_name translations['enum_value'] = message.id - enum_template = ( - ' ${enum_name} = ${enum_value},\n') + if message.vendor is None: + enum_template = ( + ' ${enum_name} = ${enum_value},\n') + else: + translations['vendor'] = message.vendor + enum_template = ( + ' ${enum_name} = ${enum_value}, /* vendor ${vendor} */\n') template += string.Template(enum_template).substitute(translations) template += ( @@ -118,6 +123,7 @@ class MessageList: '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' @@ -129,6 +135,7 @@ class MessageList: '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' @@ -138,7 +145,6 @@ class MessageList: 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') @@ -149,21 +155,39 @@ class MessageList: ' return NULL;\n' ' }\n' ' } else {\n' - ' switch (qmi_message_get_message_id (self)) {\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': + 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) - translations['enum_value'] = message.id inner_template = ( - ' case ${enum_name}:\n' - ' return message_${message_underscore}_get_printable (self, line_prefix);\n') + ' 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' + ' 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') @@ -184,6 +208,7 @@ class MessageList: 'G_GNUC_INTERNAL\n' 'gboolean __qmi_message_${service}_get_version_introduced (\n' ' QmiMessage *self,\n' + ' QmiMessageContext *context,\n' ' guint *major,\n' ' guint *minor);\n' '\n' @@ -196,27 +221,53 @@ class MessageList: 'gboolean\n' '__qmi_message_${service}_get_version_introduced (\n' ' QmiMessage *self,\n' + ' QmiMessageContext *context,\n' ' guint *major,\n' ' guint *minor)\n' '{\n' - ' switch (qmi_message_get_message_id (self)) {\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': + if message.type == 'Message' and message.vendor is None: + # 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' + ' return FALSE;\n' + ' }\n' + ' } else {\n') + + for message in self.list: + if message.type == 'Message' and message.vendor is not None: # 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] + translations['message_vendor'] = message.vendor inner_template = ( - ' case ${enum_name}:\n' - ' *major = ${message_major};\n' - ' *minor = ${message_minor};\n' - ' return TRUE;\n') + ' if (vendor_id == ${message_vendor} && (qmi_message_get_message_id (self) == ${enum_name})) {\n' + ' *major = ${message_major};\n' + ' *minor = ${message_minor};\n' + ' return TRUE;\n' + ' }\n') template += string.Template(inner_template).substitute(translations) template += ( - ' default:\n' ' return FALSE;\n' ' }\n' '}\n') -- cgit v1.1