From 08a65a0bed75d0aabd36755655aba516f4e2cbfc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Apr 2025 20:08:20 -0500 Subject: sms-mbim: remove unused code Signed-off-by: Dan Williams --- src/mm-sms-mbim.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/mm-sms-mbim.c b/src/mm-sms-mbim.c index 0a404aa5..2de9905e 100644 --- a/src/mm-sms-mbim.c +++ b/src/mm-sms-mbim.c @@ -77,7 +77,6 @@ peek_device (gpointer self, /* Send the SMS */ typedef struct { - MMBaseModem *modem; MbimDevice *device; GList *current; } SmsSendContext; @@ -86,7 +85,6 @@ static void sms_send_context_free (SmsSendContext *ctx) { g_object_unref (ctx->device); - g_object_unref (ctx->modem); g_slice_free (SmsSendContext, ctx); } @@ -199,9 +197,6 @@ sms_send (MMBaseSms *self, /* Setup the context */ ctx = g_slice_new0 (SmsSendContext); ctx->device = g_object_ref (device); - g_object_get (self, - MM_BASE_SMS_MODEM, &ctx->modem, - NULL); task = g_task_new (self, NULL, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify)sms_send_context_free); @@ -213,7 +208,6 @@ sms_send (MMBaseSms *self, /*****************************************************************************/ typedef struct { - MMBaseModem *modem; MbimDevice *device; GList *current; guint n_failed; @@ -223,7 +217,6 @@ static void sms_delete_parts_context_free (SmsDeletePartsContext *ctx) { g_object_unref (ctx->device); - g_object_unref (ctx->modem); g_slice_free (SmsDeletePartsContext, ctx); } @@ -327,9 +320,6 @@ sms_delete (MMBaseSms *self, ctx = g_slice_new0 (SmsDeletePartsContext); ctx->device = g_object_ref (device); - g_object_get (self, - MM_BASE_SMS_MODEM, &ctx->modem, - NULL); task = g_task_new (self, NULL, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify)sms_delete_parts_context_free); -- cgit v1.2.3-70-g09d2 From 683a33b3034e962bdd247708aa2170112a9f8d12 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Apr 2025 21:10:11 -0500 Subject: base-sms: determine 3GPP vs. CDMA at creation time It won't ever change over the lifetime of the BaseSMS. Signed-off-by: Dan Williams --- src/mm-base-sms.c | 41 +++++++++++++++++++++-------------------- src/mm-base-sms.h | 4 +++- src/mm-broadband-modem-mbim.c | 3 ++- src/mm-broadband-modem-qmi.c | 3 ++- src/mm-broadband-modem.c | 3 ++- src/mm-iface-modem.c | 12 ++++++------ src/mm-sms-mbim.c | 3 ++- src/mm-sms-mbim.h | 3 ++- src/mm-sms-qmi.c | 3 ++- src/mm-sms-qmi.h | 3 ++- 10 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index 0e7c7527..c3e1b87b 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -55,6 +55,7 @@ enum { PROP_IS_MULTIPART, PROP_MAX_PARTS, PROP_MULTIPART_REFERENCE, + PROP_IS_3GPP, PROP_LAST }; @@ -88,6 +89,9 @@ struct _MMBaseSmsPrivate { /* Set to true when all needed parts were received, * parsed and assembled */ gboolean is_assembled; + + /* TRUE for 3GPP SMS; FALSE for CDMA */ + gboolean is_3gpp; }; /*****************************************************************************/ @@ -310,25 +314,7 @@ static gboolean generate_submit_pdus (MMBaseSms *self, GError **error) { - MMBaseModem *modem; - gboolean is_3gpp; - - /* First; decide which kind of PDU we'll generate, based on the current modem caps */ - - g_object_get (self, - MM_BASE_SMS_MODEM, &modem, - NULL); - g_assert (modem != NULL); - - is_3gpp = mm_iface_modem_is_3gpp (MM_IFACE_MODEM (modem)); - g_object_unref (modem); - - /* On a 3GPP-capable modem, create always a 3GPP SMS (even if the modem is 3GPP+3GPP2) */ - if (is_3gpp) - return generate_3gpp_submit_pdus (self, error); - - /* Otherwise, create a 3GPP2 SMS */ - return generate_cdma_submit_pdus (self, error); + return self->priv->is_3gpp ? generate_3gpp_submit_pdus (self, error) : generate_cdma_submit_pdus (self, error); } /*****************************************************************************/ @@ -1801,11 +1787,12 @@ mm_base_sms_multipart_take_part (MMBaseSms *self, } MMBaseSms * -mm_base_sms_new (MMBaseModem *modem) +mm_base_sms_new (MMBaseModem *modem, gboolean is_3gpp) { return MM_BASE_SMS (g_object_new (MM_TYPE_BASE_SMS, MM_BASE_SMS_MODEM, modem, MM_BIND_TO, modem, + MM_BASE_SMS_IS_3GPP, is_3gpp, NULL)); } @@ -2021,6 +2008,9 @@ set_property (GObject *object, case PROP_MULTIPART_REFERENCE: self->priv->multipart_reference = g_value_get_uint (value); break; + case PROP_IS_3GPP: + self->priv->is_3gpp = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2057,6 +2047,9 @@ get_property (GObject *object, case PROP_MULTIPART_REFERENCE: g_value_set_uint (value, self->priv->multipart_reference); break; + case PROP_IS_3GPP: + g_value_set_boolean (value, self->priv->is_3gpp); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2192,4 +2185,12 @@ mm_base_sms_class_init (MMBaseSmsClass *klass) 0, G_MAXUINT, 0, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_MULTIPART_REFERENCE, properties[PROP_MULTIPART_REFERENCE]); + + properties[PROP_IS_3GPP] = + g_param_spec_boolean (MM_BASE_SMS_IS_3GPP, + "Is 3GPP", + "Whether the SMS is a 3GPP one or a CDMA one", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_IS_3GPP, properties[PROP_IS_3GPP]); } diff --git a/src/mm-base-sms.h b/src/mm-base-sms.h index 186cb8e6..ffcaf8c4 100644 --- a/src/mm-base-sms.h +++ b/src/mm-base-sms.h @@ -52,6 +52,7 @@ typedef struct _MMBaseSmsPrivate MMBaseSmsPrivate; #define MM_BASE_SMS_IS_MULTIPART "sms-is-multipart" #define MM_BASE_SMS_MAX_PARTS "sms-max-parts" #define MM_BASE_SMS_MULTIPART_REFERENCE "sms-multipart-reference" +#define MM_BASE_SMS_IS_3GPP "sms-is-3gpp" struct _MMBaseSms { MmGdbusSmsSkeleton parent; @@ -91,7 +92,8 @@ GType mm_base_sms_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseSms, g_object_unref) /* This one can be overridden by plugins */ -MMBaseSms *mm_base_sms_new (MMBaseModem *modem); +MMBaseSms *mm_base_sms_new (MMBaseModem *modem, + gboolean is_3gpp); MMBaseSms *mm_base_sms_new_from_properties (MMBaseModem *modem, MMSmsProperties *properties, GError **error); diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 8116d201..79de6291 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -9233,7 +9233,8 @@ enable_unsolicited_events_messaging (MMIfaceModemMessaging *_self, static MMBaseSms * messaging_create_sms (MMIfaceModemMessaging *self) { - return mm_sms_mbim_new (MM_BASE_MODEM (self)); + return mm_sms_mbim_new (MM_BASE_MODEM (self), + mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); } /*****************************************************************************/ diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index a2609277..d13e1995 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -8882,7 +8882,8 @@ messaging_create_sms (MMIfaceModemMessaging *_self) return iface_modem_messaging_parent->create_sms (_self); } - return mm_sms_qmi_new (MM_BASE_MODEM (self)); + return mm_sms_qmi_new (MM_BASE_MODEM (self), + mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); } diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 16d579c7..c8971afe 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -8225,7 +8225,8 @@ modem_messaging_load_initial_sms_parts (MMIfaceModemMessaging *self, static MMBaseSms * modem_messaging_create_sms (MMIfaceModemMessaging *self) { - return mm_base_sms_new (MM_BASE_MODEM (self)); + return mm_base_sms_new (MM_BASE_MODEM (self), + mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); } /*****************************************************************************/ diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c index 7bd0f0ff..1af2666b 100644 --- a/src/mm-iface-modem.c +++ b/src/mm-iface-modem.c @@ -6616,25 +6616,25 @@ mm_iface_modem_get_current_capabilities (MMIfaceModem *self) gboolean mm_iface_modem_is_3gpp (MMIfaceModem *self) { - return (mm_iface_modem_get_current_capabilities (self) & MM_MODEM_CAPABILITY_3GPP); + return !!(mm_iface_modem_get_current_capabilities (self) & MM_MODEM_CAPABILITY_3GPP); } gboolean mm_iface_modem_is_3gpp_lte (MMIfaceModem *self) { - return (mm_iface_modem_get_current_capabilities (self) & MM_MODEM_CAPABILITY_LTE); + return !!(mm_iface_modem_get_current_capabilities (self) & MM_MODEM_CAPABILITY_LTE); } gboolean mm_iface_modem_is_3gpp_5gnr (MMIfaceModem *self) { - return (mm_iface_modem_get_current_capabilities (self) & MM_MODEM_CAPABILITY_5GNR); + return !!(mm_iface_modem_get_current_capabilities (self) & MM_MODEM_CAPABILITY_5GNR); } gboolean mm_iface_modem_is_cdma (MMIfaceModem *self) { - return (mm_iface_modem_get_current_capabilities (self) & MM_MODEM_CAPABILITY_CDMA_EVDO); + return !!(mm_iface_modem_get_current_capabilities (self) & MM_MODEM_CAPABILITY_CDMA_EVDO); } gboolean @@ -6643,13 +6643,13 @@ mm_iface_modem_is_3gpp_only (MMIfaceModem *self) MMModemCapability capabilities; capabilities = mm_iface_modem_get_current_capabilities (self); - return (capabilities & MM_MODEM_CAPABILITY_3GPP) && !((MM_MODEM_CAPABILITY_3GPP ^ capabilities) & capabilities); + return !!((capabilities & MM_MODEM_CAPABILITY_3GPP) && !((MM_MODEM_CAPABILITY_3GPP ^ capabilities) & capabilities)); } gboolean mm_iface_modem_is_cdma_only (MMIfaceModem *self) { - return (mm_iface_modem_get_current_capabilities (self) == MM_MODEM_CAPABILITY_CDMA_EVDO); + return !!(mm_iface_modem_get_current_capabilities (self) == MM_MODEM_CAPABILITY_CDMA_EVDO); } /*****************************************************************************/ diff --git a/src/mm-sms-mbim.c b/src/mm-sms-mbim.c index 2de9905e..1cb442d6 100644 --- a/src/mm-sms-mbim.c +++ b/src/mm-sms-mbim.c @@ -332,11 +332,12 @@ sms_delete (MMBaseSms *self, /*****************************************************************************/ MMBaseSms * -mm_sms_mbim_new (MMBaseModem *modem) +mm_sms_mbim_new (MMBaseModem *modem, gboolean is_3gpp) { return MM_BASE_SMS (g_object_new (MM_TYPE_SMS_MBIM, MM_BASE_SMS_MODEM, modem, MM_BIND_TO, G_OBJECT (modem), + MM_BASE_SMS_IS_3GPP, is_3gpp, NULL)); } diff --git a/src/mm-sms-mbim.h b/src/mm-sms-mbim.h index 5743f262..070ff677 100644 --- a/src/mm-sms-mbim.h +++ b/src/mm-sms-mbim.h @@ -45,6 +45,7 @@ struct _MMSmsMbimClass { GType mm_sms_mbim_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSmsMbim, g_object_unref) -MMBaseSms *mm_sms_mbim_new (MMBaseModem *modem); +MMBaseSms *mm_sms_mbim_new (MMBaseModem *modem, + gboolean is_3gpp); #endif /* MM_SMS_MBIM_H */ diff --git a/src/mm-sms-qmi.c b/src/mm-sms-qmi.c index abc45649..aa5101ee 100644 --- a/src/mm-sms-qmi.c +++ b/src/mm-sms-qmi.c @@ -786,11 +786,12 @@ sms_delete (MMBaseSms *self, /*****************************************************************************/ MMBaseSms * -mm_sms_qmi_new (MMBaseModem *modem) +mm_sms_qmi_new (MMBaseModem *modem, gboolean is_3gpp) { return MM_BASE_SMS (g_object_new (MM_TYPE_SMS_QMI, MM_BASE_SMS_MODEM, modem, MM_BIND_TO, G_OBJECT (modem), + MM_BASE_SMS_IS_3GPP, is_3gpp, NULL)); } diff --git a/src/mm-sms-qmi.h b/src/mm-sms-qmi.h index af60a7f5..250e406e 100644 --- a/src/mm-sms-qmi.h +++ b/src/mm-sms-qmi.h @@ -47,6 +47,7 @@ struct _MMSmsQmiClass { GType mm_sms_qmi_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSmsQmi, g_object_unref) -MMBaseSms *mm_sms_qmi_new (MMBaseModem *modem); +MMBaseSms *mm_sms_qmi_new (MMBaseModem *modem, + gboolean is_3gpp); #endif /* MM_SMS_QMI_H */ -- cgit v1.2.3-70-g09d2 From 1283ee8c2a92c40d653168f94d8d6816d8be82b9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Apr 2025 21:54:14 -0500 Subject: base-sms,iface-modem-messaging: move lock/unlock logic into the interface Allows us to test things that rely on MMBaseSms more easily.. Signed-off-by: Dan Williams --- src/mm-base-sms.c | 58 ++++++++++++++++++------------- src/mm-broadband-modem.c | 78 +++++++++++++++++++++++------------------- src/mm-broadband-modem.h | 12 ------- src/mm-iface-modem-messaging.c | 43 +++++++++++++++++++++++ src/mm-iface-modem-messaging.h | 28 +++++++++++++++ 5 files changed, 147 insertions(+), 72 deletions(-) diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index c3e1b87b..1b022614 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -28,6 +28,7 @@ #include "mm-base-sms.h" #include "mm-broadband-modem.h" +#include "mm-auth-provider.h" #include "mm-iface-modem.h" #include "mm-iface-modem-messaging.h" #include "mm-sms-part-3gpp.h" @@ -848,8 +849,11 @@ static void sms_store_context_free (SmsStoreContext *ctx) { /* Unlock mem2 storage if we had the lock */ - if (ctx->need_unlock) - mm_broadband_modem_unlock_sms_storages (MM_BROADBAND_MODEM (ctx->modem), FALSE, TRUE); + if (ctx->need_unlock) { + mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), + FALSE, + TRUE); + } g_object_unref (ctx->port); g_object_unref (ctx->modem); g_free (ctx->msg_data); @@ -986,7 +990,7 @@ sms_store_next_part (GTask *task) } static void -store_lock_sms_storages_ready (MMBroadbandModem *modem, +store_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, GAsyncResult *res, GTask *task) { @@ -994,7 +998,7 @@ store_lock_sms_storages_ready (MMBroadbandModem *modem, SmsStoreContext *ctx; GError *error = NULL; - if (!mm_broadband_modem_lock_sms_storages_finish (modem, res, &error)) { + if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { g_task_return_error (task, error); g_object_unref (task); return; @@ -1040,15 +1044,15 @@ sms_store (MMBaseSms *self, ctx->storage = storage; /* Different ways to do it if on PDU or text mode */ + g_assert (MM_IS_IFACE_MODEM_MESSAGING (self->priv->modem)); g_object_get (self->priv->modem, MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &ctx->use_pdu_mode, NULL); g_task_set_task_data (task, ctx, (GDestroyNotify)sms_store_context_free); /* First, lock storage to use */ - g_assert (MM_IS_BROADBAND_MODEM (self->priv->modem)); - mm_broadband_modem_lock_sms_storages ( - MM_BROADBAND_MODEM (self->priv->modem), + mm_iface_modem_messaging_lock_storages ( + MM_IFACE_MODEM_MESSAGING (self->priv->modem), MM_SMS_STORAGE_UNKNOWN, /* none required for mem1 */ ctx->storage, (GAsyncReadyCallback)store_lock_sms_storages_ready, @@ -1072,8 +1076,11 @@ static void sms_send_context_free (SmsSendContext *ctx) { /* Unlock mem2 storage if we had the lock */ - if (ctx->need_unlock) - mm_broadband_modem_unlock_sms_storages (MM_BROADBAND_MODEM (ctx->modem), FALSE, TRUE); + if (ctx->need_unlock) { + mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), + FALSE, + TRUE); + } g_object_unref (ctx->port); g_object_unref (ctx->modem); g_free (ctx->msg_data); @@ -1290,15 +1297,15 @@ sms_send_next_part (GTask *task) } static void -send_lock_sms_storages_ready (MMBroadbandModem *modem, - GAsyncResult *res, - GTask *task) +send_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, + GAsyncResult *res, + GTask *task) { MMBaseSms *self; SmsSendContext *ctx; GError *error = NULL; - if (!mm_broadband_modem_lock_sms_storages_finish (modem, res, &error)) { + if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { g_task_return_error (task, error); g_object_unref (task); return; @@ -1346,9 +1353,9 @@ sms_send (MMBaseSms *self, ctx->from_storage = (mm_base_sms_get_storage (self) != MM_SMS_STORAGE_UNKNOWN); if (ctx->from_storage) { /* When sending from storage, first lock storage to use */ - g_assert (MM_IS_BROADBAND_MODEM (self->priv->modem)); - mm_broadband_modem_lock_sms_storages ( - MM_BROADBAND_MODEM (self->priv->modem), + g_assert (MM_IS_IFACE_MODEM_MESSAGING (self->priv->modem)); + mm_iface_modem_messaging_lock_storages ( + MM_IFACE_MODEM_MESSAGING (self->priv->modem), MM_SMS_STORAGE_UNKNOWN, /* none required for mem1 */ mm_base_sms_get_storage (self), (GAsyncReadyCallback)send_lock_sms_storages_ready, @@ -1377,8 +1384,11 @@ static void sms_delete_parts_context_free (SmsDeletePartsContext *ctx) { /* Unlock mem1 storage if we had the lock */ - if (ctx->need_unlock) - mm_broadband_modem_unlock_sms_storages (MM_BROADBAND_MODEM (ctx->modem), TRUE, FALSE); + if (ctx->need_unlock) { + mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), + TRUE, + FALSE); + } g_object_unref (ctx->modem); g_slice_free (SmsDeletePartsContext, ctx); } @@ -1456,15 +1466,15 @@ delete_next_part (GTask *task) } static void -delete_lock_sms_storages_ready (MMBroadbandModem *modem, - GAsyncResult *res, - GTask *task) +delete_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, + GAsyncResult *res, + GTask *task) { MMBaseSms *self; SmsDeletePartsContext *ctx; GError *error = NULL; - if (!mm_broadband_modem_lock_sms_storages_finish (modem, res, &error)) { + if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { g_task_return_error (task, error); g_object_unref (task); return; @@ -1504,8 +1514,8 @@ sms_delete (MMBaseSms *self, } /* Select specific storage to delete from */ - mm_broadband_modem_lock_sms_storages ( - MM_BROADBAND_MODEM (self->priv->modem), + mm_iface_modem_messaging_lock_storages ( + MM_IFACE_MODEM_MESSAGING (self->priv->modem), mm_base_sms_get_storage (self), MM_SMS_STORAGE_UNKNOWN, /* none required for mem2 */ (GAsyncReadyCallback)delete_lock_sms_storages_ready, diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index c8971afe..dbcc61a9 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -7185,11 +7185,13 @@ modem_messaging_init_current_storages (MMIfaceModemMessaging *self, * the default one if needed. */ -void -mm_broadband_modem_unlock_sms_storages (MMBroadbandModem *self, - gboolean mem1, - gboolean mem2) +static void +modem_messaging_unlock_storages (MMIfaceModemMessaging *_self, + gboolean mem1, + gboolean mem2) { + MMBroadbandModem *self = MM_BROADBAND_MODEM (_self); + if (mem1) { g_assert (self->priv->mem1_storage_locked); self->priv->mem1_storage_locked = FALSE; @@ -7201,10 +7203,10 @@ mm_broadband_modem_unlock_sms_storages (MMBroadbandModem *self, } } -gboolean -mm_broadband_modem_lock_sms_storages_finish (MMBroadbandModem *self, - GAsyncResult *res, - GError **error) +static gboolean +modem_messaging_lock_storages_finish (MMIfaceModemMessaging *self, + GAsyncResult *res, + GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } @@ -7246,13 +7248,14 @@ lock_storages_cpms_set_ready (MMBaseModem *_self, g_object_unref (task); } -void -mm_broadband_modem_lock_sms_storages (MMBroadbandModem *self, - MMSmsStorage mem1, /* reading/listing/deleting */ - MMSmsStorage mem2, /* storing/sending */ - GAsyncReadyCallback callback, - gpointer user_data) +static void +modem_messaging_lock_storages (MMIfaceModemMessaging *_self, + MMSmsStorage mem1, /* reading/listing/deleting */ + MMSmsStorage mem2, /* storing/sending */ + GAsyncReadyCallback callback, + gpointer user_data) { + MMBroadbandModem *self = MM_BROADBAND_MODEM (_self); LockSmsStoragesContext *ctx; GTask *task; gchar *cmd = NULL; @@ -7267,7 +7270,7 @@ mm_broadband_modem_lock_sms_storages (MMBroadbandModem *self, self, callback, user_data, - mm_broadband_modem_lock_sms_storages, + modem_messaging_lock_storages, MM_CORE_ERROR, MM_CORE_ERROR_RETRY, "SMS storage currently locked, try again later"); @@ -7547,7 +7550,7 @@ sms_part_ready (MMBroadbandModem *self, GError *error = NULL; /* Always always always unlock mem1 storage. Warned you've been. */ - mm_broadband_modem_unlock_sms_storages (self, TRUE, FALSE); + mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (self), TRUE, FALSE); response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (error) { @@ -7589,15 +7592,15 @@ sms_part_ready (MMBroadbandModem *self, } static void -indication_lock_storages_ready (MMBroadbandModem *self, - GAsyncResult *res, - GTask *task) +indication_lock_storages_ready (MMIfaceModemMessaging *messaging, + GAsyncResult *res, + GTask *task) { SmsPartContext *ctx; gchar *command; GError *error = NULL; - if (!mm_broadband_modem_lock_sms_storages_finish (self, res, &error)) { + if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { /* TODO: we should either make this lock() never fail, by automatically * retrying after some time, or otherwise retry here. */ g_task_return_error (task, error); @@ -7610,7 +7613,7 @@ indication_lock_storages_ready (MMBroadbandModem *self, /* Retrieve the message */ ctx = g_task_get_task_data (task); command = g_strdup_printf ("+CMGR=%d", ctx->idx); - mm_base_modem_at_command (MM_BASE_MODEM (self), + mm_base_modem_at_command (MM_BASE_MODEM (messaging), command, 10, FALSE, @@ -7658,11 +7661,11 @@ cmti_received (MMPortSerialAt *port, g_task_set_task_data (task, ctx, g_free); /* First, request to set the proper storage to read from */ - mm_broadband_modem_lock_sms_storages (self, - storage, - MM_SMS_STORAGE_UNKNOWN, - (GAsyncReadyCallback)indication_lock_storages_ready, - task); + mm_iface_modem_messaging_lock_storages (MM_IFACE_MODEM_MESSAGING (self), + storage, + MM_SMS_STORAGE_UNKNOWN, + (GAsyncReadyCallback)indication_lock_storages_ready, + task); } static void @@ -8120,7 +8123,7 @@ sms_pdu_part_list_ready (MMBroadbandModem *self, GList *l; /* Always always always unlock mem1 storage. Warned you've been. */ - mm_broadband_modem_unlock_sms_storages (self, TRUE, FALSE); + mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (self), TRUE, FALSE); response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (error) { @@ -8164,13 +8167,13 @@ sms_pdu_part_list_ready (MMBroadbandModem *self, } static void -list_parts_lock_storages_ready (MMBroadbandModem *self, - GAsyncResult *res, - GTask *task) +list_parts_lock_storages_ready (MMIfaceModemMessaging *self, + GAsyncResult *res, + GTask *task) { GError *error = NULL; - if (!mm_broadband_modem_lock_sms_storages_finish (self, res, &error)) { + if (!mm_iface_modem_messaging_lock_storages_finish (self, res, &error)) { /* TODO: we should either make this lock() never fail, by automatically * retrying after some time, or otherwise retry here. */ g_task_return_error (task, error); @@ -8212,11 +8215,11 @@ modem_messaging_load_initial_sms_parts (MMIfaceModemMessaging *self, mm_obj_dbg (self, "listing SMS parts in storage '%s'", mm_sms_storage_get_string (storage)); /* First, request to set the proper storage to read from */ - mm_broadband_modem_lock_sms_storages (MM_BROADBAND_MODEM (self), - storage, - MM_SMS_STORAGE_UNKNOWN, - (GAsyncReadyCallback)list_parts_lock_storages_ready, - task); + mm_iface_modem_messaging_lock_storages (self, + storage, + MM_SMS_STORAGE_UNKNOWN, + (GAsyncReadyCallback)list_parts_lock_storages_ready, + task); } /*****************************************************************************/ @@ -14541,6 +14544,9 @@ iface_modem_messaging_init (MMIfaceModemMessagingInterface *iface) 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; + iface->lock_storages = modem_messaging_lock_storages; + iface->lock_storages_finish = modem_messaging_lock_storages_finish; + iface->unlock_storages = modem_messaging_unlock_storages; } static void diff --git a/src/mm-broadband-modem.h b/src/mm-broadband-modem.h index f820e045..2370d78a 100644 --- a/src/mm-broadband-modem.h +++ b/src/mm-broadband-modem.h @@ -126,18 +126,6 @@ gchar *mm_broadband_modem_create_device_identifier (MMBroadbandModem *self, const gchar *ati1, GError **error); -/* Locking/unlocking SMS storages */ -void mm_broadband_modem_lock_sms_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, - gboolean mem1, - gboolean mem2); /* Helper to update SIM hot swap */ gboolean mm_broadband_modem_sim_hot_swap_ports_context_init (MMBroadbandModem *self, GError **error); diff --git a/src/mm-iface-modem-messaging.c b/src/mm-iface-modem-messaging.c index 581843c5..ef6b546c 100644 --- a/src/mm-iface-modem-messaging.c +++ b/src/mm-iface-modem-messaging.c @@ -101,6 +101,49 @@ mm_iface_modem_messaging_create_sms (MMIfaceModemMessaging *self) /*****************************************************************************/ +void +mm_iface_modem_messaging_lock_storages (MMIfaceModemMessaging *self, + MMSmsStorage mem1, + MMSmsStorage mem2, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_assert (MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->lock_storages != NULL); + + MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->lock_storages (self, + mem1, + mem2, + callback, + user_data); +} + +gboolean +mm_iface_modem_messaging_lock_storages_finish (MMIfaceModemMessaging *self, + GAsyncResult *res, + GError **error) + +{ + g_assert (MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->lock_storages_finish != NULL); + + return MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->lock_storages_finish (self, + res, + error); +} + +void +mm_iface_modem_messaging_unlock_storages (MMIfaceModemMessaging *self, + gboolean mem1, + gboolean mem2) +{ + g_assert (MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->unlock_storages != NULL); + + MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->unlock_storages (self, + mem1, + mem2); +} + +/*****************************************************************************/ + typedef struct { GArray *supported_mem1; GArray *supported_mem2; diff --git a/src/mm-iface-modem-messaging.h b/src/mm-iface-modem-messaging.h index 44cb077b..d341d3b0 100644 --- a/src/mm-iface-modem-messaging.h +++ b/src/mm-iface-modem-messaging.h @@ -78,6 +78,21 @@ struct _MMIfaceModemMessagingInterface { GAsyncResult *res, GError **error); + /* Lock storages (async) */ + void (*lock_storages) (MMIfaceModemMessaging *self, + MMSmsStorage mem1, /* reading/listing/deleting */ + MMSmsStorage mem2, /* storing/sending */ + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*lock_storages_finish) (MMIfaceModemMessaging *self, + GAsyncResult *res, + GError **error); + + /* Unlock storages */ + void (*unlock_storages) (MMIfaceModemMessaging *self, + gboolean mem1, + gboolean mem2); + /* Setup SMS format (async) */ void (* setup_sms_format) (MMIfaceModemMessaging *self, GAsyncReadyCallback callback, @@ -182,6 +197,19 @@ gboolean mm_iface_modem_messaging_is_storage_supported_for_receiving (MMIfaceMod /* SMS creation */ MMBaseSms *mm_iface_modem_messaging_create_sms (MMIfaceModemMessaging *self); +/* Locking/unlocking SMS storages */ +void mm_iface_modem_messaging_lock_storages (MMIfaceModemMessaging *self, + MMSmsStorage mem1, + MMSmsStorage mem2, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_messaging_lock_storages_finish (MMIfaceModemMessaging *self, + GAsyncResult *res, + GError **error); +void mm_iface_modem_messaging_unlock_storages (MMIfaceModemMessaging *self, + gboolean mem1, + gboolean mem2); + /* Look for a new valid multipart reference */ guint8 mm_iface_modem_messaging_get_local_multipart_reference (MMIfaceModemMessaging *self, const gchar *number, -- cgit v1.2.3-70-g09d2 From 6d0e4daf877e0600966bbf9fb34dfba14b2ccb54 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Apr 2025 08:12:35 -0500 Subject: base-bearer: remove unused include Signed-off-by: Dan Williams --- src/mm-base-bearer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mm-base-bearer.c b/src/mm-base-bearer.c index 7dadfff0..c2ab84cf 100644 --- a/src/mm-base-bearer.c +++ b/src/mm-base-bearer.c @@ -34,7 +34,6 @@ #include "mm-iface-modem-3gpp-profile-manager.h" #include "mm-iface-modem-cdma.h" #include "mm-base-bearer.h" -#include "mm-base-modem-at.h" #include "mm-base-modem.h" #include "mm-log-object.h" #include "mm-modem-helpers.h" -- cgit v1.2.3-70-g09d2 From 9830e3955a3e45ff82c1c76bcba3b53432eaa51e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Apr 2025 08:57:49 -0500 Subject: base-sms,sms-at: split AT-specific SMS code into MMSmsAt Simplify MMBaseSms (making it easier to use from testcases) by splitting the AT-specific code into MMSmsAt rather than keeping it in the base class. Signed-off-by: Dan Williams --- src/meson.build | 1 + src/mm-base-sms.c | 762 ------------------------------------------ src/mm-base-sms.h | 3 - src/mm-broadband-modem.c | 5 +- src/mm-sms-at.c | 835 +++++++++++++++++++++++++++++++++++++++++++++++ src/mm-sms-at.h | 59 ++++ 6 files changed, 898 insertions(+), 767 deletions(-) create mode 100644 src/mm-sms-at.c create mode 100644 src/mm-sms-at.h diff --git a/src/meson.build b/src/meson.build index c3242953..a9be07b0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -298,6 +298,7 @@ sources = files( 'mm-base-modem.c', 'mm-base-sim.c', 'mm-base-sms.c', + 'mm-sms-at.c', 'mm-bind.c', 'mm-bearer-list.c', 'mm-broadband-bearer.c', diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index 1b022614..d6c93d0c 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -32,8 +32,6 @@ #include "mm-iface-modem.h" #include "mm-iface-modem-messaging.h" #include "mm-sms-part-3gpp.h" -#include "mm-base-modem-at.h" -#include "mm-base-modem.h" #include "mm-log-object.h" #include "mm-modem-helpers.h" #include "mm-error-helpers.h" @@ -781,749 +779,6 @@ mm_base_sms_get_parts (MMBaseSms *self) /*****************************************************************************/ -static gboolean -sms_get_store_or_send_command (MMBaseSms *self, - MMSmsPart *part, - gboolean text_or_pdu, /* TRUE for PDU */ - gboolean store_or_send, /* TRUE for send */ - gchar **out_cmd, - gchar **out_msg_data, - GError **error) -{ - g_assert (out_cmd != NULL); - g_assert (out_msg_data != NULL); - - if (!text_or_pdu) { - /* Text mode */ - *out_cmd = g_strdup_printf ("+CMG%c=\"%s\"", - store_or_send ? 'S' : 'W', - mm_sms_part_get_number (part)); - *out_msg_data = g_strdup_printf ("%s\x1a", mm_sms_part_get_text (part)); - } else { - g_autofree gchar *hex = NULL; - g_autofree guint8 *pdu = NULL; - guint pdulen = 0; - guint msgstart = 0; - - /* AT+CMGW=[, ] PDU can be entered. / */ - - pdu = mm_sms_part_3gpp_get_submit_pdu (part, &pdulen, &msgstart, self, error); - if (!pdu) - /* 'error' should already be set */ - return FALSE; - - /* Convert PDU to hex */ - hex = mm_utils_bin2hexstr (pdu, pdulen); - if (!hex) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Not enough memory to send SMS PDU"); - return FALSE; - } - - /* CMGW/S length is the size of the PDU without SMSC information */ - *out_cmd = g_strdup_printf ("+CMG%c=%d", - store_or_send ? 'S' : 'W', - pdulen - msgstart); - *out_msg_data = g_strdup_printf ("%s\x1a", hex); - } - - return TRUE; -} - -/*****************************************************************************/ -/* Store the SMS */ - -typedef struct { - MMBaseModem *modem; - MMIfacePortAt *port; - MMSmsStorage storage; - gboolean need_unlock; - gboolean use_pdu_mode; - GList *current; - gchar *msg_data; -} SmsStoreContext; - -static void -sms_store_context_free (SmsStoreContext *ctx) -{ - /* Unlock mem2 storage if we had the lock */ - if (ctx->need_unlock) { - mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), - FALSE, - TRUE); - } - g_object_unref (ctx->port); - g_object_unref (ctx->modem); - g_free (ctx->msg_data); - g_slice_free (SmsStoreContext, ctx); -} - -static gboolean -sms_store_finish (MMBaseSms *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void sms_store_next_part (GTask *task); - -static void -store_msg_data_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - SmsStoreContext *ctx; - const gchar *response; - GError *error = NULL; - gint rv; - gint idx; - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Read the new part index from the reply */ - rv = sscanf (response, "+CMGW: %d", &idx); - if (rv != 1 || idx < 0) { - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't read index of already stored part: " - "%d fields parsed", - rv); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - /* Set the index in the part we hold */ - mm_sms_part_set_index ((MMSmsPart *)ctx->current->data, (guint)idx); - - ctx->current = g_list_next (ctx->current); - sms_store_next_part (task); -} - -static void -store_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - SmsStoreContext *ctx; - GError *error = NULL; - - mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - /* Send the actual message data. - * We send the data as 'raw' data because we do NOT want it to - * be treated as an AT command (i.e. we don't want it prefixed - * with AT+ and suffixed with ), plus, we want it to be - * sent right away (not queued after other AT commands). */ - mm_base_modem_at_command_full (ctx->modem, - ctx->port, - ctx->msg_data, - 10, - FALSE, - TRUE, /* raw */ - NULL, - (GAsyncReadyCallback)store_msg_data_ready, - task); -} - -static void -sms_store_next_part (GTask *task) -{ - MMBaseSms *self; - SmsStoreContext *ctx; - GError *error = NULL; - g_autofree gchar *cmd = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (!ctx->current) { - /* Done we are */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - g_clear_pointer (&ctx->msg_data, g_free); - - if (!sms_get_store_or_send_command (self, - (MMSmsPart *)ctx->current->data, - ctx->use_pdu_mode, - FALSE, - &cmd, - &ctx->msg_data, - &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_assert (cmd != NULL); - g_assert (ctx->msg_data != NULL); - - mm_base_modem_at_command_full (ctx->modem, - ctx->port, - cmd, - 10, - FALSE, - FALSE, /* raw */ - NULL, - (GAsyncReadyCallback)store_ready, - task); -} - -static void -store_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, - GAsyncResult *res, - GTask *task) -{ - MMBaseSms *self; - SmsStoreContext *ctx; - GError *error = NULL; - - if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* We are now locked. Whatever result we have here, we need to make sure - * we unlock the storages before finishing. */ - ctx->need_unlock = TRUE; - - /* Go on to store the parts */ - ctx->current = self->priv->parts; - sms_store_next_part (task); -} - -static void -sms_store (MMBaseSms *self, - MMSmsStorage storage, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SmsStoreContext *ctx; - GTask *task; - MMIfacePortAt *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 */ - ctx = g_slice_new0 (SmsStoreContext); - ctx->modem = g_object_ref (self->priv->modem); - ctx->port = g_object_ref (port); - ctx->storage = storage; - - /* Different ways to do it if on PDU or text mode */ - g_assert (MM_IS_IFACE_MODEM_MESSAGING (self->priv->modem)); - g_object_get (self->priv->modem, - MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &ctx->use_pdu_mode, - NULL); - g_task_set_task_data (task, ctx, (GDestroyNotify)sms_store_context_free); - - /* First, lock storage to use */ - mm_iface_modem_messaging_lock_storages ( - MM_IFACE_MODEM_MESSAGING (self->priv->modem), - MM_SMS_STORAGE_UNKNOWN, /* none required for mem1 */ - ctx->storage, - (GAsyncReadyCallback)store_lock_sms_storages_ready, - task); -} - -/*****************************************************************************/ -/* Send the SMS */ - -typedef struct { - MMBaseModem *modem; - MMIfacePortAt *port; - gboolean need_unlock; - gboolean from_storage; - gboolean use_pdu_mode; - GList *current; - gchar *msg_data; -} SmsSendContext; - -static void -sms_send_context_free (SmsSendContext *ctx) -{ - /* Unlock mem2 storage if we had the lock */ - if (ctx->need_unlock) { - mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), - FALSE, - TRUE); - } - g_object_unref (ctx->port); - g_object_unref (ctx->modem); - g_free (ctx->msg_data); - g_slice_free (SmsSendContext, ctx); -} - -static gboolean -sms_send_finish (MMBaseSms *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void sms_send_next_part (GTask *task); - -static gint -read_message_reference_from_reply (const gchar *response, - GError **error) -{ - gint rv = 0; - gint idx = -1; - - if (strstr (response, "+CMGS")) - rv = sscanf (strstr (response, "+CMGS"), "+CMGS: %d", &idx); - else if (strstr (response, "+CMSS")) - rv = sscanf (strstr (response, "+CMSS"), "+CMSS: %d", &idx); - - if (rv != 1 || idx < 0) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't read message reference: " - "%d fields parsed from response '%s'", - rv, response); - return -1; - } - - return idx; -} - -static void -send_generic_msg_data_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - SmsSendContext *ctx; - GError *error = NULL; - const gchar *response; - gint message_reference; - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - message_reference = read_message_reference_from_reply (response, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - mm_sms_part_set_message_reference ((MMSmsPart *)ctx->current->data, - (guint)message_reference); - - ctx->current = g_list_next (ctx->current); - sms_send_next_part (task); -} - -static void -send_generic_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - SmsSendContext *ctx; - GError *error = NULL; - - mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - ctx = g_task_get_task_data (task); - - /* Send the actual message data. - * We send the data as 'raw' data because we do NOT want it to - * be treated as an AT command (i.e. we don't want it prefixed - * with AT+ and suffixed with ), plus, we want it to be - * sent right away (not queued after other AT commands). */ - mm_base_modem_at_command_full (ctx->modem, - ctx->port, - ctx->msg_data, - MM_BASE_SMS_DEFAULT_SEND_TIMEOUT, - FALSE, - TRUE, /* raw */ - NULL, - (GAsyncReadyCallback)send_generic_msg_data_ready, - task); -} - -static void -send_from_storage_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBaseSms *self; - SmsSendContext *ctx; - GError *error = NULL; - const gchar *response; - gint message_reference; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - response = mm_base_modem_at_command_full_finish (modem, res, &error); - if (error) { - if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "couldn't send SMS from storage: %s; trying generic send...", error->message); - g_error_free (error); - - ctx->from_storage = FALSE; - sms_send_next_part (task); - return; - } - - message_reference = read_message_reference_from_reply (response, &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_sms_part_set_message_reference ((MMSmsPart *)ctx->current->data, - (guint)message_reference); - - ctx->current = g_list_next (ctx->current); - sms_send_next_part (task); -} - -static void -sms_send_next_part (GTask *task) -{ - MMBaseSms *self; - SmsSendContext *ctx; - GError *error = NULL; - g_autofree gchar *cmd = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - if (!ctx->current) { - /* Done we are */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Send from storage */ - if (ctx->from_storage) { - cmd = g_strdup_printf ("+CMSS=%d", mm_sms_part_get_index ((MMSmsPart *)ctx->current->data)); - mm_base_modem_at_command_full (ctx->modem, - ctx->port, - cmd, - MM_BASE_SMS_DEFAULT_SEND_TIMEOUT, - FALSE, - FALSE, - NULL, - (GAsyncReadyCallback)send_from_storage_ready, - task); - return; - } - - /* Generic send */ - - g_clear_pointer (&ctx->msg_data, g_free); - - if (!sms_get_store_or_send_command (self, - (MMSmsPart *)ctx->current->data, - ctx->use_pdu_mode, - TRUE, - &cmd, - &ctx->msg_data, - &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_assert (cmd != NULL); - g_assert (ctx->msg_data != NULL); - - /* no network involved in this initial AT command, so lower timeout */ - mm_base_modem_at_command_full (ctx->modem, - ctx->port, - cmd, - 10, - FALSE, - FALSE, /* raw */ - NULL, - (GAsyncReadyCallback)send_generic_ready, - task); -} - -static void -send_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, - GAsyncResult *res, - GTask *task) -{ - MMBaseSms *self; - SmsSendContext *ctx; - GError *error = NULL; - - if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* We are now locked. Whatever result we have here, we need to make sure - * we unlock the storages before finishing. */ - ctx->need_unlock = TRUE; - - /* Go on to send the parts */ - ctx->current = self->priv->parts; - sms_send_next_part (task); -} - -static void -sms_send (MMBaseSms *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SmsSendContext *ctx; - GTask *task; - MMIfacePortAt *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 */ - ctx = g_slice_new0 (SmsSendContext); - ctx->modem = g_object_ref (self->priv->modem); - ctx->port = g_object_ref (port); - g_task_set_task_data (task, ctx, (GDestroyNotify)sms_send_context_free); - - /* If the SMS is STORED, try to send from storage */ - ctx->from_storage = (mm_base_sms_get_storage (self) != MM_SMS_STORAGE_UNKNOWN); - if (ctx->from_storage) { - /* When sending from storage, first lock storage to use */ - g_assert (MM_IS_IFACE_MODEM_MESSAGING (self->priv->modem)); - mm_iface_modem_messaging_lock_storages ( - MM_IFACE_MODEM_MESSAGING (self->priv->modem), - MM_SMS_STORAGE_UNKNOWN, /* none required for mem1 */ - mm_base_sms_get_storage (self), - (GAsyncReadyCallback)send_lock_sms_storages_ready, - task); - return; - } - - /* Different ways to do it if on PDU or text mode */ - g_object_get (self->priv->modem, - MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &ctx->use_pdu_mode, - NULL); - ctx->current = self->priv->parts; - sms_send_next_part (task); -} - -/*****************************************************************************/ - -typedef struct { - MMBaseModem *modem; - gboolean need_unlock; - GList *current; - guint n_failed; -} SmsDeletePartsContext; - -static void -sms_delete_parts_context_free (SmsDeletePartsContext *ctx) -{ - /* Unlock mem1 storage if we had the lock */ - if (ctx->need_unlock) { - mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), - TRUE, - FALSE); - } - g_object_unref (ctx->modem); - g_slice_free (SmsDeletePartsContext, ctx); -} - -static gboolean -sms_delete_finish (MMBaseSms *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void delete_next_part (GTask *task); - -static void -delete_part_ready (MMBaseModem *modem, - GAsyncResult *res, - GTask *task) -{ - MMBaseSms *self; - SmsDeletePartsContext *ctx; - g_autoptr(GError) error = NULL; - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - mm_base_modem_at_command_finish (modem, res, &error); - if (error) { - ctx->n_failed++; - mm_obj_dbg (self, "couldn't delete SMS part with index %u: %s", - mm_sms_part_get_index ((MMSmsPart *)ctx->current->data), - error->message); - } - - /* We reset the index, as there is no longer that part */ - mm_sms_part_set_index ((MMSmsPart *)ctx->current->data, SMS_PART_INVALID_INDEX); - - ctx->current = g_list_next (ctx->current); - delete_next_part (task); -} - -static void -delete_next_part (GTask *task) -{ - SmsDeletePartsContext *ctx; - g_autofree gchar *cmd = NULL; - - ctx = g_task_get_task_data (task); - - /* Skip non-stored parts */ - while (ctx->current && (mm_sms_part_get_index ((MMSmsPart *)ctx->current->data) == SMS_PART_INVALID_INDEX)) - ctx->current = g_list_next (ctx->current); - - /* If all removed, we're done */ - if (!ctx->current) { - if (ctx->n_failed > 0) - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't delete %u parts from this SMS", - ctx->n_failed); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - cmd = g_strdup_printf ("+CMGD=%d", mm_sms_part_get_index ((MMSmsPart *)ctx->current->data)); - mm_base_modem_at_command (ctx->modem, - cmd, - 10, - FALSE, - (GAsyncReadyCallback)delete_part_ready, - task); -} - -static void -delete_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, - GAsyncResult *res, - GTask *task) -{ - MMBaseSms *self; - SmsDeletePartsContext *ctx; - GError *error = NULL; - - if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - - /* We are now locked. Whatever result we have here, we need to make sure - * we unlock the storages before finishing. */ - ctx->need_unlock = TRUE; - - /* Go on deleting parts */ - ctx->current = self->priv->parts; - delete_next_part (task); -} - -static void -sms_delete (MMBaseSms *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SmsDeletePartsContext *ctx; - GTask *task; - - ctx = g_slice_new0 (SmsDeletePartsContext); - ctx->modem = g_object_ref (self->priv->modem); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)sms_delete_parts_context_free); - - if (mm_base_sms_get_storage (self) == MM_SMS_STORAGE_UNKNOWN) { - mm_obj_dbg (self, "not removing parts from non-stored SMS"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - /* Select specific storage to delete from */ - mm_iface_modem_messaging_lock_storages ( - MM_IFACE_MODEM_MESSAGING (self->priv->modem), - mm_base_sms_get_storage (self), - MM_SMS_STORAGE_UNKNOWN, /* none required for mem2 */ - (GAsyncReadyCallback)delete_lock_sms_storages_ready, - task); -} - -/*****************************************************************************/ - gboolean mm_base_sms_delete_finish (MMBaseSms *self, GAsyncResult *res, @@ -1796,16 +1051,6 @@ mm_base_sms_multipart_take_part (MMBaseSms *self, return TRUE; } -MMBaseSms * -mm_base_sms_new (MMBaseModem *modem, gboolean is_3gpp) -{ - return MM_BASE_SMS (g_object_new (MM_TYPE_BASE_SMS, - MM_BASE_SMS_MODEM, modem, - MM_BIND_TO, modem, - MM_BASE_SMS_IS_3GPP, is_3gpp, - NULL)); -} - MMBaseSms * mm_base_sms_singlepart_new (MMBaseModem *modem, MMSmsState state, @@ -2139,13 +1384,6 @@ mm_base_sms_class_init (MMBaseSmsClass *klass) object_class->finalize = finalize; object_class->dispose = dispose; - klass->store = sms_store; - klass->store_finish = sms_store_finish; - klass->send = sms_send; - klass->send_finish = sms_send_finish; - klass->delete = sms_delete; - klass->delete_finish = sms_delete_finish; - properties[PROP_CONNECTION] = g_param_spec_object (MM_BASE_SMS_CONNECTION, "Connection", diff --git a/src/mm-base-sms.h b/src/mm-base-sms.h index ffcaf8c4..5fceb719 100644 --- a/src/mm-base-sms.h +++ b/src/mm-base-sms.h @@ -91,9 +91,6 @@ struct _MMBaseSmsClass { GType mm_base_sms_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseSms, g_object_unref) -/* This one can be overridden by plugins */ -MMBaseSms *mm_base_sms_new (MMBaseModem *modem, - gboolean is_3gpp); MMBaseSms *mm_base_sms_new_from_properties (MMBaseModem *modem, MMSmsProperties *properties, GError **error); diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index dbcc61a9..cb01676d 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -52,6 +52,7 @@ #include "mm-cbm-part.h" #include "mm-sms-list.h" #include "mm-sms-part-3gpp.h" +#include "mm-sms-at.h" #include "mm-call-list.h" #include "mm-base-sim.h" #include "mm-log-object.h" @@ -8228,8 +8229,8 @@ modem_messaging_load_initial_sms_parts (MMIfaceModemMessaging *self, static MMBaseSms * modem_messaging_create_sms (MMIfaceModemMessaging *self) { - return mm_base_sms_new (MM_BASE_MODEM (self), - mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); + return mm_sms_at_new (MM_BASE_MODEM (self), + mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); } /*****************************************************************************/ diff --git a/src/mm-sms-at.c b/src/mm-sms-at.c new file mode 100644 index 00000000..3fc7c155 --- /dev/null +++ b/src/mm-sms-at.c @@ -0,0 +1,835 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2008 - 2009 Novell, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. + * Copyright (C) 2012 Google, Inc. + * Copyright (C) 2025 Dan Williams + */ + +#include +#include +#include +#include +#include +#include + +#include +#define _LIBMM_INSIDE_MM +#include + +#include "mm-sms-at.h" +#include "mm-iface-modem-messaging.h" +#include "mm-sms-part-3gpp.h" +#include "mm-base-modem-at.h" +#include "mm-log-object.h" + +G_DEFINE_TYPE (MMSmsAt, mm_sms_at, MM_TYPE_BASE_SMS) + +struct _MMSmsAtPrivate { + MMBaseModem *modem; +}; + +/*****************************************************************************/ + +static gboolean +sms_get_store_or_send_command (MMSmsAt *self, + MMSmsPart *part, + gboolean text_or_pdu, /* TRUE for PDU */ + gboolean store_or_send, /* TRUE for send */ + gchar **out_cmd, + gchar **out_msg_data, + GError **error) +{ + g_assert (out_cmd != NULL); + g_assert (out_msg_data != NULL); + + if (!text_or_pdu) { + /* Text mode */ + *out_cmd = g_strdup_printf ("+CMG%c=\"%s\"", + store_or_send ? 'S' : 'W', + mm_sms_part_get_number (part)); + *out_msg_data = g_strdup_printf ("%s\x1a", mm_sms_part_get_text (part)); + } else { + g_autofree gchar *hex = NULL; + g_autofree guint8 *pdu = NULL; + guint pdulen = 0; + guint msgstart = 0; + + /* AT+CMGW=[, ] PDU can be entered. / */ + + pdu = mm_sms_part_3gpp_get_submit_pdu (part, &pdulen, &msgstart, self, error); + if (!pdu) + /* 'error' should already be set */ + return FALSE; + + /* Convert PDU to hex */ + hex = mm_utils_bin2hexstr (pdu, pdulen); + if (!hex) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Not enough memory to send SMS PDU"); + return FALSE; + } + + /* CMGW/S length is the size of the PDU without SMSC information */ + *out_cmd = g_strdup_printf ("+CMG%c=%d", + store_or_send ? 'S' : 'W', + pdulen - msgstart); + *out_msg_data = g_strdup_printf ("%s\x1a", hex); + } + + return TRUE; +} + +/*****************************************************************************/ +/* Store the SMS */ + +typedef struct { + MMBaseModem *modem; + MMIfacePortAt *port; + MMSmsStorage storage; + gboolean need_unlock; + gboolean use_pdu_mode; + GList *current; + gchar *msg_data; +} SmsStoreContext; + +static void +sms_store_context_free (SmsStoreContext *ctx) +{ + /* Unlock mem2 storage if we had the lock */ + if (ctx->need_unlock) { + mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), + FALSE, + TRUE); + } + g_object_unref (ctx->port); + g_object_unref (ctx->modem); + g_free (ctx->msg_data); + g_slice_free (SmsStoreContext, ctx); +} + +static gboolean +sms_store_finish (MMBaseSms *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void sms_store_next_part (GTask *task); + +static void +store_msg_data_ready (MMBaseModem *modem, + GAsyncResult *res, + GTask *task) +{ + SmsStoreContext *ctx; + const gchar *response; + GError *error = NULL; + gint rv; + gint idx; + + response = mm_base_modem_at_command_full_finish (modem, res, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + /* Read the new part index from the reply */ + rv = sscanf (response, "+CMGW: %d", &idx); + if (rv != 1 || idx < 0) { + g_task_return_new_error (task, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't read index of already stored part: " + "%d fields parsed", + rv); + g_object_unref (task); + return; + } + + ctx = g_task_get_task_data (task); + + /* Set the index in the part we hold */ + mm_sms_part_set_index ((MMSmsPart *)ctx->current->data, (guint)idx); + + ctx->current = g_list_next (ctx->current); + sms_store_next_part (task); +} + +static void +store_ready (MMBaseModem *modem, + GAsyncResult *res, + GTask *task) +{ + SmsStoreContext *ctx; + GError *error = NULL; + + mm_base_modem_at_command_full_finish (modem, res, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + ctx = g_task_get_task_data (task); + + /* Send the actual message data. + * We send the data as 'raw' data because we do NOT want it to + * be treated as an AT command (i.e. we don't want it prefixed + * with AT+ and suffixed with ), plus, we want it to be + * sent right away (not queued after other AT commands). */ + mm_base_modem_at_command_full (ctx->modem, + ctx->port, + ctx->msg_data, + 10, + FALSE, + TRUE, /* raw */ + NULL, + (GAsyncReadyCallback)store_msg_data_ready, + task); +} + +static void +sms_store_next_part (GTask *task) +{ + MMSmsAt *self; + SmsStoreContext *ctx; + GError *error = NULL; + g_autofree gchar *cmd = NULL; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + if (!ctx->current) { + /* Done we are */ + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + g_clear_pointer (&ctx->msg_data, g_free); + + if (!sms_get_store_or_send_command (self, + (MMSmsPart *)ctx->current->data, + ctx->use_pdu_mode, + FALSE, + &cmd, + &ctx->msg_data, + &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_assert (cmd != NULL); + g_assert (ctx->msg_data != NULL); + + mm_base_modem_at_command_full (ctx->modem, + ctx->port, + cmd, + 10, + FALSE, + FALSE, /* raw */ + NULL, + (GAsyncReadyCallback)store_ready, + task); +} + +static void +store_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, + GAsyncResult *res, + GTask *task) +{ + MMSmsAt *self; + SmsStoreContext *ctx; + GError *error = NULL; + + if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + /* We are now locked. Whatever result we have here, we need to make sure + * we unlock the storages before finishing. */ + ctx->need_unlock = TRUE; + + /* Go on to store the parts */ + ctx->current = mm_base_sms_get_parts (MM_BASE_SMS (self)); + sms_store_next_part (task); +} + +static void +sms_store (MMBaseSms *sms, + MMSmsStorage storage, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMSmsAt *self = MM_SMS_AT (sms); + SmsStoreContext *ctx; + GTask *task; + MMIfacePortAt *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 */ + ctx = g_slice_new0 (SmsStoreContext); + ctx->modem = g_object_ref (self->priv->modem); + ctx->port = g_object_ref (port); + ctx->storage = storage; + + /* Different ways to do it if on PDU or text mode */ + g_assert (MM_IS_IFACE_MODEM_MESSAGING (self->priv->modem)); + g_object_get (self->priv->modem, + MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &ctx->use_pdu_mode, + NULL); + g_task_set_task_data (task, ctx, (GDestroyNotify)sms_store_context_free); + + /* First, lock storage to use */ + mm_iface_modem_messaging_lock_storages ( + MM_IFACE_MODEM_MESSAGING (self->priv->modem), + MM_SMS_STORAGE_UNKNOWN, /* none required for mem1 */ + ctx->storage, + (GAsyncReadyCallback)store_lock_sms_storages_ready, + task); +} + +/*****************************************************************************/ +/* Send the SMS */ + +typedef struct { + MMBaseModem *modem; + MMIfacePortAt *port; + gboolean need_unlock; + gboolean from_storage; + gboolean use_pdu_mode; + GList *current; + gchar *msg_data; +} SmsSendContext; + +static void +sms_send_context_free (SmsSendContext *ctx) +{ + /* Unlock mem2 storage if we had the lock */ + if (ctx->need_unlock) { + mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), + FALSE, + TRUE); + } + g_object_unref (ctx->port); + g_object_unref (ctx->modem); + g_free (ctx->msg_data); + g_slice_free (SmsSendContext, ctx); +} + +static gboolean +sms_send_finish (MMBaseSms *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void sms_send_next_part (GTask *task); + +static gint +read_message_reference_from_reply (const gchar *response, + GError **error) +{ + gint rv = 0; + gint idx = -1; + + if (strstr (response, "+CMGS")) + rv = sscanf (strstr (response, "+CMGS"), "+CMGS: %d", &idx); + else if (strstr (response, "+CMSS")) + rv = sscanf (strstr (response, "+CMSS"), "+CMSS: %d", &idx); + + if (rv != 1 || idx < 0) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't read message reference: " + "%d fields parsed from response '%s'", + rv, response); + return -1; + } + + return idx; +} + +static void +send_generic_msg_data_ready (MMBaseModem *modem, + GAsyncResult *res, + GTask *task) +{ + SmsSendContext *ctx; + GError *error = NULL; + const gchar *response; + gint message_reference; + + response = mm_base_modem_at_command_full_finish (modem, res, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + message_reference = read_message_reference_from_reply (response, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + ctx = g_task_get_task_data (task); + + mm_sms_part_set_message_reference ((MMSmsPart *)ctx->current->data, + (guint)message_reference); + + ctx->current = g_list_next (ctx->current); + sms_send_next_part (task); +} + +static void +send_generic_ready (MMBaseModem *modem, + GAsyncResult *res, + GTask *task) +{ + SmsSendContext *ctx; + GError *error = NULL; + + mm_base_modem_at_command_full_finish (modem, res, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + ctx = g_task_get_task_data (task); + + /* Send the actual message data. + * We send the data as 'raw' data because we do NOT want it to + * be treated as an AT command (i.e. we don't want it prefixed + * with AT+ and suffixed with ), plus, we want it to be + * sent right away (not queued after other AT commands). */ + mm_base_modem_at_command_full (ctx->modem, + ctx->port, + ctx->msg_data, + MM_BASE_SMS_DEFAULT_SEND_TIMEOUT, + FALSE, + TRUE, /* raw */ + NULL, + (GAsyncReadyCallback)send_generic_msg_data_ready, + task); +} + +static void +send_from_storage_ready (MMBaseModem *modem, + GAsyncResult *res, + GTask *task) +{ + MMSmsAt *self; + SmsSendContext *ctx; + GError *error = NULL; + const gchar *response; + gint message_reference; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + response = mm_base_modem_at_command_full_finish (modem, res, &error); + if (error) { + if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + mm_obj_dbg (self, "couldn't send SMS from storage: %s; trying generic send...", error->message); + g_error_free (error); + + ctx->from_storage = FALSE; + sms_send_next_part (task); + return; + } + + message_reference = read_message_reference_from_reply (response, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + mm_sms_part_set_message_reference ((MMSmsPart *)ctx->current->data, + (guint)message_reference); + + ctx->current = g_list_next (ctx->current); + sms_send_next_part (task); +} + +static void +sms_send_next_part (GTask *task) +{ + MMSmsAt *self; + SmsSendContext *ctx; + GError *error = NULL; + g_autofree gchar *cmd = NULL; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + if (!ctx->current) { + /* Done we are */ + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + /* Send from storage */ + if (ctx->from_storage) { + cmd = g_strdup_printf ("+CMSS=%d", mm_sms_part_get_index ((MMSmsPart *)ctx->current->data)); + mm_base_modem_at_command_full (ctx->modem, + ctx->port, + cmd, + MM_BASE_SMS_DEFAULT_SEND_TIMEOUT, + FALSE, + FALSE, + NULL, + (GAsyncReadyCallback)send_from_storage_ready, + task); + return; + } + + /* Generic send */ + + g_clear_pointer (&ctx->msg_data, g_free); + + if (!sms_get_store_or_send_command (self, + (MMSmsPart *)ctx->current->data, + ctx->use_pdu_mode, + TRUE, + &cmd, + &ctx->msg_data, + &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_assert (cmd != NULL); + g_assert (ctx->msg_data != NULL); + + /* no network involved in this initial AT command, so lower timeout */ + mm_base_modem_at_command_full (ctx->modem, + ctx->port, + cmd, + 10, + FALSE, + FALSE, /* raw */ + NULL, + (GAsyncReadyCallback)send_generic_ready, + task); +} + +static void +send_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, + GAsyncResult *res, + GTask *task) +{ + MMSmsAt *self; + SmsSendContext *ctx; + GError *error = NULL; + + if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + /* We are now locked. Whatever result we have here, we need to make sure + * we unlock the storages before finishing. */ + ctx->need_unlock = TRUE; + + /* Go on to send the parts */ + ctx->current = mm_base_sms_get_parts (MM_BASE_SMS (self)); + sms_send_next_part (task); +} + +static void +sms_send (MMBaseSms *sms, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMSmsAt *self = MM_SMS_AT (sms); + SmsSendContext *ctx; + GTask *task; + MMIfacePortAt *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 */ + ctx = g_slice_new0 (SmsSendContext); + ctx->modem = g_object_ref (self->priv->modem); + ctx->port = g_object_ref (port); + g_task_set_task_data (task, ctx, (GDestroyNotify)sms_send_context_free); + + /* If the SMS is STORED, try to send from storage */ + ctx->from_storage = (mm_base_sms_get_storage (MM_BASE_SMS (self)) != MM_SMS_STORAGE_UNKNOWN); + if (ctx->from_storage) { + /* When sending from storage, first lock storage to use */ + g_assert (MM_IS_IFACE_MODEM_MESSAGING (self->priv->modem)); + mm_iface_modem_messaging_lock_storages ( + MM_IFACE_MODEM_MESSAGING (self->priv->modem), + MM_SMS_STORAGE_UNKNOWN, /* none required for mem1 */ + mm_base_sms_get_storage (MM_BASE_SMS (self)), + (GAsyncReadyCallback)send_lock_sms_storages_ready, + task); + return; + } + + /* Different ways to do it if on PDU or text mode */ + g_object_get (self->priv->modem, + MM_IFACE_MODEM_MESSAGING_SMS_PDU_MODE, &ctx->use_pdu_mode, + NULL); + ctx->current = mm_base_sms_get_parts (MM_BASE_SMS (self)); + sms_send_next_part (task); +} + +/*****************************************************************************/ + +typedef struct { + MMBaseModem *modem; + gboolean need_unlock; + GList *current; + guint n_failed; +} SmsDeletePartsContext; + +static void +sms_delete_parts_context_free (SmsDeletePartsContext *ctx) +{ + /* Unlock mem1 storage if we had the lock */ + if (ctx->need_unlock) { + mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (ctx->modem), + TRUE, + FALSE); + } + g_object_unref (ctx->modem); + g_slice_free (SmsDeletePartsContext, ctx); +} + +static gboolean +sms_delete_finish (MMBaseSms *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void delete_next_part (GTask *task); + +static void +delete_part_ready (MMBaseModem *modem, + GAsyncResult *res, + GTask *task) +{ + MMSmsAt *self; + SmsDeletePartsContext *ctx; + g_autoptr(GError) error = NULL; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + mm_base_modem_at_command_finish (modem, res, &error); + if (error) { + ctx->n_failed++; + mm_obj_dbg (self, "couldn't delete SMS part with index %u: %s", + mm_sms_part_get_index ((MMSmsPart *)ctx->current->data), + error->message); + } + + /* We reset the index, as there is no longer that part */ + mm_sms_part_set_index ((MMSmsPart *)ctx->current->data, SMS_PART_INVALID_INDEX); + + ctx->current = g_list_next (ctx->current); + delete_next_part (task); +} + +static void +delete_next_part (GTask *task) +{ + SmsDeletePartsContext *ctx; + g_autofree gchar *cmd = NULL; + + ctx = g_task_get_task_data (task); + + /* Skip non-stored parts */ + while (ctx->current && (mm_sms_part_get_index ((MMSmsPart *)ctx->current->data) == SMS_PART_INVALID_INDEX)) + ctx->current = g_list_next (ctx->current); + + /* If all removed, we're done */ + if (!ctx->current) { + if (ctx->n_failed > 0) + g_task_return_new_error (task, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't delete %u parts from this SMS", + ctx->n_failed); + else + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + cmd = g_strdup_printf ("+CMGD=%d", mm_sms_part_get_index ((MMSmsPart *)ctx->current->data)); + mm_base_modem_at_command (ctx->modem, + cmd, + 10, + FALSE, + (GAsyncReadyCallback)delete_part_ready, + task); +} + +static void +delete_lock_sms_storages_ready (MMIfaceModemMessaging *messaging, + GAsyncResult *res, + GTask *task) +{ + MMSmsAt *self; + SmsDeletePartsContext *ctx; + GError *error = NULL; + + if (!mm_iface_modem_messaging_lock_storages_finish (messaging, res, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + /* We are now locked. Whatever result we have here, we need to make sure + * we unlock the storages before finishing. */ + ctx->need_unlock = TRUE; + + /* Go on deleting parts */ + ctx->current = mm_base_sms_get_parts (MM_BASE_SMS (self)); + delete_next_part (task); +} + +static void +sms_delete (MMBaseSms *sms, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMSmsAt *self = MM_SMS_AT (sms); + SmsDeletePartsContext *ctx; + GTask *task; + + ctx = g_slice_new0 (SmsDeletePartsContext); + ctx->modem = g_object_ref (self->priv->modem); + + task = g_task_new (self, NULL, callback, user_data); + g_task_set_task_data (task, ctx, (GDestroyNotify)sms_delete_parts_context_free); + + if (mm_base_sms_get_storage (MM_BASE_SMS (self)) == MM_SMS_STORAGE_UNKNOWN) { + mm_obj_dbg (self, "not removing parts from non-stored SMS"); + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + /* Select specific storage to delete from */ + mm_iface_modem_messaging_lock_storages ( + MM_IFACE_MODEM_MESSAGING (self->priv->modem), + mm_base_sms_get_storage (MM_BASE_SMS (self)), + MM_SMS_STORAGE_UNKNOWN, /* none required for mem2 */ + (GAsyncReadyCallback)delete_lock_sms_storages_ready, + task); +} + +/*****************************************************************************/ + +MMBaseSms * +mm_sms_at_new (MMBaseModem *modem, gboolean is_3gpp) +{ + MMBaseSms *sms; + + sms = MM_BASE_SMS (g_object_new (MM_TYPE_SMS_AT, + MM_BASE_SMS_MODEM, modem, + MM_BASE_SMS_IS_3GPP, is_3gpp, + NULL)); + MM_SMS_AT (sms)->priv->modem = g_object_ref (modem); + return sms; +} + +static void +mm_sms_at_init (MMSmsAt *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_SMS_AT, MMSmsAtPrivate); +} + +static void +dispose (GObject *object) +{ + MMSmsAt *self = MM_SMS_AT (object); + + g_clear_object (&self->priv->modem); + + G_OBJECT_CLASS (mm_sms_at_parent_class)->dispose (object); +} + +static void +mm_sms_at_class_init (MMSmsAtClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMBaseSmsClass *base_sms_class = MM_BASE_SMS_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (MMSmsAtPrivate)); + + object_class->dispose = dispose; + + base_sms_class->store = sms_store; + base_sms_class->store_finish = sms_store_finish; + base_sms_class->send = sms_send; + base_sms_class->send_finish = sms_send_finish; + base_sms_class->delete = sms_delete; + base_sms_class->delete_finish = sms_delete_finish; +} diff --git a/src/mm-sms-at.h b/src/mm-sms-at.h new file mode 100644 index 00000000..26e2dae4 --- /dev/null +++ b/src/mm-sms-at.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Author: Aleksander Morgado + * + * Copyright (C) 2012 Google, Inc. + * Copyright (C) 2025 Dan Williams + */ + +#ifndef MM_SMS_AT_H +#define MM_SMS_AT_H + +#include +#include + +#define _LIBMM_INSIDE_MM +#include + +#include "mm-base-sms.h" +#include "mm-base-modem.h" + +/*****************************************************************************/ + +#define MM_TYPE_SMS_AT (mm_sms_at_get_type ()) +#define MM_SMS_AT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SMS_AT, MMSmsAt)) +#define MM_SMS_AT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SMS_AT, MMSmsAtClass)) +#define MM_IS_SMS_AT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SMS_AT)) +#define MM_IS_SMS_AT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SMS_AT)) +#define MM_SMS_AT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SMS_AT, MMSmsAtClass)) + +typedef struct _MMSmsAt MMSmsAt; +typedef struct _MMSmsAtClass MMSmsAtClass; +typedef struct _MMSmsAtPrivate MMSmsAtPrivate; + +struct _MMSmsAt { + MMBaseSms parent; + MMSmsAtPrivate *priv; +}; + +struct _MMSmsAtClass { + MMBaseSmsClass parent; +}; + +GType mm_sms_at_get_type (void); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSmsAt, g_object_unref) + +MMBaseSms *mm_sms_at_new (MMBaseModem *modem, + gboolean is_3gpp); + +#endif /* MM_SMS_AT_H */ -- cgit v1.2.3-70-g09d2 From b81f23e24aad7d4fb37e837bbdcab4f43bccfc71 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Apr 2025 10:30:58 -0500 Subject: base-sms,sms-list,iface-messaging: move MMBaseSms creation to MMBroadbandModem class This commit moves creation of the MMBaseSms objects out of MMSmsList and up into MMIfaceModemMessaging (which is already a MMBroadbandModem) and the MMBroadbandModem subclasses themselves. This flattens the creation of MMBaseSms objects by passing them down from the object that creates the SMS parts, rather than having a convoluted callback scheme relying on MMSmsList and MMBaseSms having direct knowledge of their owning modem. The goal is to eventually remove usage of MMBaseModem from MMBaseSms and MMSmsList so that we can test them more easily. Signed-off-by: Dan Williams --- src/mm-base-sms.c | 83 ++++++++++++++++---------------- src/mm-base-sms.h | 34 ++++++++------ src/mm-broadband-modem-mbim.c | 43 ++++++++++------- src/mm-broadband-modem-qmi.c | 33 +++++++------ src/mm-broadband-modem.c | 104 ++++++++++++++++++++++++++--------------- src/mm-broadband-modem.h | 7 +++ src/mm-iface-modem-messaging.c | 37 +++++++-------- src/mm-iface-modem-messaging.h | 13 +++--- src/mm-sms-list.c | 26 +++++------ src/mm-sms-list.h | 1 + 10 files changed, 216 insertions(+), 165 deletions(-) diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index d6c93d0c..daf7fb67 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -61,6 +61,8 @@ enum { static GParamSpec *properties[PROP_LAST]; struct _MMBaseSmsPrivate { + gboolean initialized; + /* The connection to the system bus */ GDBusConnection *connection; guint dbus_id; @@ -1051,19 +1053,17 @@ mm_base_sms_multipart_take_part (MMBaseSms *self, return TRUE; } -MMBaseSms * -mm_base_sms_singlepart_new (MMBaseModem *modem, - MMSmsState state, - MMSmsStorage storage, - MMSmsPart *part, - GError **error) +gboolean +mm_base_sms_singlepart_init (MMBaseSms *self, + MMBaseModem *modem, + MMSmsState state, + MMSmsStorage storage, + MMSmsPart *part, + GError **error) { - MMBaseSms *self; - g_assert (MM_IS_IFACE_MODEM_MESSAGING (modem)); + g_assert (self->priv->initialized == FALSE); - /* Create an SMS object as defined by the interface */ - self = mm_iface_modem_messaging_create_sms (MM_IFACE_MODEM_MESSAGING (modem)); g_object_set (self, "state", state, "storage", storage, @@ -1079,34 +1079,33 @@ mm_base_sms_singlepart_new (MMBaseModem *modem, /* Note: we need to remove the part from the list, as we really didn't * take it, and therefore the caller is responsible for freeing it. */ self->priv->parts = g_list_remove (self->priv->parts, part); - g_clear_object (&self); - } else - /* Only export once properly created */ - mm_base_sms_export (self); + return FALSE; + } - return self; + /* Only export once properly created */ + self->priv->initialized = TRUE; + mm_base_sms_export (self); + return TRUE; } -MMBaseSms * -mm_base_sms_multipart_new (MMBaseModem *modem, - MMSmsState state, - MMSmsStorage storage, - guint reference, - guint max_parts, - MMSmsPart *first_part, - GError **error) +gboolean +mm_base_sms_multipart_init (MMBaseSms *self, + MMBaseModem *modem, + MMSmsState state, + MMSmsStorage storage, + guint reference, + guint max_parts, + MMSmsPart *first_part, + GError **error) { - MMBaseSms *self; - g_assert (MM_IS_IFACE_MODEM_MESSAGING (modem)); + g_assert (self->priv->initialized == FALSE); /* If this is the first part of a RECEIVED SMS, we overwrite the state * as RECEIVING, to indicate that it is not completed yet. */ if (state == MM_SMS_STATE_RECEIVED) state = MM_SMS_STATE_RECEIVING; - /* Create an SMS object as defined by the interface */ - self = mm_iface_modem_messaging_create_sms (MM_IFACE_MODEM_MESSAGING (modem)); g_object_set (self, MM_BASE_SMS_IS_MULTIPART, TRUE, MM_BASE_SMS_MAX_PARTS, max_parts, @@ -1120,29 +1119,30 @@ mm_base_sms_multipart_new (MMBaseModem *modem, NULL); if (!mm_base_sms_multipart_take_part (self, first_part, error)) - g_clear_object (&self); + return FALSE; /* We do export incomplete multipart messages, in order to be able to * request removal of all parts of those multipart SMS that will never * get completed. * Only the STATE of the SMS object will be valid in the exported DBus * interface.*/ - if (self) - mm_base_sms_export (self); + self->priv->initialized = TRUE; + mm_base_sms_export (self); - return self; + return TRUE; } -MMBaseSms * -mm_base_sms_new_from_properties (MMBaseModem *modem, - MMSmsProperties *props, - GError **error) +gboolean +mm_base_sms_init_from_properties (MMBaseSms *self, + MMBaseModem *modem, + MMSmsProperties *props, + GError **error) { - MMBaseSms *self; const gchar *text; GByteArray *data; g_assert (MM_IS_IFACE_MODEM_MESSAGING (modem)); + g_assert (self->priv->initialized == FALSE); text = mm_sms_properties_get_text (props); data = mm_sms_properties_peek_data_bytearray (props); @@ -1156,7 +1156,7 @@ mm_base_sms_new_from_properties (MMBaseModem *modem, "Cannot create SMS: mandatory parameter '%s' is missing", (!mm_sms_properties_get_number (props)? "number" : "text' or 'data")); - return NULL; + return FALSE; } /* Don't create SMS from properties if both text and data are given */ @@ -1165,11 +1165,9 @@ mm_base_sms_new_from_properties (MMBaseModem *modem, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, "Cannot create SMS: both 'text' and 'data' given"); - return NULL; + return FALSE; } - /* Create an SMS object as defined by the interface */ - self = mm_iface_modem_messaging_create_sms (MM_IFACE_MODEM_MESSAGING (modem)); g_object_set (self, "state", MM_SMS_STATE_UNKNOWN, "storage", MM_SMS_STORAGE_UNKNOWN, @@ -1197,10 +1195,11 @@ mm_base_sms_new_from_properties (MMBaseModem *modem, g_variant_new ("(uv)", MM_SMS_VALIDITY_TYPE_UNKNOWN, g_variant_new_boolean (FALSE))), NULL); - /* Only export once properly created */ + /* Only export once properly initialized */ + self->priv->initialized = TRUE; mm_base_sms_export (self); - return self; + return TRUE; } /*****************************************************************************/ diff --git a/src/mm-base-sms.h b/src/mm-base-sms.h index 5fceb719..22d25ebb 100644 --- a/src/mm-base-sms.h +++ b/src/mm-base-sms.h @@ -91,21 +91,25 @@ struct _MMBaseSmsClass { GType mm_base_sms_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseSms, g_object_unref) -MMBaseSms *mm_base_sms_new_from_properties (MMBaseModem *modem, - MMSmsProperties *properties, - GError **error); -MMBaseSms *mm_base_sms_singlepart_new (MMBaseModem *modem, - MMSmsState state, - MMSmsStorage storage, - MMSmsPart *part, - GError **error); -MMBaseSms *mm_base_sms_multipart_new (MMBaseModem *modem, - MMSmsState state, - MMSmsStorage storage, - guint reference, - guint max_parts, - MMSmsPart *first_part, - GError **error); +gboolean mm_base_sms_init_from_properties (MMBaseSms *self, + MMBaseModem *modem, + MMSmsProperties *properties, + GError **error); +gboolean mm_base_sms_singlepart_init (MMBaseSms *self, + MMBaseModem *modem, + MMSmsState state, + MMSmsStorage storage, + MMSmsPart *part, + GError **error); +gboolean mm_base_sms_multipart_init (MMBaseSms *self, + MMBaseModem *modem, + MMSmsState state, + MMSmsStorage storage, + guint reference, + guint max_parts, + MMSmsPart *first_part, + GError **error); + gboolean mm_base_sms_multipart_take_part (MMBaseSms *self, MMSmsPart *part, GError **error); diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 79de6291..91a18cb2 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -9035,24 +9035,33 @@ add_sms_part (MMBroadbandModemMbim *self, self, FALSE, &error); - if (part) { - mm_obj_dbg (self, "correctly parsed PDU (%d)", pdu->message_index); - if (expected_index != SMS_PART_INVALID_INDEX && (expected_index != mm_sms_part_get_index (part))) { - /* Some Fibocom L850 modems report an invalid part index (always 1) in the response - * message. Because we know which message part was requested, we can use that value - * instead to workaround this bug. */ - mm_obj_dbg (self, "Expected SMS part index '%u' but device reports index '%u': using the expected one", - expected_index, mm_sms_part_get_index (part)); - mm_sms_part_set_index (part, expected_index); - } - mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), - part, - mm_sms_state_from_mbim_message_status (pdu->message_status), - MM_SMS_STORAGE_MT); - } else { + if (!part) { /* Don't treat the error as critical */ mm_obj_dbg (self, "error parsing PDU (%d): %s", pdu->message_index, error->message); + return; + } + + mm_obj_dbg (self, "correctly parsed PDU (%d)", pdu->message_index); + if (expected_index != SMS_PART_INVALID_INDEX && (expected_index != mm_sms_part_get_index (part))) { + /* Some Fibocom L850 modems report an invalid part index (always 1) in the response + * message. Because we know which message part was requested, we can use that value + * instead to workaround this bug. */ + mm_obj_dbg (self, "Expected SMS part index '%u' but device reports index '%u': using the expected one", + expected_index, mm_sms_part_get_index (part)); + mm_sms_part_set_index (part, expected_index); + } + + if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), + mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)), + part, + mm_sms_state_from_mbim_message_status (pdu->message_status), + MM_SMS_STORAGE_MT, + &error)) { + /* Don't treat the error as critical */ + mm_obj_dbg (self, "error adding SMS (%d): %s", + pdu->message_index, error->message); + return; } } @@ -9231,7 +9240,7 @@ enable_unsolicited_events_messaging (MMIfaceModemMessaging *_self, /* Create SMS (Messaging interface) */ static MMBaseSms * -messaging_create_sms (MMIfaceModemMessaging *self) +messaging_create_sms (MMBroadbandModem *self) { return mm_sms_mbim_new (MM_BASE_MODEM (self), mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); @@ -10717,7 +10726,6 @@ iface_modem_messaging_init (MMIfaceModemMessagingInterface *iface) iface->enable_unsolicited_events_finish = common_enable_disable_unsolicited_events_messaging_finish; iface->disable_unsolicited_events = disable_unsolicited_events_messaging; iface->disable_unsolicited_events_finish = common_enable_disable_unsolicited_events_messaging_finish; - iface->create_sms = messaging_create_sms; } static void @@ -10787,6 +10795,7 @@ mm_broadband_modem_mbim_class_init (MMBroadbandModemMbimClass *klass) /* Do not initialize the MBIM modem through AT commands */ broadband_modem_class->enabling_modem_init = NULL; broadband_modem_class->enabling_modem_init_finish = NULL; + broadband_modem_class->create_sms = messaging_create_sms; #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED g_object_class_install_property (object_class, PROP_QMI_UNSUPPORTED, diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index d13e1995..6caccc21 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -7938,8 +7938,8 @@ add_new_read_sms_part (MMIfaceModemMessaging *self, gboolean transfer_route, GArray *data) { - MMSmsPart *part = NULL; - GError *error = NULL; + MMSmsPart *part = NULL; + g_autoptr(GError) error = NULL; switch (format) { case QMI_WMS_MESSAGE_FORMAT_CDMA: @@ -7967,16 +7967,21 @@ add_new_read_sms_part (MMIfaceModemMessaging *self, break; } - if (part) { - mm_obj_dbg (self, "correctly parsed PDU (%d)", index); - mm_iface_modem_messaging_take_part (self, - part, - mm_sms_state_from_qmi_message_tag (tag), - mm_sms_storage_from_qmi_storage_type (storage)); - } else if (error) { + if (!part) { /* Don't treat the error as critical */ mm_obj_dbg (self, "error parsing PDU (%d): %s", index, error->message); - g_error_free (error); + return; + } + + mm_obj_dbg (self, "correctly parsed PDU (%d)", index); + if (!mm_iface_modem_messaging_take_part (self, + mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)), + part, + mm_sms_state_from_qmi_message_tag (tag), + mm_sms_storage_from_qmi_storage_type (storage), + &error)) { + /* Don't treat the error as critical */ + mm_obj_dbg (self, "error adding SMS (%d): %s", index, error->message); } } @@ -8870,16 +8875,16 @@ messaging_enable_unsolicited_events (MMIfaceModemMessaging *_self, } /*****************************************************************************/ -/* Create SMS (Messaging interface) */ +/* Create SMS */ static MMBaseSms * -messaging_create_sms (MMIfaceModemMessaging *_self) +messaging_create_sms (MMBroadbandModem *_self) { MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self); /* Handle AT URC only fallback */ if (self->priv->messaging_fallback_at_only) { - return iface_modem_messaging_parent->create_sms (_self); + return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_qmi_parent_class)->create_sms (_self); } return mm_sms_qmi_new (MM_BASE_MODEM (self), @@ -15331,7 +15336,6 @@ iface_modem_messaging_init (MMIfaceModemMessagingInterface *iface) iface->enable_unsolicited_events_finish = messaging_enable_unsolicited_events_finish; iface->disable_unsolicited_events = messaging_disable_unsolicited_events; iface->disable_unsolicited_events_finish = messaging_disable_unsolicited_events_finish; - iface->create_sms = messaging_create_sms; iface->init_current_storages = messaging_init_current_storages; iface->init_current_storages_finish = messaging_init_current_storages_finish; } @@ -15470,4 +15474,5 @@ mm_broadband_modem_qmi_class_init (MMBroadbandModemQmiClass *klass) /* Do not initialize the QMI modem through AT commands */ broadband_modem_class->enabling_modem_init = NULL; broadband_modem_class->enabling_modem_init_finish = NULL; + broadband_modem_class->create_sms = messaging_create_sms; } diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index cb01676d..c29c9190 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -7545,10 +7545,10 @@ sms_part_ready (MMBroadbandModem *self, GTask *task) { SmsPartContext *ctx; - MMSmsPart *part; - MM3gppPduInfo *info; - const gchar *response; - GError *error = NULL; + MMSmsPart *part; + MM3gppPduInfo *info; + const gchar *response; + GError *error = NULL; /* Always always always unlock mem1 storage. Warned you've been. */ mm_iface_modem_messaging_unlock_storages (MM_IFACE_MODEM_MESSAGING (self), TRUE, FALSE); @@ -7574,16 +7574,22 @@ sms_part_ready (MMBroadbandModem *self, } part = mm_sms_part_3gpp_new_from_pdu (info->index, info->pdu, self, &error); - if (part) { - mm_obj_dbg (self, "correctly parsed PDU (%d)", ctx->idx); - mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), - part, - MM_SMS_STATE_RECEIVED, - self->priv->modem_messaging_sms_default_storage); - } else { + if (!part) { /* Don't treat the error as critical */ mm_obj_dbg (self, "error parsing PDU (%d): %s", ctx->idx, error->message); g_error_free (error); + } else { + mm_obj_dbg (self, "correctly parsed PDU (%d)", ctx->idx); + if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), + mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)), + part, + MM_SMS_STATE_RECEIVED, + self->priv->modem_messaging_sms_default_storage, + &error)) { + /* Don't treat the error as critical */ + mm_obj_dbg (self, "error adding SMS (%d): %s", ctx->idx, error->message); + g_error_free (error); + } } /* All done */ @@ -7674,10 +7680,10 @@ cds_received (MMPortSerialAt *port, GMatchInfo *info, MMBroadbandModem *self) { - GError *error = NULL; - MMSmsPart *part; - guint length; - gchar *pdu; + g_autoptr(GError) error = NULL; + MMSmsPart *part; + guint length; + gchar *pdu; mm_obj_dbg (self, "got new non-stored message indication"); @@ -7689,16 +7695,20 @@ cds_received (MMPortSerialAt *port, return; part = mm_sms_part_3gpp_new_from_pdu (SMS_PART_INVALID_INDEX, pdu, self, &error); - if (part) { - mm_obj_dbg (self, "correctly parsed non-stored PDU"); - mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), - part, - MM_SMS_STATE_RECEIVED, - MM_SMS_STORAGE_UNKNOWN); - } else { + if (!part) { /* Don't treat the error as critical */ mm_obj_dbg (self, "error parsing non-stored PDU: %s", error->message); - g_error_free (error); + } else { + mm_obj_dbg (self, "correctly parsed non-stored PDU"); + if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), + mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)), + part, + MM_SMS_STATE_RECEIVED, + MM_SMS_STORAGE_UNKNOWN, + &error)) { + /* Don't treat the error as critical */ + mm_obj_dbg (self, "error adding SMS: %s", error->message); + } } } @@ -8082,10 +8092,16 @@ sms_text_part_list_ready (MMBroadbandModem *self, mm_sms_part_set_class (part, -1); mm_obj_dbg (self, "correctly parsed SMS list entry (%d)", idx); - mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), - part, - sms_state_from_str (stat), - ctx->list_storage); + if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), + mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)), + part, + sms_state_from_str (stat), + ctx->list_storage, + &error)) { + mm_obj_dbg (self, "failed to add SMS: %s", inner_error->message); + goto next; + } + next: g_match_info_next (match_info, NULL); } @@ -8147,16 +8163,22 @@ sms_pdu_part_list_ready (MMBroadbandModem *self, MMSmsPart *part; part = mm_sms_part_3gpp_new_from_pdu (info->index, info->pdu, self, &error); - if (part) { - mm_obj_dbg (self, "correctly parsed PDU (%d)", info->index); - mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), - part, - sms_state_from_index (info->status), - ctx->list_storage); - } else { + if (!part) { /* Don't treat the error as critical */ mm_obj_dbg (self, "error parsing PDU (%d): %s", info->index, error->message); g_clear_error (&error); + } else { + mm_obj_dbg (self, "correctly parsed PDU (%d)", info->index); + if (!mm_iface_modem_messaging_take_part (MM_IFACE_MODEM_MESSAGING (self), + mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)), + part, + sms_state_from_index (info->status), + ctx->list_storage, + &error)) { + /* Don't treat the error as critical */ + mm_obj_dbg (self, "error adding SMS (%d): %s", info->index, error->message); + g_clear_error (&error); + } } } @@ -8224,10 +8246,18 @@ modem_messaging_load_initial_sms_parts (MMIfaceModemMessaging *self, } /*****************************************************************************/ -/* Create SMS (Messaging interface) */ +/* Create SMS */ + +MMBaseSms * +mm_broadband_modem_create_sms (MMBroadbandModem *self) +{ + g_assert (MM_BROADBAND_MODEM_GET_CLASS (self)->create_sms != NULL); + + return MM_BROADBAND_MODEM_GET_CLASS (self)->create_sms (self); +} static MMBaseSms * -modem_messaging_create_sms (MMIfaceModemMessaging *self) +modem_messaging_create_sms (MMBroadbandModem *self) { return mm_sms_at_new (MM_BASE_MODEM (self), mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); @@ -14542,7 +14572,6 @@ iface_modem_messaging_init (MMIfaceModemMessagingInterface *iface) iface->enable_unsolicited_events_finish = modem_messaging_enable_unsolicited_events_finish; 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; iface->lock_storages = modem_messaging_lock_storages; @@ -14664,6 +14693,7 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass) klass->disabling_stopped = disabling_stopped; klass->load_initial_eps_bearer_cid = load_initial_eps_bearer_cid; klass->load_initial_eps_bearer_cid_finish = load_initial_eps_bearer_cid_finish; + klass->create_sms = modem_messaging_create_sms; g_object_class_override_property (object_class, PROP_MODEM_DBUS_SKELETON, diff --git a/src/mm-broadband-modem.h b/src/mm-broadband-modem.h index 2370d78a..b96e64e3 100644 --- a/src/mm-broadband-modem.h +++ b/src/mm-broadband-modem.h @@ -27,6 +27,7 @@ #include "mm-modem-helpers.h" #include "mm-charsets.h" #include "mm-base-modem.h" +#include "mm-base-sms.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)) @@ -105,6 +106,9 @@ struct _MMBroadbandModemClass { gint (* load_initial_eps_bearer_cid_finish) (MMBroadbandModem *self, GAsyncResult *res, GError **error); + + /* Create SMS objects */ + MMBaseSms * (* create_sms) (MMBroadbandModem *self); }; GType mm_broadband_modem_get_type (void); @@ -140,4 +144,7 @@ gboolean mm_broadband_modem_get_active_multiplexed_bearers (MMBroadbandModem *s /* Helper to manage initial EPS bearer */ gint mm_broadband_modem_get_initial_eps_bearer_cid (MMBroadbandModem *self); +/* Helper to create a new modem-specific SMS object */ +MMBaseSms *mm_broadband_modem_create_sms (MMBroadbandModem *self); + #endif /* MM_BROADBAND_MODEM_H */ diff --git a/src/mm-iface-modem-messaging.c b/src/mm-iface-modem-messaging.c index ef6b546c..51c8b24e 100644 --- a/src/mm-iface-modem-messaging.c +++ b/src/mm-iface-modem-messaging.c @@ -22,6 +22,7 @@ #include "mm-sms-list.h" #include "mm-error-helpers.h" #include "mm-log-object.h" +#include "mm-broadband-modem.h" #define SUPPORT_CHECKED_TAG "messaging-support-checked-tag" #define SUPPORTED_TAG "messaging-supported-tag" @@ -91,16 +92,6 @@ mm_iface_modem_messaging_bind_simple_status (MMIfaceModemMessaging *self, /*****************************************************************************/ -MMBaseSms * -mm_iface_modem_messaging_create_sms (MMIfaceModemMessaging *self) -{ - g_assert (MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->create_sms != NULL); - - return MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->create_sms (self); -} - -/*****************************************************************************/ - void mm_iface_modem_messaging_lock_storages (MMIfaceModemMessaging *self, MMSmsStorage mem1, @@ -339,8 +330,8 @@ handle_create_auth_ready (MMIfaceAuth *auth, return; } - sms = mm_base_sms_new_from_properties (MM_BASE_MODEM (self), properties, &error); - if (!sms) { + sms = mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)); + if (!mm_base_sms_init_from_properties (sms, MM_BASE_MODEM (self), properties, &error)) { mm_dbus_method_invocation_take_error (ctx->invocation, error); handle_create_context_free (ctx); return; @@ -525,13 +516,14 @@ handle_set_default_storage (MmGdbusModemMessaging *skeleton, /*****************************************************************************/ gboolean -mm_iface_modem_messaging_take_part (MMIfaceModemMessaging *self, - MMSmsPart *sms_part, - MMSmsState state, - MMSmsStorage storage) +mm_iface_modem_messaging_take_part (MMIfaceModemMessaging *self, + MMBaseSms *uninitialized_sms, + MMSmsPart *sms_part, + MMSmsState state, + MMSmsStorage storage, + GError **error) { g_autoptr(MMSmsList) list = NULL; - g_autoptr(GError) error = NULL; gboolean added = FALSE; g_object_get (self, @@ -539,15 +531,20 @@ mm_iface_modem_messaging_take_part (MMIfaceModemMessaging *self, NULL); if (list) { - added = mm_sms_list_take_part (list, sms_part, state, storage, &error); + added = mm_sms_list_take_part (list, uninitialized_sms, sms_part, state, storage, error); if (!added) - mm_obj_dbg (self, "couldn't take part in SMS list: %s", error->message); + g_prefix_error (error, "couldn't take part in SMS list: "); } - /* If part wasn't taken, we need to free the part ourselves */ + /* If part wasn't taken, we need to free the part and SMS ourselves */ if (!added) mm_sms_part_free (sms_part); + /* Always drop original ref to the uninialized SMS, as MMSmsList will have + * taken a reference to the SMS if it wants to keep it around. + */ + g_object_unref (uninitialized_sms); + return added; } diff --git a/src/mm-iface-modem-messaging.h b/src/mm-iface-modem-messaging.h index d341d3b0..f62324c9 100644 --- a/src/mm-iface-modem-messaging.h +++ b/src/mm-iface-modem-messaging.h @@ -142,9 +142,6 @@ struct _MMIfaceModemMessagingInterface { gboolean (*load_initial_sms_parts_finish) (MMIfaceModemMessaging *self, GAsyncResult *res, GError **error); - - /* Create SMS objects */ - MMBaseSms * (* create_sms) (MMIfaceModemMessaging *self); }; /* Initialize Messaging interface (async) */ @@ -181,10 +178,12 @@ void mm_iface_modem_messaging_bind_simple_status (MMIfaceModemMessaging *self, MMSimpleStatus *status); /* Report new SMS part */ -gboolean mm_iface_modem_messaging_take_part (MMIfaceModemMessaging *self, - MMSmsPart *sms_part, - MMSmsState state, - MMSmsStorage storage); +gboolean mm_iface_modem_messaging_take_part (MMIfaceModemMessaging *self, + MMBaseSms *uninitialized_sms, + MMSmsPart *sms_part, + MMSmsState state, + MMSmsStorage storage, + GError **error); /* Check storage support */ gboolean mm_iface_modem_messaging_is_storage_supported_for_storing (MMIfaceModemMessaging *self, diff --git a/src/mm-sms-list.c b/src/mm-sms-list.c index f2401dae..21515aa5 100644 --- a/src/mm-sms-list.c +++ b/src/mm-sms-list.c @@ -259,24 +259,23 @@ cmp_sms_by_part_index_and_storage (MMBaseSms *sms, static gboolean take_singlepart (MMSmsList *self, + MMBaseSms *sms, MMSmsPart *part, MMSmsState state, MMSmsStorage storage, GError **error) { - MMBaseSms *sms; - - sms = mm_base_sms_singlepart_new (self->priv->modem, + if (!mm_base_sms_singlepart_init (sms, + self->priv->modem, state, storage, part, - error); - if (!sms) + error)) return FALSE; mm_obj_dbg (sms, "creating new singlepart SMS object"); - self->priv->list = g_list_prepend (self->priv->list, sms); + self->priv->list = g_list_prepend (self->priv->list, g_object_ref (sms)); g_signal_emit (self, signals[SIGNAL_ADDED], 0, mm_base_sms_get_path (sms), state == MM_SMS_STATE_RECEIVED); @@ -285,13 +284,13 @@ take_singlepart (MMSmsList *self, static gboolean take_multipart (MMSmsList *self, + MMBaseSms *sms, MMSmsPart *part, MMSmsState state, MMSmsStorage storage, GError **error) { GList *l; - MMBaseSms *sms; guint concat_reference; concat_reference = mm_sms_part_get_concat_reference (part); @@ -304,20 +303,20 @@ take_multipart (MMSmsList *self, } /* Create new Multipart */ - sms = mm_base_sms_multipart_new (self->priv->modem, + if (!mm_base_sms_multipart_init (sms, + self->priv->modem, state, storage, concat_reference, mm_sms_part_get_concat_max (part), part, - error); - if (!sms) + error)) return FALSE; mm_obj_dbg (sms, "creating new multipart SMS object: need to receive %u parts with reference '%u'", mm_sms_part_get_concat_max (part), concat_reference); - self->priv->list = g_list_prepend (self->priv->list, sms); + self->priv->list = g_list_prepend (self->priv->list, g_object_ref (sms)); g_signal_emit (self, signals[SIGNAL_ADDED], 0, mm_base_sms_get_path (sms), (state == MM_SMS_STATE_RECEIVED || @@ -347,6 +346,7 @@ mm_sms_list_has_part (MMSmsList *self, gboolean mm_sms_list_take_part (MMSmsList *self, + MMBaseSms *uninitialized_sms, MMSmsPart *part, MMSmsState state, MMSmsStorage storage, @@ -379,7 +379,7 @@ mm_sms_list_take_part (MMSmsList *self, mm_sms_part_get_concat_sequence (part), mm_sms_part_get_concat_max (part)); - return take_multipart (self, part, state, storage, error); + return take_multipart (self, uninitialized_sms, part, state, storage, error); } /* Otherwise, we build a whole new single-part MMSms just from this part */ @@ -389,7 +389,7 @@ mm_sms_list_take_part (MMSmsList *self, mm_sms_part_get_index (part)); else mm_obj_dbg (self, "SMS part (not stored) is from a singlepart SMS"); - return take_singlepart (self, part, state, storage, error); + return take_singlepart (self, uninitialized_sms, part, state, storage, error); } /*****************************************************************************/ diff --git a/src/mm-sms-list.h b/src/mm-sms-list.h index 775611c8..e8503a22 100644 --- a/src/mm-sms-list.h +++ b/src/mm-sms-list.h @@ -68,6 +68,7 @@ gboolean mm_sms_list_has_part (MMSmsList *self, guint index); gboolean mm_sms_list_take_part (MMSmsList *self, + MMBaseSms *uninitialized_sms, MMSmsPart *part, MMSmsState state, MMSmsStorage storage, -- cgit v1.2.3-70-g09d2 From 9c8ec57c24ed8eeafaa3c84f5a458c9c41d22ae5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Apr 2025 10:57:54 -0500 Subject: base-sms: pass SMS default storage at creation time and update as needed Instead of getting it from the MMIfaceModemMessaging when the SMS is stored. This flattens dependencies between MMBaseSms and MMIfaceModemMessaging. Signed-off-by: Dan Williams --- src/mm-base-sms.c | 22 +++++++++++++++++++--- src/mm-base-sms.h | 1 + src/mm-broadband-modem-mbim.c | 6 +++++- src/mm-broadband-modem-qmi.c | 5 ++++- src/mm-broadband-modem.c | 6 +++++- src/mm-iface-modem-messaging.c | 22 +++++++++++++++++++++- src/mm-iface-modem-messaging.h | 2 ++ src/mm-sms-at.c | 5 ++++- src/mm-sms-at.h | 5 +++-- src/mm-sms-list.c | 15 +++++++++++++++ src/mm-sms-list.h | 3 +++ src/mm-sms-mbim.c | 5 ++++- src/mm-sms-mbim.h | 5 +++-- src/mm-sms-qmi.c | 5 ++++- src/mm-sms-qmi.h | 5 +++-- 15 files changed, 96 insertions(+), 16 deletions(-) diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index daf7fb67..07081aa3 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -55,6 +55,7 @@ enum { PROP_MAX_PARTS, PROP_MULTIPART_REFERENCE, PROP_IS_3GPP, + PROP_DEFAULT_STORAGE, PROP_LAST }; @@ -93,6 +94,8 @@ struct _MMBaseSmsPrivate { /* TRUE for 3GPP SMS; FALSE for CDMA */ gboolean is_3gpp; + + MMSmsStorage default_storage; }; /*****************************************************************************/ @@ -486,9 +489,7 @@ handle_store (MMBaseSms *self, if (ctx->storage == MM_SMS_STORAGE_UNKNOWN) { /* We'll set now the proper storage, taken from the default mem2 one */ - g_object_get (self->priv->modem, - MM_IFACE_MODEM_MESSAGING_SMS_DEFAULT_STORAGE, &ctx->storage, - NULL); + ctx->storage = self->priv->default_storage; g_assert (ctx->storage != MM_SMS_STORAGE_UNKNOWN); } @@ -1265,6 +1266,9 @@ set_property (GObject *object, case PROP_IS_3GPP: self->priv->is_3gpp = g_value_get_boolean (value); break; + case PROP_DEFAULT_STORAGE: + self->priv->default_storage = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1304,6 +1308,9 @@ get_property (GObject *object, case PROP_IS_3GPP: g_value_set_boolean (value, self->priv->is_3gpp); break; + case PROP_DEFAULT_STORAGE: + g_value_set_enum (value, self->priv->default_storage); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1440,4 +1447,13 @@ mm_base_sms_class_init (MMBaseSmsClass *klass) FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_IS_3GPP, properties[PROP_IS_3GPP]); + + properties[PROP_DEFAULT_STORAGE] = + g_param_spec_enum (MM_BASE_SMS_DEFAULT_STORAGE, + "Default storage", + "Default SMS storage", + MM_TYPE_SMS_STORAGE, + MM_SMS_STORAGE_UNKNOWN, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_DEFAULT_STORAGE, properties[PROP_DEFAULT_STORAGE]); } diff --git a/src/mm-base-sms.h b/src/mm-base-sms.h index 22d25ebb..14902167 100644 --- a/src/mm-base-sms.h +++ b/src/mm-base-sms.h @@ -53,6 +53,7 @@ typedef struct _MMBaseSmsPrivate MMBaseSmsPrivate; #define MM_BASE_SMS_MAX_PARTS "sms-max-parts" #define MM_BASE_SMS_MULTIPART_REFERENCE "sms-multipart-reference" #define MM_BASE_SMS_IS_3GPP "sms-is-3gpp" +#define MM_BASE_SMS_DEFAULT_STORAGE "sms-default-storage" struct _MMBaseSms { MmGdbusSmsSkeleton parent; diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 91a18cb2..5d7e37be 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -9242,8 +9242,12 @@ enable_unsolicited_events_messaging (MMIfaceModemMessaging *_self, static MMBaseSms * messaging_create_sms (MMBroadbandModem *self) { + MMSmsStorage default_storage; + + default_storage = mm_iface_modem_messaging_get_default_storage (MM_IFACE_MODEM_MESSAGING (self)); return mm_sms_mbim_new (MM_BASE_MODEM (self), - mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); + mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self)), + default_storage); } /*****************************************************************************/ diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 6caccc21..4f153009 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -8881,14 +8881,17 @@ static MMBaseSms * messaging_create_sms (MMBroadbandModem *_self) { MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self); + MMSmsStorage default_storage; /* Handle AT URC only fallback */ if (self->priv->messaging_fallback_at_only) { return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_qmi_parent_class)->create_sms (_self); } + default_storage = mm_iface_modem_messaging_get_default_storage (MM_IFACE_MODEM_MESSAGING (self)); return mm_sms_qmi_new (MM_BASE_MODEM (self), - mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); + mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self)), + default_storage); } diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index c29c9190..f164be01 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -8259,8 +8259,12 @@ mm_broadband_modem_create_sms (MMBroadbandModem *self) static MMBaseSms * modem_messaging_create_sms (MMBroadbandModem *self) { + MMSmsStorage default_storage; + + default_storage = mm_iface_modem_messaging_get_default_storage (MM_IFACE_MODEM_MESSAGING (self)); return mm_sms_at_new (MM_BASE_MODEM (self), - mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))); + mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self)), + default_storage); } /*****************************************************************************/ diff --git a/src/mm-iface-modem-messaging.c b/src/mm-iface-modem-messaging.c index 51c8b24e..941e58e0 100644 --- a/src/mm-iface-modem-messaging.c +++ b/src/mm-iface-modem-messaging.c @@ -433,7 +433,8 @@ handle_set_default_storage_ready (MMIfaceModemMessaging *self, GAsyncResult *res, HandleSetDefaultStorageContext *ctx) { - GError *error = NULL; + GError *error = NULL; + g_autoptr(MMSmsList) list = NULL; if (!MM_IFACE_MODEM_MESSAGING_GET_IFACE (self)->set_default_storage_finish (self, res, &error)) { mm_obj_warn (self, "could not set default storage: %s", error->message); @@ -446,6 +447,13 @@ handle_set_default_storage_ready (MMIfaceModemMessaging *self, MM_IFACE_MODEM_MESSAGING_SMS_DEFAULT_STORAGE, ctx->storage, NULL); + /* Update default storage in all SMSs too */ + g_object_get (self, + MM_IFACE_MODEM_MESSAGING_SMS_LIST, &list, + NULL); + if (list) + mm_sms_list_set_default_storage (list, ctx->storage); + mm_obj_info (self, "set the default storage successfully"); mm_gdbus_modem_messaging_complete_set_default_storage (ctx->skeleton, ctx->invocation); handle_set_default_storage_context_free (ctx); @@ -598,6 +606,18 @@ mm_iface_modem_messaging_is_storage_supported_for_receiving (MMIfaceModemMessagi error); } +MMSmsStorage +mm_iface_modem_messaging_get_default_storage (MMIfaceModemMessaging *self) +{ + MMSmsStorage storage = MM_SMS_STORAGE_UNKNOWN; + + g_object_get (self, + MM_IFACE_MODEM_MESSAGING_SMS_DEFAULT_STORAGE, &storage, + NULL); + g_assert (storage != MM_SMS_STORAGE_UNKNOWN); + return storage; +} + /*****************************************************************************/ static void diff --git a/src/mm-iface-modem-messaging.h b/src/mm-iface-modem-messaging.h index f62324c9..d7f29b6d 100644 --- a/src/mm-iface-modem-messaging.h +++ b/src/mm-iface-modem-messaging.h @@ -193,6 +193,8 @@ gboolean mm_iface_modem_messaging_is_storage_supported_for_receiving (MMIfaceMod MMSmsStorage storage, GError **error); +MMSmsStorage mm_iface_modem_messaging_get_default_storage (MMIfaceModemMessaging *self); + /* SMS creation */ MMBaseSms *mm_iface_modem_messaging_create_sms (MMIfaceModemMessaging *self); diff --git a/src/mm-sms-at.c b/src/mm-sms-at.c index 3fc7c155..b79a95ab 100644 --- a/src/mm-sms-at.c +++ b/src/mm-sms-at.c @@ -788,13 +788,16 @@ sms_delete (MMBaseSms *sms, /*****************************************************************************/ MMBaseSms * -mm_sms_at_new (MMBaseModem *modem, gboolean is_3gpp) +mm_sms_at_new (MMBaseModem *modem, + gboolean is_3gpp, + MMSmsStorage default_storage) { MMBaseSms *sms; sms = MM_BASE_SMS (g_object_new (MM_TYPE_SMS_AT, MM_BASE_SMS_MODEM, modem, MM_BASE_SMS_IS_3GPP, is_3gpp, + MM_BASE_SMS_DEFAULT_STORAGE, default_storage, NULL)); MM_SMS_AT (sms)->priv->modem = g_object_ref (modem); return sms; diff --git a/src/mm-sms-at.h b/src/mm-sms-at.h index 26e2dae4..551d50eb 100644 --- a/src/mm-sms-at.h +++ b/src/mm-sms-at.h @@ -53,7 +53,8 @@ struct _MMSmsAtClass { GType mm_sms_at_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSmsAt, g_object_unref) -MMBaseSms *mm_sms_at_new (MMBaseModem *modem, - gboolean is_3gpp); +MMBaseSms *mm_sms_at_new (MMBaseModem *modem, + gboolean is_3gpp, + MMSmsStorage default_storage); #endif /* MM_SMS_AT_H */ diff --git a/src/mm-sms-list.c b/src/mm-sms-list.c index 21515aa5..69c62153 100644 --- a/src/mm-sms-list.c +++ b/src/mm-sms-list.c @@ -394,6 +394,21 @@ mm_sms_list_take_part (MMSmsList *self, /*****************************************************************************/ +void +mm_sms_list_set_default_storage (MMSmsList *self, + MMSmsStorage default_storage) +{ + GList *l; + + for (l = self->priv->list; l; l = g_list_next (l)) { + g_object_set (MM_BASE_SMS (l->data), + MM_BASE_SMS_DEFAULT_STORAGE, default_storage, + NULL); + } +} + +/*****************************************************************************/ + static gchar * log_object_build_id (MMLogObject *_self) { diff --git a/src/mm-sms-list.h b/src/mm-sms-list.h index e8503a22..53fa63f0 100644 --- a/src/mm-sms-list.h +++ b/src/mm-sms-list.h @@ -89,4 +89,7 @@ gboolean mm_sms_list_has_local_multipart_reference (MMSmsList *self, const gchar *number, guint8 reference); +void mm_sms_list_set_default_storage (MMSmsList *self, + MMSmsStorage default_storage); + #endif /* MM_SMS_LIST_H */ diff --git a/src/mm-sms-mbim.c b/src/mm-sms-mbim.c index 1cb442d6..7b3edb84 100644 --- a/src/mm-sms-mbim.c +++ b/src/mm-sms-mbim.c @@ -332,12 +332,15 @@ sms_delete (MMBaseSms *self, /*****************************************************************************/ MMBaseSms * -mm_sms_mbim_new (MMBaseModem *modem, gboolean is_3gpp) +mm_sms_mbim_new (MMBaseModem *modem, + gboolean is_3gpp, + MMSmsStorage default_storage) { return MM_BASE_SMS (g_object_new (MM_TYPE_SMS_MBIM, MM_BASE_SMS_MODEM, modem, MM_BIND_TO, G_OBJECT (modem), MM_BASE_SMS_IS_3GPP, is_3gpp, + MM_BASE_SMS_DEFAULT_STORAGE, default_storage, NULL)); } diff --git a/src/mm-sms-mbim.h b/src/mm-sms-mbim.h index 070ff677..7877c3f1 100644 --- a/src/mm-sms-mbim.h +++ b/src/mm-sms-mbim.h @@ -45,7 +45,8 @@ struct _MMSmsMbimClass { GType mm_sms_mbim_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSmsMbim, g_object_unref) -MMBaseSms *mm_sms_mbim_new (MMBaseModem *modem, - gboolean is_3gpp); +MMBaseSms *mm_sms_mbim_new (MMBaseModem *modem, + gboolean is_3gpp, + MMSmsStorage default_storage); #endif /* MM_SMS_MBIM_H */ diff --git a/src/mm-sms-qmi.c b/src/mm-sms-qmi.c index aa5101ee..ebd8f845 100644 --- a/src/mm-sms-qmi.c +++ b/src/mm-sms-qmi.c @@ -786,12 +786,15 @@ sms_delete (MMBaseSms *self, /*****************************************************************************/ MMBaseSms * -mm_sms_qmi_new (MMBaseModem *modem, gboolean is_3gpp) +mm_sms_qmi_new (MMBaseModem *modem, + gboolean is_3gpp, + MMSmsStorage default_storage) { return MM_BASE_SMS (g_object_new (MM_TYPE_SMS_QMI, MM_BASE_SMS_MODEM, modem, MM_BIND_TO, G_OBJECT (modem), MM_BASE_SMS_IS_3GPP, is_3gpp, + MM_BASE_SMS_DEFAULT_STORAGE, default_storage, NULL)); } diff --git a/src/mm-sms-qmi.h b/src/mm-sms-qmi.h index 250e406e..1dda2a95 100644 --- a/src/mm-sms-qmi.h +++ b/src/mm-sms-qmi.h @@ -47,7 +47,8 @@ struct _MMSmsQmiClass { GType mm_sms_qmi_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSmsQmi, g_object_unref) -MMBaseSms *mm_sms_qmi_new (MMBaseModem *modem, - gboolean is_3gpp); +MMBaseSms *mm_sms_qmi_new (MMBaseModem *modem, + gboolean is_3gpp, + MMSmsStorage default_storage); #endif /* MM_SMS_QMI_H */ -- cgit v1.2.3-70-g09d2 From 1781ffaad469e1c2d8b8dc59a99ed3dd786627fc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Apr 2025 17:22:17 -0500 Subject: base-sms: pass supported storages in at creation time They won't change, and this lets us get rid of one more usage of MMIfaceModemMessaging. Signed-off-by: Dan Williams --- src/mm-base-sms.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++---- src/mm-base-sms.h | 1 + 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index 07081aa3..22b91244 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -56,6 +56,7 @@ enum { PROP_MULTIPART_REFERENCE, PROP_IS_3GPP, PROP_DEFAULT_STORAGE, + PROP_SUPPORTED_STORAGES, PROP_LAST }; @@ -95,7 +96,9 @@ struct _MMBaseSmsPrivate { /* TRUE for 3GPP SMS; FALSE for CDMA */ gboolean is_3gpp; - MMSmsStorage default_storage; + /* SMS storage */ + MMSmsStorage default_storage; + GArray *supported_storages; }; /*****************************************************************************/ @@ -411,6 +414,7 @@ handle_store_auth_ready (MMAuthProvider *authp, HandleStoreContext *ctx) { GError *error = NULL; + gboolean storage_supported = FALSE; if (!mm_auth_provider_authorize_finish (authp, res, &error)) { mm_dbus_method_invocation_take_error (ctx->invocation, error); @@ -442,9 +446,23 @@ handle_store_auth_ready (MMAuthProvider *authp, } /* Check if the requested storage is allowed for storing */ - if (!mm_iface_modem_messaging_is_storage_supported_for_storing (MM_IFACE_MODEM_MESSAGING (ctx->self->priv->modem), - ctx->storage, - &error)) { + if (ctx->self->priv->supported_storages) { + guint i; + + for (i = 0; i < ctx->self->priv->supported_storages->len; i++) { + if (ctx->storage == g_array_index (ctx->self->priv->supported_storages, MMSmsStorage, i)) { + storage_supported = TRUE; + break; + } + } + } + + if (!storage_supported) { + g_set_error (&error, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Storage '%s' is not supported for storing", + mm_sms_storage_get_string (ctx->storage)); mm_obj_warn (ctx->self, "failed storing SMS message: %s", error->message); mm_dbus_method_invocation_take_error (ctx->invocation, error); handle_store_context_free (ctx); @@ -1216,6 +1234,19 @@ log_object_build_id (MMLogObject *_self) /*****************************************************************************/ +/* FIXME: use g_array_copy() when glib min version is >= 2.62 */ +static GArray * +copy_storage_array (GArray *orig) +{ + GArray *copy = NULL; + + if (orig) { + copy = g_array_sized_new (FALSE, FALSE, sizeof (MMSmsStorage), orig->len); + g_array_append_vals (copy, orig->data, orig->len); + } + return copy; +} + static void set_property (GObject *object, guint prop_id, @@ -1269,6 +1300,11 @@ set_property (GObject *object, case PROP_DEFAULT_STORAGE: self->priv->default_storage = g_value_get_enum (value); break; + case PROP_SUPPORTED_STORAGES: + /* Copy the array rather than just ref-ing it */ + g_clear_pointer (&self->priv->supported_storages, (GDestroyNotify)g_array_unref); + self->priv->supported_storages = copy_storage_array (g_value_get_boxed (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1311,6 +1347,9 @@ get_property (GObject *object, case PROP_DEFAULT_STORAGE: g_value_set_enum (value, self->priv->default_storage); break; + case PROP_SUPPORTED_STORAGES: + g_value_set_boxed (value, copy_storage_array (self->priv->supported_storages)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1362,6 +1401,7 @@ dispose (GObject *object) g_clear_object (&self->priv->bind_to); g_cancellable_cancel (self->priv->authp_cancellable); g_clear_object (&self->priv->authp_cancellable); + g_clear_pointer (&self->priv->supported_storages, (GDestroyNotify)g_array_unref); G_OBJECT_CLASS (mm_base_sms_parent_class)->dispose (object); } @@ -1456,4 +1496,12 @@ mm_base_sms_class_init (MMBaseSmsClass *klass) MM_SMS_STORAGE_UNKNOWN, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_DEFAULT_STORAGE, properties[PROP_DEFAULT_STORAGE]); + + properties[PROP_SUPPORTED_STORAGES] = + g_param_spec_boxed (MM_BASE_SMS_SUPPORTED_STORAGES, + "Supported storages", + "Array of MMSmsStorage indicating supported storages for storing the SMS", + G_TYPE_ARRAY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_SUPPORTED_STORAGES, properties[PROP_SUPPORTED_STORAGES]); } diff --git a/src/mm-base-sms.h b/src/mm-base-sms.h index 14902167..dd1c10bb 100644 --- a/src/mm-base-sms.h +++ b/src/mm-base-sms.h @@ -54,6 +54,7 @@ typedef struct _MMBaseSmsPrivate MMBaseSmsPrivate; #define MM_BASE_SMS_MULTIPART_REFERENCE "sms-multipart-reference" #define MM_BASE_SMS_IS_3GPP "sms-is-3gpp" #define MM_BASE_SMS_DEFAULT_STORAGE "sms-default-storage" +#define MM_BASE_SMS_SUPPORTED_STORAGES "sms-supported-storages" struct _MMBaseSms { MmGdbusSmsSkeleton parent; -- cgit v1.2.3-70-g09d2 From c6af442053d9959107c73e564731c3cb85e28981 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Apr 2025 18:22:38 -0500 Subject: base-sms: reduce possibility of leaking multipart reference Move error paths after getting a multipart reference to before getting one, to reduce the possiblity that we get a reference from the MMSmsList that ultimately doesn't end up getting used. Signed-off-by: Dan Williams --- src/mm-base-sms.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index 22b91244..ecfee882 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -469,14 +469,6 @@ handle_store_auth_ready (MMAuthProvider *authp, return; } - /* Prepare the SMS to be stored, creating the PDU list if required */ - if (!prepare_sms_to_be_stored (ctx->self, &error)) { - mm_obj_warn (ctx->self, "failed preparing SMS message to be stored: %s", error->message); - mm_dbus_method_invocation_take_error (ctx->invocation, error); - handle_store_context_free (ctx); - return; - } - /* If not stored, check if we do support doing it */ if (!MM_BASE_SMS_GET_CLASS (ctx->self)->store || !MM_BASE_SMS_GET_CLASS (ctx->self)->store_finish) { @@ -487,6 +479,14 @@ handle_store_auth_ready (MMAuthProvider *authp, return; } + /* Prepare the SMS to be stored, creating the PDU list if required */ + if (!prepare_sms_to_be_stored (ctx->self, &error)) { + mm_obj_warn (ctx->self, "failed preparing SMS message to be stored: %s", error->message); + mm_dbus_method_invocation_take_error (ctx->invocation, error); + handle_store_context_free (ctx); + return; + } + MM_BASE_SMS_GET_CLASS (ctx->self)->store (ctx->self, ctx->storage, (GAsyncReadyCallback)handle_store_ready, -- cgit v1.2.3-70-g09d2 From 97c189910bfb6cf4974a04d34a2e53a8bd1cfdf1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Apr 2025 19:13:53 -0500 Subject: base-sms,sms-list: use signals to set multipart reference Instead of going through the messaging interface, which just asks the MMSmsList anyway, just go straight to the list. Signed-off-by: Dan Williams --- src/mm-base-sms.c | 68 ++++++++++++++++++++++++++----------- src/mm-base-sms.h | 10 ++++++ src/mm-iface-modem-messaging.c | 48 -------------------------- src/mm-iface-modem-messaging.h | 5 --- src/mm-sms-list.c | 76 ++++++++++++++++++++++++++++++++---------- 5 files changed, 117 insertions(+), 90 deletions(-) diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index ecfee882..410ccc74 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -62,6 +62,13 @@ enum { static GParamSpec *properties[PROP_LAST]; +enum { + SIGNAL_SET_LOCAL_MULTIPART_REFERENCE, + SIGNAL_LAST +}; + +static guint signals[SIGNAL_LAST] = { 0 }; + struct _MMBaseSmsPrivate { gboolean initialized; @@ -383,26 +390,22 @@ prepare_sms_to_be_stored (MMBaseSms *self, * when storing locally, as we could collide with the references used * in other existing messages. */ if (self->priv->is_multipart) { - GList *l; - guint8 reference; - - /* Look for a valid multipart reference to use. When storing, we need to - * check whether we have already stored multipart SMS with the same - * reference and destination number */ - reference = mm_iface_modem_messaging_get_local_multipart_reference ( - MM_IFACE_MODEM_MESSAGING (self->priv->modem), - mm_gdbus_sms_get_number (MM_GDBUS_SMS (self)), - error); - if (!reference) { - g_prefix_error (error, "Cannot get local multipart reference: "); + const gchar *number; + + number = mm_gdbus_sms_get_number (MM_GDBUS_SMS (self)); + g_signal_emit (self, + signals[SIGNAL_SET_LOCAL_MULTIPART_REFERENCE], + 0, + number); + if (self->priv->multipart_reference == 0) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_TOO_MANY, + "Cannot create multipart SMS: No valid multipart reference " + "available for destination number '%s'", + number); return FALSE; } - - self->priv->multipart_reference = reference; - for (l = self->priv->parts; l; l = g_list_next (l)) { - mm_sms_part_set_concat_reference ((MMSmsPart *)l->data, - self->priv->multipart_reference); - } } return TRUE; @@ -587,7 +590,7 @@ prepare_sms_to_be_sent (MMBaseSms *self, * multipart reference. When sending a message which wasn't stored * yet, we can just get a random multipart reference. */ if (self->priv->is_multipart) { - self->priv->multipart_reference = g_random_int_range (1,255); + self->priv->multipart_reference = g_random_int_range (1, 255); for (l = self->priv->parts; l; l = g_list_next (l)) { mm_sms_part_set_concat_reference ((MMSmsPart *)l->data, self->priv->multipart_reference); @@ -762,6 +765,23 @@ mm_base_sms_get_multipart_reference (MMBaseSms *self) return self->priv->multipart_reference; } +void +mm_base_sms_set_multipart_reference (MMBaseSms *self, guint reference) +{ + GList *l; + + g_return_if_fail (self->priv->is_multipart); + g_return_if_fail (reference > 0); + g_return_if_fail (reference <= 255); + g_return_if_fail (self->priv->multipart_reference == 0); + + self->priv->multipart_reference = reference; + for (l = self->priv->parts; l; l = g_list_next (l)) { + mm_sms_part_set_concat_reference ((MMSmsPart *)l->data, + self->priv->multipart_reference); + } +} + gboolean mm_base_sms_multipart_is_complete (MMBaseSms *self) { @@ -1504,4 +1524,14 @@ mm_base_sms_class_init (MMBaseSmsClass *klass) G_TYPE_ARRAY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_SUPPORTED_STORAGES, properties[PROP_SUPPORTED_STORAGES]); + + /* Signals */ + signals[SIGNAL_SET_LOCAL_MULTIPART_REFERENCE] = + g_signal_new (MM_BASE_SMS_SET_LOCAL_MULTIPART_REFERENCE, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (MMBaseSmsClass, set_local_multipart_reference), + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 0); } diff --git a/src/mm-base-sms.h b/src/mm-base-sms.h index dd1c10bb..f87a6640 100644 --- a/src/mm-base-sms.h +++ b/src/mm-base-sms.h @@ -46,6 +46,7 @@ typedef struct _MMBaseSms MMBaseSms; typedef struct _MMBaseSmsClass MMBaseSmsClass; typedef struct _MMBaseSmsPrivate MMBaseSmsPrivate; +/* Properties */ #define MM_BASE_SMS_PATH "sms-path" #define MM_BASE_SMS_CONNECTION "sms-connection" #define MM_BASE_SMS_MODEM "sms-modem" @@ -56,6 +57,9 @@ typedef struct _MMBaseSmsPrivate MMBaseSmsPrivate; #define MM_BASE_SMS_DEFAULT_STORAGE "sms-default-storage" #define MM_BASE_SMS_SUPPORTED_STORAGES "sms-supported-storages" +/* Signals */ +#define MM_BASE_SMS_SET_LOCAL_MULTIPART_REFERENCE "sms-set-local-multipart-reference" + struct _MMBaseSms { MmGdbusSmsSkeleton parent; MMBaseSmsPrivate *priv; @@ -88,6 +92,10 @@ struct _MMBaseSmsClass { gboolean (* delete_finish) (MMBaseSms *self, GAsyncResult *res, GError **error); + + /* Signal */ + void (*set_local_multipart_reference) (MMBaseSms *self, + const gchar *number); }; GType mm_base_sms_get_type (void); @@ -128,6 +136,8 @@ GList *mm_base_sms_get_parts (MMBaseSms *self); gboolean mm_base_sms_is_multipart (MMBaseSms *self); guint mm_base_sms_get_max_parts (MMBaseSms *self); guint mm_base_sms_get_multipart_reference (MMBaseSms *self); +void mm_base_sms_set_multipart_reference (MMBaseSms *self, + guint reference); gboolean mm_base_sms_multipart_is_complete (MMBaseSms *self); gboolean mm_base_sms_multipart_is_assembled (MMBaseSms *self); diff --git a/src/mm-iface-modem-messaging.c b/src/mm-iface-modem-messaging.c index 941e58e0..b6b63e49 100644 --- a/src/mm-iface-modem-messaging.c +++ b/src/mm-iface-modem-messaging.c @@ -36,54 +36,6 @@ G_DEFINE_INTERFACE (MMIfaceModemMessaging, mm_iface_modem_messaging, MM_TYPE_IFA /*****************************************************************************/ -guint8 -mm_iface_modem_messaging_get_local_multipart_reference (MMIfaceModemMessaging *self, - const gchar *number, - GError **error) -{ - MMSmsList *list = NULL; - guint8 reference; - guint8 first; - - /* Start by looking for a random number */ - reference = g_random_int_range (1,255); - - /* Then, look for the given reference in user-created messages */ - g_object_get (self, - MM_IFACE_MODEM_MESSAGING_SMS_LIST, &list, - NULL); - if (!list) - return reference; - - first = reference; - do { - if (!mm_sms_list_has_local_multipart_reference (list, number, reference)) { - g_object_unref (list); - return reference; - } - - if (reference == 255) - reference = 1; - else - reference++; - } - while (reference != first); - - g_object_unref (list); - - /* We were not able to find a new valid multipart reference :/ - * return an error */ - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_TOO_MANY, - "Cannot create multipart SMS: No valid multipart reference " - "available for destination number '%s'", - number); - return 0; -} - -/*****************************************************************************/ - void mm_iface_modem_messaging_bind_simple_status (MMIfaceModemMessaging *self, MMSimpleStatus *status) diff --git a/src/mm-iface-modem-messaging.h b/src/mm-iface-modem-messaging.h index d7f29b6d..6cf7a0f6 100644 --- a/src/mm-iface-modem-messaging.h +++ b/src/mm-iface-modem-messaging.h @@ -211,9 +211,4 @@ void mm_iface_modem_messaging_unlock_storages (MMIfaceModemMessaging *s gboolean mem1, gboolean mem2); -/* Look for a new valid multipart reference */ -guint8 mm_iface_modem_messaging_get_local_multipart_reference (MMIfaceModemMessaging *self, - const gchar *number, - GError **error); - #endif /* MM_IFACE_MODEM_MESSAGING_H */ diff --git a/src/mm-sms-list.c b/src/mm-sms-list.c index 69c62153..99f35da1 100644 --- a/src/mm-sms-list.c +++ b/src/mm-sms-list.c @@ -61,6 +61,8 @@ struct _MMSmsListPrivate { GList *list; }; +static void _release_sms_internal (MMBaseSms *sms, MMSmsList *self); + /*****************************************************************************/ gboolean @@ -161,7 +163,7 @@ delete_ready (MMBaseSms *sms, path, (GCompareFunc)cmp_sms_by_path); if (l) { - g_object_unref (MM_BASE_SMS (l->data)); + _release_sms_internal (MM_BASE_SMS (l->data), self); self->priv->list = g_list_delete_link (self->priv->list, l); } @@ -213,14 +215,61 @@ mm_sms_list_delete_sms (MMSmsList *self, /*****************************************************************************/ -void -mm_sms_list_add_sms (MMSmsList *self, - MMBaseSms *sms) +static void +set_local_multipart_reference (MMBaseSms *sms, + const gchar *number, + MMSmsList *self) +{ + guint8 reference; + guint8 first; + + /* Start by looking for a random number */ + reference = g_random_int_range (1, 255); + + /* Then, look for the given reference in user-created messages */ + first = reference; + do { + if (!mm_sms_list_has_local_multipart_reference (self, number, reference)) { + mm_base_sms_set_multipart_reference (sms, reference); + return; + } + + if (reference == 255) + reference = 1; + else + reference++; + } while (reference != first); +} + +static void +_release_sms_internal (MMBaseSms *sms, MMSmsList *self) +{ + g_signal_handlers_disconnect_by_func (sms, set_local_multipart_reference, self); + g_object_unref (sms); +} + +static void +_add_sms_internal (MMSmsList *self, + MMBaseSms *sms, + gboolean received) { self->priv->list = g_list_prepend (self->priv->list, g_object_ref (sms)); + g_signal_connect (sms, + MM_BASE_SMS_SET_LOCAL_MULTIPART_REFERENCE, + (GCallback)set_local_multipart_reference, + self); + g_signal_emit (self, signals[SIGNAL_ADDED], 0, mm_base_sms_get_path (sms), - FALSE); + received); +} + + +void +mm_sms_list_add_sms (MMSmsList *self, + MMBaseSms *sms) +{ + _add_sms_internal (self, sms, FALSE); } /*****************************************************************************/ @@ -274,11 +323,7 @@ take_singlepart (MMSmsList *self, return FALSE; mm_obj_dbg (sms, "creating new singlepart SMS object"); - - self->priv->list = g_list_prepend (self->priv->list, g_object_ref (sms)); - g_signal_emit (self, signals[SIGNAL_ADDED], 0, - mm_base_sms_get_path (sms), - state == MM_SMS_STATE_RECEIVED); + _add_sms_internal (self, sms, state == MM_SMS_STATE_RECEIVED); return TRUE; } @@ -316,12 +361,7 @@ take_multipart (MMSmsList *self, mm_obj_dbg (sms, "creating new multipart SMS object: need to receive %u parts with reference '%u'", mm_sms_part_get_concat_max (part), concat_reference); - self->priv->list = g_list_prepend (self->priv->list, g_object_ref (sms)); - g_signal_emit (self, signals[SIGNAL_ADDED], 0, - mm_base_sms_get_path (sms), - (state == MM_SMS_STATE_RECEIVED || - state == MM_SMS_STATE_RECEIVING)); - + _add_sms_internal (self, sms, (state == MM_SMS_STATE_RECEIVED || state == MM_SMS_STATE_RECEIVING)); return TRUE; } @@ -488,8 +528,8 @@ dispose (GObject *object) g_clear_object (&self->priv->modem); g_clear_object (&self->priv->bind_to); - g_list_free_full (self->priv->list, g_object_unref); - self->priv->list = NULL; + g_list_foreach (self->priv->list, (GFunc)_release_sms_internal, self); + g_clear_pointer (&self->priv->list, (GDestroyNotify)g_list_free); G_OBJECT_CLASS (mm_sms_list_parent_class)->dispose (object); } -- cgit v1.2.3-70-g09d2 From 03027b5ec2821b11c64966b2bf79d24ef42d5777 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Apr 2025 19:43:08 -0500 Subject: base-sms: remove MODEM property No longer depend on MMBaseModem since everything that specifically uses it is now removed. Signed-off-by: Dan Williams --- src/mm-base-sms.c | 34 +++-------------- src/mm-base-sms.h | 6 +-- src/mm-iface-modem-messaging.c | 2 +- src/mm-sms-at.c | 3 +- src/mm-sms-list.c | 2 - src/mm-sms-mbim.c | 60 +++++++++++++++++++----------- src/mm-sms-mbim.h | 2 + src/mm-sms-qmi.c | 84 +++++++++++++++++++++--------------------- src/mm-sms-qmi.h | 2 + 9 files changed, 95 insertions(+), 100 deletions(-) diff --git a/src/mm-base-sms.c b/src/mm-base-sms.c index 410ccc74..4f67d5ea 100644 --- a/src/mm-base-sms.c +++ b/src/mm-base-sms.c @@ -27,10 +27,7 @@ #include #include "mm-base-sms.h" -#include "mm-broadband-modem.h" #include "mm-auth-provider.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-messaging.h" #include "mm-sms-part-3gpp.h" #include "mm-log-object.h" #include "mm-modem-helpers.h" @@ -50,7 +47,6 @@ enum { PROP_PATH, PROP_CONNECTION, PROP_BIND_TO, - PROP_MODEM, PROP_IS_MULTIPART, PROP_MAX_PARTS, PROP_MULTIPART_REFERENCE, @@ -75,6 +71,12 @@ struct _MMBaseSmsPrivate { /* The connection to the system bus */ GDBusConnection *connection; guint dbus_id; + /* Object to which our connection property should be bound */ + GObject *connection_parent; + /* GObject property name of the parent's connection property to + * which this SMS"s connection should be bound. + */ + gchar *connection_parent_property_name; /* The authorization provider */ MMAuthProvider *authp; @@ -83,8 +85,6 @@ struct _MMBaseSmsPrivate { /* The object this SMS is bound to */ GObject *bind_to; - /* The modem which owns this SMS */ - MMBaseModem *modem; /* The path where the SMS object is exported */ gchar *path; @@ -1094,13 +1094,11 @@ mm_base_sms_multipart_take_part (MMBaseSms *self, gboolean mm_base_sms_singlepart_init (MMBaseSms *self, - MMBaseModem *modem, MMSmsState state, MMSmsStorage storage, MMSmsPart *part, GError **error) { - g_assert (MM_IS_IFACE_MODEM_MESSAGING (modem)); g_assert (self->priv->initialized == FALSE); g_object_set (self, @@ -1129,7 +1127,6 @@ mm_base_sms_singlepart_init (MMBaseSms *self, gboolean mm_base_sms_multipart_init (MMBaseSms *self, - MMBaseModem *modem, MMSmsState state, MMSmsStorage storage, guint reference, @@ -1137,7 +1134,6 @@ mm_base_sms_multipart_init (MMBaseSms *self, MMSmsPart *first_part, GError **error) { - g_assert (MM_IS_IFACE_MODEM_MESSAGING (modem)); g_assert (self->priv->initialized == FALSE); /* If this is the first part of a RECEIVED SMS, we overwrite the state @@ -1173,14 +1169,12 @@ mm_base_sms_multipart_init (MMBaseSms *self, gboolean mm_base_sms_init_from_properties (MMBaseSms *self, - MMBaseModem *modem, MMSmsProperties *props, GError **error) { const gchar *text; GByteArray *data; - g_assert (MM_IS_IFACE_MODEM_MESSAGING (modem)); g_assert (self->priv->initialized == FALSE); text = mm_sms_properties_get_text (props); @@ -1301,10 +1295,6 @@ set_property (GObject *object, self->priv->bind_to = g_value_dup_object (value); mm_bind_to (MM_BIND (self), MM_BASE_SMS_CONNECTION, self->priv->bind_to); break; - case PROP_MODEM: - g_clear_object (&self->priv->modem); - self->priv->modem = g_value_dup_object (value); - break; case PROP_IS_MULTIPART: self->priv->is_multipart = g_value_get_boolean (value); break; @@ -1349,9 +1339,6 @@ get_property (GObject *object, case PROP_BIND_TO: g_value_set_object (value, self->priv->bind_to); break; - case PROP_MODEM: - g_value_set_object (value, self->priv->modem); - break; case PROP_IS_MULTIPART: g_value_set_boolean (value, self->priv->is_multipart); break; @@ -1417,7 +1404,6 @@ dispose (GObject *object) g_clear_object (&self->priv->connection); } - g_clear_object (&self->priv->modem); g_clear_object (&self->priv->bind_to); g_cancellable_cancel (self->priv->authp_cancellable); g_clear_object (&self->priv->authp_cancellable); @@ -1468,14 +1454,6 @@ mm_base_sms_class_init (MMBaseSmsClass *klass) g_object_class_override_property (object_class, PROP_BIND_TO, MM_BIND_TO); - properties[PROP_MODEM] = - g_param_spec_object (MM_BASE_SMS_MODEM, - "Modem", - "The Modem which owns this SMS", - MM_TYPE_BASE_MODEM, - G_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]); - properties[PROP_IS_MULTIPART] = g_param_spec_boolean (MM_BASE_SMS_IS_MULTIPART, "Is multipart", diff --git a/src/mm-base-sms.h b/src/mm-base-sms.h index f87a6640..ecd7ad2a 100644 --- a/src/mm-base-sms.h +++ b/src/mm-base-sms.h @@ -25,7 +25,6 @@ #include #include "mm-sms-part.h" -#include "mm-base-modem.h" /*****************************************************************************/ @@ -49,13 +48,13 @@ typedef struct _MMBaseSmsPrivate MMBaseSmsPrivate; /* Properties */ #define MM_BASE_SMS_PATH "sms-path" #define MM_BASE_SMS_CONNECTION "sms-connection" -#define MM_BASE_SMS_MODEM "sms-modem" #define MM_BASE_SMS_IS_MULTIPART "sms-is-multipart" #define MM_BASE_SMS_MAX_PARTS "sms-max-parts" #define MM_BASE_SMS_MULTIPART_REFERENCE "sms-multipart-reference" #define MM_BASE_SMS_IS_3GPP "sms-is-3gpp" #define MM_BASE_SMS_DEFAULT_STORAGE "sms-default-storage" #define MM_BASE_SMS_SUPPORTED_STORAGES "sms-supported-storages" +#define MM_BASE_SMS_CONNECTION_PARENT_PROPERTY_NAME "sms-connection-parent-property-name" /* Signals */ #define MM_BASE_SMS_SET_LOCAL_MULTIPART_REFERENCE "sms-set-local-multipart-reference" @@ -102,17 +101,14 @@ GType mm_base_sms_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseSms, g_object_unref) gboolean mm_base_sms_init_from_properties (MMBaseSms *self, - MMBaseModem *modem, MMSmsProperties *properties, GError **error); gboolean mm_base_sms_singlepart_init (MMBaseSms *self, - MMBaseModem *modem, MMSmsState state, MMSmsStorage storage, MMSmsPart *part, GError **error); gboolean mm_base_sms_multipart_init (MMBaseSms *self, - MMBaseModem *modem, MMSmsState state, MMSmsStorage storage, guint reference, diff --git a/src/mm-iface-modem-messaging.c b/src/mm-iface-modem-messaging.c index b6b63e49..d349de35 100644 --- a/src/mm-iface-modem-messaging.c +++ b/src/mm-iface-modem-messaging.c @@ -283,7 +283,7 @@ handle_create_auth_ready (MMIfaceAuth *auth, } sms = mm_broadband_modem_create_sms (MM_BROADBAND_MODEM (self)); - if (!mm_base_sms_init_from_properties (sms, MM_BASE_MODEM (self), properties, &error)) { + if (!mm_base_sms_init_from_properties (sms, properties, &error)) { mm_dbus_method_invocation_take_error (ctx->invocation, error); handle_create_context_free (ctx); return; diff --git a/src/mm-sms-at.c b/src/mm-sms-at.c index b79a95ab..4f817e65 100644 --- a/src/mm-sms-at.c +++ b/src/mm-sms-at.c @@ -32,6 +32,7 @@ #include "mm-sms-part-3gpp.h" #include "mm-base-modem-at.h" #include "mm-log-object.h" +#include "mm-bind.h" G_DEFINE_TYPE (MMSmsAt, mm_sms_at, MM_TYPE_BASE_SMS) @@ -795,7 +796,7 @@ mm_sms_at_new (MMBaseModem *modem, MMBaseSms *sms; sms = MM_BASE_SMS (g_object_new (MM_TYPE_SMS_AT, - MM_BASE_SMS_MODEM, modem, + MM_BIND_TO, G_OBJECT (modem), MM_BASE_SMS_IS_3GPP, is_3gpp, MM_BASE_SMS_DEFAULT_STORAGE, default_storage, NULL)); diff --git a/src/mm-sms-list.c b/src/mm-sms-list.c index 99f35da1..b4b8619b 100644 --- a/src/mm-sms-list.c +++ b/src/mm-sms-list.c @@ -315,7 +315,6 @@ take_singlepart (MMSmsList *self, GError **error) { if (!mm_base_sms_singlepart_init (sms, - self->priv->modem, state, storage, part, @@ -349,7 +348,6 @@ take_multipart (MMSmsList *self, /* Create new Multipart */ if (!mm_base_sms_multipart_init (sms, - self->priv->modem, state, storage, concat_reference, diff --git a/src/mm-sms-mbim.c b/src/mm-sms-mbim.c index 7b3edb84..ffb6b466 100644 --- a/src/mm-sms-mbim.c +++ b/src/mm-sms-mbim.c @@ -35,25 +35,22 @@ G_DEFINE_TYPE (MMSmsMbim, mm_sms_mbim, MM_TYPE_BASE_SMS) +struct _MMSmsMbimPrivate { + MMBaseModem *modem; +}; + /*****************************************************************************/ static gboolean -peek_device (gpointer self, - MbimDevice **o_device, - GAsyncReadyCallback callback, - gpointer user_data) +peek_device (MMSmsMbim *self, + MbimDevice **o_device, + GAsyncReadyCallback callback, + gpointer user_data) { - MMBaseModem *modem = NULL; - - g_object_get (G_OBJECT (self), - MM_BASE_SMS_MODEM, &modem, - NULL); - g_assert (MM_IS_BASE_MODEM (modem)); - if (o_device) { MMPortMbim *port; - port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (modem)); + port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self->priv->modem)); if (!port) { g_task_report_new_error (self, callback, @@ -62,14 +59,12 @@ peek_device (gpointer self, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't peek MBIM port"); - g_object_unref (modem); return FALSE; } *o_device = mm_port_mbim_peek_device (port); } - g_object_unref (modem); return TRUE; } @@ -191,7 +186,7 @@ sms_send (MMBaseSms *self, MbimDevice *device; GTask *task; - if (!peek_device (self, &device, callback, user_data)) + if (!peek_device (MM_SMS_MBIM (self), &device, callback, user_data)) return; /* Setup the context */ @@ -315,7 +310,7 @@ sms_delete (MMBaseSms *self, MbimDevice *device; GTask *task; - if (!peek_device (self, &device, callback, user_data)) + if (!peek_device (MM_SMS_MBIM (self), &device, callback, user_data)) return; ctx = g_slice_new0 (SmsDeletePartsContext); @@ -336,24 +331,45 @@ mm_sms_mbim_new (MMBaseModem *modem, gboolean is_3gpp, MMSmsStorage default_storage) { - return MM_BASE_SMS (g_object_new (MM_TYPE_SMS_MBIM, - MM_BASE_SMS_MODEM, modem, - MM_BIND_TO, G_OBJECT (modem), - MM_BASE_SMS_IS_3GPP, is_3gpp, - MM_BASE_SMS_DEFAULT_STORAGE, default_storage, - NULL)); + MMBaseSms *sms; + + g_return_val_if_fail (MM_IS_BROADBAND_MODEM_MBIM (modem), NULL); + + sms = MM_BASE_SMS (g_object_new (MM_TYPE_SMS_MBIM, + MM_BIND_TO, G_OBJECT (modem), + MM_BASE_SMS_IS_3GPP, is_3gpp, + MM_BASE_SMS_DEFAULT_STORAGE, default_storage, + NULL)); + MM_SMS_MBIM (sms)->priv->modem = g_object_ref (modem); + return sms; } static void mm_sms_mbim_init (MMSmsMbim *self) { + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_SMS_MBIM, MMSmsMbimPrivate); +} + +static void +dispose (GObject *object) +{ + MMSmsMbim *self = MM_SMS_MBIM (object); + + g_clear_object (&self->priv->modem); + + G_OBJECT_CLASS (mm_sms_mbim_parent_class)->dispose (object); } static void mm_sms_mbim_class_init (MMSmsMbimClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); MMBaseSmsClass *base_sms_class = MM_BASE_SMS_CLASS (klass); + g_type_class_add_private (object_class, sizeof (MMSmsMbimPrivate)); + + object_class->dispose = dispose; + base_sms_class->store = NULL; base_sms_class->store_finish = NULL; base_sms_class->send = sms_send; diff --git a/src/mm-sms-mbim.h b/src/mm-sms-mbim.h index 7877c3f1..b045b99c 100644 --- a/src/mm-sms-mbim.h +++ b/src/mm-sms-mbim.h @@ -33,9 +33,11 @@ typedef struct _MMSmsMbim MMSmsMbim; typedef struct _MMSmsMbimClass MMSmsMbimClass; +typedef struct _MMSmsMbimPrivate MMSmsMbimPrivate; struct _MMSmsMbim { MMBaseSms parent; + MMSmsMbimPrivate *priv; }; struct _MMSmsMbimClass { diff --git a/src/mm-sms-qmi.c b/src/mm-sms-qmi.c index ebd8f845..a131ccc9 100644 --- a/src/mm-sms-qmi.c +++ b/src/mm-sms-qmi.c @@ -37,6 +37,10 @@ G_DEFINE_TYPE (MMSmsQmi, mm_sms_qmi, MM_TYPE_BASE_SMS) +struct _MMSmsQmiPrivate { + MMBaseModem *modem; +}; + /*****************************************************************************/ static gboolean @@ -46,18 +50,10 @@ ensure_qmi_client (MMSmsQmi *self, GAsyncReadyCallback callback, gpointer user_data) { - MMBaseModem *modem = NULL; QmiClient *client; MMPortQmi *port; - g_object_get (self, - MM_BASE_SMS_MODEM, &modem, - NULL); - g_assert (MM_IS_BASE_MODEM (modem)); - - port = mm_broadband_modem_qmi_peek_port_qmi (MM_BROADBAND_MODEM_QMI (modem)); - g_object_unref (modem); - + port = mm_broadband_modem_qmi_peek_port_qmi (MM_BROADBAND_MODEM_QMI (self->priv->modem)); if (!port) { g_task_report_new_error (self, callback, @@ -119,7 +115,6 @@ check_sms_type_support (MMSmsQmi *self, /* Store the SMS */ typedef struct { - MMBaseModem *modem; QmiClientWms *client; MMSmsStorage storage; GList *current; @@ -129,7 +124,6 @@ static void sms_store_context_free (SmsStoreContext *ctx) { g_object_unref (ctx->client); - g_object_unref (ctx->modem); g_slice_free (SmsStoreContext, ctx); } @@ -260,11 +254,12 @@ sms_store_next_part (GTask *task) } static void -sms_store (MMBaseSms *self, +sms_store (MMBaseSms *_self, MMSmsStorage storage, GAsyncReadyCallback callback, gpointer user_data) { + MMSmsQmi *self = MM_SMS_QMI (_self); SmsStoreContext *ctx; QmiClient *client = NULL; GError *error = NULL; @@ -280,17 +275,13 @@ sms_store (MMBaseSms *self, ctx = g_slice_new0 (SmsStoreContext); ctx->client = QMI_CLIENT_WMS (g_object_ref (client)); ctx->storage = storage; - g_object_get (self, - MM_BASE_SMS_MODEM, &ctx->modem, - NULL); - - ctx->current = mm_base_sms_get_parts (self); + ctx->current = mm_base_sms_get_parts (_self); task = g_task_new (self, NULL, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify)sms_store_context_free); /* Check whether we support the given SMS type */ - if (!check_sms_type_support (MM_SMS_QMI (self), ctx->modem, (MMSmsPart *)ctx->current->data, &error)) { + if (!check_sms_type_support (MM_SMS_QMI (self), self->priv->modem, (MMSmsPart *)ctx->current->data, &error)) { g_task_return_error (task, error); g_object_unref (task); return; @@ -304,7 +295,6 @@ sms_store (MMBaseSms *self, /* Send the SMS */ typedef struct { - MMBaseModem *modem; QmiClientWms *client; gboolean from_storage; GList *current; @@ -314,7 +304,6 @@ static void sms_send_context_free (SmsSendContext *ctx) { g_object_unref (ctx->client); - g_object_unref (ctx->modem); g_slice_free (SmsSendContext, ctx); } @@ -595,10 +584,11 @@ sms_send_next_part (GTask *task) } static void -sms_send (MMBaseSms *self, - GAsyncReadyCallback callback, - gpointer user_data) +sms_send (MMBaseSms *_self, + GAsyncReadyCallback callback, + gpointer user_data) { + MMSmsQmi *self = MM_SMS_QMI (_self); SmsSendContext *ctx; QmiClient *client = NULL; GError *error = NULL; @@ -613,20 +603,16 @@ sms_send (MMBaseSms *self, /* Setup the context */ ctx = g_slice_new0 (SmsSendContext); ctx->client = QMI_CLIENT_WMS (g_object_ref (client)); - g_object_get (self, - MM_BASE_SMS_MODEM, &ctx->modem, - NULL); - /* If the SMS is STORED, try to send from storage */ - ctx->from_storage = (mm_base_sms_get_storage (self) != MM_SMS_STORAGE_UNKNOWN); + ctx->from_storage = (mm_base_sms_get_storage (_self) != MM_SMS_STORAGE_UNKNOWN); - ctx->current = mm_base_sms_get_parts (self); + ctx->current = mm_base_sms_get_parts (_self); task = g_task_new (self, NULL, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify)sms_send_context_free); /* Check whether we support the given SMS type */ - if (!check_sms_type_support (MM_SMS_QMI (self), ctx->modem, (MMSmsPart *)ctx->current->data, &error)) { + if (!check_sms_type_support (MM_SMS_QMI (self), self->priv->modem, (MMSmsPart *)ctx->current->data, &error)) { g_task_return_error (task, error); g_object_unref (task); return; @@ -638,7 +624,6 @@ sms_send (MMBaseSms *self, /*****************************************************************************/ typedef struct { - MMBaseModem *modem; QmiClientWms *client; GList *current; guint n_failed; @@ -648,7 +633,6 @@ static void sms_delete_parts_context_free (SmsDeletePartsContext *ctx) { g_object_unref (ctx->client); - g_object_unref (ctx->modem); g_slice_free (SmsDeletePartsContext, ctx); } @@ -771,9 +755,6 @@ sms_delete (MMBaseSms *self, ctx = g_slice_new0 (SmsDeletePartsContext); ctx->client = QMI_CLIENT_WMS (g_object_ref (client)); - g_object_get (self, - MM_BASE_SMS_MODEM, &ctx->modem, - NULL); task = g_task_new (self, NULL, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify)sms_delete_parts_context_free); @@ -790,24 +771,45 @@ mm_sms_qmi_new (MMBaseModem *modem, gboolean is_3gpp, MMSmsStorage default_storage) { - return MM_BASE_SMS (g_object_new (MM_TYPE_SMS_QMI, - MM_BASE_SMS_MODEM, modem, - MM_BIND_TO, G_OBJECT (modem), - MM_BASE_SMS_IS_3GPP, is_3gpp, - MM_BASE_SMS_DEFAULT_STORAGE, default_storage, - NULL)); + MMBaseSms *sms; + + g_return_val_if_fail (MM_IS_BROADBAND_MODEM_QMI (modem), NULL); + + sms = MM_BASE_SMS (g_object_new (MM_TYPE_SMS_QMI, + MM_BIND_TO, G_OBJECT (modem), + MM_BASE_SMS_IS_3GPP, is_3gpp, + MM_BASE_SMS_DEFAULT_STORAGE, default_storage, + NULL)); + MM_SMS_QMI (sms)->priv->modem = g_object_ref (modem); + return sms; } static void mm_sms_qmi_init (MMSmsQmi *self) { + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_SMS_QMI, MMSmsQmiPrivate); +} + +static void +dispose (GObject *object) +{ + MMSmsQmi *self = MM_SMS_QMI (object); + + g_clear_object (&self->priv->modem); + + G_OBJECT_CLASS (mm_sms_qmi_parent_class)->dispose (object); } static void mm_sms_qmi_class_init (MMSmsQmiClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); MMBaseSmsClass *base_sms_class = MM_BASE_SMS_CLASS (klass); + g_type_class_add_private (object_class, sizeof (MMSmsQmiPrivate)); + + object_class->dispose = dispose; + base_sms_class->store = sms_store; base_sms_class->store_finish = sms_store_finish; base_sms_class->send = sms_send; diff --git a/src/mm-sms-qmi.h b/src/mm-sms-qmi.h index 1dda2a95..e59ff4ec 100644 --- a/src/mm-sms-qmi.h +++ b/src/mm-sms-qmi.h @@ -35,9 +35,11 @@ typedef struct _MMSmsQmi MMSmsQmi; typedef struct _MMSmsQmiClass MMSmsQmiClass; +typedef struct _MMSmsQmiPrivate MMSmsQmiPrivate; struct _MMSmsQmi { MMBaseSms parent; + MMSmsQmiPrivate *priv; }; struct _MMSmsQmiClass { -- cgit v1.2.3-70-g09d2 From 51ff44f1f5fc54470596ee538855e1ca42ee43b8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Apr 2025 20:26:43 -0500 Subject: sms-list: remove usage of MMBaseModem Not used for anything anymore so we can remove the property. Signed-off-by: Dan Williams --- src/mm-iface-modem-messaging.c | 2 +- src/mm-sms-list.c | 24 +----------------------- src/mm-sms-list.h | 7 ++----- 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/mm-iface-modem-messaging.c b/src/mm-iface-modem-messaging.c index d349de35..93cd0ae1 100644 --- a/src/mm-iface-modem-messaging.c +++ b/src/mm-iface-modem-messaging.c @@ -1020,7 +1020,7 @@ interface_enabling_step (GTask *task) case ENABLING_STEP_FIRST: { MMSmsList *list; - list = mm_sms_list_new (MM_BASE_MODEM (self), G_OBJECT (self)); + list = mm_sms_list_new (G_OBJECT (self)); g_object_set (self, MM_IFACE_MODEM_MESSAGING_SMS_LIST, list, NULL); diff --git a/src/mm-sms-list.c b/src/mm-sms-list.c index b4b8619b..30ce1cc4 100644 --- a/src/mm-sms-list.c +++ b/src/mm-sms-list.c @@ -24,7 +24,6 @@ #define _LIBMM_INSIDE_MM #include -#include "mm-iface-modem-messaging.h" #include "mm-sms-list.h" #include "mm-base-sms.h" #include "mm-log-object.h" @@ -40,10 +39,8 @@ G_DEFINE_TYPE_EXTENDED (MMSmsList, mm_sms_list, G_TYPE_OBJECT, 0, enum { PROP_0, PROP_BIND_TO, - PROP_MODEM, PROP_LAST }; -static GParamSpec *properties[PROP_LAST]; enum { SIGNAL_ADDED, @@ -55,8 +52,6 @@ static guint signals[SIGNAL_LAST]; struct _MMSmsListPrivate { /* The object this SMS list is bound to */ GObject *bind_to; - /* The owner modem */ - MMBaseModem *modem; /* List of sms objects */ GList *list; }; @@ -456,11 +451,10 @@ log_object_build_id (MMLogObject *_self) /*****************************************************************************/ MMSmsList * -mm_sms_list_new (MMBaseModem *modem, GObject *bind_to) +mm_sms_list_new (GObject *bind_to) { /* Create the object */ return g_object_new (MM_TYPE_SMS_LIST, - MM_SMS_LIST_MODEM, modem, MM_BIND_TO, bind_to, NULL); } @@ -479,10 +473,6 @@ set_property (GObject *object, self->priv->bind_to = g_value_dup_object (value); mm_bind_to (MM_BIND (self), NULL, self->priv->bind_to); break; - case PROP_MODEM: - g_clear_object (&self->priv->modem); - self->priv->modem = g_value_dup_object (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -501,9 +491,6 @@ get_property (GObject *object, case PROP_BIND_TO: g_value_set_object (value, self->priv->bind_to); break; - case PROP_MODEM: - g_value_set_object (value, self->priv->modem); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -524,7 +511,6 @@ dispose (GObject *object) { MMSmsList *self = MM_SMS_LIST (object); - g_clear_object (&self->priv->modem); g_clear_object (&self->priv->bind_to); g_list_foreach (self->priv->list, (GFunc)_release_sms_internal, self); g_clear_pointer (&self->priv->list, (GDestroyNotify)g_list_free); @@ -556,14 +542,6 @@ mm_sms_list_class_init (MMSmsListClass *klass) object_class->dispose = dispose; /* Properties */ - properties[PROP_MODEM] = - g_param_spec_object (MM_SMS_LIST_MODEM, - "Modem", - "The Modem which owns this SMS list", - MM_TYPE_BASE_MODEM, - G_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]); - g_object_class_override_property (object_class, PROP_BIND_TO, MM_BIND_TO); /* Signals */ diff --git a/src/mm-sms-list.h b/src/mm-sms-list.h index 53fa63f0..51228672 100644 --- a/src/mm-sms-list.h +++ b/src/mm-sms-list.h @@ -19,7 +19,7 @@ #include #include -#include "mm-base-modem.h" +#include "mm-base-sms.h" #include "mm-sms-part.h" #define MM_TYPE_SMS_LIST (mm_sms_list_get_type ()) @@ -33,8 +33,6 @@ typedef struct _MMSmsList MMSmsList; typedef struct _MMSmsListClass MMSmsListClass; typedef struct _MMSmsListPrivate MMSmsListPrivate; -#define MM_SMS_LIST_MODEM "sms-list-modem" - #define MM_SMS_ADDED "sms-added" #define MM_SMS_DELETED "sms-deleted" @@ -57,8 +55,7 @@ struct _MMSmsListClass { GType mm_sms_list_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSmsList, g_object_unref) -MMSmsList *mm_sms_list_new (MMBaseModem *modem, - GObject *bind_to); +MMSmsList *mm_sms_list_new (GObject *bind_to); GStrv mm_sms_list_get_paths (MMSmsList *self); guint mm_sms_list_get_count (MMSmsList *self); -- cgit v1.2.3-70-g09d2 From 1d5cc0addb6576d007183454c0702d8ee3ab586f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Apr 2025 20:31:53 -0500 Subject: broadband-modem-qmi,broadband-modem-mbim: always use SMS_PART_INVALID_INDEX unstored parts MMSmsList has logic to allow multiple unstored messages as long as they use SMS_PART_INVALID_INDEX. These messages aren't stored so they don't have an index. But the MBIM and QMI modems used index 0 for unstored messages, meaning there could only ever be one and also that multipart messages would fail to be combined. Let's fix that by just using SMS_PART_INVALID_INDEX for every scenario where an unstored message comes in. Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/979 Signed-off-by: Dan Williams --- src/meson.build | 33 ++++++++-- src/mm-broadband-modem-mbim.c | 31 ++++++++-- src/mm-broadband-modem-qmi.c | 10 +-- src/tests/meson.build | 1 + src/tests/test-sms-list.c | 140 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 199 insertions(+), 16 deletions(-) create mode 100644 src/tests/test-sms-list.c diff --git a/src/meson.build b/src/meson.build index a9be07b0..6e1aae89 100644 --- a/src/meson.build +++ b/src/meson.build @@ -210,6 +210,7 @@ libport_dep = declare_dependency( sources = files( 'mm-auth-provider.c', 'mm-context.c', + 'mm-bind.c', ) incs = [ @@ -239,6 +240,33 @@ libauth_dep = declare_dependency( link_with: libauth, ) +# SMS library +sources = files( + 'mm-sms-list.c', + 'mm-base-sms.c', +) + +incs = [ + top_inc, +] + +deps = [libmm_glib_dep, libhelpers_dep, libauth_dep] + +private_deps = [] + +libsms = static_library( + 'sms', + sources: sources, + include_directories: incs, + dependencies: deps, +) + +libsms_dep = declare_dependency( + include_directories: ['.'], + dependencies: deps, + link_with: libsms, +) + # Daemon enums, required by plugins headers = files( 'mm-base-bearer.h', @@ -297,15 +325,12 @@ sources = files( 'mm-base-modem-at.c', 'mm-base-modem.c', 'mm-base-sim.c', - 'mm-base-sms.c', 'mm-sms-at.c', - 'mm-bind.c', 'mm-bearer-list.c', 'mm-broadband-bearer.c', 'mm-broadband-modem.c', 'mm-call-list.c', 'mm-cbm-list.c', - 'mm-context.c', 'mm-device.c', 'mm-dispatcher.c', 'mm-dispatcher-connection.c', @@ -334,7 +359,6 @@ sources = files( 'mm-port-probe.c', 'mm-port-probe-at.c', 'mm-private-boxed-types.c', - 'mm-sms-list.c', 'mm-sleep-context.c', ) @@ -344,6 +368,7 @@ deps = [ gmodule_dep, libport_dep, libqcdm_dep, + libsms_dep, libauth_dep, ] diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 5d7e37be..9957fe9e 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -5840,6 +5840,7 @@ static gboolean process_pdu_messages (MMBroadbandModemMbim *self, guint32 messages_count, MbimSmsPduReadRecordArray *pdu_messages, guint expected_index, + gboolean unstored, GError **error); static void @@ -5864,6 +5865,7 @@ sms_notification_read_flash_sms (MMBroadbandModemMbim *self, messages_count, pdu_messages, SMS_PART_INVALID_INDEX, + TRUE, &error)) mm_obj_dbg (self, "flash SMS message reading failed: %s", error->message); } @@ -5943,6 +5945,7 @@ alert_sms_read_query_ready (MbimDevice *device, messages_count, pdu_messages, ctx->expected_index, + FALSE, &error)) mm_obj_dbg (ctx->self, "SMS message reading failed: %s", error->message); @@ -9024,12 +9027,13 @@ load_initial_sms_parts_finish (MMIfaceModemMessaging *self, static void add_sms_part (MMBroadbandModemMbim *self, const MbimSmsPduReadRecord *pdu, + guint part_index, guint expected_index) { MMSmsPart *part; g_autoptr(GError) error = NULL; - part = mm_sms_part_3gpp_new_from_binary_pdu (pdu->message_index, + part = mm_sms_part_3gpp_new_from_binary_pdu (part_index, pdu->pdu_data, pdu->pdu_data_size, self, @@ -9071,6 +9075,7 @@ process_pdu_messages (MMBroadbandModemMbim *self, guint32 messages_count, MbimSmsPduReadRecordArray *pdu_messages, guint expected_index, + gboolean unstored, GError **error) { guint i; @@ -9096,11 +9101,26 @@ process_pdu_messages (MMBroadbandModemMbim *self, mm_obj_dbg (self, "%u SMS PDUs reported", messages_count); for (i = 0; i < messages_count; i++) { - if (pdu_messages[i]) { - mm_obj_dbg (self, "processing SMS PDU %u/%u...", i+1, messages_count); - add_sms_part (self, pdu_messages[i], expected_index); - } else + guint message_index; + + if (!pdu_messages[i]) { mm_obj_dbg (self, "ignoring invalid SMS PDU %u/%u...", i+1, messages_count); + continue; + } + + mm_obj_dbg (self, "processing SMS PDU %u/%u...", i+1, messages_count); + + message_index = pdu_messages[i]->message_index; + if (unstored && message_index != 0) { + mm_obj_warn (self, + "processed unstored PDU with non-zero message index (%u)", + message_index); + } + + add_sms_part (self, + pdu_messages[i], + unstored ? SMS_PART_INVALID_INDEX : message_index, + expected_index); } return TRUE; @@ -9135,6 +9155,7 @@ sms_read_query_ready (MbimDevice *device, messages_count, pdu_messages, SMS_PART_INVALID_INDEX, + FALSE, &error)) g_task_return_error (task, error); else diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 4f153009..6d5b8b20 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -8414,7 +8414,6 @@ messaging_event_report_indication_cb (QmiClientNas *client, QmiWmsAckIndicator ack_ind; guint32 transaction_id; QmiWmsMessageFormat msg_format; - QmiWmsMessageTagType tag; GArray *raw_data = NULL; /* Handle transfer-route MT messages */ @@ -8459,13 +8458,10 @@ messaging_event_report_indication_cb (QmiClientNas *client, } /* Defaults for transfer-route messages, which are not stored anywhere */ - storage = QMI_WMS_STORAGE_TYPE_NONE; - memory_index = 0; - tag = QMI_WMS_MESSAGE_TAG_TYPE_MT_NOT_READ; add_new_read_sms_part (MM_IFACE_MODEM_MESSAGING (self), - storage, - memory_index, - tag, + QMI_WMS_STORAGE_TYPE_NONE, + SMS_PART_INVALID_INDEX, + QMI_WMS_MESSAGE_TAG_TYPE_MT_NOT_READ, msg_format, TRUE, raw_data); diff --git a/src/tests/meson.build b/src/tests/meson.build index a6a1ae72..ea9ea3a3 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -10,6 +10,7 @@ test_units = { 'modem-helpers': libhelpers_dep, 'sms-part-3gpp': libhelpers_dep, 'sms-part-cdma': libhelpers_dep, + 'sms-list': libsms_dep, 'udev-rules': libkerneldevice_dep, } diff --git a/src/tests/test-sms-list.c b/src/tests/test-sms-list.c new file mode 100644 index 00000000..335d6cec --- /dev/null +++ b/src/tests/test-sms-list.c @@ -0,0 +1,140 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2025 Dan Williams + */ + +#include +#include +#include +#include +#include + +#define _LIBMM_INSIDE_MM +#include + +#include "mm-sms-part-3gpp.h" +#include "mm-sms-list.h" +#include "mm-log-test.h" +#include "mm-base-modem.h" + +#include "mm-iface-modem-messaging.h" + +/****************************************************************/ + +static void +test_mbim_multipart_unstored (void) +{ + static const gchar *part1_pdu = + "07912160130300f4440b915155685703f900005240713104738a3e050003c40202da6f37881e96" + "9fcbf4b4fb0ccabfeb20f4fb0ea287e5e7323ded3e83dae17519747fcbd96490b95c6683d27310" + "1d5d0601"; + static const gchar *part2_pdu = + "07912160130300f4440b915155685703f900005240713104738aa0050003c40201ac69373d7c2e" + "83e87538bc2cbf87e565d039dc2e83c220769a4e6797416132394d4fbfdda0fb5b4e4783c2ee3c" + "888e2e83e86fd0db0c1a86e769f71b647eb3d9ef7bda7d06a5e7a0b09b0c9ab3df74109c1dce83" + "e8e8301d44479741f9771d949e83e861f9b94c4fbbcf20f13b4c9f83e8e832485c068ddfedf6db" + "0da2a3cba0fcbb0e1abfdb"; + MMSmsPart *part1, *part2; + MMSmsList *list; + MMBaseSms *sms1, *sms2; + GError *error = NULL; + + /* Some MBIM devices (Dell 5821e) report SMSes via the MBIM_CID_SMS_READ + * unsolicited notification usually used for Class-0 (flash/alert) messages. + * These always have a message index of 0; thus when a multipart SMS + * arrives it comes as two individual notifications both with 0 indexes. + * The MBIM modem code used SMS_PART_INVALID_INDEX for unstored SMSes. + * Ensure the MMSmsList can handle combining the two parts with the same + * index. + */ + part1 = mm_sms_part_3gpp_new_from_pdu (SMS_PART_INVALID_INDEX, part1_pdu, NULL, &error); + g_assert_no_error (error); + part2 = mm_sms_part_3gpp_new_from_pdu (SMS_PART_INVALID_INDEX, part2_pdu, NULL, &error); + g_assert_no_error (error); + + list = mm_sms_list_new (NULL); + + sms1 = MM_BASE_SMS (g_object_new (MM_TYPE_BASE_SMS, + MM_BASE_SMS_IS_3GPP, TRUE, + MM_BASE_SMS_DEFAULT_STORAGE, MM_SMS_STORAGE_MT, + NULL)); + mm_sms_list_take_part (list, + sms1, + part1, + MM_SMS_STATE_RECEIVED, + MM_SMS_STORAGE_MT, + &error); + g_assert_no_error (error); + + sms2 = MM_BASE_SMS (g_object_new (MM_TYPE_BASE_SMS, + MM_BASE_SMS_IS_3GPP, TRUE, + MM_BASE_SMS_DEFAULT_STORAGE, MM_SMS_STORAGE_MT, + NULL)); + mm_sms_list_take_part (list, + sms2, + part2, + MM_SMS_STATE_RECEIVED, + MM_SMS_STORAGE_MT, + &error); + g_assert_no_error (error); + + g_assert_cmpint (mm_sms_list_get_count (list), ==, 1); +} + +/****************************************************************/ + +static void +test_mbim_multipart_zero_index (void) +{ + static const gchar *pdu = + "07912160130300f4440b915155685703f900005240713104738a3e050003c40202da6f37881e96" + "9fcbf4b4fb0ccabfeb20f4fb0ea287e5e7323ded3e83dae17519747fcbd96490b95c6683d27310" + "1d5d0601"; + MMSmsPart *part; + MMSmsList *list; + MMBaseSms *sms; + GError *error = NULL; + + part = mm_sms_part_3gpp_new_from_pdu (0, pdu, NULL, &error); + g_assert_no_error (error); + + list = mm_sms_list_new (NULL); + + sms = MM_BASE_SMS (g_object_new (MM_TYPE_BASE_SMS, + MM_BASE_SMS_IS_3GPP, TRUE, + MM_BASE_SMS_DEFAULT_STORAGE, MM_SMS_STORAGE_MT, + NULL)); + mm_sms_list_take_part (list, + sms, + part, + MM_SMS_STATE_RECEIVED, + MM_SMS_STORAGE_MT, + &error); + g_assert_no_error (error); + + g_assert_cmpint (mm_sms_list_get_count (list), ==, 1); +} + +/****************************************************************/ + +int main (int argc, char **argv) +{ + setlocale (LC_ALL, ""); + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/MM/SMS/3GPP/sms-list/zero-index", test_mbim_multipart_zero_index); + g_test_add_func ("/MM/SMS/3GPP/sms-list/mbim-multipart-unstored", test_mbim_multipart_unstored); + + return g_test_run (); +} -- cgit v1.2.3-70-g09d2