[PATCH] iface-modem-3gpp: add SubscriptionState property

Aleksander Morgado aleksander at lanedo.com
Mon Oct 7 02:35:06 PDT 2013


On 28/09/13 01:53, Thieu Le wrote:
> This patch adds a new property, SubscriptionState, to
> org.freedesktop.ModemManager1.Modem.Modem3gpp.  The subscription state
> is used to indicate whether an account has been provisioned, and if so,
> whether the account has any data left.
> 
> There will be two subsequent patches that will make use of this new property.
> 
> Change-Id: Ic7af0e111a323bf2e49feae3a819b630ee4d89ed


So; I see there are two ways to get this new property updated:
 * One is letting the plugin call
mm_iface_modem_3gpp_update_subscription_state().
 * The other one is letting the plugin implement load_subscription_state().

Seems that the altair-lte implementation in the follow-up patch only
uses the first approach. Do we also need to have the second one? Will
there be any other follow-up patch using the second one?

More comments inline below.

> ---
>  include/ModemManager-enums.h                       |  17 +++
>  ...g.freedesktop.ModemManager1.Modem.Modem3gpp.xml |  12 ++
>  src/mm-broadband-modem.c                           |   4 +-
>  src/mm-iface-modem-3gpp.c                          | 144 ++++++++++++++++-----
>  src/mm-iface-modem-3gpp.h                          |  28 ++--
>  5 files changed, 159 insertions(+), 46 deletions(-)
> 
> diff --git a/include/ModemManager-enums.h b/include/ModemManager-enums.h
> index 8fb0b08..a71b82e 100644
> --- a/include/ModemManager-enums.h
> +++ b/include/ModemManager-enums.h
> @@ -772,6 +772,23 @@ typedef enum { /*< underscore_name=mm_modem_3gpp_network_availability >*/
>  } MMModem3gppNetworkAvailability;
>  
>  /**
> + * MModem3gppSubscriptionState:
> + * @MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN: The subscription state is unknown.
> + * @MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNPROVISIONED: The account is unprovisioned.
> + * @MM_MODEM_3GPP_SUBSCRIPTION_STATE_PROVISIONED: The account is provisioned and has data available.
> + * @MM_MODEM_3GPP_SUBSCRIPTION_STATE_OUT_OF_DATA: The account is provisioned but there is no data left.
> + *
> + * Describes the current subscription status of the SIM.  This value is only available after the
> + * modem attempts to register with the network.
> + */
> +typedef enum { /*< underscore_name=mm_modem_3gpp_subscription_state >*/
> +    MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN       = 0,
> +    MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNPROVISIONED = 1,
> +    MM_MODEM_3GPP_SUBSCRIPTION_STATE_PROVISIONED   = 2,
> +    MM_MODEM_3GPP_SUBSCRIPTION_STATE_OUT_OF_DATA   = 3,
> +} MMModem3gppSubscriptionState;
> +
> +/**
>   * MMModem3gppUssdSessionState:
>   * @MM_MODEM_3GPP_USSD_SESSION_STATE_UNKNOWN: Unknown state.
>   * @MM_MODEM_3GPP_USSD_SESSION_STATE_IDLE: No active session.
> diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
> index 3298473..ebf00ed 100644
> --- a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
> +++ b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
> @@ -136,5 +136,17 @@
>      -->
>      <property name="EnabledFacilityLocks" type="u" access="read" />
>  
> +    <!--
> +        SubscriptionState:
> +
> +        Indicates the activation status of the SIM and whether there is any
> +        data remaining.  Possible values are:
> +            0 - Unknown
> +            1 - Account is unprovisioned
> +            2 - Account is provisioned with data available
> +            3 - Account is provisioned but data exhausted
> +    -->
> +    <property name="SubscriptionState" type="u" access="read" />
> +


No need to explain which the possible values are. Something like this is
probably more appropriate:

A <link
linkend="MMModem3gppSubscriptionState">MMModem3gppSubscriptionState</link>
value representing the subscription status of the SIM and whether there
is any data remaining, given as an unsigned integer (signature
<literal>"u"</literal>)


>    </interface>
>  </node>
> diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
> index 1657b11..edac4cb 100644
> --- a/src/mm-broadband-modem.c
> +++ b/src/mm-broadband-modem.c
> @@ -7412,10 +7412,10 @@ enable_location_gathering (MMIfaceModemLocation *self,
>          mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))) {
>          /* Reload registration to get LAC/CI */
>          mm_iface_modem_3gpp_run_registration_checks (MM_IFACE_MODEM_3GPP (self), NULL, NULL);
> -        /* Reload operator to get MCC/MNC */
> +        /* Reload registration information to get MCC/MNC */
>          if (MM_BROADBAND_MODEM (self)->priv->modem_3gpp_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
>              MM_BROADBAND_MODEM (self)->priv->modem_3gpp_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
> -            mm_iface_modem_3gpp_reload_current_operator (MM_IFACE_MODEM_3GPP (self), NULL, NULL);
> +            mm_iface_modem_3gpp_reload_current_registration_info (MM_IFACE_MODEM_3GPP (self), NULL, NULL);
>      }
>  
>      /* Done we are */
> diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
> index 53399d5..6af1cde 100644
> --- a/src/mm-iface-modem-3gpp.c
> +++ b/src/mm-iface-modem-3gpp.c
> @@ -75,7 +75,7 @@ typedef struct {
>      MMModem3gppRegistrationState eps;
>      gboolean manual_registration;
>      GCancellable *pending_registration_cancellable;
> -    gboolean reloading_operator;
> +    gboolean reloading_registration_info;
>  } RegistrationStateContext;
>  
>  static void
> @@ -760,33 +760,34 @@ typedef struct {
>      GSimpleAsyncResult *result;
>      gboolean operator_code_loaded;
>      gboolean operator_name_loaded;
> -} ReloadCurrentOperatorContext;
> +    gboolean subscription_state_loaded;
> +} ReloadCurrentRegistrationInfoContext;
>  
>  static void
> -reload_current_operator_context_complete_and_free (ReloadCurrentOperatorContext *ctx)
> +reload_current_registration_info_context_complete_and_free (ReloadCurrentRegistrationInfoContext *ctx)
>  {
>      g_simple_async_result_complete_in_idle (ctx->result);
>      g_object_unref (ctx->result);
>      if (ctx->skeleton)
>          g_object_unref (ctx->skeleton);
>      g_object_unref (ctx->self);
> -    g_slice_free (ReloadCurrentOperatorContext, ctx);
> +    g_slice_free (ReloadCurrentRegistrationInfoContext, ctx);
>  }
>  
>  gboolean
> -mm_iface_modem_3gpp_reload_current_operator_finish (MMIfaceModem3gpp *self,
> -                                                    GAsyncResult *res,
> -                                                    GError **error)
> +mm_iface_modem_3gpp_reload_current_registration_info_finish (MMIfaceModem3gpp *self,
> +                                                             GAsyncResult *res,
> +                                                             GError **error)
>  {
>      return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
>  }
>  
> -static void reload_current_operator_context_step (ReloadCurrentOperatorContext *ctx);
> +static void reload_current_registration_info_context_step (ReloadCurrentRegistrationInfoContext *ctx);
>  
>  static void
>  load_operator_name_ready (MMIfaceModem3gpp *self,
>                            GAsyncResult *res,
> -                          ReloadCurrentOperatorContext *ctx)
> +                          ReloadCurrentRegistrationInfoContext *ctx)
>  {
>      GError *error = NULL;
>      gchar *str;
> @@ -802,7 +803,7 @@ load_operator_name_ready (MMIfaceModem3gpp *self,
>      g_free (str);
>  
>      ctx->operator_name_loaded = TRUE;
> -    reload_current_operator_context_step (ctx);
> +    reload_current_registration_info_context_step (ctx);
>  }
>  
>  static gboolean
> @@ -836,7 +837,7 @@ parse_mcc_mnc (const gchar *mccmnc,
>  static void
>  load_operator_code_ready (MMIfaceModem3gpp *self,
>                            GAsyncResult *res,
> -                          ReloadCurrentOperatorContext *ctx)
> +                          ReloadCurrentRegistrationInfoContext *ctx)
>  {
>      GError *error = NULL;
>      gchar *str;
> @@ -861,11 +862,33 @@ load_operator_code_ready (MMIfaceModem3gpp *self,
>      g_free (str);
>  
>      ctx->operator_code_loaded = TRUE;
> -    reload_current_operator_context_step (ctx);
> +    reload_current_registration_info_context_step (ctx);
>  }
>  
>  static void
> -reload_current_operator_context_step (ReloadCurrentOperatorContext *ctx)
> +load_subscription_state_ready (MMIfaceModem3gpp *self,
> +                               GAsyncResult *res,
> +                               ReloadCurrentRegistrationInfoContext *ctx)
> +{
> +    GError *error = NULL;
> +    MMModem3gppSubscriptionState subscription_state = MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN;
> +
> +    subscription_state = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_subscription_state_finish (self, res, &error);
> +    if (error) {
> +        mm_warn ("Couldn't load Subscription State: '%s'", error->message);
> +        g_error_free (error);
> +    }
> +
> +    if (ctx->skeleton)
> +        mm_gdbus_modem3gpp_set_subscription_state (ctx->skeleton, subscription_state);
> +
> +    ctx->subscription_state_loaded = TRUE;
> +    reload_current_registration_info_context_step (ctx);
> +}
> +
> +
> +static void
> +reload_current_registration_info_context_step (ReloadCurrentRegistrationInfoContext *ctx)
>  {
>      if (!ctx->operator_code_loaded) {
>          /* Launch operator code update */
> @@ -885,24 +908,33 @@ reload_current_operator_context_step (ReloadCurrentOperatorContext *ctx)
>          return;
>      }
>  
> -    /* If both loaded, all done */
> +    if (!ctx->subscription_state_loaded) {
> +        /* Launch subscription state update */
> +        MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->load_subscription_state (
> +            ctx->self,
> +            (GAsyncReadyCallback)load_subscription_state_ready,
> +            ctx);
> +        return;
> +    }
> +
> +    /* If all are loaded, all done */
>      g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
> -    reload_current_operator_context_complete_and_free (ctx);
> +    reload_current_registration_info_context_complete_and_free (ctx);
>  }
>  
>  void
> -mm_iface_modem_3gpp_reload_current_operator (MMIfaceModem3gpp *self,
> -                                             GAsyncReadyCallback callback,
> -                                             gpointer user_data)
> +mm_iface_modem_3gpp_reload_current_registration_info (MMIfaceModem3gpp *self,
> +                                                      GAsyncReadyCallback callback,
> +                                                      gpointer user_data)
>  {
> -    ReloadCurrentOperatorContext *ctx;
> +    ReloadCurrentRegistrationInfoContext *ctx;
>  
> -    ctx = g_slice_new0 (ReloadCurrentOperatorContext);
> +    ctx = g_slice_new0 (ReloadCurrentRegistrationInfoContext);
>      ctx->self = g_object_ref (self);
>      ctx->result = g_simple_async_result_new (G_OBJECT (self),
>                                               callback,
>                                               user_data,
> -                                             mm_iface_modem_3gpp_reload_current_operator);
> +                                             mm_iface_modem_3gpp_reload_current_registration_info);
>  
>      g_object_get (self,
>                    MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &ctx->skeleton,
> @@ -912,7 +944,7 @@ mm_iface_modem_3gpp_reload_current_operator (MMIfaceModem3gpp *self,
>                                           MM_CORE_ERROR,
>                                           MM_CORE_ERROR_FAILED,
>                                           "Couldn't get interface skeleton");
> -        reload_current_operator_context_complete_and_free (ctx);
> +        reload_current_registration_info_context_complete_and_free (ctx);
>          return;
>      }
>  
> @@ -929,7 +961,12 @@ mm_iface_modem_3gpp_reload_current_operator (MMIfaceModem3gpp *self,
>      if (ctx->operator_name_loaded)
>          mm_gdbus_modem3gpp_set_operator_name (ctx->skeleton, NULL);
>  
> -    reload_current_operator_context_step (ctx);
> +    ctx->subscription_state_loaded = !(MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_subscription_state &&
> +                                       MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_subscription_state_finish);
> +    if (ctx->subscription_state_loaded)
> +      mm_gdbus_modem3gpp_set_subscription_state (ctx->skeleton, MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN);

Two whitespaces missing in the indentation in the previous line.

> +
> +    reload_current_registration_info_context_step (ctx);
>  }
>  
>  void
> @@ -949,6 +986,19 @@ mm_iface_modem_3gpp_clear_current_operator (MMIfaceModem3gpp *self)
>          mm_iface_modem_location_3gpp_update_mcc_mnc (MM_IFACE_MODEM_LOCATION (self), 0, 0);
>  }
>  
> +static void
> +clear_subscription_state (MMIfaceModem3gpp *self)
> +{
> +    MmGdbusModem3gpp *skeleton = NULL;
> +
> +    g_object_get (self,
> +                  MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton,
> +                  NULL);
> +    if (!skeleton)
> +        return;
> +    mm_gdbus_modem3gpp_set_subscription_state (skeleton, MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN);
> +}
> +
>  /*****************************************************************************/
>  
>  void
> @@ -969,7 +1019,7 @@ mm_iface_modem_3gpp_update_access_technologies (MMIfaceModem3gpp *self,
>       * but only if something valid to report */
>      if (state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
>          state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
> -        ctx->reloading_operator) {
> +        ctx->reloading_registration_info) {
>          if (access_tech != MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN)
>              mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self),
>                                                         access_tech,
> @@ -1009,9 +1059,9 @@ mm_iface_modem_3gpp_update_location (MMIfaceModem3gpp *self,
>  /*****************************************************************************/
>  
>  static void
> -update_registration_reload_current_operator_ready (MMIfaceModem3gpp *self,
> -                                                   GAsyncResult *res,
> -                                                   gpointer user_data)
> +update_registration_reload_current_registration_info_ready (MMIfaceModem3gpp *self,
> +                                                            GAsyncResult *res,
> +                                                            gpointer user_data)
>  {
>      MMModem3gppRegistrationState new_state;
>      RegistrationStateContext *ctx;
> @@ -1034,7 +1084,7 @@ update_registration_reload_current_operator_ready (MMIfaceModem3gpp *self,
>                                             MM_MODEM_STATE_CHANGE_REASON_UNKNOWN);
>  
>      ctx = get_registration_state_context (self);
> -    ctx->reloading_operator = FALSE;
> +    ctx->reloading_registration_info = FALSE;
>  }
>  
>  static void
> @@ -1045,6 +1095,14 @@ update_non_registered_state (MMIfaceModem3gpp *self,
>      /* Not registered neither in home nor roaming network */
>      mm_iface_modem_3gpp_clear_current_operator (self);
>  
> +    /* The subscription state can be computed in two ways: a) via PCO which is
> +     * sent by the carrier during registration or b) by looking at the
> +     * registration reject error code.  If b), we want to make sure we
> +     * preserve the subscription state */
> +    if (old_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
> +        old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
> +        clear_subscription_state (self);
> +
>      /* The property in the interface is bound to the property
>       * in the skeleton, so just updating here is enough */
>      g_object_set (self,
> @@ -1081,20 +1139,20 @@ update_registration_state (MMIfaceModem3gpp *self,
>  
>      if (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
>          new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
> -        /* If already reloading operator, skip it */
> -        if (ctx->reloading_operator)
> +        /* If already reloading registration info, skip it */
> +        if (ctx->reloading_registration_info)
>              return;
>  
>          mm_info ("Modem %s: 3GPP Registration state changed (%s -> registering)",
>                   g_dbus_object_get_object_path (G_DBUS_OBJECT (self)),
>                   mm_modem_3gpp_registration_state_get_string (old_state));
>  
> -        /* Reload current operator. ONLY update the state to REGISTERED after
> -         * having loaded operator code/name */
> -        ctx->reloading_operator = TRUE;
> -        mm_iface_modem_3gpp_reload_current_operator (
> +        /* Reload current registration info. ONLY update the state to REGISTERED
> +         * after having loaded operator code/name/subscription state */
> +        ctx->reloading_registration_info = TRUE;
> +        mm_iface_modem_3gpp_reload_current_registration_info (
>              self,
> -            (GAsyncReadyCallback)update_registration_reload_current_operator_ready,
> +            (GAsyncReadyCallback)update_registration_reload_current_registration_info_ready,
>              GUINT_TO_POINTER (new_state));
>          return;
>      }
> @@ -1164,6 +1222,21 @@ mm_iface_modem_3gpp_update_eps_registration_state (MMIfaceModem3gpp *self,
>      update_registration_state (self, get_consolidated_reg_state (ctx), TRUE);
>  }
>  
> +void
> +mm_iface_modem_3gpp_update_subscription_state (MMIfaceModem3gpp *self,
> +                                               MMModem3gppSubscriptionState state)
> +{
> +    MmGdbusModem3gpp *skeleton = NULL;
> +
> +    g_object_get (self,
> +                  MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton,
> +                  NULL);
> +    if (skeleton) {
> +        mm_gdbus_modem3gpp_set_subscription_state (skeleton, state);
> +        g_object_unref (skeleton);
> +    }
> +}
> +
>  /*****************************************************************************/
>  
>  typedef struct {
> @@ -1954,6 +2027,7 @@ mm_iface_modem_3gpp_initialize (MMIfaceModem3gpp *self,
>          mm_gdbus_modem3gpp_set_operator_code (skeleton, NULL);
>          mm_gdbus_modem3gpp_set_operator_name (skeleton, NULL);
>          mm_gdbus_modem3gpp_set_enabled_facility_locks (skeleton, MM_MODEM_3GPP_FACILITY_NONE);
> +        mm_gdbus_modem3gpp_set_subscription_state (skeleton, MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN);
>  
>          /* Bind our RegistrationState property */
>          g_object_bind_property (self, MM_IFACE_MODEM_3GPP_REGISTRATION_STATE,
> diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h
> index f4014c4..8497d20 100644
> --- a/src/mm-iface-modem-3gpp.h
> +++ b/src/mm-iface-modem-3gpp.h
> @@ -176,6 +176,14 @@ struct _MMIfaceModem3gpp {
>                                            GAsyncResult *res,
>                                            GError **error);
>  
> +    /* Loading of the subscription state property */
> +    void (*load_subscription_state) (MMIfaceModem3gpp *self,
> +                                     GAsyncReadyCallback callback,
> +                                     gpointer user_data);
> +    MMModem3gppSubscriptionState (*load_subscription_state_finish) (MMIfaceModem3gpp *self,
> +                                                                    GAsyncResult *res,
> +                                                                    GError **error);
> +
>      /* Scan current networks, expect a GList of MMModem3gppNetworkInfo */
>      void (* scan_networks) (MMIfaceModem3gpp *self,
>                              GAsyncReadyCallback callback,
> @@ -216,7 +224,7 @@ gboolean mm_iface_modem_3gpp_disable_finish (MMIfaceModem3gpp *self,
>  /* Shutdown Modem 3GPP interface */
>  void mm_iface_modem_3gpp_shutdown (MMIfaceModem3gpp *self);
>  
> -/* Objects implementing this interface can report new registration states,
> +/* Objects implementing this interface can report new registration info,
>   * access technologies and location.
>   * This may happen when handling unsolicited registration messages, or when
>   * the interface asks to run registration state checks. */
> @@ -226,6 +234,8 @@ void mm_iface_modem_3gpp_update_ps_registration_state (MMIfaceModem3gpp *self,
>                                                         MMModem3gppRegistrationState state);
>  void mm_iface_modem_3gpp_update_eps_registration_state (MMIfaceModem3gpp *self,
>                                                          MMModem3gppRegistrationState state);
> +void mm_iface_modem_3gpp_update_subscription_state (MMIfaceModem3gpp *self,
> +                                                    MMModem3gppSubscriptionState state);
>  void mm_iface_modem_3gpp_update_access_technologies (MMIfaceModem3gpp *self,
>                                                       MMModemAccessTechnology access_tech);
>  void mm_iface_modem_3gpp_update_location            (MMIfaceModem3gpp *self,
> @@ -240,14 +250,14 @@ gboolean mm_iface_modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *s
>                                                               GAsyncResult *res,
>                                                               GError **error);
>  
> -/* Request to reload current operator */
> -void     mm_iface_modem_3gpp_reload_current_operator        (MMIfaceModem3gpp *self,
> -                                                             GAsyncReadyCallback callback,
> -                                                             gpointer user_data);
> -gboolean mm_iface_modem_3gpp_reload_current_operator_finish (MMIfaceModem3gpp *self,
> -                                                             GAsyncResult *res,
> -                                                             GError **error);
> -void     mm_iface_modem_3gpp_clear_current_operator         (MMIfaceModem3gpp *self);
> +/* Request to reload current registration information */
> +void     mm_iface_modem_3gpp_reload_current_registration_info        (MMIfaceModem3gpp *self,
> +                                                                      GAsyncReadyCallback callback,
> +                                                                      gpointer user_data);
> +gboolean mm_iface_modem_3gpp_reload_current_registration_info_finish (MMIfaceModem3gpp *self,
> +                                                                      GAsyncResult *res,
> +                                                                      GError **error);
> +void     mm_iface_modem_3gpp_clear_current_operator                  (MMIfaceModem3gpp *self);
>  
>  /* Allow registering in the network */
>  gboolean mm_iface_modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self,
> 


-- 
Aleksander


More information about the ModemManager-devel mailing list