summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-05-23 16:40:03 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-07-03 16:08:55 +0200
commitcbfac5dadfa6713e124aba7400937abd4c8daf93 (patch)
tree2f4d36aa888669a00fcabd446ff795620e68a41c
parent8fe7fae49a233b7ecc9e180b709a8cba69c0406c (diff)
qmi-codegen: improve message/TLV printability
-rw-r--r--build-aux/qmi-codegen/Message.py118
-rw-r--r--build-aux/qmi-codegen/MessageList.py41
-rw-r--r--build-aux/qmi-codegen/utils.py1
-rw-r--r--src/Makefile.am3
-rw-r--r--src/qmi-message.c162
-rw-r--r--src/qmi-message.h10
-rw-r--r--src/qmi-utils.c6
-rw-r--r--src/qmi-utils.h6
8 files changed, 280 insertions, 67 deletions
diff --git a/build-aux/qmi-codegen/Message.py b/build-aux/qmi-codegen/Message.py
index 5be7feb..a2ec70e 100644
--- a/build-aux/qmi-codegen/Message.py
+++ b/build-aux/qmi-codegen/Message.py
@@ -219,6 +219,118 @@ class Message:
'}\n')
+ def __emit_get_printable(self, hfile, cfile):
+ translations = { 'name' : self.name,
+ 'service' : self.service,
+ 'id' : self.id,
+ 'underscore' : utils.build_underscore_name (self.name) }
+
+ template = (
+ '\n'
+ 'struct ${underscore}_context {\n'
+ ' QmiMessage *self;\n'
+ ' const gchar *line_prefix;\n'
+ ' GString *printable;\n'
+ '};\n'
+ '\n'
+ 'static void\n'
+ '${underscore}_get_tlv_printable (\n'
+ ' guint8 type,\n'
+ ' gsize length,\n'
+ ' gconstpointer value,\n'
+ ' struct ${underscore}_context *ctx)\n'
+ '{\n'
+ ' const gchar *tlv_type_str = NULL;\n'
+ '\n'
+ ' if (!qmi_message_is_response (ctx->self)) {\n'
+ ' switch (type) {\n')
+
+ if self.input.fields is not None:
+ for field in self.input.fields:
+ translations['field_enum'] = field.id_enum_name
+ translations['field_name'] = field.name
+ field_template = (
+ ' case ${field_enum}:\n'
+ ' tlv_type_str = "${field_name}";\n'
+ ' break;\n')
+ template += string.Template(field_template).substitute(translations)
+
+ template += (
+ ' default:\n'
+ ' break;\n'
+ ' }\n'
+ ' } else {\n'
+ ' switch (type) {\n')
+
+ for field in self.output.fields:
+ translations['field_enum'] = field.id_enum_name
+ translations['field_name'] = field.name
+ field_template = (
+ ' case ${field_enum}:\n'
+ ' tlv_type_str = "${field_name}";\n'
+ ' break;\n')
+ template += string.Template(field_template).substitute(translations)
+
+ template += (
+ ' default:\n'
+ ' break;\n'
+ ' }\n'
+ ' }\n'
+ '\n'
+ '\n'
+ '\n'
+ ' if (!tlv_type_str) {\n'
+ ' gchar *value_str = NULL;\n'
+ '\n'
+ ' value_str = qmi_message_get_tlv_printable (ctx->self,\n'
+ ' ctx->line_prefix,\n'
+ ' type,\n'
+ ' length,\n'
+ ' value);\n'
+ ' g_string_append (ctx->printable, value_str);\n'
+ ' g_free (value_str);\n'
+ ' } else {\n'
+ ' gchar *value_hex;\n'
+ '\n'
+ ' value_hex = qmi_utils_str_hex (value, length, \':\');\n'
+ ' g_string_append_printf (ctx->printable,\n'
+ ' "%sTLV:\\n"\n'
+ ' "%s type = \\"%s\\" (0x%02x)\\n"\n'
+ ' "%s length = %u\\n"\n'
+ ' "%s value = %s\\n",\n'
+ ' ctx->line_prefix,\n'
+ ' ctx->line_prefix, tlv_type_str, type,\n'
+ ' ctx->line_prefix, length,\n'
+ ' ctx->line_prefix, value_hex);\n'
+ ' g_free (value_hex);\n'
+ ' }\n'
+ '}\n'
+ '\n'
+ 'static gchar *\n'
+ '${underscore}_get_printable (\n'
+ ' QmiMessage *self,\n'
+ ' const gchar *line_prefix)\n'
+ '{\n'
+ ' struct ${underscore}_context ctx;\n'
+ ' GString *printable;\n'
+ '\n'
+ ' printable = g_string_new ("");\n'
+ ' g_string_append_printf (printable,\n'
+ ' "%s message = \\\"${name}\\\" (${id})\\n",\n'
+ ' line_prefix);\n'
+ '\n'
+ ' ctx.self = self;\n'
+ ' ctx.line_prefix = line_prefix;\n'
+ ' ctx.printable = printable;\n'
+ ' qmi_message_tlv_foreach (self,\n'
+ ' (QmiMessageForeachTlvFn)${underscore}_get_tlv_printable,\n'
+ ' &ctx);\n'
+ '\n'
+ ' return g_string_free (printable, FALSE);\n'
+ '}\n')
+ cfile.write(string.Template(template).substitute(translations))
+
+
def emit(self, hfile, cfile):
utils.add_separator(hfile, 'REQUEST/RESPONSE', self.fullname);
utils.add_separator(cfile, 'REQUEST/RESPONSE', self.fullname);
@@ -226,9 +338,11 @@ class Message:
hfile.write('\n/* --- Input -- */\n');
cfile.write('\n/* --- Input -- */\n');
self.input.emit(hfile, cfile)
- self.__emit_request_creator (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_parser(hfile, cfile)
+
+ self.__emit_get_printable(hfile, cfile)
diff --git a/build-aux/qmi-codegen/MessageList.py b/build-aux/qmi-codegen/MessageList.py
index f2129af..eafb068 100644
--- a/build-aux/qmi-codegen/MessageList.py
+++ b/build-aux/qmi-codegen/MessageList.py
@@ -67,6 +67,42 @@ class MessageList:
f.write(string.Template(template).substitute(translations))
+ def __emit_get_printable(self, hfile, cfile):
+ translations = { 'service' : string.lower(self.service) }
+
+ template = (
+ '\n'
+ 'gchar *qmi_message_${service}_get_printable (\n'
+ ' QmiMessage *self,\n'
+ ' const gchar *line_prefix);\n')
+ hfile.write(string.Template(template).substitute(translations))
+
+ template = (
+ '\n'
+ 'gchar *\n'
+ 'qmi_message_${service}_get_printable (\n'
+ ' QmiMessage *self,\n'
+ ' const gchar *line_prefix)\n'
+ '{\n'
+ ' 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)
+
+ template += (
+ ' default:\n'
+ ' return NULL;\n'
+ ' }\n'
+ '}\n')
+ cfile.write(string.Template(template).substitute(translations))
+
+
def emit(self, hfile, cfile):
# First, emit the message IDs enum
self.emit_message_ids_enum(cfile)
@@ -74,3 +110,8 @@ class MessageList:
# Then, emit all message handlers
for message in self.list:
message.emit(hfile, cfile)
+
+ # First, emit common class code
+ utils.add_separator(hfile, 'PRINTABLE', self.service);
+ utils.add_separator(cfile, 'PRINTABLE', self.service);
+ self.__emit_get_printable(hfile, cfile)
diff --git a/build-aux/qmi-codegen/utils.py b/build-aux/qmi-codegen/utils.py
index 44284f9..a13443b 100644
--- a/build-aux/qmi-codegen/utils.py
+++ b/build-aux/qmi-codegen/utils.py
@@ -94,6 +94,7 @@ def add_source_start(f, output_name):
"#include \"${name}.h\"\n"
"#include \"qmi-error-types.h\"\n"
"#include \"qmi-device.h\"\n"
+ "#include \"qmi-utils.h\"\n"
'\n'
'#define QMI_STATUS_SUCCESS 0x0000\n'
'#define QMI_STATUS_FAILURE 0x0001\n'
diff --git a/src/Makefile.am b/src/Makefile.am
index cd61bfd..16d6b18 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,8 +64,7 @@ qmi-wds.stamp: $(top_srcdir)/data/qmi-service-wds.json $(top_srcdir)/build-aux/q
# Additional dependencies
qmi-device.c: qmi-error-types.h qmi-enum-types.h
qmi-client.c: qmi-error-types.h qmi-enum-types.h
-qmi-message.c: qmi-error-types.h qmi-enum-types.h
-qmi-message-dms.c: qmi-error-types.h
+qmi-message.c: qmi-error-types.h qmi-enum-types.h qmi-ctl.h qmi-dms.h qmi-wds.h
qmi-ctl.h: qmi-ctl.stamp
qmi-ctl.c: qmi-error-types.h qmi-enum-types.h qmi-ctl.stamp
qmi-dms.h: qmi-dms.stamp
diff --git a/src/qmi-message.c b/src/qmi-message.c
index ca49a1f..f9b1f15 100644
--- a/src/qmi-message.c
+++ b/src/qmi-message.c
@@ -38,6 +38,10 @@
#include "qmi-enum-types.h"
#include "qmi-error-types.h"
+#include "qmi-ctl.h"
+#include "qmi-dms.h"
+#include "qmi-wds.h"
+
#define PACKED __attribute__((packed))
struct qmux {
@@ -93,17 +97,17 @@ struct _QmiMessage {
volatile gint ref_count; /* the ref count */
};
-static inline uint16_t
-qmux_length (QmiMessage *self)
+guint16
+qmi_message_get_qmux_length (QmiMessage *self)
{
- return le16toh (self->buf->qmux.length);
+ return GUINT16_FROM_LE (self->buf->qmux.length);
}
static inline void
set_qmux_length (QmiMessage *self,
uint16_t length)
{
- self->buf->qmux.length = htole16 (length);
+ self->buf->qmux.length = GUINT16_TO_LE (length);
}
gboolean
@@ -208,23 +212,23 @@ qmi_message_get_length (QmiMessage *self)
return self->len;
}
-static uint16_t
-qmi_tlv_length (QmiMessage *self)
+guint16
+qmi_message_get_tlv_length (QmiMessage *self)
{
if (qmi_message_is_control (self))
- return le16toh (self->buf->qmi.control.header.tlv_length);
+ return GUINT16_FROM_LE (self->buf->qmi.control.header.tlv_length);
- return le16toh (self->buf->qmi.service.header.tlv_length);
+ return GUINT16_FROM_LE (self->buf->qmi.service.header.tlv_length);
}
static void
-set_qmi_tlv_length (QmiMessage *self,
- uint16_t length)
+set_qmi_message_get_tlv_length (QmiMessage *self,
+ guint16 length)
{
if (qmi_message_is_control (self))
- self->buf->qmi.control.header.tlv_length = htole16 (length);
+ self->buf->qmi.control.header.tlv_length = GUINT16_TO_LE (length);
else
- self->buf->qmi.service.header.tlv_length = htole16 (length);
+ self->buf->qmi.service.header.tlv_length = GUINT16_TO_LE (length);
}
static struct tlv *
@@ -251,7 +255,7 @@ tlv_next (struct tlv *tlv)
static struct tlv *
qmi_tlv_first (QmiMessage *self)
{
- if (qmi_tlv_length (self))
+ if (qmi_message_get_tlv_length (self))
return qmi_tlv (self);
return NULL;
@@ -300,12 +304,12 @@ qmi_message_check (QmiMessage *self,
return FALSE;
}
- if (qmux_length (self) < sizeof (struct qmux)) {
+ if (qmi_message_get_qmux_length (self) < sizeof (struct qmux)) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_INVALID_MESSAGE,
"QMUX length too short for QMUX header (%u < %" G_GSIZE_FORMAT ")",
- qmux_length (self), sizeof (struct qmux));
+ qmi_message_get_qmux_length (self), sizeof (struct qmux));
return FALSE;
}
@@ -313,12 +317,12 @@ qmi_message_check (QmiMessage *self,
* qmux length is one byte shorter than buffer length because qmux
* length does not include the qmux frame marker.
*/
- if (qmux_length (self) != self->len - 1) {
+ if (qmi_message_get_qmux_length (self) != self->len - 1) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_INVALID_MESSAGE,
"QMUX length and buffer length don't match (%u != %" G_GSIZE_FORMAT ")",
- qmux_length (self), self->len - 1);
+ qmi_message_get_qmux_length (self), self->len - 1);
return FALSE;
}
@@ -326,21 +330,21 @@ qmi_message_check (QmiMessage *self,
sizeof (struct control_header) :
sizeof (struct service_header));
- if (qmux_length (self) < header_length) {
+ if (qmi_message_get_qmux_length (self) < header_length) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_INVALID_MESSAGE,
"QMUX length too short for QMI header (%u < %" G_GSIZE_FORMAT ")",
- qmux_length (self), header_length);
+ qmi_message_get_qmux_length (self), header_length);
return FALSE;
}
- if (qmux_length (self) - header_length != qmi_tlv_length (self)) {
+ if (qmi_message_get_qmux_length (self) - header_length != qmi_message_get_tlv_length (self)) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_INVALID_MESSAGE,
"QMUX length and QMI TLV lengths don't match (%u - %" G_GSIZE_FORMAT " != %u)",
- qmux_length (self), header_length, qmi_tlv_length (self));
+ qmi_message_get_qmux_length (self), header_length, qmi_message_get_tlv_length (self));
return FALSE;
}
@@ -411,7 +415,7 @@ qmi_message_new (QmiService service,
self->buf->qmi.service.header.message = htole16 (message_id);
}
- set_qmi_tlv_length (self, 0);
+ set_qmi_message_get_tlv_length (self, 0);
g_assert (qmi_message_check (self, NULL));
@@ -586,7 +590,7 @@ qmi_message_tlv_add (QmiMessage *self,
tlv_len = sizeof (struct tlv) + length;
/* Check for overflow of message size. */
- if (qmux_length (self) + tlv_len > UINT16_MAX) {
+ if (qmi_message_get_qmux_length (self) + tlv_len > UINT16_MAX) {
g_set_error (error,
QMI_CORE_ERROR,
QMI_CORE_ERROR_TLV_TOO_LONG,
@@ -606,8 +610,8 @@ qmi_message_tlv_add (QmiMessage *self,
memcpy (tlv->value, value, length);
/* Update length fields. */
- set_qmux_length (self, (uint16_t)(qmux_length (self) + tlv_len));
- set_qmi_tlv_length (self, (uint16_t)(qmi_tlv_length(self) + tlv_len));
+ set_qmux_length (self, (uint16_t)(qmi_message_get_qmux_length (self) + tlv_len));
+ set_qmi_message_get_tlv_length (self, (uint16_t)(qmi_message_get_tlv_length(self) + tlv_len));
/* Make sure we didn't break anything. */
if (!qmi_message_check (self, error)) {
@@ -647,14 +651,65 @@ qmi_message_new_from_raw (const guint8 *raw,
return self;
}
+gchar *
+qmi_message_get_tlv_printable (QmiMessage *self,
+ const gchar *line_prefix,
+ guint8 type,
+ gsize length,
+ gconstpointer value)
+{
+ gchar *printable;
+ gchar *value_hex;
+
+ value_hex = qmi_utils_str_hex (value, length, ':');
+ printable = g_strdup_printf ("%sTLV:\n"
+ "%s type = 0x%02x\n"
+ "%s length = %u\n"
+ "%s value = %s\n",
+ line_prefix,
+ line_prefix, type,
+ line_prefix, length,
+ line_prefix, value_hex);
+ g_free (value_hex);
+ return printable;
+}
+
static gchar *
get_generic_printable (QmiMessage *self,
const gchar *line_prefix)
{
GString *printable;
- gchar *qmi_flags_str;
struct tlv *tlv;
+ printable = g_string_new ("");
+
+ g_string_append_printf (printable,
+ "%s message = (0x%04x)\n",
+ line_prefix, qmi_message_get_message_id (self));
+
+ for (tlv = qmi_tlv_first (self); tlv; tlv = qmi_tlv_next (self, tlv)) {
+ gchar *printable_tlv;
+
+ printable_tlv = qmi_message_get_tlv_printable (self,
+ line_prefix,
+ tlv->type,
+ tlv->length,
+ tlv->value);
+ g_string_append (printable, printable_tlv);
+ g_free (printable_tlv);
+ }
+
+ return g_string_free (printable, FALSE);
+}
+
+gchar *
+qmi_message_get_printable (QmiMessage *self,
+ const gchar *line_prefix)
+{
+ GString *printable;
+ gchar *qmi_flags_str;
+ gchar *contents;
+
if (!qmi_message_check (self, NULL))
return NULL;
@@ -664,15 +719,15 @@ get_generic_printable (QmiMessage *self,
printable = g_string_new ("");
g_string_append_printf (printable,
"%sQMUX:\n"
- "%s length = %u (0x%04x)\n"
+ "%s length = %u\n"
"%s flags = 0x%02x\n"
- "%s service = \"%s\" (0x%02x)\n"
- "%s client = %u (0x%02x)\n",
+ "%s service = \"%s\"\n"
+ "%s client = %u\n",
line_prefix,
- line_prefix, qmux_length (self), qmux_length (self),
+ line_prefix, qmi_message_get_qmux_length (self),
line_prefix, qmi_message_get_qmux_flags (self),
- line_prefix, qmi_service_get_string (qmi_message_get_service (self)), qmi_message_get_service (self),
- line_prefix, qmi_message_get_client_id (self), qmi_message_get_client_id (self));
+ line_prefix, qmi_service_get_string (qmi_message_get_service (self)),
+ line_prefix, qmi_message_get_client_id (self));
if (qmi_message_get_service (self) == QMI_SERVICE_CTL)
qmi_flags_str = qmi_ctl_flag_build_string_from_mask (qmi_message_get_qmi_flags (self));
@@ -683,37 +738,32 @@ get_generic_printable (QmiMessage *self,
"%sQMI:\n"
"%s flags = \"%s\"\n"
"%s transaction = %u\n"
- "%s message = 0x%04x\n"
"%s tlv_length = %u\n",
line_prefix,
line_prefix, qmi_flags_str,
line_prefix, qmi_message_get_transaction_id (self),
- line_prefix, qmi_message_get_message_id (self),
- line_prefix, qmi_tlv_length (self));
+ line_prefix, qmi_message_get_tlv_length (self));
g_free (qmi_flags_str);
- for (tlv = qmi_tlv_first (self); tlv; tlv = qmi_tlv_next (self, tlv)) {
- gchar *value_hex;
-
- value_hex = qmi_utils_str_hex (tlv->value, GUINT16_FROM_LE (tlv->length), ':');
- g_string_append_printf (printable,
- "%sTLV:\n"
- "%s type = 0x%02x\n"
- "%s length = %u\n"
- "%s value = %s\n",
- line_prefix,
- line_prefix, tlv->type,
- line_prefix, GUINT16_FROM_LE (tlv->length),
- line_prefix, value_hex);
- g_free (value_hex);
+ contents = NULL;
+ switch (qmi_message_get_service (self)) {
+ case QMI_SERVICE_CTL:
+ contents = qmi_message_ctl_get_printable (self, line_prefix);
+ break;
+ case QMI_SERVICE_DMS:
+ contents = qmi_message_dms_get_printable (self, line_prefix);
+ break;
+ case QMI_SERVICE_WDS:
+ contents = qmi_message_wds_get_printable (self, line_prefix);
+ break;
+ default:
+ break;
}
- return g_string_free (printable, FALSE);
-}
+ if (!contents)
+ contents = get_generic_printable (self, line_prefix);
+ g_string_append (printable, contents);
+ g_free (contents);
-gchar *
-qmi_message_get_printable (QmiMessage *self,
- const gchar *line_prefix)
-{
- return get_generic_printable (self, line_prefix);
+ return g_string_free (printable, FALSE);
}
diff --git a/src/qmi-message.h b/src/qmi-message.h
index dd76768..0aab9f9 100644
--- a/src/qmi-message.h
+++ b/src/qmi-message.h
@@ -81,11 +81,19 @@ gconstpointer qmi_message_get_raw (QmiMessage *self,
gsize *length,
GError **error);
-gsize qmi_message_get_length (QmiMessage *self);
+guint16 qmi_message_get_qmux_length (QmiMessage *self);
+guint16 qmi_message_get_tlv_length (QmiMessage *self);
+gsize qmi_message_get_length (QmiMessage *self);
gchar *qmi_message_get_printable (QmiMessage *self,
const gchar *line_prefix);
+gchar *qmi_message_get_tlv_printable (QmiMessage *self,
+ const gchar *line_prefix,
+ guint8 type,
+ gsize length,
+ gconstpointer value);
+
gboolean qmi_message_check (QmiMessage *self,
GError **error);
diff --git a/src/qmi-utils.c b/src/qmi-utils.c
index c41719b..2a5aed8 100644
--- a/src/qmi-utils.c
+++ b/src/qmi-utils.c
@@ -28,9 +28,9 @@
#include "qmi-utils.h"
gchar *
-qmi_utils_str_hex (gpointer mem,
- gsize size,
- gchar delimiter)
+qmi_utils_str_hex (gconstpointer mem,
+ gsize size,
+ gchar delimiter)
{
const guint8 *data = mem;
gsize i;
diff --git a/src/qmi-utils.h b/src/qmi-utils.h
index b221189..f1a2f27 100644
--- a/src/qmi-utils.h
+++ b/src/qmi-utils.h
@@ -30,9 +30,9 @@
G_BEGIN_DECLS
-gchar *qmi_utils_str_hex (gpointer mem,
- gsize size,
- gchar delimiter);
+gchar *qmi_utils_str_hex (gconstpointer mem,
+ gsize size,
+ gchar delimiter);
G_END_DECLS