diff options
author | Carlo Lobrano <c.lobrano@gmail.com> | 2016-03-09 11:27:43 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-03-09 14:43:08 +0100 |
commit | be317e8b80cd984149ea152c9d00c6bb814e7c88 (patch) | |
tree | b59255b3611d3be0804a0f081e298c967d4b44c5 | |
parent | 7c2d5b1aa358c4edb94203d7de586d489b656576 (diff) |
broadband-modem: fix +CPMS empty parameter support
* 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.
https://bugs.freedesktop.org/show_bug.cgi?id=93135
-rw-r--r-- | src/mm-broadband-modem.c | 92 | ||||
-rw-r--r-- | src/mm-iface-modem-messaging.c | 37 | ||||
-rw-r--r-- | src/mm-iface-modem-messaging.h | 7 | ||||
-rw-r--r-- | src/mm-modem-helpers.c | 76 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 10 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 35 |
6 files changed, 256 insertions, 1 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 6fc0663d..e57195be 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 d2ef6e86..0cff1f2e 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 c27e100c..57fa4521 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 58394ee6..74e55462 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 975a493b..476b3156 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 db84f016..ddd25af4 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)); |