[PATCH v3] Fix Bug 93135 +CPMS emtpy parameter support

Aleksander Morgado aleksander at aleksander.es
Wed Mar 9 13:46:01 UTC 2016


On 09/03/16 11:27, c.lobrano at gmail.com wrote:
> From: Carlo Lobrano <c.lobrano at gmail.com>
> 
> * Add new async virtual method init_current_storages to
>   MMIfaceModemMessaging
> * Add logic of init_current_storages to MMBroadbandModem
> * Add step "INIT_CURRENT_STORAGES" in MMIfaceModemMessaging
>   initialization in order to load and store current SMS
>   storages for mem1 and mem2.
> * Add usage of current sms storage value for mem1 in place
>   of an empty string parameter when the command AT+CPMS
>   is used.
> 

Rewrote a bit the commit message and pushed it to git master; thanks!


> ---
>  src/mm-broadband-modem.c       | 92 +++++++++++++++++++++++++++++++++++++++++-
>  src/mm-iface-modem-messaging.c | 37 +++++++++++++++++
>  src/mm-iface-modem-messaging.h |  7 ++++
>  src/mm-modem-helpers.c         | 76 ++++++++++++++++++++++++++++++++++
>  src/mm-modem-helpers.h         | 10 +++++
>  src/tests/test-modem-helpers.c | 35 ++++++++++++++++
>  6 files changed, 256 insertions(+), 1 deletion(-)
> 
> diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
> index 6fc0663..e57195b 100644
> --- a/src/mm-broadband-modem.c
> +++ b/src/mm-broadband-modem.c
> @@ -5242,6 +5242,77 @@ modem_messaging_load_supported_storages (MMIfaceModemMessaging *self,
>  }
>  
>  /*****************************************************************************/
> +/* Init current SMS storages (Messaging interface) */
> +
> +static gboolean
> +modem_messaging_init_current_storages_finish (MMIfaceModemMessaging *_self,
> +                                              GAsyncResult *res,
> +                                              GError **error)
> +{
> +    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
> +}
> +
> +static void
> +cpms_query_ready (MMBroadbandModem *self,
> +                  GAsyncResult *res,
> +                  GSimpleAsyncResult *simple)
> +{
> +    const gchar *response;
> +    GError *error = NULL;
> +    MMSmsStorage mem1;
> +    MMSmsStorage mem2;
> +
> +    response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
> +    if (error) {
> +        g_simple_async_result_take_error (simple, error);
> +        g_simple_async_result_complete (simple);
> +        g_object_unref (simple);
> +        return;
> +    }
> +
> +    /* Parse reply */
> +    if (!mm_3gpp_parse_cpms_query_response (response,
> +                                            &mem1,
> +                                            &mem2,
> +                                            &error)) {
> +        g_simple_async_result_take_error (simple, error);
> +    } else {
> +        self->priv->current_sms_mem1_storage = mem1;
> +        self->priv->current_sms_mem2_storage = mem2;
> +
> +        mm_dbg ("Current storages initialized:");
> +        mm_dbg ("  mem1 (list/read/delete) storages: '%s'",
> +                mm_common_build_sms_storages_string (&mem1, 1));
> +        mm_dbg ("  mem2 (write/send) storages:       '%s'",
> +                mm_common_build_sms_storages_string (&mem2, 1));
> +    }
> +
> +    g_simple_async_result_complete (simple);
> +    g_object_unref (simple);
> +}
> +
> +static void
> +modem_messaging_init_current_storages (MMIfaceModemMessaging *self,
> +                                       GAsyncReadyCallback callback,
> +                                       gpointer user_data)
> +{
> +    GSimpleAsyncResult *result;
> +
> +    result = g_simple_async_result_new (G_OBJECT (self),
> +                                        callback,
> +                                        user_data,
> +                                        modem_messaging_init_current_storages);
> +
> +    /* Check support storages */
> +    mm_base_modem_at_command (MM_BASE_MODEM (self),
> +                              "+CPMS?",
> +                              3,
> +                              TRUE,
> +                              (GAsyncReadyCallback)cpms_query_ready,
> +                              result);
> +}
> +
> +/*****************************************************************************/
>  /* Lock/unlock SMS storage (Messaging interface implementation helper)
>   *
>   * The basic commands to work with SMS storages play with AT+CPMS and three
> @@ -5382,6 +5453,15 @@ mm_broadband_modem_lock_sms_storages (MMBroadbandModem *self,
>          self->priv->mem2_storage_locked = TRUE;
>          self->priv->current_sms_mem2_storage = mem2;
>          mem2_str = g_ascii_strup (mm_sms_storage_get_string (self->priv->current_sms_mem2_storage), -1);
> +
> +        if (mem1 == MM_SMS_STORAGE_UNKNOWN) {
> +            /* Some modems may not support empty string parameters. Then if mem1 is
> +             * UNKNOWN, we send again the already locked mem1 value in place of an
> +             * empty string. This way we also avoid to confuse the environment of
> +             * other async operation that have potentially locked mem1 previoulsy.
> +             * */
> +            mem1_str = g_ascii_strup (mm_sms_storage_get_string (self->priv->current_sms_mem1_storage), -1);
> +        }
>      }
>  
>      /* We don't touch 'mem3' here */
> @@ -5446,6 +5526,7 @@ modem_messaging_set_default_storage (MMIfaceModemMessaging *_self,
>      MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
>      gchar *cmd;
>      GSimpleAsyncResult *result;
> +    gchar *mem1_str;
>      gchar *mem_str;
>  
>      result = g_simple_async_result_new (G_OBJECT (self),
> @@ -5456,14 +5537,21 @@ modem_messaging_set_default_storage (MMIfaceModemMessaging *_self,
>      /* Set defaults as current */
>      self->priv->current_sms_mem2_storage = storage;
>  
> +    /* We provide the current sms storage for mem1 if not UNKNOWN */
> +    mem1_str = g_ascii_strup (mm_sms_storage_get_string (self->priv->current_sms_mem1_storage), -1);
> +
>      mem_str = g_ascii_strup (mm_sms_storage_get_string (storage), -1);
> -    cmd = g_strdup_printf ("+CPMS=\"\",\"%s\",\"%s\"", mem_str, mem_str);
> +    cmd = g_strdup_printf ("+CPMS=\"%s\",\"%s\",\"%s\"",
> +                           mem1_str ? mem1_str : "",
> +                           mem_str,
> +                           mem_str);
>      mm_base_modem_at_command (MM_BASE_MODEM (self),
>                                cmd,
>                                3,
>                                FALSE,
>                                (GAsyncReadyCallback)cpms_set_ready,
>                                result);
> +    g_free (mem1_str);
>      g_free (mem_str);
>      g_free (cmd);
>  }
> @@ -10390,6 +10478,8 @@ iface_modem_messaging_init (MMIfaceModemMessaging *iface)
>      iface->cleanup_unsolicited_events = modem_messaging_cleanup_unsolicited_events;
>      iface->cleanup_unsolicited_events_finish = modem_messaging_setup_cleanup_unsolicited_events_finish;
>      iface->create_sms = modem_messaging_create_sms;
> +    iface->init_current_storages = modem_messaging_init_current_storages;
> +    iface->init_current_storages_finish = modem_messaging_init_current_storages_finish;
>  }
>  
>  static void
> diff --git a/src/mm-iface-modem-messaging.c b/src/mm-iface-modem-messaging.c
> index d2ef6e8..0cff1f2 100644
> --- a/src/mm-iface-modem-messaging.c
> +++ b/src/mm-iface-modem-messaging.c
> @@ -1057,6 +1057,7 @@ typedef enum {
>      INITIALIZATION_STEP_CHECK_SUPPORT,
>      INITIALIZATION_STEP_FAIL_IF_UNSUPPORTED,
>      INITIALIZATION_STEP_LOAD_SUPPORTED_STORAGES,
> +    INITIALIZATION_STEP_INIT_CURRENT_STORAGES,
>      INITIALIZATION_STEP_LAST
>  } InitializationStep;
>  
> @@ -1213,6 +1214,30 @@ check_support_ready (MMIfaceModemMessaging *self,
>  }
>  
>  static void
> +init_current_storages_ready (MMIfaceModemMessaging *self,
> +                             GAsyncResult *res,
> +                             InitializationContext *ctx)
> +{
> +    StorageContext *storage_ctx;
> +    GError *error = NULL;
> +
> +    storage_ctx = get_storage_context (self);
> +    if (!MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (self)->init_current_storages_finish (
> +            self,
> +            res,
> +            &error)) {
> +        mm_dbg ("Couldn't initialize current storages: '%s'", error->message);
> +        g_error_free (error);
> +    } else {
> +        mm_dbg ("Current storages initialized");
> +    }
> +
> +    /* Go on to next step */
> +    ctx->step++;
> +    interface_initialization_step (ctx);
> +}
> +
> +static void
>  interface_initialization_step (InitializationContext *ctx)
>  {
>      /* Don't run new steps if we're cancelled */
> @@ -1284,6 +1309,18 @@ interface_initialization_step (InitializationContext *ctx)
>          /* Fall down to next step */
>          ctx->step++;
>  
> +    case INITIALIZATION_STEP_INIT_CURRENT_STORAGES:
> +        if (MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->init_current_storages &&
> +            MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->init_current_storages_finish) {
> +            MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->init_current_storages (
> +                ctx->self,
> +                (GAsyncReadyCallback)init_current_storages_ready,
> +                ctx);
> +            return;
> +        }
> +        /* Fall down to next step */
> +        ctx->step++;
> +
>      case INITIALIZATION_STEP_LAST:
>          /* We are done without errors! */
>  
> diff --git a/src/mm-iface-modem-messaging.h b/src/mm-iface-modem-messaging.h
> index c27e100..57fa452 100644
> --- a/src/mm-iface-modem-messaging.h
> +++ b/src/mm-iface-modem-messaging.h
> @@ -62,6 +62,13 @@ struct _MMIfaceModemMessaging {
>                                                  GArray **mem2,
>                                                  GArray **mem3,
>                                                  GError **error);
> +    /* Initializes the state of the storages */
> +    void (* init_current_storages) (MMIfaceModemMessaging *self,
> +                                    GAsyncReadyCallback callback,
> +                                    gpointer user_data);
> +    gboolean (*init_current_storages_finish) (MMIfaceModemMessaging *self,
> +                                              GAsyncResult *res,
> +                                              GError **error);
>  
>      /* Set default storage (async) */
>      void (* set_default_storage) (MMIfaceModemMessaging *self,
> diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
> index 58394ee..74e5546 100644
> --- a/src/mm-modem-helpers.c
> +++ b/src/mm-modem-helpers.c
> @@ -1507,6 +1507,82 @@ mm_3gpp_parse_cpms_test_response (const gchar *reply,
>      return FALSE;
>  }
>  
> +/**********************************************************************
> + * AT+CPMS?
> + * +CPMS: <memr>,<usedr>,<totalr>,<memw>,<usedw>,<totalw>, <mems>,<useds>,<totals>
> + */
> +
> +#define CPMS_QUERY_REGEX "\\+CPMS:\\s*\"(?P<memr>.*)\",[0-9]+,[0-9]+,\"(?P<memw>.*)\",[0-9]+,[0-9]+,\"(?P<mems>.*)\",[0-9]+,[0-9]"
> +
> +gboolean
> +mm_3gpp_parse_cpms_query_response (const gchar *reply,
> +                                   MMSmsStorage *memr,
> +                                   MMSmsStorage *memw,
> +                                   GError **error)
> +{
> +    GRegex *r = NULL;
> +    gboolean ret = FALSE;
> +    GMatchInfo *match_info = NULL;
> +
> +    r = g_regex_new (CPMS_QUERY_REGEX, G_REGEX_RAW, 0, NULL);
> +
> +    g_assert(r);
> +
> +    if (!g_regex_match (r, reply, 0, &match_info)) {
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
> +                     "Could not parse CPMS query reponse '%s'", reply);
> +        goto end;
> +    }
> +
> +    if (!g_match_info_matches(match_info)) {
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
> +                     "Could not find matches in CPMS query reply '%s'", reply);
> +        goto end;
> +    }
> +
> +    if (!mm_3gpp_get_cpms_storage_match (match_info, "memr", memr, error)) {
> +        goto end;
> +    }
> +
> +    if (!mm_3gpp_get_cpms_storage_match (match_info, "memw", memw, error)) {
> +        goto end;
> +    }
> +
> +    ret = TRUE;
> +
> +end:
> +    if (r != NULL)
> +        g_regex_unref (r);
> +
> +    if (match_info != NULL)
> +        g_match_info_free (match_info);
> +
> +    return ret;
> +}
> +
> +gboolean
> +mm_3gpp_get_cpms_storage_match (GMatchInfo *match_info,
> +                                const gchar *match_name,
> +                                MMSmsStorage *storage,
> +                                GError **error)
> +{
> +    gboolean ret = TRUE;
> +    gchar *str = NULL;
> +
> +    str = g_match_info_fetch_named(match_info, match_name);
> +    if (str == NULL || str[0] == '\0') {
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
> +                     "Could not find '%s' from CPMS reply", match_name);
> +        ret = FALSE;
> +    } else {
> +        *storage = storage_from_str (str);
> +    }
> +
> +    g_free (str);
> +
> +    return ret;
> +}
> +
>  /*************************************************************************/
>  
>  gboolean
> diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
> index 975a493..476b315 100644
> --- a/src/mm-modem-helpers.h
> +++ b/src/mm-modem-helpers.h
> @@ -158,6 +158,16 @@ gboolean mm_3gpp_parse_cpms_test_response (const gchar *reply,
>                                             GArray **mem2,
>                                             GArray **mem3);
>  
> +/* AT+CPMS? (Current SMS storage) response parser */
> +gboolean mm_3gpp_parse_cpms_query_response (const gchar *reply,
> +                                            MMSmsStorage *mem1,
> +                                            MMSmsStorage *mem2,
> +                                            GError** error);
> +gboolean mm_3gpp_get_cpms_storage_match (GMatchInfo *match_info,
> +                                         const gchar *match_name,
> +                                         MMSmsStorage *storage,
> +                                         GError **error);
> +
>  /* AT+CSCS=? (Supported charsets) response parser */
>  gboolean mm_3gpp_parse_cscs_test_response (const gchar *reply,
>                                             MMModemCharset *out_charsets);
> diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
> index db84f01..ddd25af 100644
> --- a/src/tests/test-modem-helpers.c
> +++ b/src/tests/test-modem-helpers.c
> @@ -2070,6 +2070,40 @@ test_cpms_response_empty_fields (void *f, gpointer d)
>      g_array_unref (mem3);
>  }
>  
> +typedef struct {
> +    const gchar *query;
> +    MMSmsStorage mem1_want;
> +    MMSmsStorage mem2_want;
> +} CpmsQueryTest;
> +
> +CpmsQueryTest cpms_query_test[] = {
> +    {"+CPMS: \"ME\",1,100,\"MT\",5,100,\"TA\",1,100", 2, 3},
> +    {"+CPMS: \"SM\",100,100,\"SR\",5,10,\"TA\",1,100", 1, 4},
> +    {"+CPMS: \"XX\",100,100,\"BM\",5,10,\"TA\",1,100", 0, 5},
> +    {"+CPMS: \"XX\",100,100,\"YY\",5,10,\"TA\",1,100", 0, 0},
> +    {NULL, 0, 0}
> +};
> +
> +static void
> +test_cpms_query_response (void *f, gpointer d) {
> +    MMSmsStorage mem1;
> +    MMSmsStorage mem2;
> +    gboolean ret;
> +    GError *error = NULL;
> +    int i;
> +
> +    for (i = 0; cpms_query_test[i].query != NULL; i++){
> +        ret = mm_3gpp_parse_cpms_query_response (cpms_query_test[i].query,
> +                                                 &mem1,
> +                                                 &mem2,
> +                                                 &error);
> +        g_assert(ret);
> +        g_assert_no_error (error);
> +        g_assert_cmpuint (cpms_query_test[i].mem1_want, ==, mem1);
> +        g_assert_cmpuint (cpms_query_test[i].mem2_want, ==, mem2);
> +    }
> +}
> +
>  /*****************************************************************************/
>  /* Test CNUM responses */
>  
> @@ -2821,6 +2855,7 @@ int main (int argc, char **argv)
>      g_test_suite_add (suite, TESTCASE (test_cpms_response_mixed,        NULL));
>      g_test_suite_add (suite, TESTCASE (test_cpms_response_mixed_spaces, NULL));
>      g_test_suite_add (suite, TESTCASE (test_cpms_response_empty_fields, NULL));
> +    g_test_suite_add (suite, TESTCASE (test_cpms_query_response,        NULL));
>  
>      g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_single, NULL));
>      g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_multiple, NULL));
> 


-- 
Aleksander
https://aleksander.es


More information about the ModemManager-devel mailing list