diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2021-10-07 21:32:10 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-10-12 22:27:12 +0200 |
commit | 56983e658f961825ac948fd3e544108dd09b4d5f (patch) | |
tree | f0c9132ecebc4d7db667fdeeb6027d5709688114 | |
parent | 8c781c81b1a18ba206dbc5df3595363f4f485c4c (diff) |
libmbim-glib: new MbimTlv generic type
The Microsoft Extensions define a new generic TLV type that allows
including any kind of data in it: from strings, to arrays of uints, to
more complex types.
We define support for the generic 'tlv' type and the generic
'tlv-list' type, which allow implementing the "unnamed IEs" that are
appended to some new messages in the MS extensions.
And we also define support for a more specific 'tlv-string', used
exclusively when the TLVs are part of the named fields, so that we can
provide strings in our libmbim-glib APIs, instead of requiring the
user to build MbimTlv instances.
-rw-r--r-- | build-aux/mbim-codegen/Message.py | 143 | ||||
-rw-r--r-- | build-aux/mbim-codegen/utils.py | 1 | ||||
-rwxr-xr-x | data/mbim-service-ms-basic-connect-extensions.json | 12 | ||||
-rwxr-xr-x | docs/reference/libmbim-glib/libmbim-glib-common.sections | 20 | ||||
-rw-r--r-- | docs/reference/libmbim-glib/libmbim-glib-docs.xml | 1 | ||||
-rw-r--r-- | src/libmbim-glib/generated/meson.build | 2 | ||||
-rw-r--r-- | src/libmbim-glib/libmbim-glib.h | 1 | ||||
-rw-r--r-- | src/libmbim-glib/mbim-message-private.h | 22 | ||||
-rw-r--r-- | src/libmbim-glib/mbim-message.c | 162 | ||||
-rw-r--r-- | src/libmbim-glib/mbim-tlv-private.h | 69 | ||||
-rw-r--r-- | src/libmbim-glib/mbim-tlv.c | 259 | ||||
-rw-r--r-- | src/libmbim-glib/mbim-tlv.h | 224 | ||||
-rw-r--r-- | src/libmbim-glib/meson.build | 2 | ||||
-rw-r--r-- | src/libmbim-glib/test/test-message-builder.c | 237 | ||||
-rw-r--r-- | src/libmbim-glib/test/test-message-parser.c | 254 | ||||
-rw-r--r-- | src/mbimcli/mbimcli-ms-basic-connect-extensions.c | 2 |
16 files changed, 1402 insertions, 9 deletions
diff --git a/build-aux/mbim-codegen/Message.py b/build-aux/mbim-codegen/Message.py index 94c522b..29de874 100644 --- a/build-aux/mbim-codegen/Message.py +++ b/build-aux/mbim-codegen/Message.py @@ -86,6 +86,12 @@ def validate_fields(fields): pass elif field['format'] == 'ipv6-array': flag_always_read_field(fields, field['array-size-field']) + elif field['format'] == 'tlv': + pass + elif field['format'] == 'tlv-string': + pass + elif field['format'] == 'tlv-list': + pass else: raise ValueError('Cannot handle field type \'%s\'' % field['format']) @@ -278,6 +284,12 @@ class Message: inner_template = (' * @${field}: (in): the \'${name}\' field, given as a #MbimIPv6.\n') elif field['format'] == 'ipv6-array': inner_template = (' * @${field}: (in)(array zero-terminated=1)(element-type MbimIPv6): the \'${name}\' field, given as an array of #MbimIPv6 items.\n') + elif field['format'] == 'tlv': + inner_template = (' * @${field}: (in)(transfer none): the \'${name}\' field, given as a #${struct} item.\n') + elif field['format'] == 'tlv-string': + inner_template = (' * @${field}: (in): the \'${name}\' field, given as a string.\n') + elif field['format'] == 'tlv-list': + inner_template = (' * @${field}: (in)(element-type MbimTlv)(transfer none): the \'${name}\' field, given as a list of #${struct} items.\n') template += (string.Template(inner_template).substitute(translations)) @@ -340,6 +352,12 @@ class Message: inner_template = (' const MbimIPv6 *${field},\n') elif field['format'] == 'ipv6-array': inner_template = (' const MbimIPv6 *${field},\n') + elif field['format'] == 'tlv': + inner_template = (' const MbimTlv *${field},\n') + elif field['format'] == 'tlv-string': + inner_template = (' const gchar *${field},\n') + elif field['format'] == 'tlv-list': + inner_template = (' const GList *${field},\n') template += (string.Template(inner_template).substitute(translations)) @@ -401,6 +419,12 @@ class Message: inner_template = (' const MbimIPv6 *${field},\n') elif field['format'] == 'ipv6-array': inner_template = (' const MbimIPv6 *${field},\n') + elif field['format'] == 'tlv': + inner_template = (' const MbimTlv *${field},\n') + elif field['format'] == 'tlv-string': + inner_template = (' const gchar *${field},\n') + elif field['format'] == 'tlv-list': + inner_template = (' const GList *${field},\n') template += (string.Template(inner_template).substitute(translations)) @@ -477,6 +501,13 @@ class Message: inner_template += (' _mbim_message_command_builder_append_ipv6 (builder, ${field}, TRUE);\n') elif field['format'] == 'ipv6-array': inner_template += (' _mbim_message_command_builder_append_ipv6_array (builder, ${field}, ${array_size_field});\n') + elif field['format'] == 'tlv': + inner_template += (' _mbim_message_command_builder_append_tlv (builder, ${field});\n') + elif field['format'] == 'tlv-string': + inner_template += (' _mbim_message_command_builder_append_tlv_string (builder, ${field});\n') + elif field['format'] == 'tlv-list': + inner_template += (' _mbim_message_command_builder_append_tlv_list (builder, ${field});\n') + else: raise ValueError('Cannot handle field type \'%s\'' % field['format']) @@ -557,6 +588,12 @@ class Message: inner_template = (' * @out_${field}: (out)(optional)(transfer none): return location for a #MbimIPv6, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n') elif field['format'] == 'ipv6-array': inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type MbimIPv6): return location for a newly allocated array of #MbimIPv6 items, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n') + elif field['format'] == 'tlv': + inner_template = (' * @out_${field}: (out)(optional)(transfer full): return location for a newly allocated #MbimTlv, or %NULL if the \'${name}\' field is not needed. Free the returned value with mbim_tlv_unref().\n') + elif field['format'] == 'tlv-string': + inner_template = (' * @out_${field}: (out)(optional)(transfer full): return location for a newly allocated string, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n') + elif field['format'] == 'tlv-list': + inner_template = (' * @out_${field}: (out)(optional)(element-type MbimTlv)(transfer full): return location for a newly allocated list of #MbimTlv items, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_list_free_full() using mbim_tlv_unref() as #GDestroyNotify.\n') template += (string.Template(inner_template).substitute(translations)) @@ -618,6 +655,12 @@ class Message: inner_template = (' const MbimIPv6 **out_${field},\n') elif field['format'] == 'ipv6-array': inner_template = (' MbimIPv6 **out_${field},\n') + elif field['format'] == 'tlv': + inner_template = (' MbimTlv **out_${field},\n') + elif field['format'] == 'tlv-string': + inner_template = (' gchar **out_${field},\n') + elif field['format'] == 'tlv-list': + inner_template = (' GList **out_${field},\n') else: raise ValueError('Cannot handle field type \'%s\'' % field['format']) @@ -679,6 +722,12 @@ class Message: inner_template = (' const MbimIPv6 **out_${field},\n') elif field['format'] == 'ipv6-array': inner_template = (' MbimIPv6 **out_${field},\n') + elif field['format'] == 'tlv': + inner_template = (' MbimTlv **out_${field},\n') + elif field['format'] == 'tlv-string': + inner_template = (' gchar **out_${field},\n') + elif field['format'] == 'tlv-list': + inner_template = (' GList **out_${field},\n') template += (string.Template(inner_template).substitute(translations)) @@ -727,6 +776,15 @@ class Message: elif field['format'] == 'ipv6-array': count_allocated_variables += 1 inner_template = (' MbimIPv6 *_${field} = NULL;\n') + elif field['format'] == 'tlv': + count_allocated_variables += 1 + inner_template = (' MbimTlv *_${field} = NULL;\n') + elif field['format'] == 'tlv-string': + count_allocated_variables += 1 + inner_template = (' gchar *_${field} = NULL;\n') + elif field['format'] == 'tlv-list': + count_allocated_variables += 1 + inner_template = (' GList *_${field} = NULL;\n') template += (string.Template(inner_template).substitute(translations)) if message_type == 'response': @@ -1022,6 +1080,42 @@ class Message: ' if ((out_${field} != NULL) && !_mbim_message_read_ipv6_array (message, _${array_size_field}, offset, &_${field}, error))\n' ' goto out;\n' ' offset += 4;\n') + elif field['format'] == 'tlv': + inner_template += ( + ' MbimTlv *tmp = NULL;\n' + ' guint32 bytes_read = 0;\n' + '\n' + ' if (!_mbim_message_read_tlv (message, offset, &tmp, &bytes_read, error))\n' + ' goto out;\n' + ' if (out_${field} != NULL)\n' + ' _${field} = tmp;\n' + ' else\n' + ' mbim_tlv_unref (tmp);\n' + ' offset += bytes_read;\n') + elif field['format'] == 'tlv-string': + inner_template += ( + ' gchar *tmp = NULL;\n' + ' guint32 bytes_read = 0;\n' + '\n' + ' if (!_mbim_message_read_tlv_string (message, offset, &tmp, &bytes_read, error))\n' + ' goto out;\n' + ' if (out_${field} != NULL)\n' + ' _${field} = tmp;\n' + ' else\n' + ' g_free (tmp);\n' + ' offset += bytes_read;\n') + elif field['format'] == 'tlv-list': + inner_template += ( + ' GList *tmp = NULL;\n' + ' guint32 bytes_read = 0;\n' + '\n' + ' if (!_mbim_message_read_tlv_list (message, offset, &tmp, &bytes_read, error))\n' + ' goto out;\n' + ' if (out_${field} != NULL)\n' + ' _${field} = tmp;\n' + ' else\n' + ' g_list_free_full (tmp, (GDestroyNotify)mbim_tlv_unref);\n' + ' offset += bytes_read;\n') inner_template += ( ' }\n') @@ -1053,7 +1147,10 @@ class Message: field['format'] == 'ref-struct-array' or \ field['format'] == 'ms-struct-array' or \ field['format'] == 'ipv4-array' or \ - field['format'] == 'ipv6-array': + field['format'] == 'ipv6-array' or \ + field['format'] == 'tlv' or \ + field['format'] == 'tlv-string' or \ + field['format'] == 'tlv-list': inner_template = (' if (out_${field} != NULL)\n' ' *out_${field} = _${field};\n') template += (string.Template(inner_template).substitute(translations)) @@ -1066,7 +1163,8 @@ class Message: inner_template = '' if field['format'] == 'string' or \ field['format'] == 'ipv4-array' or \ - field['format'] == 'ipv6-array': + field['format'] == 'ipv6-array' or \ + field['format'] == 'tlv-string': inner_template = (' g_free (_${field});\n') elif field['format'] == 'string-array': inner_template = (' g_strfreev (_${field});\n') @@ -1074,6 +1172,10 @@ class Message: inner_template = (' ${struct_underscore}_free (_${field});\n') elif field['format'] == 'struct-array' or field['format'] == 'ref-struct-array' or field['format'] == 'ms-struct-array': inner_template = (' ${struct_underscore}_array_free (_${field});\n') + elif field['format'] == 'tlv': + inner_template = (' mbim_tlv_unref (_${field});\n') + elif field['format'] == 'tlv-list': + inner_template = (' g_list_free_full (_${field}, (GDestroyNotify)mbim_tlv_unref);\n') template += (string.Template(inner_template).substitute(translations)) template += ( ' }\n') @@ -1476,6 +1578,43 @@ class Message: ' }\n' ' g_string_append (str, "\'");\n') + elif field['format'] == 'tlv' or field['format'] == 'tlv-string': + inner_template += ( + ' g_autoptr(MbimTlv) tmp = NULL;\n' + ' guint32 bytes_read = 0;\n' + ' g_autofree gchar *tlv_str = NULL;\n' + ' g_autofree gchar *new_line_prefix = NULL;\n' + '\n' + ' if (!_mbim_message_read_tlv (message, offset, &tmp, &bytes_read, &inner_error))\n' + ' goto out;\n' + ' offset += bytes_read;\n' + '\n' + ' new_line_prefix = g_strdup_printf ("%s ", line_prefix);\n' + ' tlv_str = _mbim_tlv_print (tmp, new_line_prefix);\n' + ' g_string_append_printf (str, "\'%s\'", tlv_str);\n') + + elif field['format'] == 'tlv-list': + inner_template += ( + ' GList *tmp = NULL;\n' + ' GList *walker = NULL;\n' + ' guint32 bytes_read = 0;\n' + ' g_autofree gchar *new_line_prefix = NULL;\n' + '\n' + ' if (!_mbim_message_read_tlv_list (message, offset, &tmp, &bytes_read, &inner_error))\n' + ' goto out;\n' + ' offset += bytes_read;\n' + '\n' + ' new_line_prefix = g_strdup_printf ("%s ", line_prefix);\n' + ' g_string_append (str, "\'[ ");\n' + ' for (walker = tmp; walker; walker = g_list_next (walker)) {\n' + ' g_autofree gchar *tlv_str = NULL;\n' + '\n' + ' tlv_str = _mbim_tlv_print ((MbimTlv *)walker->data, new_line_prefix);\n' + ' g_string_append_printf (str, "%s,", tlv_str);\n' + ' }\n' + ' g_string_append_printf (str, "\\n%s ]\'", line_prefix);\n' + ' g_list_free_full (tmp, (GDestroyNotify)mbim_tlv_unref);\n') + else: raise ValueError('Field format \'%s\' not printable' % field['format']) diff --git a/build-aux/mbim-codegen/utils.py b/build-aux/mbim-codegen/utils.py index c3a8ac3..5ed3ff0 100644 --- a/build-aux/mbim-codegen/utils.py +++ b/build-aux/mbim-codegen/utils.py @@ -76,6 +76,7 @@ def add_source_start(f, output_name): "\n" "#include \"${name}.h\"\n" "#include \"mbim-message-private.h\"\n" + "#include \"mbim-tlv-private.h\"\n" "#include \"mbim-enum-types.h\"\n" "#include \"mbim-error-types.h\"\n" "#include \"mbim-device.h\"\n" diff --git a/data/mbim-service-ms-basic-connect-extensions.json b/data/mbim-service-ms-basic-connect-extensions.json index b53f96c..9c544e8 100755 --- a/data/mbim-service-ms-basic-connect-extensions.json +++ b/data/mbim-service-ms-basic-connect-extensions.json @@ -367,9 +367,9 @@ "public-format" : "MbimDefaultPduActivationHint" }, { "name" : "ReRegisterIfNedeed", "format" : "guint32", - "public-format" : "gboolean" } - // Optional unnamed IEs encoded as MBIM_TLV_IE are currently ignored - ], + "public-format" : "gboolean" }, + { "name" : "UnnamedIes", + "format" : "tlv-list" } ], "query" : [], "response" : [ { "name" : "MicoMode", "format" : "guint32", @@ -385,9 +385,9 @@ "public-format" : "MbimDefaultPduActivationHint" }, { "name" : "ReRegisterIfNedeed", "format" : "guint32", - "public-format" : "gboolean" } - // Optional unnamed IEs encoded as MBIM_TLV_IE are currently ignored - ] }, + "public-format" : "gboolean" }, + { "name" : "UnnamedIes", + "format" : "tlv-list" } ] }, // ********************************************************************************* { "name" : "MbimCellInfoServingGsm", diff --git a/docs/reference/libmbim-glib/libmbim-glib-common.sections b/docs/reference/libmbim-glib/libmbim-glib-common.sections index ddc3b1a..121e83b 100755 --- a/docs/reference/libmbim-glib/libmbim-glib-common.sections +++ b/docs/reference/libmbim-glib/libmbim-glib-common.sections @@ -761,6 +761,26 @@ mbim_utils_set_traces_enabled </SECTION> <SECTION> +<FILE>mbim-tlv</FILE> +MbimTlv +MbimTlvType +<SUBSECTION Methods> +mbim_tlv_new +mbim_tlv_dup +mbim_tlv_ref +mbim_tlv_unref +mbim_tlv_get_raw +mbim_tlv_get_tlv_type +mbim_tlv_get_tlv_data +mbim_tlv_type_get_string +<SUBSECTION Private> +mbim_tlv_type_build_string_from_mask +<SUBSECTION Standard> +MBIM_TYPE_TLV +mbim_tlv_get_type +</SECTION> + +<SECTION> <FILE>mbim-compat</FILE> <SUBSECTION> MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBER_LIST diff --git a/docs/reference/libmbim-glib/libmbim-glib-docs.xml b/docs/reference/libmbim-glib/libmbim-glib-docs.xml index 9974e5c..a9d5d31 100644 --- a/docs/reference/libmbim-glib/libmbim-glib-docs.xml +++ b/docs/reference/libmbim-glib/libmbim-glib-docs.xml @@ -59,6 +59,7 @@ <xi:include href="xml/mbim-enums.xml"/> <xi:include href="xml/mbim-errors.xml"/> <xi:include href="xml/mbim-utils.xml"/> + <xi:include href="xml/mbim-tlv.xml"/> </chapter> <chapter> diff --git a/src/libmbim-glib/generated/meson.build b/src/libmbim-glib/generated/meson.build index 8673609..744ce48 100644 --- a/src/libmbim-glib/generated/meson.build +++ b/src/libmbim-glib/generated/meson.build @@ -65,7 +65,7 @@ gen_headers += custom_target( command: [ python, mbim_mkenums, - '--fhead', '#ifndef __LIBMBIM_GLIB_ENUM_TYPES_H__\n#define __LIBMBIM_GLIB_ENUM_TYPES_H__\n#include "mbim-uuid.h"\n#include "mbim-cid.h"\n#include "mbim-message.h"\n#include "mbim-enums.h"\n', + '--fhead', '#ifndef __LIBMBIM_GLIB_ENUM_TYPES_H__\n#define __LIBMBIM_GLIB_ENUM_TYPES_H__\n#include "mbim-uuid.h"\n#include "mbim-cid.h"\n#include "mbim-message.h"\n#include "mbim-enums.h"\n#include "mbim-tlv.h"\n', '--template', files(templates_dir / enum_types + '.h.template'), '--ftail', '#endif /* __LIBMBIM_GLIB_ENUM_TYPES_H__ */\n', '@INPUT@'], diff --git a/src/libmbim-glib/libmbim-glib.h b/src/libmbim-glib/libmbim-glib.h index 7fdf8e0..ca5ac26 100644 --- a/src/libmbim-glib/libmbim-glib.h +++ b/src/libmbim-glib/libmbim-glib.h @@ -21,6 +21,7 @@ #include "mbim-device.h" #include "mbim-enums.h" #include "mbim-proxy.h" +#include "mbim-tlv.h" /* generated */ #include "mbim-enum-types.h" diff --git a/src/libmbim-glib/mbim-message-private.h b/src/libmbim-glib/mbim-message-private.h index c17046f..2a27c16 100644 --- a/src/libmbim-glib/mbim-message-private.h +++ b/src/libmbim-glib/mbim-message-private.h @@ -18,6 +18,7 @@ #include <glib.h> #include "mbim-message.h" +#include "mbim-tlv.h" G_BEGIN_DECLS @@ -247,6 +248,12 @@ void _mbim_message_command_builder_append_ipv6 (M void _mbim_message_command_builder_append_ipv6_array (MbimMessageCommandBuilder *builder, const MbimIPv6 *values, guint32 n_values); +void _mbim_message_command_builder_append_tlv (MbimMessageCommandBuilder *builder, + const MbimTlv *tlv); +void _mbim_message_command_builder_append_tlv_string (MbimMessageCommandBuilder *builder, + const gchar *str); +void _mbim_message_command_builder_append_tlv_list (MbimMessageCommandBuilder *builder, + const GList *tlvs); /*****************************************************************************/ /* Message parser */ @@ -323,6 +330,21 @@ gboolean _mbim_message_read_string_tlv (const MbimMessage *self, gchar **str, guint32 *tpv_size, GError **error); +gboolean _mbim_message_read_tlv (const MbimMessage *self, + guint32 relative_offset, + MbimTlv **tlv, + guint32 *bytes_read, + GError **error); +gboolean _mbim_message_read_tlv_string (const MbimMessage *self, + guint32 relative_offset, + gchar **str, + guint32 *bytes_read, + GError **error); +gboolean _mbim_message_read_tlv_list (const MbimMessage *self, + guint32 relative_offset, + GList **tlv, + guint32 *bytes_read, + GError **error); G_END_DECLS diff --git a/src/libmbim-glib/mbim-message.c b/src/libmbim-glib/mbim-message.c index 7bd23ac..27f9c35 100644 --- a/src/libmbim-glib/mbim-message.c +++ b/src/libmbim-glib/mbim-message.c @@ -16,6 +16,7 @@ #include "mbim-message-private.h" #include "mbim-error-types.h" #include "mbim-enum-types.h" +#include "mbim-tlv-private.h" #include "mbim-basic-connect.h" #include "mbim-auth.h" @@ -885,6 +886,126 @@ _mbim_message_read_ipv6_array (const MbimMessage *self, return TRUE; } +gboolean +_mbim_message_read_tlv (const MbimMessage *self, + guint32 relative_offset, + MbimTlv **tlv, + guint32 *bytes_read, + GError **error) +{ + guint32 information_buffer_offset; + guint64 tlv_offset; + guint64 required_size; + const guint8 *tlv_raw; + guint64 tlv_size; + + information_buffer_offset = _mbim_message_get_information_buffer_offset (self); + tlv_offset = (guint64)information_buffer_offset + (guint64)relative_offset; + tlv_raw = (const guint8 *) G_STRUCT_MEMBER_P (self->data, tlv_offset); + tlv_size = ((guint64)sizeof (struct tlv) + + (guint64)GUINT32_FROM_LE (((struct tlv *)tlv_raw)->data_length) + + (guint64)((struct tlv *)tlv_raw)->padding_length); + + required_size = tlv_offset + tlv_size; + if ((guint64)self->len < required_size) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, + "cannot read TLV (%" G_GUINT64_FORMAT " bytes) (%u < %" G_GUINT64_FORMAT ")", + tlv_size, self->len, required_size); + return FALSE; + } + + *tlv = _mbim_tlv_new_from_raw (tlv_raw, (guint32)tlv_size, bytes_read, error); + return (*tlv) ? TRUE : FALSE; +} + +gboolean +_mbim_message_read_tlv_string (const MbimMessage *self, + guint32 relative_offset, + gchar **str, + guint32 *bytes_read, + GError **error) +{ + g_autoptr(MbimTlv) tlv = NULL; + guint32 tlv_bytes_read = 0; + gchar *tlv_str; + + if (!_mbim_message_read_tlv (self, + relative_offset, + &tlv, + &tlv_bytes_read, + error)) + return FALSE; + + tlv_str = mbim_tlv_string_get (tlv, error); + if (!tlv_str) + return FALSE; + + *str = tlv_str; + *bytes_read = tlv_bytes_read; + return TRUE; +} + +gboolean +_mbim_message_read_tlv_list (const MbimMessage *self, + guint32 relative_offset, + GList **tlv_list, + guint32 *bytes_read, + GError **error) +{ + guint32 information_buffer_offset; + guint64 tlv_list_offset; + const guint8 *tlv_list_raw; + guint32 tlv_list_raw_size; + GList *list = NULL; + guint32 total_bytes_read = 0; + GError *inner_error = NULL; + + information_buffer_offset = _mbim_message_get_information_buffer_offset (self); + tlv_list_offset = (guint64)information_buffer_offset + (guint64)relative_offset; + + /* TLV list always at the end of the message */ + if ((guint64)self->len < tlv_list_offset) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, + "cannot read TLV at offset (%u < %" G_GUINT64_FORMAT ")", + self->len, tlv_list_offset); + return FALSE; + } + + tlv_list_raw_size = self->len - (guint32)tlv_list_offset; + tlv_list_raw = (const guint8 *) G_STRUCT_MEMBER_P (self->data, tlv_list_offset); + + while ((tlv_list_raw_size > 0) && !inner_error) { + MbimTlv *tlv; + guint32 tlv_size; + + if (tlv_list_raw_size < sizeof (struct tlv)) { + g_warning ("Left %u bytes unused after the TLV list", tlv_list_raw_size); + break; + } + + tlv = _mbim_tlv_new_from_raw (tlv_list_raw, tlv_list_raw_size, &tlv_size, &inner_error); + if (!tlv) + break; + + list = g_list_append (list, tlv); + total_bytes_read += tlv_size; + + g_assert (tlv_list_raw_size >= tlv_size); + tlv_list_raw += tlv_size; + tlv_list_raw_size -= tlv_size; + } + + if (inner_error) { + g_propagate_error (error, inner_error); + g_list_free_full (list, (GDestroyNotify)mbim_tlv_unref); + return FALSE; + } + + *bytes_read = total_bytes_read; + *tlv_list = list; + return TRUE; +} + /*****************************************************************************/ /* Struct builder interface * @@ -1446,6 +1567,47 @@ _mbim_message_command_builder_append_ipv6_array (MbimMessageCommandBuilder *buil } /*****************************************************************************/ +/* TLVs only expected as primary message fields, not inside structs */ + +void +_mbim_message_command_builder_append_tlv (MbimMessageCommandBuilder *builder, + const MbimTlv *tlv) +{ + const guint8 *raw_tlv; + guint32 raw_tlv_size; + + raw_tlv = mbim_tlv_get_raw (tlv, &raw_tlv_size, NULL); + _mbim_struct_builder_append_byte_array (builder->contents_builder, + FALSE, FALSE, FALSE, + raw_tlv, raw_tlv_size, + FALSE); +} + +void +_mbim_message_command_builder_append_tlv_string (MbimMessageCommandBuilder *builder, + const gchar *str) +{ + g_autoptr(MbimTlv) tlv = NULL; + g_autoptr(GError) error = NULL; + + tlv = mbim_tlv_string_new (str, &error); + if (!tlv) + g_warning ("Error appending TLV: %s", error->message); + else + _mbim_message_command_builder_append_tlv (builder, tlv); +} + +void +_mbim_message_command_builder_append_tlv_list (MbimMessageCommandBuilder *builder, + const GList *tlvs) +{ + const GList *l; + + for (l = tlvs; l; l = g_list_next (l)) + _mbim_message_command_builder_append_tlv (builder, (MbimTlv *)(l->data)); +} + +/*****************************************************************************/ /* Generic message interface */ MbimMessage * diff --git a/src/libmbim-glib/mbim-tlv-private.h b/src/libmbim-glib/mbim-tlv-private.h new file mode 100644 index 0000000..7dc2d8f --- /dev/null +++ b/src/libmbim-glib/mbim-tlv-private.h @@ -0,0 +1,69 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * libmbim-glib -- GLib/GIO based library to control MBIM devices + * + * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es> + * Copyright (C) 2021 Intel Corporation + * + * This is a private non-installed header + */ + +#ifndef _LIBMBIM_GLIB_MBIM_TLV_PRIVATE_H_ +#define _LIBMBIM_GLIB_MBIM_TLV_PRIVATE_H_ + +#if !defined (LIBMBIM_GLIB_COMPILATION) +#error "This is a private header!!" +#endif + +#include <glib.h> + +#include "mbim-tlv.h" + +G_BEGIN_DECLS + +/*****************************************************************************/ +/* The MbimTlv */ + +/* Defined in the same way as GByteArray */ +struct _MbimTlv { + guint8 *data; + guint len; +}; + +struct tlv { + guint16 type; + guint8 reserved; + guint8 padding_length; + guint32 data_length; + guint8 data[]; +} __attribute__((packed)); + +#define MBIM_TLV_HEADER(self) ((struct tlv *)(((MbimTlv *)self)->data)) + +#define MBIM_TLV_FIELD_TYPE(self) MBIM_TLV_HEADER (self)->type +#define MBIM_TLV_FIELD_RESERVED(self) MBIM_TLV_HEADER (self)->reserved +#define MBIM_TLV_FIELD_PADDING_LENGTH(self) MBIM_TLV_HEADER (self)->padding_length +#define MBIM_TLV_FIELD_DATA_LENGTH(self) MBIM_TLV_HEADER (self)->data_length +#define MBIM_TLV_FIELD_DATA(self) MBIM_TLV_HEADER (self)->data + +#define MBIM_TLV_GET_TLV_TYPE(self) (MbimTlvType) GUINT16_FROM_LE (MBIM_TLV_FIELD_TYPE (self)) +#define MBIM_TLV_GET_DATA_LENGTH(self) GUINT32_FROM_LE (MBIM_TLV_FIELD_DATA_LENGTH (self)) + +/*****************************************************************************/ +/* Print support */ + +gchar *_mbim_tlv_print (const MbimTlv *tlv, + const gchar *line_prefix); + +/*****************************************************************************/ +/* Parsing support */ + +MbimTlv *_mbim_tlv_new_from_raw (const guint8 *raw, + guint32 raw_length, + guint32 *bytes_read, + GError **error); + +G_END_DECLS + +#endif /* _LIBMBIM_GLIB_MBIM_TLV_PRIVATE_H_ */ diff --git a/src/libmbim-glib/mbim-tlv.c b/src/libmbim-glib/mbim-tlv.c new file mode 100644 index 0000000..df5fba6 --- /dev/null +++ b/src/libmbim-glib/mbim-tlv.c @@ -0,0 +1,259 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * libmbim-glib -- GLib/GIO based library to control MBIM devices + * + * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es> + * Copyright (C) 2021 Intel Corporation + */ + +#include <glib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <endian.h> + +#include "mbim-tlv.h" +#include "mbim-tlv-private.h" +#include "mbim-error-types.h" +#include "mbim-enum-types.h" +#include "mbim-common.h" + +/*****************************************************************************/ + +GType +mbim_tlv_get_type (void) +{ + static gsize g_define_type_id_initialized = 0; + + if (g_once_init_enter (&g_define_type_id_initialized)) { + GType g_define_type_id = + g_boxed_type_register_static (g_intern_static_string ("MbimTlv"), + (GBoxedCopyFunc) mbim_tlv_ref, + (GBoxedFreeFunc) mbim_tlv_unref); + + g_once_init_leave (&g_define_type_id_initialized, g_define_type_id); + } + + return g_define_type_id_initialized; +} + +/*****************************************************************************/ + +gchar * +_mbim_tlv_print (const MbimTlv *tlv, + const gchar *line_prefix) +{ + GString *str; + MbimTlvType tlv_type; + const gchar *tlv_type_str; + const guint8 *tlv_data; + guint32 tlv_data_size; + g_autofree gchar *tlv_data_str = NULL; + + tlv_type = mbim_tlv_get_tlv_type (tlv); + tlv_type_str = mbim_tlv_type_get_string (tlv_type); + + str = g_string_new (""); + g_string_append_printf (str, "{\n"); + g_string_append_printf (str, "%s tlv type = %s (0x%04x)\n", line_prefix, tlv_type_str ? tlv_type_str : "unknown", tlv_type); + + tlv_data = mbim_tlv_get_tlv_data (tlv, &tlv_data_size); + tlv_data_str = mbim_common_str_hex (tlv_data, tlv_data_size, ':'); + g_string_append_printf (str, "%s tlv data = %s\n", line_prefix, tlv_data_str ? tlv_data_str : ""); + + if (tlv_type == MBIM_TLV_TYPE_WCHAR_STR) { + g_autoptr(GError) error = NULL; + g_autofree gchar *tlv_data_string_str = NULL; + + tlv_data_string_str = mbim_tlv_string_get (tlv, &error); + if (!tlv_data_string_str) + tlv_data_string_str = g_strdup_printf ("*** error: %s", error->message); + g_string_append_printf (str, "%s tlv string = %s\n", line_prefix, tlv_data_string_str ? tlv_data_string_str : ""); + } + + g_string_append_printf (str, "%s}", line_prefix); + + return g_string_free (str, FALSE); +} + +/*****************************************************************************/ + +MbimTlv * +mbim_tlv_new (MbimTlvType tlv_type, + const guint8 *tlv_data, + guint32 tlv_data_length) +{ + GByteArray *self; + guint32 tlv_size; + guint32 padding_size; + + g_return_val_if_fail (tlv_type != MBIM_TLV_TYPE_INVALID, NULL); + + /* Compute size of the TLV and allocate heap for it */ + padding_size = (tlv_data_length % 4) ? (4 - (tlv_data_length % 4)) : 0; + tlv_size = sizeof (struct tlv) + tlv_data_length + padding_size; + self = g_byte_array_sized_new (tlv_size); + g_byte_array_set_size (self, tlv_size); + + /* Set TLV header */ + MBIM_TLV_FIELD_TYPE (self) = GUINT16_TO_LE (tlv_type); + MBIM_TLV_FIELD_RESERVED (self) = 0; + MBIM_TLV_FIELD_PADDING_LENGTH (self) = padding_size; + MBIM_TLV_FIELD_DATA_LENGTH (self) = GUINT32_TO_LE (tlv_data_length); + + if (tlv_data && tlv_data_length) { + memcpy (MBIM_TLV_FIELD_DATA (self), tlv_data, tlv_data_length); + if (padding_size) + memset (MBIM_TLV_FIELD_DATA (self) + tlv_data_length, 0, padding_size); + } + + return (MbimTlv *)self; +} + +MbimTlv * +_mbim_tlv_new_from_raw (const guint8 *raw, + guint32 raw_length, + guint32 *bytes_read, + GError **error) +{ + guint32 tlv_size; + + g_assert (raw_length >= sizeof (struct tlv)); + tlv_size = sizeof (struct tlv) + GUINT32_FROM_LE (((struct tlv *)raw)->data_length) + ((struct tlv *)raw)->padding_length; + + *bytes_read = tlv_size; + return (MbimTlv *) g_byte_array_append (g_byte_array_sized_new (tlv_size), raw, tlv_size); +} + +MbimTlv * +mbim_tlv_dup (const MbimTlv *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return mbim_tlv_new (MBIM_TLV_GET_TLV_TYPE (self), + MBIM_TLV_FIELD_DATA (self), + MBIM_TLV_GET_DATA_LENGTH (self)); +} + +MbimTlv * +mbim_tlv_ref (MbimTlv *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return (MbimTlv *) g_byte_array_ref ((GByteArray *)self); +} + +void +mbim_tlv_unref (MbimTlv *self) +{ + g_return_if_fail (self != NULL); + + g_byte_array_unref ((GByteArray *)self); +} + +MbimTlvType +mbim_tlv_get_tlv_type (const MbimTlv *self) +{ + g_return_val_if_fail (self != NULL, MBIM_TLV_TYPE_INVALID); + + return MBIM_TLV_GET_TLV_TYPE (self); +} + +const guint8 * +mbim_tlv_get_tlv_data (const MbimTlv *self, + guint32 *out_length) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (out_length != NULL, NULL); + + *out_length = MBIM_TLV_GET_DATA_LENGTH (self); + return MBIM_TLV_FIELD_DATA (self); +} + +const guint8 * +mbim_tlv_get_raw (const MbimTlv *self, + guint32 *length, + GError **error) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (length != NULL, NULL); + + if (!self->data || !self->len) { + g_set_error_literal (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "TLV is invalid"); + return NULL; + } + + *length = (guint32) self->len; + return self->data; +} + +/*****************************************************************************/ + +MbimTlv * +mbim_tlv_string_new (const gchar *str, + GError **error) +{ + g_autofree gunichar2 *utf16 = NULL; + guint32 utf16_bytes = 0; + + /* Convert the string from UTF-8 to UTF-16HE */ + if (str && str[0]) { + glong items_written = 0; + + utf16 = g_utf8_to_utf16 (str, + -1, + NULL, /* bytes */ + &items_written, /* gunichar2 */ + error); + if (!utf16) + return NULL; + + utf16_bytes = items_written * 2; + + /* For BE systems, convert from BE to LE */ + if (G_BYTE_ORDER == G_BIG_ENDIAN) { + guint i; + + for (i = 0; i < items_written; i++) + utf16[i] = GUINT16_TO_LE (utf16[i]); + } + } + + return mbim_tlv_new (MBIM_TLV_TYPE_WCHAR_STR, (const guint8 *)utf16, utf16_bytes); +} + +gchar * +mbim_tlv_string_get (const MbimTlv *self, + GError **error) +{ + const gunichar2 *utf16 = NULL; + g_autofree gunichar2 *utf16d = NULL; + guint32 size; + + g_return_val_if_fail (self != NULL, NULL); + + if (MBIM_TLV_GET_TLV_TYPE (self) != MBIM_TLV_TYPE_WCHAR_STR) { + g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, + "TLV is not a WCHAR string"); + return NULL; + } + + utf16 = (const gunichar2 *) MBIM_TLV_FIELD_DATA (self); + size = MBIM_TLV_FIELD_DATA_LENGTH (self); + + /* For BE systems, convert from LE to BE */ + if (G_BYTE_ORDER == G_BIG_ENDIAN) { + guint i; + + utf16d = (gunichar2 *) g_malloc (size); + for (i = 0; i < (size / 2); i++) + utf16d[i] = GUINT16_FROM_LE (utf16[i]); + } + + return g_utf16_to_utf8 (utf16d ? utf16d : utf16, + size / 2, + NULL, + NULL, + error); +} diff --git a/src/libmbim-glib/mbim-tlv.h b/src/libmbim-glib/mbim-tlv.h new file mode 100644 index 0000000..2300cd5 --- /dev/null +++ b/src/libmbim-glib/mbim-tlv.h @@ -0,0 +1,224 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * libmbim-glib -- GLib/GIO based library to control MBIM devices + * + * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es> + * Copyright (C) 2021 Intel Corporation + */ + +#ifndef _LIBMBIM_GLIB_MBIM_TLV_H_ +#define _LIBMBIM_GLIB_MBIM_TLV_H_ + +#if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) +#error "Only <libmbim-glib.h> can be included directly." +#endif + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +/** + * SECTION:mbim-tlv + * @title: MbimTlv + * @short_description: A variable-sized data structure specified in Microsoft MBIM extensions. + * + * The #MbimTlv structure is capable of exchanging a wide range of information + * between an MBIM host and an MBIM device. + * + * CID payloads for requests, responses, and/or notifications may contain zero + * or more unnamed and optional Information Elements (IE) encoded as #MbimTlv + * fields. + */ + +/** + * MbimTlv: + * + * An opaque type representing a MBIM TLV. + * + * Since: 1.28 + */ +typedef struct _MbimTlv MbimTlv; + +GType mbim_tlv_get_type (void) G_GNUC_CONST; +#define MBIM_TYPE_TLV (mbim_tlv_get_type ()) + +/*****************************************************************************/ +/* Generic TLV interface */ + +/** + * MbimTlvType: + * @MBIM_TLV_TYPE_INVALID: Invalid TLV type. + * @MBIM_TLV_TYPE_UE_POLICITES: UE policies. + * @MBIM_TLV_TYPE_SINGLE_NSSAI: Single NSSAI. + * @MBIM_TLV_TYPE_ALLOWED_NSSAI: Allowed NSSAI. + * @MBIM_TLV_TYPE_CFG_NSSAI: Configured NSSAI. + * @MBIM_TLV_TYPE_DFLT_CFG_NSSAI: Default configured NSSAI. + * @MBIM_TLV_TYPE_PRECFG_DFLT_CFG_NSSAI: Preconfigured default configured NSSAI. + * @MBIM_TLV_TYPE_REJ_NSSAI: Rejected NSSAI. + * @MBIM_TLV_TYPE_LADN: Local Area Data Network (LADN). + * @MBIM_TLV_TYPE_TAI: Tracking Area Identity (TAI). + * @MBIM_TLV_TYPE_WCHAR_STR: WCHAR string. + * @MBIM_TLV_TYPE_UINT16_TBL: Array of 1 or more @guint16 entries. + * @MBIM_TLV_TYPE_EAP_PACKET: Extensible Authentication Protocol packet. + * @MBIM_TLV_TYPE_PCO: Protocol Configuration Option (PCO). + * @MBIM_TLV_TYPE_ROUTE_SELECTION_DESCRIPTORS: One or more route selection descriptors. + * @MBIM_TLV_TYPE_TRAFFIC_PARAMETERS: A traffic parameters record. + * @MBIM_TLV_TYPE_WAKE_COMMAND: Wake command. + * @MBIM_TLV_TYPE_WAKE_PACKET: Wake packet. + * + * Type of the MBIM TLV. + * + * Since: 1.28 + */ +typedef enum { + MBIM_TLV_TYPE_INVALID = 0, + MBIM_TLV_TYPE_UE_POLICITES = 1, + MBIM_TLV_TYPE_SINGLE_NSSAI = 2, + MBIM_TLV_TYPE_ALLOWED_NSSAI = 3, + MBIM_TLV_TYPE_CFG_NSSAI = 4, + MBIM_TLV_TYPE_DFLT_CFG_NSSAI = 5, + MBIM_TLV_TYPE_PRECFG_DFLT_CFG_NSSAI = 6, + MBIM_TLV_TYPE_REJ_NSSAI = 7, + MBIM_TLV_TYPE_LADN = 8, + MBIM_TLV_TYPE_TAI = 9, + MBIM_TLV_TYPE_WCHAR_STR = 10, + MBIM_TLV_TYPE_UINT16_TBL = 11, + MBIM_TLV_TYPE_EAP_PACKET = 12, + MBIM_TLV_TYPE_PCO = 13, + MBIM_TLV_TYPE_ROUTE_SELECTION_DESCRIPTORS = 14, + MBIM_TLV_TYPE_TRAFFIC_PARAMETERS = 15, + MBIM_TLV_TYPE_WAKE_COMMAND = 16, + MBIM_TLV_TYPE_WAKE_PACKET = 17, +} MbimTlvType; + +/** + * mbim_tlv_new: + * @type: a #MbimTlvType. + * @data: contents of the TLV. + * @data_length: length of the message. + * + * Create a #MbimTlv with the given contents. + * + * Returns: (transfer full): a newly created #MbimTlv, which should be freed with mbim_tlv_unref(). + * + * Since: 1.28 + */ +MbimTlv *mbim_tlv_new (MbimTlvType type, + const guint8 *data, + guint32 data_length); + +/** + * mbim_tlv_dup: + * @self: a #MbimTlv to duplicate. + * + * Create a #MbimTlv with the same contents as @self. + * + * Returns: (transfer full): a newly created #MbimTlv, which should be freed with mbim_tlv_unref(). + * + * Since: 1.28 + */ +MbimTlv *mbim_tlv_dup (const MbimTlv *self); + +/** + * mbim_tlv_ref: + * @self: a #MbimTlv. + * + * Atomically increments the reference count of @self by one. + * + * Returns: (transfer full): the new reference to @self. + * + * Since: 1.28 + */ +MbimTlv *mbim_tlv_ref (MbimTlv *self); + +/** + * mbim_tlv_unref: + * @self: a #MbimTlv. + * + * Atomically decrements the reference count of @self by one. + * If the reference count drops to 0, @self is completely disposed. + * + * Since: 1.28 + */ +void mbim_tlv_unref (MbimTlv *self); + +/** + * mbim_tlv_get_raw: + * @self: a #MbimTlv. + * @length: (out): return location for the size of the output buffer. + * @error: return location for error or %NULL. + * + * Gets the whole raw data buffer of the #MbimTlv. + * + * Returns: The raw data buffer, or #NULL if @error is set. + * + * Since: 1.28 + */ +const guint8 *mbim_tlv_get_raw (const MbimTlv *self, + guint32 *length, + GError **error); + +/** + * mbim_tlv_get_tlv_type: + * @self: a #MbimTlv. + * + * Gets the message type. + * + * Returns: a #MbimTlvType. + * + * Since: 1.28 + */ +MbimTlvType mbim_tlv_get_tlv_type (const MbimTlv *self); + +/** + * mbim_tlv_get_tlv_data: + * @self: a #MbimTlv. + * @out_length: (out): return location for the size of the output buffer. + * + * Gets the TLV raw data. + * + * Returns: (transfer none): The raw data buffer, or #NULL if empty. + * + * Since: 1.28 + */ +const guint8 *mbim_tlv_get_tlv_data (const MbimTlv *self, + guint32 *out_length); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimTlv, mbim_tlv_unref) + +/*****************************************************************************/ +/* String TLV type helpers */ + +/** + * mbim_tlv_string_new: + * @str: a string. + * @error: return location for error or %NULL. + * + * Create a #MbimTlv of type %MBIM_TLV_TYPE_WCHAR_STR with the given contents. + * + * Returns: (transfer full): a newly created #MbimTlv which should be freed with mbim_tlv_unref(), or %NULL if @error is set. + * + * Since: 1.28 + */ +MbimTlv *mbim_tlv_string_new (const gchar *str, + GError **error); + +/** + * mbim_tlv_string_get: + * @self: a #MbimTlv of type %MBIM_TLV_TYPE_WCHAR_STR. + * @error: return location for error or %NULL. + * + * Get a string with the contents in the #MbimTlv. + * + * Returns: (transfer full): a newly created string, which should be freed with g_free(), or %NULL if @error is set. + * + * Since: 1.28 + */ +gchar *mbim_tlv_string_get (const MbimTlv *self, + GError **error); + +G_END_DECLS + +#endif /* _LIBMBIM_GLIB_MBIM_TLV_H_ */ diff --git a/src/libmbim-glib/meson.build b/src/libmbim-glib/meson.build index 211836c..7574f5b 100644 --- a/src/libmbim-glib/meson.build +++ b/src/libmbim-glib/meson.build @@ -10,6 +10,7 @@ mbim_enums_headers = files( 'mbim-enums.h', 'mbim-message.h', 'mbim-uuid.h', + 'mbim-tlv.h', ) subdir('generated') @@ -44,6 +45,7 @@ sources = files( 'mbim-proxy-helpers.c', 'mbim-utils.c', 'mbim-uuid.c', + 'mbim-tlv.c', ) deps = [ diff --git a/src/libmbim-glib/test/test-message-builder.c b/src/libmbim-glib/test/test-message-builder.c index 45442d7..2b5784f 100644 --- a/src/libmbim-glib/test/test-message-builder.c +++ b/src/libmbim-glib/test/test-message-builder.c @@ -18,6 +18,7 @@ #include "mbim-stk.h" #include "mbim-dss.h" #include "mbim-ms-host-shutdown.h" +#include "mbim-ms-basic-connect-extensions.h" #if defined ENABLE_TEST_MESSAGE_TRACES static void @@ -1337,6 +1338,239 @@ test_message_builder_ms_host_shutdown_notify_set (void) mbim_message_unref (message); } +static void +test_message_builder_ms_basic_connect_extensions_registration_parameters_set_0_unnamed_tlvs (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) message = NULL; + const guint8 expected_message [] = { + /* header */ + 0x03, 0x00, 0x00, 0x00, /* type */ + 0x44, 0x00, 0x00, 0x00, /* length */ + 0x01, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x11, 0x00, 0x00, 0x00, /* command id */ + 0x01, 0x00, 0x00, 0x00, /* command_type */ + 0x14, 0x00, 0x00, 0x00, /* buffer length */ + /* information buffer */ + 0x00, 0x00, 0x00, 0x00, /* mico mode */ + 0x00, 0x00, 0x00, 0x00, /* drx cycle */ + 0x00, 0x00, 0x00, 0x00, /* ladn info */ + 0x01, 0x00, 0x00, 0x00, /* pdu hint */ + 0x01, 0x00, 0x00, 0x00, /* re register if needed */ + /* no unnamed TLVs */ + }; + + message = (mbim_message_ms_basic_connect_extensions_registration_parameters_set_new ( + MBIM_MICO_MODE_DISABLED, + MBIM_DRX_CYCLE_NOT_SPECIFIED, + MBIM_LADN_INFO_NOT_NEEDED, + MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY, + TRUE, + NULL, /* 0 unnamed ies */ + &error)); + g_assert_no_error (error); + g_assert (message != NULL); + + mbim_message_set_transaction_id (message, 1); + + test_message_trace ((const guint8 *)((GByteArray *)message)->data, + ((GByteArray *)message)->len, + expected_message, + sizeof (expected_message)); + + g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); + g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); + g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); + + g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS); + g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS); + g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); + + g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); + g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); +} + +static void +test_message_builder_ms_basic_connect_extensions_registration_parameters_set_1_unnamed_tlv (void) +{ + MbimTlv *tlv; + GList *tlv_list = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) message = NULL; + const guint8 expected_message [] = { + /* header */ + 0x03, 0x00, 0x00, 0x00, /* type */ + 0x58, 0x00, 0x00, 0x00, /* length */ + 0x01, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x11, 0x00, 0x00, 0x00, /* command id */ + 0x01, 0x00, 0x00, 0x00, /* command_type */ + 0x28, 0x00, 0x00, 0x00, /* buffer length */ + /* information buffer */ + 0x00, 0x00, 0x00, 0x00, /* mico mode */ + 0x00, 0x00, 0x00, 0x00, /* drx cycle */ + 0x00, 0x00, 0x00, 0x00, /* ladn info */ + 0x01, 0x00, 0x00, 0x00, /* pdu hint */ + 0x01, 0x00, 0x00, 0x00, /* re register if needed */ + /* First unnamed TLV */ + 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ + 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ + 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ + 0x61, 0x00, 0x6E, 0x00, + 0x67, 0x00, 0x65, 0x00, + }; + + tlv = mbim_tlv_string_new ("Orange", &error); + g_assert_no_error (error); + g_assert (tlv); + tlv_list = g_list_append (tlv_list, tlv); + + message = (mbim_message_ms_basic_connect_extensions_registration_parameters_set_new ( + MBIM_MICO_MODE_DISABLED, + MBIM_DRX_CYCLE_NOT_SPECIFIED, + MBIM_LADN_INFO_NOT_NEEDED, + MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY, + TRUE, + tlv_list, + &error)); + g_assert_no_error (error); + g_assert (message != NULL); + + mbim_message_set_transaction_id (message, 1); + + test_message_trace ((const guint8 *)((GByteArray *)message)->data, + ((GByteArray *)message)->len, + expected_message, + sizeof (expected_message)); + + g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); + g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); + g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); + + g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS); + g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS); + g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); + + g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); + g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); + + g_list_free_full (tlv_list, (GDestroyNotify)mbim_tlv_unref); +} + +static void +test_message_builder_ms_basic_connect_extensions_registration_parameters_set_3_unnamed_tlvs (void) +{ + MbimTlv *tlv; + GList *tlv_list = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) message = NULL; + const guint8 pco[] = { + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B }; + const guint8 expected_message [] = { + /* header */ + 0x03, 0x00, 0x00, 0x00, /* type */ + 0x80, 0x00, 0x00, 0x00, /* length */ + 0x01, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x11, 0x00, 0x00, 0x00, /* command id */ + 0x01, 0x00, 0x00, 0x00, /* command_type */ + 0x50, 0x00, 0x00, 0x00, /* buffer length */ + /* information buffer */ + 0x00, 0x00, 0x00, 0x00, /* mico mode */ + 0x00, 0x00, 0x00, 0x00, /* drx cycle */ + 0x00, 0x00, 0x00, 0x00, /* ladn info */ + 0x01, 0x00, 0x00, 0x00, /* pdu hint */ + 0x01, 0x00, 0x00, 0x00, /* re register if needed */ + /* First unnamed TLV */ + 0x0A, 0x00, 0x00, 0x02, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, padding 2 */ + 0x0A, 0x00, 0x00, 0x00, /* TLV data length */ + 0x61, 0x00, 0x62, 0x00, /* TLV data string */ + 0x63, 0x00, 0x64, 0x00, + 0x65, 0x00, 0x00, 0x00, + /* Second unnamed TLV */ + 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ + 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ + 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ + 0x61, 0x00, 0x6E, 0x00, + 0x67, 0x00, 0x65, 0x00, + /* Third unnamed TLV */ + 0x0D, 0x00, 0x00, 0x01, /* TLV type MBIM_TLV_TYPE_PCO, padding 1 */ + 0x0B, 0x00, 0x00, 0x00, /* TLV data length */ + 0x01, 0x02, 0x03, 0x04, /* TLV data bytes */ + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x00, + }; + + tlv = mbim_tlv_string_new ("abcde", &error); + g_assert_no_error (error); + g_assert (tlv); + tlv_list = g_list_append (tlv_list, tlv); + + tlv = mbim_tlv_string_new ("Orange", &error); + g_assert_no_error (error); + g_assert (tlv); + tlv_list = g_list_append (tlv_list, tlv); + + tlv = mbim_tlv_new (MBIM_TLV_TYPE_PCO, pco, sizeof (pco)); + g_assert (tlv); + tlv_list = g_list_append (tlv_list, tlv); + + message = (mbim_message_ms_basic_connect_extensions_registration_parameters_set_new ( + MBIM_MICO_MODE_DISABLED, + MBIM_DRX_CYCLE_NOT_SPECIFIED, + MBIM_LADN_INFO_NOT_NEEDED, + MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY, + TRUE, + tlv_list, + &error)); + g_assert_no_error (error); + g_assert (message != NULL); + + mbim_message_set_transaction_id (message, 1); + + test_message_trace ((const guint8 *)((GByteArray *)message)->data, + ((GByteArray *)message)->len, + expected_message, + sizeof (expected_message)); + + g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); + g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); + g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); + + g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS); + g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS); + g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); + + g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); + g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); + + g_list_free_full (tlv_list, (GDestroyNotify)mbim_tlv_unref); +} + int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); @@ -1358,6 +1592,9 @@ int main (int argc, char **argv) g_test_add_func ("/libmbim-glib/message/builder/dss/connect/set", test_message_builder_dss_connect_set); g_test_add_func ("/libmbim-glib/message/builder/basic-connect/multicarrier-providers/set", test_message_builder_basic_connect_multicarrier_providers_set); g_test_add_func ("/libmbim-glib/message/builder/ms-host-shutdown/notify/set", test_message_builder_ms_host_shutdown_notify_set); + g_test_add_func ("/libmbim-glib/message/builder/ms-basic-connect-extensions/registration-parameters/set/0-unnamed-tlvs", test_message_builder_ms_basic_connect_extensions_registration_parameters_set_0_unnamed_tlvs); + g_test_add_func ("/libmbim-glib/message/builder/ms-basic-connect-extensions/registration-parameters/set/1-unnamed-tlv", test_message_builder_ms_basic_connect_extensions_registration_parameters_set_1_unnamed_tlv); + g_test_add_func ("/libmbim-glib/message/builder/ms-basic-connect-extensions/registration-parameters/set/3-unnamed-tlvs", test_message_builder_ms_basic_connect_extensions_registration_parameters_set_3_unnamed_tlvs); return g_test_run (); } diff --git a/src/libmbim-glib/test/test-message-parser.c b/src/libmbim-glib/test/test-message-parser.c index 96109f6..fe850a6 100644 --- a/src/libmbim-glib/test/test-message-parser.c +++ b/src/libmbim-glib/test/test-message-parser.c @@ -15,6 +15,7 @@ #include "mbim-ms-firmware-id.h" #include "mbim-ms-basic-connect-extensions.h" #include "mbim-message.h" +#include "mbim-tlv.h" #include "mbim-cid.h" #include "mbim-common.h" #include "mbim-error-types.h" @@ -1975,6 +1976,256 @@ test_message_parser_ms_basic_connect_extensions_base_stations (void) g_assert_null (cdma_cells); } +static void +test_message_parser_ms_basic_connect_extensions_registration_parameters_0_unnamed_tlvs (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) response = NULL; + gboolean result; + MbimMicoMode mico_mode; + MbimDrxCycle drx_cycle; + MbimLadnInfo ladn_info; + MbimDefaultPduActivationHint pdu_hint; + gboolean re_register_if_needed; + GList *unnamed_ies = NULL; + + const guint8 buffer [] = { + /* header */ + 0x03, 0x00, 0x00, 0x80, /* type */ + 0x44, 0x00, 0x00, 0x00, /* length */ + 0x04, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x11, 0x00, 0x00, 0x00, /* command id */ + 0x00, 0x00, 0x00, 0x00, /* status code */ + 0x14, 0x00, 0x00, 0x00, /* buffer length */ + /* information buffer */ + 0x00, 0x00, 0x00, 0x00, /* mico mode */ + 0x00, 0x00, 0x00, 0x00, /* drx cycle */ + 0x00, 0x00, 0x00, 0x00, /* ladn info */ + 0x01, 0x00, 0x00, 0x00, /* pdu hint */ + 0x01, 0x00, 0x00, 0x00, /* re register if needed */ + /* no unnamed TLVs */ + }; + + response = mbim_message_new (buffer, sizeof (buffer)); + + result = (mbim_message_ms_basic_connect_extensions_registration_parameters_response_parse ( + response, + &mico_mode, + &drx_cycle, + &ladn_info, + &pdu_hint, + &re_register_if_needed, + &unnamed_ies, + &error)); + + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (mico_mode, ==, MBIM_MICO_MODE_DISABLED); + g_assert_cmpuint (drx_cycle, ==, MBIM_DRX_CYCLE_NOT_SPECIFIED); + g_assert_cmpuint (ladn_info, ==, MBIM_LADN_INFO_NOT_NEEDED); + g_assert_cmpuint (pdu_hint, ==, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY); + g_assert_cmpuint (re_register_if_needed, ==, TRUE); + g_assert_cmpuint (g_list_length (unnamed_ies), ==, 0); +} + +static void +test_message_parser_ms_basic_connect_extensions_registration_parameters_1_unnamed_tlv (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) response = NULL; + gboolean result; + MbimMicoMode mico_mode; + MbimDrxCycle drx_cycle; + MbimLadnInfo ladn_info; + MbimDefaultPduActivationHint pdu_hint; + gboolean re_register_if_needed; + GList *unnamed_ies = NULL; + MbimTlv *tlv; + g_autofree gchar *tlv_str = NULL; + + const guint8 buffer [] = { + /* header */ + 0x03, 0x00, 0x00, 0x80, /* type */ + 0x58, 0x00, 0x00, 0x00, /* length */ + 0x04, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x11, 0x00, 0x00, 0x00, /* command id */ + 0x00, 0x00, 0x00, 0x00, /* status code */ + 0x28, 0x00, 0x00, 0x00, /* buffer length */ + /* information buffer */ + 0x00, 0x00, 0x00, 0x00, /* mico mode */ + 0x00, 0x00, 0x00, 0x00, /* drx cycle */ + 0x00, 0x00, 0x00, 0x00, /* ladn info */ + 0x01, 0x00, 0x00, 0x00, /* pdu hint */ + 0x01, 0x00, 0x00, 0x00, /* re register if needed */ + /* First unnamed TLV */ + 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ + 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ + 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ + 0x61, 0x00, 0x6E, 0x00, + 0x67, 0x00, 0x65, 0x00, + }; + + response = mbim_message_new (buffer, sizeof (buffer)); + + result = (mbim_message_ms_basic_connect_extensions_registration_parameters_response_parse ( + response, + &mico_mode, + &drx_cycle, + &ladn_info, + &pdu_hint, + &re_register_if_needed, + &unnamed_ies, + &error)); + + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (mico_mode, ==, MBIM_MICO_MODE_DISABLED); + g_assert_cmpuint (drx_cycle, ==, MBIM_DRX_CYCLE_NOT_SPECIFIED); + g_assert_cmpuint (ladn_info, ==, MBIM_LADN_INFO_NOT_NEEDED); + g_assert_cmpuint (pdu_hint, ==, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY); + g_assert_cmpuint (re_register_if_needed, ==, TRUE); + g_assert_cmpuint (g_list_length (unnamed_ies), ==, 1); + + tlv = (MbimTlv *)(unnamed_ies->data); + g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); + + tlv_str = mbim_tlv_string_get (tlv, &error); + g_assert_no_error (error); + g_assert_cmpstr (tlv_str, ==, "Orange"); + + g_list_free_full (unnamed_ies, (GDestroyNotify)mbim_tlv_unref); +} + +static void +test_message_parser_ms_basic_connect_extensions_registration_parameters_3_unnamed_tlvs (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(MbimMessage) response = NULL; + gboolean result; + MbimMicoMode mico_mode; + MbimDrxCycle drx_cycle; + MbimLadnInfo ladn_info; + MbimDefaultPduActivationHint pdu_hint; + gboolean re_register_if_needed; + GList *unnamed_ies = NULL; + GList *iter; + MbimTlv *tlv; + g_autofree gchar *tlv_str_1 = NULL; + const gchar *expected_tlv_str_1 = "abcde"; + g_autofree gchar *tlv_str_2 = NULL; + const gchar *expected_tlv_str_2 = "Orange"; + const guint8 *pco_3 = NULL; + guint32 pco_3_size = 0; + const guint8 expected_pco[] = { 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B }; + + const guint8 buffer [] = { + /* header */ + 0x03, 0x00, 0x00, 0x80, /* type */ + 0x80, 0x00, 0x00, 0x00, /* length */ + 0x04, 0x00, 0x00, 0x00, /* transaction id */ + /* fragment header */ + 0x01, 0x00, 0x00, 0x00, /* total */ + 0x00, 0x00, 0x00, 0x00, /* current */ + /* command_done_message */ + 0x3D, 0x01, 0xDC, 0xC5, /* service id */ + 0xFE, 0xF5, 0x4D, 0x05, + 0x0D, 0x3A, 0xBE, 0xF7, + 0x05, 0x8E, 0x9A, 0xAF, + 0x11, 0x00, 0x00, 0x00, /* command id */ + 0x00, 0x00, 0x00, 0x00, /* status code */ + 0x50, 0x00, 0x00, 0x00, /* buffer length */ + /* information buffer */ + 0x00, 0x00, 0x00, 0x00, /* mico mode */ + 0x00, 0x00, 0x00, 0x00, /* drx cycle */ + 0x00, 0x00, 0x00, 0x00, /* ladn info */ + 0x01, 0x00, 0x00, 0x00, /* pdu hint */ + 0x01, 0x00, 0x00, 0x00, /* re register if needed */ + /* First unnamed TLV */ + 0x0A, 0x00, 0x00, 0x02, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, padding 2 */ + 0x0A, 0x00, 0x00, 0x00, /* TLV data length */ + 0x61, 0x00, 0x62, 0x00, /* TLV data string */ + 0x63, 0x00, 0x64, 0x00, + 0x65, 0x00, 0x00, 0x00, + /* Second unnamed TLV */ + 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ + 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ + 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ + 0x61, 0x00, 0x6E, 0x00, + 0x67, 0x00, 0x65, 0x00, + /* Third unnamed TLV */ + 0x0D, 0x00, 0x00, 0x01, /* TLV type MBIM_TLV_TYPE_PCO, padding 1 */ + 0x0B, 0x00, 0x00, 0x00, /* TLV data length */ + 0x01, 0x02, 0x03, 0x04, /* TLV data bytes */ + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x00, + }; + + response = mbim_message_new (buffer, sizeof (buffer)); + + result = (mbim_message_ms_basic_connect_extensions_registration_parameters_response_parse ( + response, + &mico_mode, + &drx_cycle, + &ladn_info, + &pdu_hint, + &re_register_if_needed, + &unnamed_ies, + &error)); + + g_assert_no_error (error); + g_assert (result); + + g_assert_cmpuint (mico_mode, ==, MBIM_MICO_MODE_DISABLED); + g_assert_cmpuint (drx_cycle, ==, MBIM_DRX_CYCLE_NOT_SPECIFIED); + g_assert_cmpuint (ladn_info, ==, MBIM_LADN_INFO_NOT_NEEDED); + g_assert_cmpuint (pdu_hint, ==, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY); + g_assert_cmpuint (re_register_if_needed, ==, TRUE); + g_assert_cmpuint (g_list_length (unnamed_ies), ==, 3); + + iter = unnamed_ies; + tlv = (MbimTlv *)(iter->data); + g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); + tlv_str_1 = mbim_tlv_string_get (tlv, &error); + g_assert_no_error (error); + g_assert_cmpstr (tlv_str_1, ==, expected_tlv_str_1); + + iter = g_list_next (iter); + tlv = (MbimTlv *)(iter->data); + g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); + tlv_str_2 = mbim_tlv_string_get (tlv, &error); + g_assert_no_error (error); + g_assert_cmpstr (tlv_str_2, ==, expected_tlv_str_2); + + iter = g_list_next (iter); + tlv = (MbimTlv *)(iter->data); + g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_PCO); + pco_3 = mbim_tlv_get_tlv_data (tlv, &pco_3_size); + g_assert_cmpuint (pco_3_size, ==, sizeof (expected_pco)); + g_assert (memcmp (pco_3, expected_pco, sizeof (expected_pco)) == 0); + + g_list_free_full (unnamed_ies, (GDestroyNotify)mbim_tlv_unref); +} + int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); @@ -2002,6 +2253,9 @@ int main (int argc, char **argv) g_test_add_func ("/libmbim-glib/message/parser/basic-connect/connect/short", test_message_parser_basic_connect_connect_short); g_test_add_func ("/libmbim-glib/message/parser/basic-connect/visible-providers/overflow", test_message_parser_basic_connect_visible_providers_overflow); g_test_add_func ("/libmbim-glib/message/parser/basic-connect-extensions/base-stations", test_message_parser_ms_basic_connect_extensions_base_stations); + g_test_add_func ("/libmbim-glib/message/parser/basic-connect-extensions/registration-parameters/0-unnamed-tlvs", test_message_parser_ms_basic_connect_extensions_registration_parameters_0_unnamed_tlvs); + g_test_add_func ("/libmbim-glib/message/parser/basic-connect-extensions/registration-parameters/1-unnamed-tlv", test_message_parser_ms_basic_connect_extensions_registration_parameters_1_unnamed_tlv); + g_test_add_func ("/libmbim-glib/message/parser/basic-connect-extensions/registration-parameters/3-unnamed-tlvs", test_message_parser_ms_basic_connect_extensions_registration_parameters_3_unnamed_tlvs); return g_test_run (); } diff --git a/src/mbimcli/mbimcli-ms-basic-connect-extensions.c b/src/mbimcli/mbimcli-ms-basic-connect-extensions.c index b6face8..4240952 100644 --- a/src/mbimcli/mbimcli-ms-basic-connect-extensions.c +++ b/src/mbimcli/mbimcli-ms-basic-connect-extensions.c @@ -1052,6 +1052,7 @@ registration_parameters_ready (MbimDevice *device, &ladn_info, &pdu_hint, &re_register_if_nedeed, + NULL, /* ignore unnamed IEs for now */ &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); @@ -1750,6 +1751,7 @@ mbimcli_ms_basic_connect_extensions_run (MbimDevice *device, params.ladn_info, params.pdu_hint, params.re_register_if_needed, + NULL, /* ignore unnamed IEs for now */ NULL); mbim_device_command (ctx->device, request, |