diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-05-23 16:40:03 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-07-03 16:08:55 +0200 |
commit | cbfac5dadfa6713e124aba7400937abd4c8daf93 (patch) | |
tree | 2f4d36aa888669a00fcabd446ff795620e68a41c | |
parent | 8fe7fae49a233b7ecc9e180b709a8cba69c0406c (diff) |
qmi-codegen: improve message/TLV printability
-rw-r--r-- | build-aux/qmi-codegen/Message.py | 118 | ||||
-rw-r--r-- | build-aux/qmi-codegen/MessageList.py | 41 | ||||
-rw-r--r-- | build-aux/qmi-codegen/utils.py | 1 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/qmi-message.c | 162 | ||||
-rw-r--r-- | src/qmi-message.h | 10 | ||||
-rw-r--r-- | src/qmi-utils.c | 6 | ||||
-rw-r--r-- | src/qmi-utils.h | 6 |
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 |