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

Dan Williams dcbw at redhat.com
Fri Sep 27 22:13:39 PDT 2013


On Fri, 2013-09-27 at 16:53 -0700, 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.

There seems to be some conceptual overlap with the 3gpp2
MMModemCdmaActivationState, perhaps this property could instead be a
generic Modem interface property instead, and the 3GPP2 stuff could
update both ActivateState and the generic SubscriptionStatus property
from the same data?

Or are there potentially more 3GPP states for the subscription than what
you've defined here?

Dan

> Change-Id: Ic7af0e111a323bf2e49feae3a819b630ee4d89ed
> ---
>  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" />
> +
>    </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);
> +
> +    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,




More information about the ModemManager-devel mailing list