[PATCH] libmm-glib: add MMPco for handling raw PCO data

Ben Chan benchan at chromium.org
Tue Aug 14 06:16:33 UTC 2018


---
Hi Aleksander,

Before submitting further patches, I just want to make sure the MMPco
gobject implemented in this patch is what you're looking for. MMPco will
be mostly kept in GList (unless you prefer another gobject).

If this is the right API to be in libmm-glib, I'll submit a few
follow-up patches to integrate the rest of the PCO support. Otherwise, I
can move it to src/ instead.

Thanks,
Ben


 docs/reference/libmm-glib/libmm-glib-docs.xml |   4 +
 .../libmm-glib/libmm-glib-sections.txt        |  28 ++
 libmm-glib/Makefile.am                        |   3 +
 libmm-glib/libmm-glib.h                       |   1 +
 libmm-glib/mm-pco.c                           | 256 ++++++++++++++++++
 libmm-glib/mm-pco.h                           |  85 ++++++
 6 files changed, 377 insertions(+)
 create mode 100644 libmm-glib/mm-pco.c
 create mode 100644 libmm-glib/mm-pco.h

diff --git a/docs/reference/libmm-glib/libmm-glib-docs.xml b/docs/reference/libmm-glib/libmm-glib-docs.xml
index 4b0a564c..80b3ce57 100644
--- a/docs/reference/libmm-glib/libmm-glib-docs.xml
+++ b/docs/reference/libmm-glib/libmm-glib-docs.xml
@@ -129,6 +129,10 @@
         <title>Voice support</title>
         <xi:include href="xml/mm-modem-voice.xml"/>
       </section>
+      <section>
+        <title>PCO support</title>
+        <xi:include href="xml/mm-pco.xml"/>
+      </section>
     </chapter>
 
     <chapter>
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index bfa57f1c..01a5de27 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -1308,6 +1308,34 @@ MM_TYPE_CALL_PROPERTIES
 mm_call_properties_get_type
 </SECTION>
 
+<SECTION>
+<FILE>mm-pco</FILE>
+<TITLE>MMPco</TITLE>
+MMPco
+<SUBSECTION New>
+mm_pco_new
+<SUBSECTION GettersSetters>
+mm_pco_get_session_id
+mm_pco_is_complete
+mm_pco_get_data
+<SUBSECTION Private>
+mm_pco_from_variant
+mm_pco_to_variant
+mm_pco_set_session_id
+mm_pco_set_complete
+mm_pco_set_data
+<SUBSECTION Standard>
+MMPcoClass
+MMPcoPrivate
+MM_IS_PCO
+MM_IS_PCO_CLASS
+MM_PCO
+MM_PCO_CLASS
+MM_PCO_GET_CLASS
+MM_TYPE_PCO
+mm_pco_get_type
+</SECTION>
+
 <SECTION>
 <FILE>mm-enums-types</FILE>
 <TITLE>Flags and Enumerations</TITLE>
diff --git a/libmm-glib/Makefile.am b/libmm-glib/Makefile.am
index 7d554ad0..4c890592 100644
--- a/libmm-glib/Makefile.am
+++ b/libmm-glib/Makefile.am
@@ -83,6 +83,8 @@ libmm_glib_la_SOURCES = \
 	mm-signal.c \
 	mm-kernel-event-properties.h \
 	mm-kernel-event-properties.c \
+	mm-pco.h \
+	mm-pco.c \
 	$(NULL)
 
 libmm_glib_la_CPPFLAGS = \
@@ -152,6 +154,7 @@ include_HEADERS = \
 	mm-cdma-manual-activation-properties.h \
 	mm-signal.h \
 	mm-kernel-event-properties.h \
+	mm-pco.h \
 	$(NULL)
 
 CLEANFILES =
diff --git a/libmm-glib/libmm-glib.h b/libmm-glib/libmm-glib.h
index 81175ca9..d45a6b12 100644
--- a/libmm-glib/libmm-glib.h
+++ b/libmm-glib/libmm-glib.h
@@ -78,6 +78,7 @@
 #include <mm-cdma-manual-activation-properties.h>
 #include <mm-signal.h>
 #include <mm-kernel-event-properties.h>
+#include <mm-pco.h>
 
 /* generated */
 #include <mm-errors-types.h>
diff --git a/libmm-glib/mm-pco.c b/libmm-glib/mm-pco.c
new file mode 100644
index 00000000..21390b84
--- /dev/null
+++ b/libmm-glib/mm-pco.c
@@ -0,0 +1,256 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright 2018 Google LLC.
+ */
+
+#include <string.h>
+#include <glib.h>
+
+#include "mm-enums-types.h"
+#include "mm-errors-types.h"
+#include "mm-common-helpers.h"
+#include "mm-pco.h"
+
+/**
+ * SECTION: mm-pco
+ * @title: MMPco
+ * @short_description: Helper object to handle 3GPP PCO.
+ *
+ * The #MMPco is an object handling the raw 3GPP Protocol Configuration Options
+ * (PCO) that the modem has received from the network.
+ *
+ * This object is retrieved with either mm_modem_3gpp_get_pco() or
+ * mm_modem_3gpp_get_pco_sync().
+ */
+
+G_DEFINE_TYPE (MMPco, mm_pco, G_TYPE_OBJECT);
+
+struct _MMPcoPrivate {
+    /* Session ID, signature 'u' */
+    guint32 session_id;
+    /* Flag indicating if the PCO data is complete or partial, signature 'b' */
+    gboolean is_complete;
+    /* Raw PCO data, signature 'ay' */
+    GBytes *data;
+};
+
+/*****************************************************************************/
+
+static GBytes *
+_g_variant_get_bytes (GVariant *variant)
+{
+    GByteArray *byte_array;
+    guint num_bytes;
+    GVariantIter iter;
+    GVariant *value;
+
+    g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE ("ay")));
+
+    num_bytes = g_variant_n_children (variant);
+    if (num_bytes == 0)
+        return NULL;
+
+    byte_array = g_byte_array_sized_new (num_bytes);
+
+    g_variant_iter_init (&iter, variant);
+    while (g_variant_iter_loop (&iter, "y", &value)) {
+        guint8 byte;
+
+        byte = g_variant_get_byte (value);
+        g_byte_array_append (byte_array, &byte, sizeof (byte));
+    }
+
+    return g_byte_array_free_to_bytes (byte_array);
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_pco_get_session_id:
+ * @self: a #MMPco.
+ *
+ * Gets the session ID associated with the PCO.
+ *
+ * Returns: the session ID.
+ */
+guint32
+mm_pco_get_session_id (MMPco *self)
+{
+    g_return_val_if_fail (MM_IS_PCO (self), G_MAXUINT32);
+
+    return self->priv->session_id;
+}
+
+void
+mm_pco_set_session_id (MMPco *self,
+                       guint32 session_id)
+{
+    g_return_if_fail (MM_IS_PCO (self));
+
+    self->priv->session_id = session_id;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_pco_is_complete:
+ * @self: a #MMPco.
+ *
+ * Gets the complete flag that indicates whether the PCO data contains the
+ * complete PCO structure received from the network.
+ *
+ * Returns: %TRUE if the PCO data contains the complete PCO structure, %FALSE otherwise.
+ */
+gboolean
+mm_pco_is_complete (MMPco *self)
+{
+    g_return_val_if_fail (MM_IS_PCO (self), FALSE);
+
+    return self->priv->is_complete;
+}
+
+void
+mm_pco_set_complete (MMPco *self,
+                     gboolean is_complete)
+{
+    g_return_if_fail (MM_IS_PCO (self));
+
+    self->priv->is_complete = is_complete;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_pco_get_data:
+ * @self: a #MMPco.
+ *
+ * Gets the PCO data in raw bytes.
+ *
+ * Returns: (transfer none): the PCO data.
+ */
+GBytes *
+mm_pco_get_data (MMPco *self)
+{
+    g_return_val_if_fail (MM_IS_PCO (self), NULL);
+
+    return self->priv->data;
+}
+
+void
+mm_pco_set_data (MMPco *self,
+                 GBytes *data)
+{
+    g_return_if_fail (MM_IS_PCO (self));
+
+    g_bytes_unref (self->priv->data);
+
+    self->priv->data = data ? g_bytes_ref (data) : NULL;
+}
+
+/*****************************************************************************/
+
+MMPco *
+mm_pco_from_variant (GVariant *variant,
+                     GError **error)
+{
+    MMPco *pco;
+
+    pco = mm_pco_new ();
+    if (!variant)
+        return pco;
+
+    if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("(ubay)"))) {
+        g_set_error (error,
+                     MM_CORE_ERROR,
+                     MM_CORE_ERROR_INVALID_ARGS,
+                     "Cannot create PCO from variant: "
+                     "invalid variant type received");
+        g_object_unref (pco);
+        return NULL;
+    }
+
+    pco->priv->session_id = g_variant_get_uint32 (variant);
+    pco->priv->is_complete = g_variant_get_boolean (variant);
+
+    g_bytes_unref (pco->priv->data);
+    pco->priv->data = _g_variant_get_bytes (variant);
+
+    return pco;
+}
+
+/*****************************************************************************/
+
+GVariant *
+mm_pco_to_variant (MMPco *self)
+{
+    GVariantBuilder builder;
+    gsize i, pco_data_size;
+    const guint8 *pco_data;
+
+    /* Allow NULL */
+    if (!self)
+        return NULL;
+
+    g_return_val_if_fail (MM_IS_PCO (self), NULL);
+
+    g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ubay)"));
+
+    g_variant_builder_add (&builder, "u", self->priv->session_id);
+    g_variant_builder_add (&builder, "b", self->priv->is_complete);
+
+    g_variant_builder_open (&builder, G_VARIANT_TYPE ("ay"));
+    if (self->priv->data) {
+        pco_data = g_bytes_get_data (self->priv->data, &pco_data_size);
+        for (i = 0; i < pco_data_size; ++i)
+            g_variant_builder_add (&builder, "y", pco_data[i]);
+    }
+    g_variant_builder_close (&builder);
+
+    return g_variant_ref_sink (g_variant_builder_end (&builder));
+}
+
+/*****************************************************************************/
+
+MMPco *
+mm_pco_new (void)
+{
+    return (MM_PCO (g_object_new (MM_TYPE_PCO, NULL)));
+}
+
+static void
+mm_pco_init (MMPco *self)
+{
+    self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_PCO, MMPcoPrivate);
+
+    self->priv->session_id = G_MAXUINT32;
+}
+
+static void
+finalize (GObject *object)
+{
+    MMPco *self = MM_PCO (object);
+
+    g_bytes_unref (self->priv->data);
+
+    G_OBJECT_CLASS (mm_pco_parent_class)->finalize (object);
+}
+
+static void
+mm_pco_class_init (MMPcoClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    g_type_class_add_private (object_class, sizeof (MMPcoPrivate));
+
+    object_class->finalize = finalize;
+}
diff --git a/libmm-glib/mm-pco.h b/libmm-glib/mm-pco.h
new file mode 100644
index 00000000..85a221b9
--- /dev/null
+++ b/libmm-glib/mm-pco.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright 2018 Google LLC.
+ */
+
+#ifndef MM_PCO_H
+#define MM_PCO_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_PCO            (mm_pco_get_type ())
+#define MM_PCO(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PCO, MMPco))
+#define MM_PCO_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  MM_TYPE_PCO, MMPcoClass))
+#define MM_IS_PCO(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PCO))
+#define MM_IS_PCO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  MM_TYPE_PCO))
+#define MM_PCO_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  MM_TYPE_PCO, MMPcoClass))
+
+typedef struct _MMPco MMPco;
+typedef struct _MMPcoClass MMPcoClass;
+typedef struct _MMPcoPrivate MMPcoPrivate;
+
+/**
+ * MMPco:
+ *
+ * The #MMPco structure contains private data and should only be accessed
+ * using the provided API.
+ */
+struct _MMPco {
+    /*< private >*/
+    GObject parent;
+    MMPcoPrivate *priv;
+};
+
+struct _MMPcoClass {
+    /*< private >*/
+    GObjectClass parent;
+};
+
+GType mm_pco_get_type (void);
+
+
+guint32   mm_pco_get_session_id (MMPco *self);
+gboolean  mm_pco_is_complete    (MMPco *self);
+GBytes   *mm_pco_get_data       (MMPco *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) ||    \
+    defined (_LIBMM_INSIDE_MMCLI) || \
+    defined (LIBMM_GLIB_COMPILATION)
+
+MMPco    *mm_pco_new            (void);
+MMPco    *mm_pco_from_variant   (GVariant *variant,
+                                 GError **error);
+GVariant *mm_pco_to_variant     (MMPco *self);
+void      mm_pco_set_session_id (MMPco *self,
+                                 guint32 session_id);
+void      mm_pco_set_complete   (MMPco *self,
+                                 gboolean is_complete);
+void      mm_pco_set_data       (MMPco *self,
+                                 GBytes *data);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_PCO_H */
-- 
2.18.0.597.ga71716f1ad-goog



More information about the ModemManager-devel mailing list