diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-01-22 18:17:09 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-01-29 10:37:53 +0100 |
commit | 9bd604224f56fcf6fb0be577a646e62f59200594 (patch) | |
tree | e0eb725cd2f094502f8c613866ce027536a4aa42 /src/libqmi-glib | |
parent | 132bd1b0ef5c3b8b9f2544261a9e57e0fd589c14 (diff) | |
download | external_libqmi-9bd604224f56fcf6fb0be577a646e62f59200594.zip external_libqmi-9bd604224f56fcf6fb0be577a646e62f59200594.tar.gz external_libqmi-9bd604224f56fcf6fb0be577a646e62f59200594.tar.bz2 |
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.
Diffstat (limited to 'src/libqmi-glib')
-rw-r--r-- | src/libqmi-glib/Makefile.am | 2 | ||||
-rw-r--r-- | src/libqmi-glib/libqmi-glib.h | 1 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-device.c | 226 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-device.h | 34 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-message-context.c | 123 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-message-context.h | 74 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-message.c | 121 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-message.h | 30 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-proxy.c | 3 |
9 files changed, 498 insertions, 116 deletions
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, |