base-sms: ensure send/store always uses the same port

When sending or storing an SMS, the per-part operation is itself split
into two steps: first we send the AT command specifying the index, and
then we send the actual PDU data with a raw command. We must ensure
that the raw command is sent exactly in the same port as the AT
command.
This commit is contained in:
Aleksander Morgado
2024-04-10 08:41:31 +00:00
committed by Aleksander Morgado
parent b855dca7f7
commit 338b299fe2
+92 -51
View File
@@ -839,12 +839,13 @@ sms_get_store_or_send_command (MMBaseSms *self,
/* Store the SMS */ /* Store the SMS */
typedef struct { typedef struct {
MMBaseModem *modem; MMBaseModem *modem;
MMSmsStorage storage; MMPortSerialAt *port;
gboolean need_unlock; MMSmsStorage storage;
gboolean use_pdu_mode; gboolean need_unlock;
GList *current; gboolean use_pdu_mode;
gchar *msg_data; GList *current;
gchar *msg_data;
} SmsStoreContext; } SmsStoreContext;
static void static void
@@ -853,6 +854,7 @@ sms_store_context_free (SmsStoreContext *ctx)
/* Unlock mem2 storage if we had the lock */ /* Unlock mem2 storage if we had the lock */
if (ctx->need_unlock) if (ctx->need_unlock)
mm_broadband_modem_unlock_sms_storages (MM_BROADBAND_MODEM (ctx->modem), FALSE, TRUE); mm_broadband_modem_unlock_sms_storages (MM_BROADBAND_MODEM (ctx->modem), FALSE, TRUE);
g_object_unref (ctx->port);
g_object_unref (ctx->modem); g_object_unref (ctx->modem);
g_free (ctx->msg_data); g_free (ctx->msg_data);
g_slice_free (SmsStoreContext, ctx); g_slice_free (SmsStoreContext, ctx);
@@ -879,7 +881,7 @@ store_msg_data_ready (MMBaseModem *modem,
gint rv; gint rv;
gint idx; gint idx;
response = mm_base_modem_at_command_finish (modem, res, &error); response = mm_base_modem_at_command_full_finish (modem, res, &error);
if (error) { if (error) {
g_task_return_error (task, error); g_task_return_error (task, error);
g_object_unref (task); g_object_unref (task);
@@ -916,7 +918,7 @@ store_ready (MMBaseModem *modem,
SmsStoreContext *ctx; SmsStoreContext *ctx;
GError *error = NULL; GError *error = NULL;
mm_base_modem_at_command_finish (modem, res, &error); mm_base_modem_at_command_full_finish (modem, res, &error);
if (error) { if (error) {
g_task_return_error (task, error); g_task_return_error (task, error);
g_object_unref (task); g_object_unref (task);
@@ -930,12 +932,15 @@ store_ready (MMBaseModem *modem,
* be treated as an AT command (i.e. we don't want it prefixed * be treated as an AT command (i.e. we don't want it prefixed
* with AT+ and suffixed with <CR><LF>), plus, we want it to be * with AT+ and suffixed with <CR><LF>), plus, we want it to be
* sent right away (not queued after other AT commands). */ * sent right away (not queued after other AT commands). */
mm_base_modem_at_command_raw (ctx->modem, mm_base_modem_at_command_full (ctx->modem,
ctx->msg_data, ctx->port,
10, ctx->msg_data,
FALSE, 10,
(GAsyncReadyCallback)store_msg_data_ready, FALSE,
task); TRUE, /* raw */
NULL,
(GAsyncReadyCallback)store_msg_data_ready,
task);
} }
static void static void
@@ -973,12 +978,15 @@ sms_store_next_part (GTask *task)
g_assert (cmd != NULL); g_assert (cmd != NULL);
g_assert (ctx->msg_data != NULL); g_assert (ctx->msg_data != NULL);
mm_base_modem_at_command (ctx->modem, mm_base_modem_at_command_full (ctx->modem,
cmd, ctx->port,
10, cmd,
FALSE, 10,
(GAsyncReadyCallback)store_ready, FALSE,
task); FALSE, /* raw */
NULL,
(GAsyncReadyCallback)store_ready,
task);
} }
static void static void
@@ -1016,18 +1024,29 @@ sms_store (MMBaseSms *self,
{ {
SmsStoreContext *ctx; SmsStoreContext *ctx;
GTask *task; GTask *task;
MMPortSerialAt *port;
GError *error = NULL;
task = g_task_new (self, NULL, callback, user_data);
/* Select port for the operation */
port = mm_base_modem_peek_best_at_port (self->priv->modem, &error);
if (!port) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
/* Setup the context */ /* Setup the context */
ctx = g_slice_new0 (SmsStoreContext); ctx = g_slice_new0 (SmsStoreContext);
ctx->modem = g_object_ref (self->priv->modem); ctx->modem = g_object_ref (self->priv->modem);
ctx->port = g_object_ref (port);
ctx->storage = storage; ctx->storage = storage;
/* Different ways to do it if on PDU or text mode */ /* Different ways to do it if on PDU or text mode */
g_object_get (self->priv->modem, g_object_get (self->priv->modem,
MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &ctx->use_pdu_mode, MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &ctx->use_pdu_mode,
NULL); NULL);
task = g_task_new (self, NULL, callback, user_data);
g_task_set_task_data (task, ctx, (GDestroyNotify)sms_store_context_free); g_task_set_task_data (task, ctx, (GDestroyNotify)sms_store_context_free);
/* First, lock storage to use */ /* First, lock storage to use */
@@ -1044,12 +1063,13 @@ sms_store (MMBaseSms *self,
/* Send the SMS */ /* Send the SMS */
typedef struct { typedef struct {
MMBaseModem *modem; MMBaseModem *modem;
gboolean need_unlock; MMPortSerialAt *port;
gboolean from_storage; gboolean need_unlock;
gboolean use_pdu_mode; gboolean from_storage;
GList *current; gboolean use_pdu_mode;
gchar *msg_data; GList *current;
gchar *msg_data;
} SmsSendContext; } SmsSendContext;
static void static void
@@ -1058,6 +1078,7 @@ sms_send_context_free (SmsSendContext *ctx)
/* Unlock mem2 storage if we had the lock */ /* Unlock mem2 storage if we had the lock */
if (ctx->need_unlock) if (ctx->need_unlock)
mm_broadband_modem_unlock_sms_storages (MM_BROADBAND_MODEM (ctx->modem), FALSE, TRUE); mm_broadband_modem_unlock_sms_storages (MM_BROADBAND_MODEM (ctx->modem), FALSE, TRUE);
g_object_unref (ctx->port);
g_object_unref (ctx->modem); g_object_unref (ctx->modem);
g_free (ctx->msg_data); g_free (ctx->msg_data);
g_slice_free (SmsSendContext, ctx); g_slice_free (SmsSendContext, ctx);
@@ -1108,7 +1129,7 @@ send_generic_msg_data_ready (MMBaseModem *modem,
const gchar *response; const gchar *response;
gint message_reference; gint message_reference;
response = mm_base_modem_at_command_finish (modem, res, &error); response = mm_base_modem_at_command_full_finish (modem, res, &error);
if (error) { if (error) {
g_task_return_error (task, error); g_task_return_error (task, error);
g_object_unref (task); g_object_unref (task);
@@ -1139,7 +1160,7 @@ send_generic_ready (MMBaseModem *modem,
SmsSendContext *ctx; SmsSendContext *ctx;
GError *error = NULL; GError *error = NULL;
mm_base_modem_at_command_finish (modem, res, &error); mm_base_modem_at_command_full_finish (modem, res, &error);
if (error) { if (error) {
g_task_return_error (task, error); g_task_return_error (task, error);
g_object_unref (task); g_object_unref (task);
@@ -1153,12 +1174,15 @@ send_generic_ready (MMBaseModem *modem,
* be treated as an AT command (i.e. we don't want it prefixed * be treated as an AT command (i.e. we don't want it prefixed
* with AT+ and suffixed with <CR><LF>), plus, we want it to be * with AT+ and suffixed with <CR><LF>), plus, we want it to be
* sent right away (not queued after other AT commands). */ * sent right away (not queued after other AT commands). */
mm_base_modem_at_command_raw (ctx->modem, mm_base_modem_at_command_full (ctx->modem,
ctx->msg_data, ctx->port,
MM_BASE_SMS_DEFAULT_SEND_TIMEOUT, ctx->msg_data,
FALSE, MM_BASE_SMS_DEFAULT_SEND_TIMEOUT,
(GAsyncReadyCallback)send_generic_msg_data_ready, FALSE,
task); TRUE, /* raw */
NULL,
(GAsyncReadyCallback)send_generic_msg_data_ready,
task);
} }
static void static void
@@ -1175,7 +1199,7 @@ send_from_storage_ready (MMBaseModem *modem,
self = g_task_get_source_object (task); self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
response = mm_base_modem_at_command_finish (modem, res, &error); response = mm_base_modem_at_command_full_finish (modem, res, &error);
if (error) { if (error) {
if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) {
g_task_return_error (task, error); g_task_return_error (task, error);
@@ -1226,12 +1250,15 @@ sms_send_next_part (GTask *task)
/* Send from storage */ /* Send from storage */
if (ctx->from_storage) { if (ctx->from_storage) {
cmd = g_strdup_printf ("+CMSS=%d", mm_sms_part_get_index ((MMSmsPart *)ctx->current->data)); cmd = g_strdup_printf ("+CMSS=%d", mm_sms_part_get_index ((MMSmsPart *)ctx->current->data));
mm_base_modem_at_command (ctx->modem, mm_base_modem_at_command_full (ctx->modem,
cmd, ctx->port,
MM_BASE_SMS_DEFAULT_SEND_TIMEOUT, cmd,
FALSE, MM_BASE_SMS_DEFAULT_SEND_TIMEOUT,
(GAsyncReadyCallback)send_from_storage_ready, FALSE,
task); FALSE,
NULL,
(GAsyncReadyCallback)send_from_storage_ready,
task);
return; return;
} }
@@ -1255,12 +1282,15 @@ sms_send_next_part (GTask *task)
g_assert (ctx->msg_data != NULL); g_assert (ctx->msg_data != NULL);
/* no network involved in this initial AT command, so lower timeout */ /* no network involved in this initial AT command, so lower timeout */
mm_base_modem_at_command (ctx->modem, mm_base_modem_at_command_full (ctx->modem,
cmd, ctx->port,
10, cmd,
FALSE, 10,
(GAsyncReadyCallback)send_generic_ready, FALSE,
task); FALSE, /* raw */
NULL,
(GAsyncReadyCallback)send_generic_ready,
task);
} }
static void static void
@@ -1297,12 +1327,23 @@ sms_send (MMBaseSms *self,
{ {
SmsSendContext *ctx; SmsSendContext *ctx;
GTask *task; GTask *task;
MMPortSerialAt *port;
GError *error = NULL;
task = g_task_new (self, NULL, callback, user_data);
/* Select port for the operation */
port = mm_base_modem_peek_best_at_port (self->priv->modem, &error);
if (!port) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
/* Setup the context */ /* Setup the context */
ctx = g_slice_new0 (SmsSendContext); ctx = g_slice_new0 (SmsSendContext);
ctx->modem = g_object_ref (self->priv->modem); ctx->modem = g_object_ref (self->priv->modem);
ctx->port = g_object_ref (port);
task = g_task_new (self, NULL, callback, user_data);
g_task_set_task_data (task, ctx, (GDestroyNotify)sms_send_context_free); g_task_set_task_data (task, ctx, (GDestroyNotify)sms_send_context_free);
/* If the SMS is STORED, try to send from storage */ /* If the SMS is STORED, try to send from storage */