summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build-aux/qmi-codegen/Client.py46
-rw-r--r--build-aux/qmi-codegen/Message.py5
-rw-r--r--build-aux/qmi-codegen/MessageList.py85
-rw-r--r--docs/reference/libqmi-glib/libqmi-glib-common.sections18
-rw-r--r--docs/reference/libqmi-glib/libqmi-glib-docs.xml1
-rw-r--r--src/libqmi-glib/Makefile.am2
-rw-r--r--src/libqmi-glib/libqmi-glib.h1
-rw-r--r--src/libqmi-glib/qmi-device.c226
-rw-r--r--src/libqmi-glib/qmi-device.h34
-rw-r--r--src/libqmi-glib/qmi-message-context.c123
-rw-r--r--src/libqmi-glib/qmi-message-context.h74
-rw-r--r--src/libqmi-glib/qmi-message.c121
-rw-r--r--src/libqmi-glib/qmi-message.h30
-rw-r--r--src/libqmi-glib/qmi-proxy.c3
14 files changed, 627 insertions, 142 deletions
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')
diff --git a/docs/reference/libqmi-glib/libqmi-glib-common.sections b/docs/reference/libqmi-glib/libqmi-glib-common.sections
index a81af67..6edf5fe 100644
--- a/docs/reference/libqmi-glib/libqmi-glib-common.sections
+++ b/docs/reference/libqmi-glib/libqmi-glib-common.sections
@@ -73,6 +73,8 @@ qmi_device_set_instance_id
qmi_device_set_instance_id_finish
qmi_device_command
qmi_device_command_finish
+qmi_device_command_full
+qmi_device_command_full_finish
qmi_device_get_service_version_info
qmi_device_get_service_version_info_finish
qmi_device_open_flags_build_string_from_mask
@@ -1060,6 +1062,7 @@ qmi_message_get_message_id
qmi_message_get_length
qmi_message_get_raw
qmi_message_get_version_introduced
+qmi_message_get_version_introduced_full
<SUBSECTION TLV writer>
qmi_message_tlv_write_init
qmi_message_tlv_write_reset
@@ -1097,10 +1100,25 @@ qmi_message_add_raw_tlv
qmi_message_set_transaction_id
<SUBSECTION Printable>
qmi_message_get_printable
+qmi_message_get_printable_full
qmi_message_get_tlv_printable
</SECTION>
<SECTION>
+<FILE>qmi-message-context</FILE>
+QMI_MESSAGE_VENDOR_GENERIC
+QmiMessageContext
+qmi_message_context_new
+qmi_message_context_ref
+qmi_message_context_unref
+<SUBSECTION Vendor>
+qmi_message_context_set_vendor_id
+qmi_message_context_get_vendor_id
+<SUBSECTION Standard>
+qmi_message_context_get_type
+</SECTION>
+
+<SECTION>
<FILE>qmi-utils</FILE>
QmiEndian
<SUBSECTION Traces>
diff --git a/docs/reference/libqmi-glib/libqmi-glib-docs.xml b/docs/reference/libqmi-glib/libqmi-glib-docs.xml
index 07f9795..55f4ec8 100644
--- a/docs/reference/libqmi-glib/libqmi-glib-docs.xml
+++ b/docs/reference/libqmi-glib/libqmi-glib-docs.xml
@@ -45,6 +45,7 @@
<title>Core</title>
<xi:include href="xml/qmi-version.xml"/>
<xi:include href="xml/qmi-message.xml"/>
+ <xi:include href="xml/qmi-message-context.xml"/>
<xi:include href="xml/qmi-device.xml"/>
<xi:include href="xml/qmi-client.xml"/>
<xi:include href="xml/qmi-proxy.xml"/>
diff --git a/src/libqmi-glib/Makefile.am b/src/libqmi-glib/Makefile.am
index 8731de7..e379b0b 100644
--- a/src/libqmi-glib/Makefile.am
+++ b/src/libqmi-glib/Makefile.am
@@ -35,6 +35,7 @@ libqmi_glib_la_SOURCES = \
qmi-utils.h qmi-utils.c \
qmi-compat.h qmi-compat.c \
qmi-message.h qmi-message.c \
+ qmi-message-context.h qmi-message-context.c \
qmi-device.h qmi-device.c \
qmi-client.h qmi-client.c \
qmi-proxy.h qmi-proxy.c
@@ -68,6 +69,7 @@ include_HEADERS = \
qmi-enums-voice.h \
qmi-utils.h \
qmi-message.h \
+ qmi-message-context.h \
qmi-device.h \
qmi-client.h \
qmi-proxy.h
diff --git a/src/libqmi-glib/libqmi-glib.h b/src/libqmi-glib/libqmi-glib.h
index f954342..1e1459e 100644
--- a/src/libqmi-glib/libqmi-glib.h
+++ b/src/libqmi-glib/libqmi-glib.h
@@ -33,6 +33,7 @@
#include "qmi-client.h"
#include "qmi-proxy.h"
#include "qmi-message.h"
+#include "qmi-message-context.h"
#include "qmi-enums.h"
#include "qmi-utils.h"
diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c
index d93044d..6f7ed48 100644
--- a/src/libqmi-glib/qmi-device.c
+++ b/src/libqmi-glib/qmi-device.c
@@ -18,7 +18,7 @@
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2012 Lanedo GmbH
- * Copyright (C) 2012-2015 Aleksander Morgado <aleksander@aleksander.es>
+ * Copyright (C) 2012-2017 Aleksander Morgado <aleksander@aleksander.es>
*/
#include <config.h>
@@ -143,25 +143,28 @@ typedef struct {
} TransactionWaitContext;
typedef struct {
- QmiMessage *message;
- GSimpleAsyncResult *result;
- GSource *timeout_source;
- GCancellable *cancellable;
- gulong cancellable_id;
+ QmiMessage *message;
+ QmiMessageContext *message_context;
+ GSimpleAsyncResult *result;
+ GSource *timeout_source;
+ GCancellable *cancellable;
+ gulong cancellable_id;
TransactionWaitContext *wait_ctx;
} Transaction;
static Transaction *
-transaction_new (QmiDevice *self,
- QmiMessage *message,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+transaction_new (QmiDevice *self,
+ QmiMessage *message,
+ QmiMessageContext *message_context,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
Transaction *tr;
tr = g_slice_new0 (Transaction);
tr->message = qmi_message_ref (message);
+ tr->message_context = (message_context ? qmi_message_context_ref (message_context) : NULL);
tr->result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
@@ -200,6 +203,8 @@ transaction_complete_and_free (Transaction *tr,
g_simple_async_result_complete_in_idle (tr->result);
g_object_unref (tr->result);
+ if (tr->message_context)
+ qmi_message_context_unref (tr->message_context);
qmi_message_unref (tr->message);
g_slice_free (Transaction, tr);
}
@@ -1590,32 +1595,69 @@ report_indication (QmiClient *client,
}
static void
-process_message (QmiDevice *self,
- QmiMessage *message)
-{
- if (qmi_utils_get_traces_enabled ()) {
- gchar *printable;
+trace_message (QmiDevice *self,
+ QmiMessage *message,
+ gboolean sent_or_received,
+ const gchar *message_str,
+ QmiMessageContext *message_context)
+{
+ gchar *printable;
+ const gchar *prefix_str;
+ const gchar *action_str;
+ gchar *vendor_str = NULL;
+
+ if (!qmi_utils_get_traces_enabled ())
+ return;
- printable = __qmi_utils_str_hex (((GByteArray *)message)->data,
- ((GByteArray *)message)->len,
- ':');
- g_debug ("[%s] Received message...\n"
- ">>>>>> RAW:\n"
- ">>>>>> length = %u\n"
- ">>>>>> data = %s\n",
- self->priv->path_display,
- ((GByteArray *)message)->len,
- printable);
- g_free (printable);
+ if (sent_or_received) {
+ prefix_str = "<<<<<< ";
+ action_str = "sent";
+ } else {
+ prefix_str = "<<<<<< ";
+ action_str = "received";
+ }
+
+ printable = __qmi_utils_str_hex (((GByteArray *)message)->data,
+ ((GByteArray *)message)->len,
+ ':');
+ g_debug ("[%s] %s message...\n"
+ "%sRAW:\n"
+ "%s length = %u\n"
+ "%s data = %s\n",
+ self->priv->path_display, action_str,
+ prefix_str,
+ prefix_str, ((GByteArray *)message)->len,
+ prefix_str, printable);
+ g_free (printable);
+
+ if (message_context) {
+ guint16 vendor_id;
+
+ vendor_id = qmi_message_context_get_vendor_id (message_context);
+ if (vendor_id != QMI_MESSAGE_VENDOR_GENERIC)
+ vendor_str = g_strdup_printf ("vendor-specific (0x%04x)", vendor_id);
+ }
+
+ printable = qmi_message_get_printable_full (message, message_context, prefix_str);
+ g_debug ("[%s] %s %s %s (translated)...\n%s",
+ self->priv->path_display,
+ action_str,
+ vendor_str ? vendor_str : "generic",
+ message_str,
+ printable);
+ g_free (printable);
- printable = qmi_message_get_printable (message, ">>>>>> ");
- g_debug ("[%s] Received message (translated)...\n%s",
- self->priv->path_display,
- printable);
- g_free (printable);
- }
+ g_free (vendor_str);
+}
+static void
+process_message (QmiDevice *self,
+ QmiMessage *message)
+{
if (qmi_message_is_indication (message)) {
+ /* Indication traces translated without an explicit vendor */
+ trace_message (self, message, FALSE, "indication", NULL);
+
/* Generic emission of the indication */
g_signal_emit (self, signals[SIGNAL_INDICATION], 0, message);
@@ -1647,16 +1689,23 @@ process_message (QmiDevice *self,
Transaction *tr;
tr = device_match_transaction (self, message);
- if (!tr)
+ if (!tr) {
+ /* Unmatched transactions translated without an explicit context */
+ trace_message (self, message, FALSE, "response", NULL);
g_debug ("[%s] No transaction matched in received message",
self->priv->path_display);
- else
+ } else {
+ /* Matched transactions translated with the same context as the request */
+ trace_message (self, message, FALSE, "response", tr->message_context);
/* Report the reply message */
transaction_complete_and_free (tr, message, NULL);
+ }
return;
}
+ /* Unexpected message types translated without an explicit context */
+ trace_message (self, message, FALSE, "unexpected message", NULL);
g_debug ("[%s] Message received but it is neither an indication nor a response. Skipping it.",
self->priv->path_display);
}
@@ -2755,19 +2804,19 @@ mbim_command (QmiDevice *self,
/* Command */
/**
- * qmi_device_command_finish:
+ * qmi_device_command_full_finish:
* @self: a #QmiDevice.
* @res: a #GAsyncResult.
* @error: Return location for error or %NULL.
*
- * Finishes an operation started with qmi_device_command().
+ * Finishes an operation started with qmi_device_command_full().
*
* Returns: a #QmiMessage response, or #NULL if @error is set. The returned value should be freed with qmi_message_unref().
*/
QmiMessage *
-qmi_device_command_finish (QmiDevice *self,
- GAsyncResult *res,
- GError **error)
+qmi_device_command_full_finish (QmiDevice *self,
+ GAsyncResult *res,
+ GError **error)
{
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
return NULL;
@@ -2794,9 +2843,10 @@ transaction_early_error (QmiDevice *self,
}
/**
- * qmi_device_command:
+ * qmi_device_command_full:
* @self: a #QmiDevice.
* @message: the message to send.
+ * @message_context: the context of the message.
* @timeout: maximum time, in seconds, to wait for the response.
* @cancellable: a #GCancellable, or %NULL.
* @callback: a #GAsyncReadyCallback to call when the operation is finished.
@@ -2804,16 +2854,22 @@ transaction_early_error (QmiDevice *self,
*
* Asynchronously sends a #QmiMessage to the device.
*
+ * The message will be processed according to the specific @message_context
+ * given.
+ *
* When the operation is finished @callback will be called. You can then call
- * qmi_device_command_finish() to get the result of the operation.
+ * qmi_device_command_full_finish() to get the result of the operation.
+ *
+ * If no @context given, the behavior is the same as qmi_device_command().
*/
void
-qmi_device_command (QmiDevice *self,
- QmiMessage *message,
- guint timeout,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+qmi_device_command_full (QmiDevice *self,
+ QmiMessage *message,
+ QmiMessageContext *message_context,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GError *error = NULL;
Transaction *tr;
@@ -2835,7 +2891,7 @@ qmi_device_command (QmiDevice *self,
self->priv->client_ctl)));
}
- tr = transaction_new (self, message, cancellable, callback, user_data);
+ tr = transaction_new (self, message, message_context, cancellable, callback, user_data);
/* Device must be open */
if (!self->priv->istream || !self->priv->ostream) {
@@ -2896,27 +2952,7 @@ qmi_device_command (QmiDevice *self,
/* From now on, if we want to complete the transaction with an early error,
* it needs to be removed from the tracking table as well. */
- if (qmi_utils_get_traces_enabled ()) {
- gchar *printable;
-
- printable = __qmi_utils_str_hex (((GByteArray *)message)->data,
- ((GByteArray *)message)->len,
- ':');
- g_debug ("[%s] Sent message...\n"
- "<<<<<< RAW:\n"
- "<<<<<< length = %u\n"
- "<<<<<< data = %s\n",
- self->priv->path_display,
- ((GByteArray *)message)->len,
- printable);
- g_free (printable);
-
- printable = qmi_message_get_printable (message, "<<<<<< ");
- g_debug ("[%s] Sent message (translated)...\n%s",
- self->priv->path_display,
- printable);
- g_free (printable);
- }
+ trace_message (self, message, TRUE, "request", message_context);
#if defined MBIM_QMUX_ENABLED
if (self->priv->mbimdev) {
@@ -2950,6 +2986,56 @@ qmi_device_command (QmiDevice *self,
}
/*****************************************************************************/
+/* Generic command */
+
+/**
+ * qmi_device_command_finish:
+ * @self: a #QmiDevice.
+ * @res: a #GAsyncResult.
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with qmi_device_command().
+ *
+ * Returns: a #QmiMessage response, or #NULL if @error is set. The returned value should be freed with qmi_message_unref().
+ *
+ * Deprecated: 1.18.
+ */
+QmiMessage *
+qmi_device_command_finish (QmiDevice *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return qmi_device_command_full_finish (self, res, error);
+}
+
+/**
+ * qmi_device_command:
+ * @self: a #QmiDevice.
+ * @message: the message to send.
+ * @timeout: maximum time, in seconds, to wait for the response.
+ * @cancellable: a #GCancellable, or %NULL.
+ * @callback: a #GAsyncReadyCallback to call when the operation is finished.
+ * @user_data: the data to pass to callback function.
+ *
+ * Asynchronously sends a generic #QmiMessage to the device with no context.
+ *
+ * When the operation is finished @callback will be called. You can then call
+ * qmi_device_command_finish() to get the result of the operation.
+ *
+ * Deprecated: 1.18: Use qmi_device_command_full() instead.
+ */
+void
+qmi_device_command (QmiDevice *self,
+ QmiMessage *message,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ qmi_device_command_full (self, message, NULL, timeout, cancellable, callback, user_data);
+}
+
+/*****************************************************************************/
/* New QMI device */
/**
diff --git a/src/libqmi-glib/qmi-device.h b/src/libqmi-glib/qmi-device.h
index 957efac..51e07ae 100644
--- a/src/libqmi-glib/qmi-device.h
+++ b/src/libqmi-glib/qmi-device.h
@@ -17,7 +17,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
- * Copyright (C) 2012-2015 Aleksander Morgado <aleksander@aleksander.es>
+ * Copyright (C) 2012-2017 Aleksander Morgado <aleksander@aleksander.es>
*/
#ifndef _LIBQMI_GLIB_QMI_DEVICE_H_
@@ -32,6 +32,7 @@
#include "qmi-enums.h"
#include "qmi-message.h"
+#include "qmi-message-context.h"
#include "qmi-client.h"
G_BEGIN_DECLS
@@ -171,15 +172,28 @@ gboolean qmi_device_set_instance_id_finish (QmiDevice *self,
guint16 *link_id,
GError **error);
-void qmi_device_command (QmiDevice *self,
- QmiMessage *message,
- guint timeout,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-QmiMessage *qmi_device_command_finish (QmiDevice *self,
- GAsyncResult *res,
- GError **error);
+G_DEPRECATED
+void qmi_device_command (QmiDevice *self,
+ QmiMessage *message,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+G_DEPRECATED
+QmiMessage *qmi_device_command_finish (QmiDevice *self,
+ GAsyncResult *res,
+ GError **error);
+
+void qmi_device_command_full (QmiDevice *self,
+ QmiMessage *message,
+ QmiMessageContext *message_context,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+QmiMessage *qmi_device_command_full_finish (QmiDevice *self,
+ GAsyncResult *res,
+ GError **error);
/**
* QmiDeviceServiceVersionInfo:
diff --git a/src/libqmi-glib/qmi-message-context.c b/src/libqmi-glib/qmi-message-context.c
new file mode 100644
index 0000000..96f7a67
--- /dev/null
+++ b/src/libqmi-glib/qmi-message-context.c
@@ -0,0 +1,123 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * libqmi-glib -- GLib/GIO based library to control QMI devices
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2017 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include <glib.h>
+
+#include "qmi-message-context.h"
+
+/*****************************************************************************/
+/* Basic context */
+
+struct _QmiMessageContext {
+ volatile gint ref_count;
+
+ /* Vendor ID */
+ guint16 vendor_id;
+};
+
+/**
+ * qmi_message_context_new:
+ *
+ * Create a new empty #QmiMessageContext.
+ *
+ * Returns: (transfer full): a newly created #QmiMessageContext. The returned value should be freed with qmi_message_context_unref().
+ */
+QmiMessageContext *
+qmi_message_context_new (void)
+{
+ QmiMessageContext *self;
+
+ self = g_slice_new0 (QmiMessageContext);
+ self->ref_count = 1;
+ return self;
+}
+
+GType
+qmi_message_context_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile)) {
+ GType g_define_type_id =
+ g_boxed_type_register_static (g_intern_static_string ("QmiMessageContext"),
+ (GBoxedCopyFunc) qmi_message_context_ref,
+ (GBoxedFreeFunc) qmi_message_context_unref);
+
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+/**
+ * qmi_message_context_ref:
+ * @self: a #QmiMessageContext.
+ *
+ * Atomically increments the reference count of @self by one.
+ *
+ * Returns: (transfer full) the new reference to @self.
+ */
+QmiMessageContext *
+qmi_message_context_ref (QmiMessageContext *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ g_atomic_int_inc (&self->ref_count);
+ return self;
+}
+
+/**
+ * qmi_message_context_unref:
+ * @self: a #QmiMessageContext.
+ *
+ * Atomically decrements the reference count of @self by one.
+ * If the reference count drops to 0, @self is completely disposed.
+ */
+void
+qmi_message_context_unref (QmiMessageContext *self)
+{
+ g_return_if_fail (self != NULL);
+
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ g_slice_free (QmiMessageContext, self);
+ }
+}
+
+/*****************************************************************************/
+/* Vendor ID */
+
+void
+qmi_message_context_set_vendor_id (QmiMessageContext *self,
+ guint16 vendor_id)
+{
+ g_return_if_fail (self != NULL);
+
+ self->vendor_id = vendor_id;
+}
+
+guint16
+qmi_message_context_get_vendor_id (QmiMessageContext *self)
+{
+ g_return_val_if_fail (self != NULL, QMI_MESSAGE_VENDOR_GENERIC);
+ return self->vendor_id;
+}
diff --git a/src/libqmi-glib/qmi-message-context.h b/src/libqmi-glib/qmi-message-context.h
new file mode 100644
index 0000000..2dcf2ec
--- /dev/null
+++ b/src/libqmi-glib/qmi-message-context.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * libqmi-glib -- GLib/GIO based library to control QMI devices
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2017 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef _LIBQMI_GLIB_QMI_MESSAGE_CONTEXT_H_
+#define _LIBQMI_GLIB_QMI_MESSAGE_CONTEXT_H_
+
+#if !defined (__LIBQMI_GLIB_H_INSIDE__) && !defined (LIBQMI_GLIB_COMPILATION)
+#error "Only <libqmi-glib.h> can be included directly."
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * QmiMessageContext:
+ *
+ * An opaque type representing a QMI message context.
+ *
+ * The context defines non-standard features of the QMI message associated with
+ * it, which may be required for a correct processing.
+ *
+ * When a context is given when sending a request with qmi_device_command_full(),
+ * the same context will then be applied for the associated response.
+ */
+typedef struct _QmiMessageContext QmiMessageContext;
+
+GType qmi_message_context_get_type (void);
+
+/*****************************************************************************/
+/* Basic context */
+
+QmiMessageContext *qmi_message_context_new (void);
+QmiMessageContext *qmi_message_context_ref (QmiMessageContext *self);
+void qmi_message_context_unref (QmiMessageContext *self);
+
+/*****************************************************************************/
+/* Vendor ID */
+
+/**
+ * QMI_MESSAGE_VENDOR_GENERIC:
+ *
+ * Generic vendor id (0x0000).
+ */
+#define QMI_MESSAGE_VENDOR_GENERIC 0x0000
+
+void qmi_message_context_set_vendor_id (QmiMessageContext *self,
+ guint16 vendor_id);
+guint16 qmi_message_context_get_vendor_id (QmiMessageContext *self);
+
+G_END_DECLS
+
+#endif /* _LIBQMI_GLIB_QMI_MESSAGE_CONTEXT_H_ */
diff --git a/src/libqmi-glib/qmi-message.c b/src/libqmi-glib/qmi-message.c
index 23afa29..bbf08b6 100644
--- a/src/libqmi-glib/qmi-message.c
+++ b/src/libqmi-glib/qmi-message.c
@@ -24,7 +24,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
- * Copyright (C) 2012-2015 Aleksander Morgado <aleksander@aleksander.es>
+ * Copyright (C) 2012-2017 Aleksander Morgado <aleksander@aleksander.es>
*/
#include <glib.h>
@@ -2077,20 +2077,27 @@ get_generic_printable (QmiMessage *self,
}
/**
- * qmi_message_get_printable:
+ * qmi_message_get_printable_full:
* @self: a #QmiMessage.
+ * @context: a #QmiMessageContext.
* @line_prefix: prefix string to use in each new generated line.
*
* Gets a printable string with the contents of the whole QMI message.
*
- * If known, the printable string will contain translated TLV values as well as the raw
- * data buffer contents.
+ * If known, the printable string will contain translated TLV values as well as
+ * the raw data buffer contents.
+ *
+ * The translation of the contents may be specific to the @context provided,
+ * e.g. for vendor-specific messages.
+ *
+ * If no @context given, the behavior is the same as qmi_message_get_printable().
*
* Returns: (transfer full): a newly allocated string, which should be freed with g_free().
*/
gchar *
-qmi_message_get_printable (QmiMessage *self,
- const gchar *line_prefix)
+qmi_message_get_printable_full (QmiMessage *self,
+ QmiMessageContext *context,
+ const gchar *line_prefix)
{
GString *printable;
gchar *qmi_flags_str;
@@ -2134,40 +2141,40 @@ qmi_message_get_printable (QmiMessage *self,
contents = NULL;
switch (qmi_message_get_service (self)) {
case QMI_SERVICE_CTL:
- contents = __qmi_message_ctl_get_printable (self, line_prefix);
+ contents = __qmi_message_ctl_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_DMS:
- contents = __qmi_message_dms_get_printable (self, line_prefix);
+ contents = __qmi_message_dms_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_WDS:
- contents = __qmi_message_wds_get_printable (self, line_prefix);
+ contents = __qmi_message_wds_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_NAS:
- contents = __qmi_message_nas_get_printable (self, line_prefix);
+ contents = __qmi_message_nas_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_WMS:
- contents = __qmi_message_wms_get_printable (self, line_prefix);
+ contents = __qmi_message_wms_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_PDC:
- contents = __qmi_message_pdc_get_printable (self, line_prefix);
+ contents = __qmi_message_pdc_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_PDS:
- contents = __qmi_message_pds_get_printable (self, line_prefix);
+ contents = __qmi_message_pds_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_PBM:
- contents = __qmi_message_pbm_get_printable (self, line_prefix);
+ contents = __qmi_message_pbm_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_UIM:
- contents = __qmi_message_uim_get_printable (self, line_prefix);
+ contents = __qmi_message_uim_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_OMA:
- contents = __qmi_message_oma_get_printable (self, line_prefix);
+ contents = __qmi_message_oma_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_WDA:
- contents = __qmi_message_wda_get_printable (self, line_prefix);
+ contents = __qmi_message_wda_get_printable (self, context, line_prefix);
break;
case QMI_SERVICE_VOICE:
- contents = __qmi_message_voice_get_printable (self, line_prefix);
+ contents = __qmi_message_voice_get_printable (self, context, line_prefix);
break;
default:
break;
@@ -2182,19 +2189,48 @@ qmi_message_get_printable (QmiMessage *self,
}
/**
- * qmi_message_get_version_introduced:
+ * qmi_message_get_printable:
* @self: a #QmiMessage.
+ * @line_prefix: prefix string to use in each new generated line.
+ *
+ * Gets a printable string with the contents of the whole QMI message.
+ *
+ * If known, the printable string will contain translated TLV values as well as the raw
+ * data buffer contents.
+ *
+ * Returns: (transfer full): a newly allocated string, which should be freed with g_free().
+ *
+ * Deprecated: 1.18: Use qmi_message_get_printable_full() instead.
+ */
+gchar *
+qmi_message_get_printable (QmiMessage *self,
+ const gchar *line_prefix)
+{
+ return qmi_message_get_printable_full (self, NULL, line_prefix);
+}
+
+/**
+ * qmi_message_get_version_introduced_full:
+ * @self: a #QmiMessage.
+ * @context: a #QmiMessageContext.
* @major: (out) return location for the major version.
* @minor: (out) return location for the minor version.
*
- * Gets, if known, the service version in which the given message was first introduced.
+ * Gets, if known, the service version in which the given message was first
+ * introduced.
+ *
+ * The lookup of the version may be specific to the @context provided, e.g. for
+ * vendor-specific messages.
+ *
+ * If no @context given, the behavior is the same as qmi_message_get_version_introduced().
*
* Returns: %TRUE if @major and @minor are set, %FALSE otherwise.
*/
gboolean
-qmi_message_get_version_introduced (QmiMessage *self,
- guint *major,
- guint *minor)
+qmi_message_get_version_introduced_full (QmiMessage *self,
+ QmiMessageContext *context,
+ guint *major,
+ guint *minor)
{
switch (qmi_message_get_service (self)) {
case QMI_SERVICE_CTL:
@@ -2204,34 +2240,55 @@ qmi_message_get_version_introduced (QmiMessage *self,
return TRUE;
case QMI_SERVICE_DMS:
- return __qmi_message_dms_get_version_introduced (self, major, minor);
+ return __qmi_message_dms_get_version_introduced (self, context, major, minor);
case QMI_SERVICE_WDS:
- return __qmi_message_wds_get_version_introduced (self, major, minor);
+ return __qmi_message_wds_get_version_introduced (self, context, major, minor);
case QMI_SERVICE_NAS:
- return __qmi_message_nas_get_version_introduced (self, major, minor);
+ return __qmi_message_nas_get_version_introduced (self, context, major, minor);
case QMI_SERVICE_WMS:
- return __qmi_message_wms_get_version_introduced (self, major, minor);
+ return __qmi_message_wms_get_version_introduced (self, context, major, minor);
case QMI_SERVICE_PDS:
- return __qmi_message_pds_get_version_introduced (self, major, minor);
+ return __qmi_message_pds_get_version_introduced (self, context, major, minor);
case QMI_SERVICE_PBM:
- return __qmi_message_pbm_get_version_introduced (self, major, minor);
+ return __qmi_message_pbm_get_version_introduced (self, context, major, minor);
case QMI_SERVICE_UIM:
- return __qmi_message_uim_get_version_introduced (self, major, minor);
+ return __qmi_message_uim_get_version_introduced (self, context, major, minor);
case QMI_SERVICE_OMA:
- return __qmi_message_oma_get_version_introduced (self, major, minor);
+ return __qmi_message_oma_get_version_introduced (self, context, major, minor);
case QMI_SERVICE_WDA:
- return __qmi_message_wda_get_version_introduced (self, major, minor);
+ return __qmi_message_wda_get_version_introduced (self, context, major, minor);
default:
/* For the still unsupported services, cannot do anything */
return FALSE;
}
}
+
+/**
+ * qmi_message_get_version_introduced:
+ * @self: a #QmiMessage.
+ * @major: (out) return location for the major version.
+ * @minor: (out) return location for the minor version.
+ *
+ * Gets, if known, the service version in which the given message was first
+ * introduced.
+ *
+ * Returns: %TRUE if @major and @minor are set, %FALSE otherwise.
+ *
+ * Deprecated: 1.18: Use qmi_message_get_version_introduced_full() instead.
+ */
+gboolean
+qmi_message_get_version_introduced (QmiMessage *self,
+ guint *major,
+ guint *minor)
+{
+ return qmi_message_get_version_introduced_full (self, NULL, major, minor);
+}
diff --git a/src/libqmi-glib/qmi-message.h b/src/libqmi-glib/qmi-message.h
index 4f21560..7ca240e 100644
--- a/src/libqmi-glib/qmi-message.h
+++ b/src/libqmi-glib/qmi-message.h
@@ -24,7 +24,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
- * Copyright (C) 2012-2015 Aleksander Morgado <aleksander@aleksander.es>
+ * Copyright (C) 2012-2017 Aleksander Morgado <aleksander@aleksander.es>
*/
#ifndef _LIBQMI_GLIB_QMI_MESSAGE_H_
@@ -39,6 +39,7 @@
#include "qmi-utils.h"
#include "qmi-enums.h"
#include "qmi-errors.h"
+#include "qmi-message-context.h"
G_BEGIN_DECLS
@@ -51,6 +52,13 @@ G_BEGIN_DECLS
*/
typedef GByteArray QmiMessage;
+/**
+ * QMI_MESSAGE_VENDOR_GENERIC:
+ *
+ * Generic vendor id (0x0000).
+ */
+#define QMI_MESSAGE_VENDOR_GENERIC 0x0000
+
/*****************************************************************************/
/* QMI Message life cycle */
@@ -79,10 +87,19 @@ gsize qmi_message_get_length (QmiMessage *self);
const guint8 *qmi_message_get_raw (QmiMessage *self,
gsize *length,
GError **error);
-gboolean qmi_message_get_version_introduced (QmiMessage *self,
- guint *major,
- guint *minor);
+/*****************************************************************************/
+/* Version support from the database */
+
+G_DEPRECATED
+gboolean qmi_message_get_version_introduced (QmiMessage *self,
+ guint *major,
+ guint *minor);
+
+gboolean qmi_message_get_version_introduced_full (QmiMessage *self,
+ QmiMessageContext *context,
+ guint *major,
+ guint *minor);
/*****************************************************************************/
/* TLV builder & writer */
@@ -250,9 +267,14 @@ void qmi_message_set_transaction_id (QmiMessage *self,
/*****************************************************************************/
/* Printable helpers */
+G_DEPRECATED
gchar *qmi_message_get_printable (QmiMessage *self,
const gchar *line_prefix);
+gchar *qmi_message_get_printable_full (QmiMessage *self,
+ QmiMessageContext *context,
+ const gchar *line_prefix);
+
gchar *qmi_message_get_tlv_printable (QmiMessage *self,
const gchar *line_prefix,
guint8 type,
diff --git a/src/libqmi-glib/qmi-proxy.c b/src/libqmi-glib/qmi-proxy.c
index 5077041..592ed8b 100644
--- a/src/libqmi-glib/qmi-proxy.c
+++ b/src/libqmi-glib/qmi-proxy.c
@@ -608,6 +608,9 @@ process_message (QmiProxy *self,
* complete, otherwise the remote clients will lose the reply if they
* configured a timeout bigger than this internal one. We should likely
* make this value configurable per-client, instead of a hardcoded value.
+ *
+ * Note: the proxy will not translate vendor-specific messages in its
+ * logs (as it doesn't have the orignal message context with the vendor id).
*/
qmi_device_command (client->device,
message,