[PATCH] libmm-glib: add MMPco for handling raw PCO data
Aleksander Morgado
aleksander at aleksander.es
Tue Aug 14 07:48:24 UTC 2018
Hey,
>
> 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.
>
It looks good to me. We should probably wait to have all remaining
patches ready before integrating this one, though. How about you
re-suggest this one in a MR along with the remainining ones?
Cheers!
>
>
> 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
>
--
Aleksander
https://aleksander.es
More information about the ModemManager-devel
mailing list