summaryrefslogtreecommitdiff
path: root/src/libmbim-glib/mbim-message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmbim-glib/mbim-message.c')
-rw-r--r--src/libmbim-glib/mbim-message.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/libmbim-glib/mbim-message.c b/src/libmbim-glib/mbim-message.c
index 3439dae..7bd23ac 100644
--- a/src/libmbim-glib/mbim-message.c
+++ b/src/libmbim-glib/mbim-message.c
@@ -374,6 +374,78 @@ _mbim_message_read_string (const MbimMessage *self,
}
gboolean
+_mbim_message_read_string_tlv (const MbimMessage *self,
+ guint32 struct_start_offset,
+ guint32 relative_offset,
+ gchar **str,
+ guint32 *tpv_size,
+ GError **error)
+{
+ guint32 required_size;
+ guint32 size = 0;
+ guint32 information_buffer_offset;
+ gunichar2 *utf16d = NULL;
+ const gunichar2 *utf16 = NULL;
+
+ information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
+ required_size = information_buffer_offset + relative_offset;
+
+ if (self->len < required_size) {
+ g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
+ "cannot read string offset and size (%u < %u)",
+ self->len, required_size);
+ return FALSE;
+ }
+
+ size = GUINT32_FROM_LE (G_STRUCT_MEMBER (
+ guint32,
+ self->data,
+ (information_buffer_offset + relative_offset)));
+
+ if (!size) {
+ *str = NULL;
+ *tpv_size = 4;
+ return TRUE;
+ } else {
+ *tpv_size = size+4;
+ }
+ required_size = information_buffer_offset + struct_start_offset + size;
+
+ if (self->len < required_size) {
+ g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
+ "cannot read string data (%u bytes) (%u < %u)",
+ size, self->len, required_size);
+ return FALSE;
+ }
+
+ utf16 = (const gunichar2 *) G_STRUCT_MEMBER_P (self->data, (information_buffer_offset + relative_offset+4 ));
+
+ /* 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]);
+ }
+
+ *str = g_utf16_to_utf8 (utf16d ? utf16d : utf16,
+ size / 2,
+ NULL,
+ NULL,
+ error);
+
+ g_free (utf16d);
+
+ if (!(*str)) {
+ g_prefix_error (error, "Error converting string to UTF-8: ");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
_mbim_message_read_string_array (const MbimMessage *self,
guint32 array_size,
guint32 struct_start_offset,
@@ -1092,6 +1164,61 @@ _mbim_struct_builder_append_string (MbimStructBuilder *builder,
}
void
+_mbim_struct_builder_append_string_tlv (MbimStructBuilder *builder,
+ const gchar *value)
+{
+ guint8 reserved = 0;
+ guint8 padding = 0;
+ guint32 length;
+ gunichar2 *utf16 = NULL;
+ guint32 utf16_bytes = 0;
+ GError *error = NULL;
+
+ /* Add the reserved value */
+ g_byte_array_append (builder->fixed_buffer, (guint8 *)&reserved, sizeof (reserved));
+
+ /* Convert the string from UTF-8 to UTF-16HE */
+ if (value && value[0]) {
+ glong items_written = 0;
+ utf16 = g_utf8_to_utf16 (value,
+ -1,
+ NULL, /* bytes */
+ &items_written, /* gunichar2 */
+ &error);
+
+ if (!utf16) {
+ g_warning ("Error converting string: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+ utf16_bytes = items_written * 2;
+
+ /* Add the padding value */
+ padding = utf16_bytes % 4;
+ g_byte_array_append (builder->fixed_buffer, (guint8 *)&padding, sizeof (padding));
+ g_debug ("padding:%d", padding);
+ }
+
+ /* Add the length value */
+ length = GUINT32_TO_LE (utf16_bytes);
+ g_byte_array_append (builder->fixed_buffer, (guint8 *)&length, sizeof (length));
+
+ /* And finally, the string itself to the variable buffer */
+ if (utf16_bytes) {
+ /* For BE systems, convert from BE to LE */
+ if (G_BYTE_ORDER == G_BIG_ENDIAN) {
+ guint i;
+
+ for (i = 0; i < (utf16_bytes / 2); i++)
+ utf16[i] = GUINT16_TO_LE (utf16[i]);
+ }
+ g_byte_array_append (builder->variable_buffer, (const guint8 *)utf16, (guint)utf16_bytes);
+ bytearray_apply_padding (builder->variable_buffer, &utf16_bytes);
+ }
+ g_free (utf16);
+}
+
+void
_mbim_struct_builder_append_string_array (MbimStructBuilder *builder,
const gchar *const *values,
guint32 n_values)