aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-09-10 13:45:23 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-09-14 07:05:22 +0200
commit4f9817741ff6284c895a90ff15cab3ab056ac21b (patch)
treecbe6f5b12768b252ed640403ccbc154a9f4ca11c /src
parent83dc9e3e1d32eb72ed60163a066c20d553f4c468 (diff)
broadband-modem: new methods to lock/unlock current SMS storages
The default AT commands to play with SMS rely on AT+CPMS to select the default memory storages for different operations. AT+CPMS defines 3 different storages, called 'mem1' (for reading/listing/deleting), 'mem2' (for storing or sending from storage) and 'mem3' (for receiving). For example, when an SMS is to be deleted, we first need to select with AT+CPMS the proper 'mem1' storage before issuing the command to delete the SMS part. But, in order to do this properly we need to synchronize the access to the currently set storages, so that no more than one action is run in the storages at the same time (e.g. don't store an SMS while another SMS is being deleted). In order to synchronize this access, we now provide commands to lock()/unlock() the storages, which should be used when we want to do some operation on them. Note that this logic is only required because we cannot specify the storage explicitly in the specific AT command operations. With QMI we don't need this locking/unlocking.
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem.c147
-rw-r--r--src/mm-broadband-modem.h12
2 files changed, 158 insertions, 1 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 3863c71c..c9a2bd58 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -170,6 +170,10 @@ struct _MMBroadbandModemPrivate {
/* Implementation helpers */
gboolean sms_supported_modes_checked;
GHashTable *known_sms_parts;
+ gboolean storages_locked;
+ MMSmsStorage current_sms_mem1_storage;
+ MMSmsStorage current_sms_mem2_storage;
+
/*<--- Modem Time interface --->*/
/* Properties */
@@ -4141,6 +4145,142 @@ modem_messaging_load_supported_storages (MMIfaceModemMessaging *self,
}
/*****************************************************************************/
+/* Lock/unlock SMS storage (Messaging interface implementation helper)
+ *
+ * The basic commands to work with SMS storages play with AT+CPMS and three
+ * different storages: mem1, mem2 and mem3.
+ * 'mem1' is the storage for reading, listing and deleting.
+ * 'mem2' is the storage for writing and sending from storage.
+ * 'mem3' is the storage for receiving.
+ *
+ * When a command is to be issued for a specific storage, we need a way to
+ * lock the access so that other actions are forbidden until the current one
+ * finishes. Just think of two sequential actions to store two different
+ * SMS into 2 different storages. If the second action is run while the first
+ * one is still running, we should issue a RETRY error.
+ *
+ * Note that mem3 cannot be locked; we just set the default mem3 and that's it.
+ *
+ * When we unlock the storage, we don't go back to the default storage
+ * automatically, we just keep track of which is the current one and only go to
+ * the default one if needed.
+ */
+
+void
+mm_broadband_modem_unlock_sms_storages (MMBroadbandModem *self)
+{
+ g_assert (self->priv->storages_locked);
+ self->priv->storages_locked = FALSE;
+}
+
+gboolean
+mm_broadband_modem_lock_sms_storages_finish (MMBroadbandModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+typedef struct {
+ GSimpleAsyncResult *result;
+ MMBroadbandModem *self;
+ MMSmsStorage previous_mem1;
+ MMSmsStorage previous_mem2;
+} LockSmsStoragesContext;
+
+static void
+lock_sms_storages_context_complete_and_free (LockSmsStoragesContext *ctx)
+{
+ g_simple_async_result_complete (ctx->result);
+ g_object_unref (ctx->result);
+ g_object_unref (ctx->self);
+ g_slice_free (LockSmsStoragesContext, ctx);
+}
+
+static void
+lock_storages_cpms_set_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ LockSmsStoragesContext *ctx)
+{
+ GError *error = NULL;
+
+ mm_base_modem_at_command_finish (self, res, &error);
+ if (error) {
+ g_simple_async_result_take_error (ctx->result, error);
+ /* Reset previous storages and set unlocked */
+ ctx->self->priv->current_sms_mem1_storage = ctx->previous_mem1;
+ ctx->self->priv->current_sms_mem2_storage = ctx->previous_mem2;
+ ctx->self->priv->storages_locked = FALSE;
+ }
+ else
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+
+ lock_sms_storages_context_complete_and_free (ctx);
+}
+
+void
+mm_broadband_modem_lock_storages (MMBroadbandModem *self,
+ MMSmsStorage mem1, /* reading/listing/deleting */
+ MMSmsStorage mem2, /* storing/sending */
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ LockSmsStoragesContext *ctx;
+ gchar *cmd;
+ gchar *mem1_str;
+ gchar *mem2_str;
+
+ /* If storages are currently locked by someone else, just return an
+ * error */
+ if (self->priv->storages_locked) {
+ g_simple_async_report_error_in_idle (
+ G_OBJECT (self),
+ callback,
+ user_data,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_RETRY,
+ "SMS storages currently locked, try again later");
+ return;
+ }
+
+ /* Acquire lock */
+ self->priv->storages_locked = TRUE;
+
+ g_assert (mem1 != MM_SMS_STORAGE_UNKNOWN ||
+ mem2 != MM_SMS_STORAGE_UNKNOWN);
+
+ ctx = g_slice_new (LockSmsStoragesContext);
+ ctx->self = g_object_ref (self);
+ ctx->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ mm_broadband_modem_lock_sms_storages);
+
+ if (mem1 != MM_SMS_STORAGE_UNKNOWN)
+ self->priv->current_sms_mem1_storage = mem1;
+ if (mem2 != MM_SMS_STORAGE_UNKNOWN)
+ self->priv->current_sms_mem2_storage = mem2;
+
+ /* We don't touch 'mem3' here */
+ mem1_str = g_ascii_strup (mm_sms_storage_get_string (self->priv->current_sms_mem1_storage), -1);
+ mem2_str = g_ascii_strup (mm_sms_storage_get_string (self->priv->current_sms_mem2_storage), -1);
+
+ mm_dbg ("Locking SMS storages to: mem1 (%s), mem2 (%s)...",
+ mem1_str, mem2_str);
+
+ cmd = g_strdup_printf ("+CPMS=\"%s\",\"%s\"", mem1_str, mem2_str);
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ cmd,
+ 3,
+ FALSE,
+ (GAsyncReadyCallback)lock_storages_cpms_set_ready,
+ ctx);
+ g_free (mem1_str);
+ g_free (mem2_str);
+ g_free (cmd);
+}
+
+/*****************************************************************************/
/* Set preferred SMS storage (Messaging interface) */
static gboolean
@@ -4168,13 +4308,14 @@ cpms_set_ready (MMBroadbandModem *self,
}
static void
-modem_messaging_set_preferred_storages (MMIfaceModemMessaging *self,
+modem_messaging_set_preferred_storages (MMIfaceModemMessaging *_self,
MMSmsStorage mem1,
MMSmsStorage mem2,
MMSmsStorage mem3,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
gchar *cmd;
GSimpleAsyncResult *result;
gchar *mem1_str;
@@ -4186,6 +4327,10 @@ modem_messaging_set_preferred_storages (MMIfaceModemMessaging *self,
user_data,
modem_messaging_set_preferred_storages);
+ /* Set defaults as current */
+ self->priv->current_sms_mem1_storage = mem1;
+ self->priv->current_sms_mem2_storage = mem2;
+
mem1_str = g_ascii_strup (mm_sms_storage_get_string (mem1), -1);
mem2_str = g_ascii_strup (mm_sms_storage_get_string (mem2), -1);
mem3_str = g_ascii_strup (mm_sms_storage_get_string (mem3), -1);
diff --git a/src/mm-broadband-modem.h b/src/mm-broadband-modem.h
index 33ea53f3..db987c6e 100644
--- a/src/mm-broadband-modem.h
+++ b/src/mm-broadband-modem.h
@@ -22,6 +22,7 @@
#include <glib-object.h>
#include "mm-base-modem.h"
+#include "ModemManager-enums.h"
#define MM_TYPE_BROADBAND_MODEM (mm_broadband_modem_get_type ())
#define MM_BROADBAND_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM, MMBroadbandModem))
@@ -98,4 +99,15 @@ gchar *mm_broadband_modem_create_device_identifier (MMBroadbandModem *self,
const gchar *ati,
const gchar *ati1);
+/* Locking/unlocking SMS storages */
+void mm_broadband_modem_lock_storages (MMBroadbandModem *self,
+ MMSmsStorage mem1, /* reading/listing/deleting */
+ MMSmsStorage mem2, /* storing/sending */
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mm_broadband_modem_lock_sms_storages_finish (MMBroadbandModem *self,
+ GAsyncResult *res,
+ GError **error);
+void mm_broadband_modem_unlock_sms_storages (MMBroadbandModem *self);
+
#endif /* MM_BROADBAND_MODEM_H */