diff options
-rw-r--r-- | plugins/icera/mm-broadband-modem-icera.c | 16 | ||||
-rw-r--r-- | src/mm-base-bearer.c | 9 | ||||
-rw-r--r-- | src/mm-base-bearer.h | 1 | ||||
-rw-r--r-- | src/mm-bearer-list.c | 16 | ||||
-rw-r--r-- | src/mm-bearer-list.h | 2 | ||||
-rw-r--r-- | src/mm-broadband-bearer.c | 1 | ||||
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 251 | ||||
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 19 | ||||
-rw-r--r-- | src/mm-broadband-modem.c | 26 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp-profile-manager.c | 190 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp-profile-manager.h | 7 | ||||
-rw-r--r-- | src/mm-modem-helpers.c | 21 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 4 |
13 files changed, 354 insertions, 209 deletions
diff --git a/plugins/icera/mm-broadband-modem-icera.c b/plugins/icera/mm-broadband-modem-icera.c index e60d4bd5..26016c4c 100644 --- a/plugins/icera/mm-broadband-modem-icera.c +++ b/plugins/icera/mm-broadband-modem-icera.c @@ -1954,15 +1954,21 @@ store_profile_context_free (StoreProfileContext *ctx) static gint modem_3gpp_profile_manager_store_profile_finish (MMIfaceModem3gppProfileManager *self, GAsyncResult *res, + gint *out_profile_id, + MMBearerApnType *out_apn_type, GError **error) { StoreProfileContext *ctx; if (!g_task_propagate_boolean (G_TASK (res), error)) - return MM_3GPP_PROFILE_ID_UNKNOWN; + return FALSE; ctx = g_task_get_task_data (G_TASK (res)); - return ctx->profile_id; + if (out_profile_id) + *out_profile_id = ctx->profile_id; + if (out_apn_type) + *out_apn_type = MM_BEARER_APN_TYPE_NONE; + return TRUE; } static void profile_manager_store_profile_auth_settings (GTask *task); @@ -2076,7 +2082,7 @@ profile_manager_parent_store_profile_ready (MMIfaceModem3gppProfileManager *self { GError *error = NULL; - if (iface_modem_3gpp_profile_manager_parent->store_profile_finish (self, res, &error) == MM_3GPP_PROFILE_ID_UNKNOWN) { + if (!iface_modem_3gpp_profile_manager_parent->store_profile_finish (self, res, NULL, NULL, &error)) { g_task_return_error (task, error); g_object_unref (task); return; @@ -2088,12 +2094,15 @@ profile_manager_parent_store_profile_ready (MMIfaceModem3gppProfileManager *self static void modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, MM3gppProfile *profile, + const gchar *index_field, GAsyncReadyCallback callback, gpointer user_data) { StoreProfileContext *ctx; GTask *task; + g_assert (g_strcmp0 (index_field, "profile-id") == 0); + task = g_task_new (self, NULL, callback, user_data); ctx = g_slice_new0 (StoreProfileContext); ctx->profile = g_object_ref (profile); @@ -2104,6 +2113,7 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, iface_modem_3gpp_profile_manager_parent->store_profile ( self, profile, + index_field, (GAsyncReadyCallback)profile_manager_parent_store_profile_ready, task); } diff --git a/src/mm-base-bearer.c b/src/mm-base-bearer.c index cd6365ac..a6b5c65f 100644 --- a/src/mm-base-bearer.c +++ b/src/mm-base-bearer.c @@ -1427,6 +1427,15 @@ mm_base_bearer_get_profile_id (MMBaseBearer *self) return mm_gdbus_bearer_get_profile_id (MM_GDBUS_BEARER (self)); } +MMBearerApnType +mm_base_bearer_get_apn_type (MMBaseBearer *self) +{ + /* when none explicitly requested, apn type always defaults to internet */ + return (self->priv->config ? + mm_bearer_properties_get_apn_type (self->priv->config) : + MM_BEARER_APN_TYPE_DEFAULT); +} + /*****************************************************************************/ static void diff --git a/src/mm-base-bearer.h b/src/mm-base-bearer.h index 7432c04a..c497a6d5 100644 --- a/src/mm-base-bearer.h +++ b/src/mm-base-bearer.h @@ -197,6 +197,7 @@ MMBearerStatus mm_base_bearer_get_status (MMBaseBearer *self); MMBearerProperties *mm_base_bearer_peek_config (MMBaseBearer *self); MMBearerProperties *mm_base_bearer_get_config (MMBaseBearer *self); gint mm_base_bearer_get_profile_id (MMBaseBearer *self); +MMBearerApnType mm_base_bearer_get_apn_type (MMBaseBearer *self); void mm_base_bearer_connect (MMBaseBearer *self, GAsyncReadyCallback callback, diff --git a/src/mm-bearer-list.c b/src/mm-bearer-list.c index 24fdac0a..790115eb 100644 --- a/src/mm-bearer-list.c +++ b/src/mm-bearer-list.c @@ -171,6 +171,22 @@ mm_bearer_list_find_by_profile_id (MMBearerList *self, return NULL; } +MMBaseBearer * +mm_bearer_list_find_by_apn_type (MMBearerList *self, + MMBearerApnType apn_type) +{ + GList *l; + + g_assert (apn_type != MM_BEARER_APN_TYPE_NONE); + + for (l = self->priv->bearers; l; l = g_list_next (l)) { + if (mm_base_bearer_get_apn_type (MM_BASE_BEARER (l->data)) == apn_type) + return g_object_ref (l->data); + } + + return NULL; +} + /*****************************************************************************/ typedef struct { diff --git a/src/mm-bearer-list.h b/src/mm-bearer-list.h index 71a394ba..8f3c8d49 100644 --- a/src/mm-bearer-list.h +++ b/src/mm-bearer-list.h @@ -76,6 +76,8 @@ MMBaseBearer *mm_bearer_list_find_by_path (MMBearerList *self, const gchar *path); MMBaseBearer *mm_bearer_list_find_by_profile_id (MMBearerList *self, gint profile_id); +MMBaseBearer *mm_bearer_list_find_by_apn_type (MMBearerList *self, + MMBearerApnType apn_type); void mm_bearer_list_disconnect_all_bearers (MMBearerList *self, GAsyncReadyCallback callback, diff --git a/src/mm-broadband-bearer.c b/src/mm-broadband-bearer.c index 1ae07dcf..ffb5d6e8 100644 --- a/src/mm-broadband-bearer.c +++ b/src/mm-broadband-bearer.c @@ -660,6 +660,7 @@ select_profile_3gpp (MMBroadbandBearer *self, mm_iface_modem_3gpp_profile_manager_set_profile ( MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (modem), mm_bearer_properties_peek_3gpp_profile (bearer_properties), + "profile-id", FALSE, /* not strict! */ (GAsyncReadyCallback)select_profile_3gpp_set_profile_ready, task); diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 55f855ea..a5e11e68 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -6330,15 +6330,29 @@ modem_3gpp_profile_manager_list_profiles (MMIfaceModem3gppProfileManager *_self /*****************************************************************************/ /* Store profile (3GPP profile management interface) */ -static gint +typedef struct { + gint profile_id; + MMBearerApnType apn_type; +} StoreProfileContext; + +static gboolean modem_3gpp_profile_manager_store_profile_finish (MMIfaceModem3gppProfileManager *self, GAsyncResult *res, + gint *out_profile_id, + MMBearerApnType *out_apn_type, GError **error) { + StoreProfileContext *ctx; + if (!g_task_propagate_boolean (G_TASK (res), error)) - return MM_3GPP_PROFILE_ID_UNKNOWN; + return FALSE; - return GPOINTER_TO_INT (g_task_get_task_data (G_TASK (res))); + ctx = g_task_get_task_data (G_TASK (res)); + if (out_profile_id) + *out_profile_id = ctx->profile_id; + if (out_apn_type) + *out_apn_type = ctx->apn_type; + return TRUE; } static void @@ -6360,15 +6374,15 @@ profile_manager_provisioned_contexts_set_ready (MbimDevice *device, static void modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *_self, MM3gppProfile *profile, + const gchar *index_field, GAsyncReadyCallback callback, gpointer user_data) { MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + StoreProfileContext *ctx = NULL; MbimDevice *device; GTask *task; GError *error = NULL; - gint profile_id; - MMBearerApnType apn_type; MMBearerAllowedAuth allowed_auth; MbimAuthProtocol auth_protocol = MBIM_AUTH_PROTOCOL_NONE; MbimContextType context_type; @@ -6384,27 +6398,28 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *_self, task = g_task_new (self, NULL, callback, user_data); - profile_id = mm_3gpp_profile_get_profile_id (profile); - g_assert (profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); - g_task_set_task_data (task, GINT_TO_POINTER (profile_id), NULL); + ctx = g_new0 (StoreProfileContext, 1); + ctx->profile_id = MM_3GPP_PROFILE_ID_UNKNOWN; + ctx->apn_type = MM_BEARER_APN_TYPE_NONE; - apn = mm_3gpp_profile_get_apn (profile); + g_task_set_task_data (task, ctx, (GDestroyNotify) g_free); + + ctx->profile_id = mm_3gpp_profile_get_profile_id (profile); - apn_type = mm_3gpp_profile_get_apn_type (profile); - context_type = mm_bearer_apn_type_to_mbim_context_type (apn_type, self, &error); + ctx->apn_type = mm_3gpp_profile_get_apn_type (profile); + apn_type_str = mm_bearer_apn_type_build_string_from_mask (ctx->apn_type); + context_type = mm_bearer_apn_type_to_mbim_context_type (ctx->apn_type, self, &error); if (error) { g_prefix_error (&error, "Failed to convert mbim context type from apn type: "); g_task_return_error (task, error); g_object_unref (task); return; } - context_type_uuid = mbim_uuid_from_context_type (context_type); - apn_type_str = mm_bearer_apn_type_build_string_from_mask (apn_type); + apn = mm_3gpp_profile_get_apn (profile); user = mm_3gpp_profile_get_user (profile); password = mm_3gpp_profile_get_password (profile); - allowed_auth = mm_3gpp_profile_get_allowed_auth (profile); if ((allowed_auth != MM_BEARER_ALLOWED_AUTH_UNKNOWN) || user || password) { auth_protocol = mm_bearer_allowed_auth_to_mbim_auth_protocol (allowed_auth, self, &error); @@ -6416,13 +6431,27 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *_self, } } - if (self->priv->is_profile_management_ext_supported) { + if (g_strcmp0 (index_field, "profile-id") == 0) { + mm_obj_dbg (self, "storing profile '%d': apn '%s', apn type '%s'", + ctx->profile_id, apn, apn_type_str); + message = mbim_message_provisioned_contexts_set_new (ctx->profile_id, + context_type_uuid, + apn ? apn : "", + user ? user : "", + password ? password : "", + MBIM_COMPRESSION_NONE, + auth_protocol, + "", /* provider id */ + &error); + } else if (g_strcmp0 (index_field, "apn-type") == 0) { MbimContextIpType ip_type; MbimContextState state; MbimContextRoamingControl roaming; MbimContextMediaType media_type; MbimContextSource source; + g_assert (self->priv->is_profile_management_ext_supported); + state = mm_boolean_to_mbim_context_state (mm_3gpp_profile_get_enabled (profile)); ip_type = mm_bearer_ip_family_to_mbim_context_ip_type (mm_3gpp_profile_get_ip_type (profile), &error); @@ -6454,15 +6483,10 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *_self, return; } - /* We don't pass the profile ID, because the MS extended version does - * not support it. This is extremely wrong, and I have no idea how we - * can make this work reliably. According to the documentation, the - * modem would choose automatically which profile to update based on - * the specified context type... but what if we have multiple contexts - * of the same type? */ + if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) + mm_obj_warn (self, "ignoring profile id '%d' when storing profile: unsupported", ctx->profile_id); - mm_obj_dbg (self, "using MS extensions to manage provisioned contexts: updating profiles matching context type"); - mm_obj_dbg (self, "updating profiles with context type '%s'", mbim_context_type_get_string (context_type)); + mm_obj_dbg (self, "storing profile '%s': apn '%s'", apn_type_str, apn); message = mbim_message_ms_basic_connect_extensions_provisioned_contexts_set_new (MBIM_CONTEXT_OPERATION_DEFAULT, context_type_uuid, ip_type, @@ -6476,19 +6500,8 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *_self, MBIM_COMPRESSION_NONE, auth_protocol, &error); - } else { - mm_obj_dbg (self, "storing profile '%d': apn '%s', apn type '%s'", - profile_id, apn, apn_type_str); - message = mbim_message_provisioned_contexts_set_new (profile_id, - context_type_uuid, - apn ? apn : "", - user ? user : "", - password ? password : "", - MBIM_COMPRESSION_NONE, - auth_protocol, - "", /* provider id */ - &error); - } + } else + g_assert_not_reached (); if (error) { g_task_return_error (task, error); @@ -6507,19 +6520,6 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *_self, /*****************************************************************************/ /* Delete profile (3GPP profile management interface) */ -typedef struct { - MbimDevice *device; - MM3gppProfile *profile; -} DeleteProfileContext; - -static void -delete_profile_context_free (DeleteProfileContext *ctx) -{ - g_object_unref (ctx->device); - g_object_unref (ctx->profile); - g_slice_free (DeleteProfileContext, ctx); -} - static gboolean modem_3gpp_profile_manager_delete_profile_finish (MMIfaceModem3gppProfileManager *self, GAsyncResult *res, @@ -6545,91 +6545,9 @@ profile_manager_provisioned_contexts_reset_ready (MbimDevice *device, } static void -list_profiles_delete_ready (MMIfaceModem3gppProfileManager *self, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(MbimMessage) message = NULL; - DeleteProfileContext *ctx; - MbimContextType context_type; - const MbimUuid *context_type_uuid = NULL; - GError *error = NULL; - GList *profiles = NULL; - MM3gppProfile *found = NULL; - GList *l; - - ctx = g_task_get_task_data (task); - - if (!modem_3gpp_profile_manager_list_profiles_finish (self, res, &profiles, &error)) { - g_prefix_error (&error, "Couldn't list profiles during delete operation: "); - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* look for the exact profile id match */ - for (l = profiles; l; l = g_list_next (l)) { - MM3gppProfile *profile; - - profile = MM_3GPP_PROFILE (l->data); - if (mm_3gpp_profile_get_profile_id (profile) == mm_3gpp_profile_get_profile_id (ctx->profile)) { - found = profile; - break; - } - } - - if (!found) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't find profile with id '%u'", mm_3gpp_profile_get_profile_id (ctx->profile)); - g_object_unref (task); - g_list_free_full (profiles, g_object_unref); - return; - } - - context_type = mm_bearer_apn_type_to_mbim_context_type (mm_3gpp_profile_get_apn_type (found), self, &error); - if (error) { - g_prefix_error (&error, "Failed to convert mbim context type from apn type: "); - g_task_return_error (task, error); - g_object_unref (task); - g_list_free_full (profiles, g_object_unref); - return; - } - context_type_uuid = mbim_uuid_from_context_type (context_type); - g_list_free_full (profiles, g_object_unref); - - mm_obj_dbg (self, "using MS extensions to manage provisioned contexts: deleting profiles matching context type"); - mm_obj_dbg (self, "deleting profiles with context type '%s'", mbim_context_type_get_string (context_type)); - - message = mbim_message_ms_basic_connect_extensions_provisioned_contexts_set_new (MBIM_CONTEXT_OPERATION_DELETE, - context_type_uuid, - MBIM_CONTEXT_IP_TYPE_DEFAULT, - MBIM_CONTEXT_STATE_DISABLED, - MBIM_CONTEXT_ROAMING_CONTROL_ALLOW_ALL, - MBIM_CONTEXT_MEDIA_TYPE_ALL, - MBIM_CONTEXT_SOURCE_ADMIN, - "", /* access string */ - "", /* user */ - "", /* password */ - MBIM_COMPRESSION_NONE, - MBIM_AUTH_PROTOCOL_NONE, - &error); - if (error) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mbim_device_command (ctx->device, - message, - 10, - NULL, - (GAsyncReadyCallback)profile_manager_provisioned_contexts_reset_ready, - task); -} - -static void modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *_self, MM3gppProfile *profile, + const gchar *index_field, GAsyncReadyCallback callback, gpointer user_data) { @@ -6637,7 +6555,6 @@ modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *_self MbimDevice *device; GTask *task; GError *error = NULL; - gint profile_id; g_autoptr(MbimMessage) message = NULL; if (!peek_device (self, &device, callback, user_data)) @@ -6645,33 +6562,55 @@ modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *_self task = g_task_new (self, NULL, callback, user_data); - profile_id = mm_3gpp_profile_get_profile_id (profile); - g_assert (profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); + if (g_strcmp0 (index_field, "profile-id") == 0) { + gint profile_id; - if (self->priv->is_profile_management_ext_supported) { - DeleteProfileContext *ctx; + profile_id = mm_3gpp_profile_get_profile_id (profile); + g_assert (profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); - ctx = g_slice_new0 (DeleteProfileContext); - ctx->profile = g_object_ref (profile); - ctx->device = g_object_ref (device); - g_task_set_task_data (task, ctx, (GDestroyNotify)delete_profile_context_free); + mm_obj_dbg (self, "deleting profile '%d'", profile_id); + message = mbim_message_provisioned_contexts_set_new (profile_id, + mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_NONE), + "", /* access string */ + "", /* user */ + "", /* pass */ + MBIM_COMPRESSION_NONE, + MBIM_AUTH_PROTOCOL_NONE, + "", /* provider id */ + &error); + } else if (g_strcmp0 (index_field, "apn-type") == 0) { + MMBearerApnType apn_type; + MbimContextType context_type; - modem_3gpp_profile_manager_list_profiles (_self, - (GAsyncReadyCallback)list_profiles_delete_ready, - task); - return; - } + g_assert (self->priv->is_profile_management_ext_supported); + + apn_type = mm_3gpp_profile_get_apn_type (profile); + g_assert (apn_type != MM_BEARER_APN_TYPE_NONE); + + context_type = mm_bearer_apn_type_to_mbim_context_type (apn_type, self, &error); + if (error) + g_prefix_error (&error, "Failed to convert mbim context type from apn type: "); + else { + const MbimUuid *context_type_uuid; + + context_type_uuid = mbim_uuid_from_context_type (context_type); + message = mbim_message_ms_basic_connect_extensions_provisioned_contexts_set_new (MBIM_CONTEXT_OPERATION_DELETE, + context_type_uuid, + MBIM_CONTEXT_IP_TYPE_DEFAULT, + MBIM_CONTEXT_STATE_DISABLED, + MBIM_CONTEXT_ROAMING_CONTROL_ALLOW_ALL, + MBIM_CONTEXT_MEDIA_TYPE_ALL, + MBIM_CONTEXT_SOURCE_ADMIN, + "", /* access string */ + "", /* user */ + "", /* password */ + MBIM_COMPRESSION_NONE, + MBIM_AUTH_PROTOCOL_NONE, + &error); + } + } else + g_assert_not_reached (); - mm_obj_dbg (self, "deleting profile '%d'", profile_id); - message = mbim_message_provisioned_contexts_set_new (profile_id, - mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_NONE), - "", /* access string */ - "", /* user */ - "", /* pass */ - MBIM_COMPRESSION_NONE, - MBIM_AUTH_PROTOCOL_NONE, - "", /* provider id */ - &error); if (error) { g_task_return_error (task, error); g_object_unref (task); diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 68f84f73..990ffce4 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -6118,18 +6118,24 @@ store_profile_context_free (StoreProfileContext *ctx) g_slice_free (StoreProfileContext, ctx); } -static gint +static gboolean modem_3gpp_profile_manager_store_profile_finish (MMIfaceModem3gppProfileManager *self, GAsyncResult *res, + gint *out_profile_id, + MMBearerApnType *out_apn_type, GError **error) { StoreProfileContext *ctx; if (!g_task_propagate_boolean (G_TASK (res), error)) - return MM_3GPP_PROFILE_ID_UNKNOWN; + return FALSE; ctx = g_task_get_task_data (G_TASK (res)); - return ctx->profile_id; + if (out_profile_id) + *out_profile_id = ctx->profile_id; + if (out_apn_type) + *out_apn_type = MM_BEARER_APN_TYPE_NONE; + return TRUE; } static void store_profile_run (GTask *task); @@ -6274,6 +6280,7 @@ store_profile_run (GTask *task) static void modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, MM3gppProfile *profile, + const gchar *index_field, GAsyncReadyCallback callback, gpointer user_data) { @@ -6284,6 +6291,8 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, MMBearerApnType apn_type; MMBearerAllowedAuth allowed_auth; + g_assert (g_strcmp0 (index_field, "profile-id") == 0); + if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self), QMI_SERVICE_WDS, &client, callback, user_data)) @@ -6363,6 +6372,7 @@ delete_profile_ready (QmiClientWds *client, static void modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *self, MM3gppProfile *profile, + const gchar *index_field, GAsyncReadyCallback callback, gpointer user_data) { @@ -6371,6 +6381,8 @@ modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *self, gint profile_id; g_autoptr(QmiMessageWdsDeleteProfileInput) input = NULL; + g_assert (g_strcmp0 (index_field, "profile-id") == 0); + if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self), QMI_SERVICE_WDS, &client, callback, user_data)) @@ -10164,6 +10176,7 @@ set_initial_eps_bearer_modify_profile (GTask *task) mm_iface_modem_3gpp_profile_manager_set_profile (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self), ctx->profile, + "profile-id", TRUE, (GAsyncReadyCallback)set_initial_eps_bearer_modify_profile_ready, task); diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 28a17401..cf7bc83e 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -10497,15 +10497,18 @@ profile_manager_cgdel_set_ready (MMBaseModem *self, } static void -modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *self, - MM3gppProfile *profile, - GAsyncReadyCallback callback, - gpointer user_data) +modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *self, + MM3gppProfile *profile, + const gchar *index_field, + GAsyncReadyCallback callback, + gpointer user_data) { g_autofree gchar *cmd = NULL; GTask *task; gint profile_id; + g_assert (g_strcmp0 (index_field, "profile-id") == 0); + task = g_task_new (self, NULL, callback, user_data); profile_id = mm_3gpp_profile_get_profile_id (profile); @@ -10669,15 +10672,21 @@ modem_3gpp_profile_manager_deactivate_profile (MMIfaceModem3gppProfileManager *s /*****************************************************************************/ /* Store profile (3GPP profile management interface) */ -static gint +static gboolean modem_3gpp_profile_manager_store_profile_finish (MMIfaceModem3gppProfileManager *self, GAsyncResult *res, + gint *out_profile_id, + MMBearerApnType *out_apn_type, GError **error) { if (!g_task_propagate_boolean (G_TASK (res), error)) - return MM_3GPP_PROFILE_ID_UNKNOWN; + return FALSE; - return GPOINTER_TO_INT (g_task_get_task_data (G_TASK (res))); + if (out_profile_id) + *out_profile_id = GPOINTER_TO_INT (g_task_get_task_data (G_TASK (res))); + if (out_apn_type) + *out_apn_type = MM_BEARER_APN_TYPE_NONE; + return TRUE; } static void @@ -10697,6 +10706,7 @@ store_profile_cgdcont_set_ready (MMBaseModem *self, static void modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, MM3gppProfile *profile, + const gchar *index_field, GAsyncReadyCallback callback, gpointer user_data) { @@ -10709,6 +10719,8 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, g_autofree gchar *quoted_apn = NULL; g_autofree gchar *cmd = NULL; + g_assert (g_strcmp0 (index_field, "profile-id") == 0); + task = g_task_new (self, NULL, callback, user_data); profile_id = mm_3gpp_profile_get_profile_id (profile); diff --git a/src/mm-iface-modem-3gpp-profile-manager.c b/src/mm-iface-modem-3gpp-profile-manager.c index 0dfa9026..d2b11fec 100644 --- a/src/mm-iface-modem-3gpp-profile-manager.c +++ b/src/mm-iface-modem-3gpp-profile-manager.c @@ -59,24 +59,39 @@ mm_iface_modem_3gpp_profile_manager_updated (MMIfaceModem3gppProfileManager *sel static gboolean profile_manager_fail_if_connected_bearer (MMIfaceModem3gppProfileManager *self, + const gchar *index_field, gint profile_id, + MMBearerApnType apn_type, GError **error) { g_autoptr(MMBearerList) bearer_list = NULL; g_autoptr(MMBaseBearer) bearer = NULL; - g_assert (profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); - g_object_get (self, MM_IFACE_MODEM_BEARER_LIST, &bearer_list, NULL); - if (bearer_list) - bearer = mm_bearer_list_find_by_profile_id (bearer_list, profile_id); + if (bearer_list) { + if (g_strcmp0 (index_field, "profile-id") == 0) + bearer = mm_bearer_list_find_by_profile_id (bearer_list, profile_id); + else if (g_strcmp0 (index_field, "apn-type") == 0) + bearer = mm_bearer_list_find_by_apn_type (bearer_list, apn_type); + else + g_assert_not_reached (); + } /* If a bearer is found reporting the profile id we're targeting to use, * it means we have a known connected bearer, and we must abort the * operation right away. */ if (bearer) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, - "Cannot use profile %d: found an already connected bearer", profile_id); + if (g_strcmp0 (index_field, "profile-id") == 0) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, + "Cannot use profile %d: found an already connected bearer", profile_id); + } else if (g_strcmp0 (index_field, "apn-type") == 0) { + g_autofree gchar *apn_type_str; + + apn_type_str = mm_bearer_apn_type_build_string_from_mask (apn_type); + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_CONNECTED, + "Cannot use profile %s: found an already connected bearer", apn_type_str); + } else + g_assert_not_reached (); return FALSE; } @@ -101,6 +116,8 @@ typedef enum { typedef struct { SetProfileStep step; MM3gppProfile *requested; + gchar *index_field; + gchar *index_field_value_str; gboolean strict; gboolean new_id; gint min_profile_id; @@ -108,6 +125,8 @@ typedef struct { GEqualFunc profile_apn_cmp; MM3gppProfileCmpFlags profile_cmp_flags; gint profile_id; + MMBearerApnType apn_type; + gchar *apn_type_str; GList *before_list; MM3gppProfile *stored; } SetProfileContext; @@ -118,6 +137,9 @@ set_profile_context_free (SetProfileContext *ctx) mm_3gpp_profile_list_free (ctx->before_list); g_clear_object (&ctx->requested); g_clear_object (&ctx->stored); + g_free (ctx->apn_type_str); + g_free (ctx->index_field); + g_free (ctx->index_field_value_str); g_slice_free (SetProfileContext, ctx); } @@ -177,11 +199,11 @@ profile_manager_store_profile_ready (MMIfaceModem3gppProfileManager *self, SetProfileContext *ctx; GError *error = NULL; gint profile_id; + MMBearerApnType apn_type; ctx = g_task_get_task_data (task); - profile_id = MM_IFACE_MODEM_3GPP_PROFILE_MANAGER_GET_INTERFACE (self)->store_profile_finish (self, res, &error); - if (profile_id == MM_3GPP_PROFILE_ID_UNKNOWN) { + if (!MM_IFACE_MODEM_3GPP_PROFILE_MANAGER_GET_INTERFACE (self)->store_profile_finish (self, res, &profile_id, &apn_type, &error)) { g_task_return_error (task, error); g_object_unref (task); return; @@ -189,11 +211,16 @@ profile_manager_store_profile_ready (MMIfaceModem3gppProfileManager *self, /* when creating a new profile with an unbound input profile id, store the * one received after store */ - if (ctx->profile_id == MM_3GPP_PROFILE_ID_UNKNOWN) - ctx->profile_id = profile_id; + if (g_strcmp0 (ctx->index_field, "profile-id") == 0) { + if (ctx->profile_id == MM_3GPP_PROFILE_ID_UNKNOWN) { + ctx->profile_id = profile_id; + g_free (ctx->index_field_value_str); + ctx->index_field_value_str = g_strdup_printf ("%d", ctx->profile_id); + } + g_assert (ctx->profile_id == profile_id); + } - g_assert (ctx->profile_id == profile_id); - mm_obj_dbg (self, "stored profile with id '%d'", ctx->profile_id); + mm_obj_dbg (self, "stored profile '%s'", ctx->index_field_value_str); ctx->step++; set_profile_step (task); @@ -213,6 +240,7 @@ set_profile_step_store_profile (GTask *task) MM_IFACE_MODEM_3GPP_PROFILE_MANAGER_GET_INTERFACE (self)->store_profile ( self, ctx->requested, + ctx->index_field, (GAsyncReadyCallback) profile_manager_store_profile_ready, task); } @@ -229,9 +257,9 @@ profile_manager_deactivate_profile_ready (MMIfaceModem3gppProfileManager *self, /* profile deactivation errors aren't fatal per se */ if (!MM_IFACE_MODEM_3GPP_PROFILE_MANAGER_GET_INTERFACE (self)->deactivate_profile_finish (self, res, &error)) - mm_obj_dbg (self, "couldn't deactivate profile with id '%d': %s", ctx->profile_id, error->message); + mm_obj_dbg (self, "couldn't deactivate profile '%s': %s", ctx->index_field_value_str, error->message); else - mm_obj_dbg (self, "deactivated profile with id '%d'", ctx->profile_id); + mm_obj_dbg (self, "deactivated profile '%s'", ctx->index_field_value_str); ctx->step++; set_profile_step (task); @@ -278,14 +306,14 @@ profile_manager_check_activated_profile_ready (MMIfaceModem3gppProfileManager *s ctx = g_task_get_task_data (task); if (!MM_IFACE_MODEM_3GPP_PROFILE_MANAGER_GET_INTERFACE (self)->check_activated_profile_finish (self, res, &activated, &error)) { - mm_obj_dbg (self, "couldn't check if profile '%d' is activated: %s", ctx->profile_id, error->message); + mm_obj_dbg (self, "couldn't check if profile '%s' is activated: %s", ctx->index_field_value_str, error->message); ctx->step = SET_PROFILE_STEP_DEACTIVATE_PROFILE; } else if (activated) { - mm_obj_dbg (self, "profile '%d' is activated", ctx->profile_id); + mm_obj_dbg (self, "profile '%s' is activated", ctx->index_field_value_str); ctx->step = SET_PROFILE_STEP_DEACTIVATE_PROFILE; } else { - mm_obj_dbg (self, "profile '%d' is not activated", ctx->profile_id); + mm_obj_dbg (self, "profile '%s' is not activated", ctx->index_field_value_str); ctx->step = SET_PROFILE_STEP_STORE_PROFILE; } set_profile_step (task); @@ -301,11 +329,16 @@ set_profile_step_check_activated_profile (GTask *task) self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); - g_assert (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); + g_assert (((g_strcmp0 (ctx->index_field, "profile-id") == 0) && (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN)) || + ((g_strcmp0 (ctx->index_field, "apn-type") == 0) && (ctx->apn_type != MM_BEARER_APN_TYPE_NONE))); /* First, a quick check on our own bearer list. If we have a known bearer * connected using the same profile id, we fail the operation right away. */ - if (!profile_manager_fail_if_connected_bearer (self, ctx->profile_id, &error)) { + if (!profile_manager_fail_if_connected_bearer (self, + ctx->index_field, + ctx->profile_id, + ctx->apn_type, + &error)) { g_task_return_error (task, error); g_object_unref (task); return; @@ -338,12 +371,19 @@ set_profile_step_select_profile_exact (GTask *task) self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); - g_assert (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); - /* Look for the exact profile we want to use */ - existing = mm_3gpp_profile_list_find_by_profile_id (ctx->before_list, - ctx->profile_id, - &error); + if (g_strcmp0 (ctx->index_field, "profile-id") == 0) { + g_assert (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); + existing = mm_3gpp_profile_list_find_by_profile_id (ctx->before_list, + ctx->profile_id, + &error); + } else if (g_strcmp0 (ctx->index_field, "apn-type") == 0) { + g_assert (ctx->apn_type != MM_BEARER_APN_TYPE_NONE); + existing = mm_3gpp_profile_list_find_by_apn_type (ctx->before_list, + ctx->apn_type, + &error); + } else + g_assert_not_reached (); if (!existing) { g_task_return_error (task, error); g_object_unref (task); @@ -352,10 +392,10 @@ set_profile_step_select_profile_exact (GTask *task) /* If the profile is 100% equal to what we require, nothing to do */ if (mm_3gpp_profile_cmp (existing, ctx->requested, ctx->profile_apn_cmp, ctx->profile_cmp_flags)) { + mm_obj_dbg (self, "reusing profile '%s'", ctx->index_field_value_str); ctx->stored = g_object_ref (existing); - mm_obj_dbg (self, "reusing profile '%d'", ctx->profile_id); } else - mm_obj_dbg (self, "overwriting profile '%d'", ctx->profile_id); + mm_obj_dbg (self, "overwritting profile '%s'", ctx->index_field_value_str); ctx->step++; set_profile_step (task); @@ -371,6 +411,7 @@ set_profile_step_select_profile_new (GTask *task) self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); + g_assert (g_strcmp0 (ctx->index_field, "profile-id") == 0); g_assert (ctx->profile_id == MM_3GPP_PROFILE_ID_UNKNOWN); g_assert (ctx->strict); @@ -404,6 +445,7 @@ set_profile_step_select_profile_best (GTask *task) self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); + g_assert (g_strcmp0 (ctx->index_field, "profile-id") == 0); g_assert (ctx->profile_id == MM_3GPP_PROFILE_ID_UNKNOWN); g_assert (!ctx->strict); @@ -532,12 +574,14 @@ set_profile_step (GTask *task) return; case SET_PROFILE_STEP_SELECT_PROFILE: - if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) { + if (((g_strcmp0 (ctx->index_field, "profile-id") == 0) && (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN)) || + (g_strcmp0 (ctx->index_field, "apn-type") == 0)) { mm_obj_dbg (self, "set profile state (%d/%d): select profile (exact)", ctx->step, SET_PROFILE_STEP_LAST); set_profile_step_select_profile_exact (task); return; } + /* when using profile-id, allow non-strict and new */ if (!ctx->strict) { mm_obj_dbg (self, "set profile state (%d/%d): select profile (best)", ctx->step, SET_PROFILE_STEP_LAST); @@ -560,7 +604,8 @@ set_profile_step (GTask *task) /* If the modem/protocol doesn't allow preselecting the profile id of * a new profile we're going to create, then we won't have a profile id * set at this point. If so, just skip this step. */ - if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) { + if (((g_strcmp0 (ctx->index_field, "profile-id") == 0) && (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN)) || + (g_strcmp0 (ctx->index_field, "apn-type") == 0)) { mm_obj_dbg (self, "set profile state (%d/%d): check activated profile", ctx->step, SET_PROFILE_STEP_LAST); set_profile_step_check_activated_profile (task); @@ -573,7 +618,8 @@ set_profile_step (GTask *task) /* If the modem/protocol doesn't allow preselecting the profile id of * a new profile we're going to create, then we won't have a profile id * set at this point. If so, just skip this step. */ - if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) { + if (((g_strcmp0 (ctx->index_field, "profile-id") == 0) && (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN)) || + (g_strcmp0 (ctx->index_field, "apn-type") == 0)) { mm_obj_dbg (self, "set profile state (%d/%d): deactivate profile", ctx->step, SET_PROFILE_STEP_LAST); set_profile_step_deactivate_profile (task); @@ -586,7 +632,6 @@ set_profile_step (GTask *task) /* if we're reusing an already existing profile, we can jump * to the last step now, there is no need to store any update */ if (ctx->stored) { - g_assert (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); mm_obj_dbg (self, "set profile state (%d/%d): profile already stored", ctx->step, SET_PROFILE_STEP_LAST); ctx->step = SET_PROFILE_STEP_LAST; @@ -620,6 +665,7 @@ set_profile_step (GTask *task) void mm_iface_modem_3gpp_profile_manager_set_profile (MMIfaceModem3gppProfileManager *self, MM3gppProfile *requested, + const gchar *index_field, gboolean strict, GAsyncReadyCallback callback, gpointer user_data) @@ -633,10 +679,33 @@ mm_iface_modem_3gpp_profile_manager_set_profile (MMIfaceModem3gppProfileManager ctx = g_slice_new0 (SetProfileContext); ctx->step = SET_PROFILE_STEP_FIRST; ctx->requested = g_object_ref (requested); + ctx->index_field = g_strdup (index_field); ctx->strict = strict; ctx->profile_id = mm_3gpp_profile_get_profile_id (requested); + ctx->apn_type = mm_3gpp_profile_get_apn_type (requested); + ctx->apn_type_str = mm_bearer_apn_type_build_string_from_mask (ctx->apn_type); g_task_set_task_data (task, ctx, (GDestroyNotify)set_profile_context_free); + /* Validate input setup: + * - allow 'profile-id' as index field, both strict and not strict. + * - allow 'apn-type' as index field, always strict. + */ + if (g_strcmp0 (ctx->index_field, "profile-id") == 0) + ctx->index_field_value_str = g_strdup_printf ("%d", ctx->profile_id); + else if (g_strcmp0 (ctx->index_field, "apn-type") == 0) { + g_assert (ctx->strict); + ctx->index_field_value_str = g_strdup (ctx->apn_type_str); + /* when using apn-type as index, the field is mandatory because both "create" + * and "update" are actually the same operation. */ + if (ctx->apn_type == MM_BEARER_APN_TYPE_NONE) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Missing index field ('apn-type') in profile settings"); + g_object_unref (task); + return; + } + } else + g_assert_not_reached (); + /* normalize IP family right away */ ip_family = mm_3gpp_profile_get_ip_type (requested); mm_3gpp_normalize_ip_family (&ip_family); @@ -944,8 +1013,11 @@ handle_set_auth_ready (MMBaseModem *self, GAsyncResult *res, HandleSetContext *ctx) { + const gchar *index_field; GError *error = NULL; g_autoptr(MM3gppProfile) profile_requested = NULL; + gint profile_id = MM_3GPP_PROFILE_ID_UNKNOWN; + MMBearerApnType apn_type = MM_BEARER_APN_TYPE_NONE; if (!mm_base_modem_authorize_finish (self, res, &error)) { g_dbus_method_invocation_take_error (ctx->invocation, error); @@ -974,11 +1046,32 @@ handle_set_auth_ready (MMBaseModem *self, return; } + index_field = mm_gdbus_modem3gpp_profile_manager_get_index_field (ctx->skeleton); + if (g_strcmp0 (index_field, "profile-id") == 0) { + profile_id = mm_3gpp_profile_get_profile_id (profile_requested); + if (profile_id == MM_3GPP_PROFILE_ID_UNKNOWN) { + g_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Missing index field ('profile-id') in profile settings"); + handle_set_context_free (ctx); + return; + } + } else if (g_strcmp0 (index_field, "apn-type") == 0) { + apn_type = mm_3gpp_profile_get_apn_type (profile_requested); + if (apn_type == MM_BEARER_APN_TYPE_NONE) { + g_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Missing index field ('apn-type') in profile settings"); + handle_set_context_free (ctx); + return; + } + } else + g_assert_not_reached (); + /* Don't call the class callback directly, use the common helper method * that is also used by other internal operations. */ mm_iface_modem_3gpp_profile_manager_set_profile ( MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self), profile_requested, + index_field, TRUE, /* strict always! */ (GAsyncReadyCallback)set_profile_ready, ctx); @@ -1044,9 +1137,11 @@ handle_delete_auth_ready (MMBaseModem *self, GAsyncResult *res, HandleDeleteContext *ctx) { - gint profile_id; + const gchar *index_field; GError *error = NULL; g_autoptr(MM3gppProfile) profile = NULL; + gint profile_id = MM_3GPP_PROFILE_ID_UNKNOWN; + MMBearerApnType apn_type = MM_BEARER_APN_TYPE_NONE; if (!mm_base_modem_authorize_finish (self, res, &error)) { g_dbus_method_invocation_take_error (ctx->invocation, error); @@ -1083,15 +1178,31 @@ handle_delete_auth_ready (MMBaseModem *self, return; } - profile_id = mm_3gpp_profile_get_profile_id (profile); - if (profile_id == MM_3GPP_PROFILE_ID_UNKNOWN) { - g_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, - "Missing 'profile-id' in profile settings"); - handle_delete_context_free (ctx); - return; - } + index_field = mm_gdbus_modem3gpp_profile_manager_get_index_field (ctx->skeleton); + if (g_strcmp0 (index_field, "profile-id") == 0) { + profile_id = mm_3gpp_profile_get_profile_id (profile); + if (profile_id == MM_3GPP_PROFILE_ID_UNKNOWN) { + g_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Missing index field ('profile-id') in profile settings"); + handle_delete_context_free (ctx); + return; + } + } else if (g_strcmp0 (index_field, "apn-type") == 0) { + apn_type = mm_3gpp_profile_get_apn_type (profile); + if (apn_type == MM_BEARER_APN_TYPE_NONE) { + g_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Missing index field ('apn-type') in profile settings"); + handle_delete_context_free (ctx); + return; + } + } else + g_assert_not_reached (); - if (!profile_manager_fail_if_connected_bearer (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self), profile_id, &error)) { + if (!profile_manager_fail_if_connected_bearer (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self), + index_field, + profile_id, + apn_type, + &error)) { g_dbus_method_invocation_take_error (ctx->invocation, error); handle_delete_context_free (ctx); return; @@ -1100,6 +1211,7 @@ handle_delete_auth_ready (MMBaseModem *self, MM_IFACE_MODEM_3GPP_PROFILE_MANAGER_GET_INTERFACE (self)->delete_profile ( MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self), profile, + index_field, (GAsyncReadyCallback)delete_profile_ready, ctx); } diff --git a/src/mm-iface-modem-3gpp-profile-manager.h b/src/mm-iface-modem-3gpp-profile-manager.h index e6f2833e..e9724087 100644 --- a/src/mm-iface-modem-3gpp-profile-manager.h +++ b/src/mm-iface-modem-3gpp-profile-manager.h @@ -101,6 +101,7 @@ struct _MMIfaceModem3gppProfileManager { /* Delete */ void (* delete_profile) (MMIfaceModem3gppProfileManager *self, MM3gppProfile *requested, + const gchar *index_field, GAsyncReadyCallback callback, gpointer user_data); gboolean (* delete_profile_finish) (MMIfaceModem3gppProfileManager *self, @@ -177,10 +178,13 @@ struct _MMIfaceModem3gppProfileManager { /* Store profile (substep of 'set profiles') */ void (* store_profile) (MMIfaceModem3gppProfileManager *self, MM3gppProfile *requested, + const gchar *index_field, GAsyncReadyCallback callback, gpointer user_data); - gint (* store_profile_finish) (MMIfaceModem3gppProfileManager *self, + gboolean (* store_profile_finish) (MMIfaceModem3gppProfileManager *self, GAsyncResult *res, + gint *out_profile_id, + MMBearerApnType *out_apn_type, GError **error); }; @@ -238,6 +242,7 @@ gboolean mm_iface_modem_3gpp_profile_manager_list_profiles_finish (MMIface GError **error); void mm_iface_modem_3gpp_profile_manager_set_profile (MMIfaceModem3gppProfileManager *self, MM3gppProfile *requested, + const gchar *index_field, gboolean strict, GAsyncReadyCallback callback, gpointer user_data); diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index 6f645dbb..3e22262c 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -1549,6 +1549,27 @@ mm_3gpp_profile_list_find_by_profile_id (GList *profile_list, return NULL; } +MM3gppProfile * +mm_3gpp_profile_list_find_by_apn_type (GList *profile_list, + MMBearerApnType apn_type, + GError **error) +{ + g_autofree gchar *apn_type_str = NULL; + GList *l; + + for (l = profile_list; l; l = g_list_next (l)) { + MM3gppProfile *iter_profile = l->data; + + if (mm_3gpp_profile_get_apn_type (iter_profile) == apn_type) + return g_object_ref (iter_profile); + } + + apn_type_str = mm_bearer_apn_type_build_string_from_mask (apn_type); + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, + "Profile '%s' not found", apn_type_str); + return NULL; +} + gint mm_3gpp_profile_list_find_empty (GList *profile_list, gint min_profile_id, diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index ed5364ef..0d8b96a0 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -479,6 +479,10 @@ MM3gppProfile *mm_3gpp_profile_list_find_by_profile_id (GList *profile_list, gint profile_id, GError **error); +MM3gppProfile *mm_3gpp_profile_list_find_by_apn_type (GList *profile_list, + MMBearerApnType apn_type, + GError **error); + /*****************************************************************************/ /* CDMA specific helpers and utilities */ /*****************************************************************************/ |