[PATCH] Fix Bug 93135 +CPMS emtpy parameter not always supported
c.lobrano at gmail.com
c.lobrano at gmail.com
Mon Mar 7 14:04:53 UTC 2016
From: Carlo Lobrano <c.lobrano at gmail.com>
- Add new async virtual method load_current_storages to
MMIfaceModemMessaging
- Add logic of load_current_storages to MMBroadbandModem
- Add step "LOAD_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.
---
src/mm-broadband-modem.c | 89 +++++++++++++++++++++++++++++++++++++++++-
src/mm-iface-modem-messaging.c | 37 ++++++++++++++++++
src/mm-iface-modem-messaging.h | 11 ++++++
src/mm-modem-helpers.c | 77 ++++++++++++++++++++++++++++++++++++
src/mm-modem-helpers.h | 10 +++++
src/tests/test-modem-helpers.c | 36 +++++++++++++++++
6 files changed, 258 insertions(+), 2 deletions(-)
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 6fc0663..08c8f13 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -5242,6 +5242,82 @@ modem_messaging_load_supported_storages (MMIfaceModemMessaging *self,
}
/*****************************************************************************/
+/* Load current SMS storages (Messaging interface) */
+
+static gboolean
+modem_messaging_load_current_storages_finish (MMIfaceModemMessaging *_self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return FALSE;
+
+ return TRUE;
+}
+
+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 loaded:");
+ 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_load_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_load_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
@@ -5373,8 +5449,9 @@ mm_broadband_modem_lock_sms_storages (MMBroadbandModem *self,
ctx->previous_mem1 = self->priv->current_sms_mem1_storage;
self->priv->mem1_storage_locked = TRUE;
self->priv->current_sms_mem1_storage = mem1;
- mem1_str = g_ascii_strup (mm_sms_storage_get_string (self->priv->current_sms_mem1_storage), -1);
}
+ /* We always provide a non empty string parameter as mem1 */
+ mem1_str = g_ascii_strup (mm_sms_storage_get_string (self->priv->current_sms_mem1_storage), -1);
if (mem2 != MM_SMS_STORAGE_UNKNOWN) {
ctx->mem2_locked = TRUE;
@@ -5446,6 +5523,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,8 +5534,13 @@ modem_messaging_set_default_storage (MMIfaceModemMessaging *_self,
/* Set defaults as current */
self->priv->current_sms_mem2_storage = storage;
+ /* Some modems do no support empty string as parameter.
+ * Here we keep the value or Memr as the one get with
+ * load_current_storages step */
+ 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, mem_str, mem_str);
mm_base_modem_at_command (MM_BASE_MODEM (self),
cmd,
3,
@@ -10390,6 +10473,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->load_current_storages = modem_messaging_load_current_storages;
+ iface->load_current_storages_finish = modem_messaging_load_current_storages_finish;
}
static void
diff --git a/src/mm-iface-modem-messaging.c b/src/mm-iface-modem-messaging.c
index d2ef6e8..5058569 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_LOAD_CURRENT_STORAGES,
INITIALIZATION_STEP_LAST
} InitializationStep;
@@ -1213,6 +1214,30 @@ check_support_ready (MMIfaceModemMessaging *self,
}
static void
+load_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)->load_current_storages_finish (
+ self,
+ res,
+ &error)) {
+ mm_dbg ("Couldn't load current storages: '%s'", error->message);
+ g_error_free (error);
+ } else {
+ mm_dbg ("Current storages loaded");
+ }
+
+ /* 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_LOAD_CURRENT_STORAGES:
+ if (MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->load_current_storages &&
+ MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->load_current_storages_finish) {
+ MM_IFACE_MODEM_MESSAGING_GET_INTERFACE (ctx->self)->load_current_storages (
+ ctx->self,
+ (GAsyncReadyCallback)load_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..0a289df 100644
--- a/src/mm-iface-modem-messaging.h
+++ b/src/mm-iface-modem-messaging.h
@@ -62,6 +62,17 @@ struct _MMIfaceModemMessaging {
GArray **mem2,
GArray **mem3,
GError **error);
+ /* Load current storages for...
+ * mem1: listing/reading/deleting
+ * mem2: writing/sending
+ * mem3: receiving
+ */
+ void (* load_current_storages) (MMIfaceModemMessaging *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (*load_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..3c64263 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -1507,6 +1507,83 @@ 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);
+ }
+
+ if (str != NULL)
+ 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..837317f 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -2070,6 +2070,41 @@ 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;
+ 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_cmpuint (cpms_query_test[i].mem1_want, ==, mem1);
+ g_assert_cmpuint (cpms_query_test[i].mem2_want, ==, mem2);
+ }
+
+}
+
/*****************************************************************************/
/* Test CNUM responses */
@@ -2821,6 +2856,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));
--
2.1.4
More information about the ModemManager-devel
mailing list