diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2021-04-05 00:07:01 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-04-29 10:13:22 +0000 |
commit | 72879e4095bde2ee354a61f475ebc8bc847541c5 (patch) | |
tree | ca5b49dbad5d356e12019ef5e005c4017ec8730f | |
parent | 49b63cc62b46777c419b6a8e63629d228953fe95 (diff) |
broadband-modem-mbim: implement profile management support
We use the "Provisioned Contexts" message support to add and edit
profiles.
We also use the same message, with context-type set to "none" to
attempt deleting it, although that doesn't seem to be fully supported
by all modems. E.g. the EM7345 (FIH7160_V1.1_MODEM_01.1349.12) will
still report contexts 'deleted' in this way, with the context-type set
to "none".ยบ
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 535 | ||||
-rw-r--r-- | src/mm-modem-helpers-mbim.c | 64 | ||||
-rw-r--r-- | src/mm-modem-helpers-mbim.h | 4 |
3 files changed, 590 insertions, 13 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index c3248e5d..6439e225 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -35,6 +35,7 @@ #include "mm-bearer-list.h" #include "mm-iface-modem.h" #include "mm-iface-modem-3gpp.h" +#include "mm-iface-modem-3gpp-profile-manager.h" #include "mm-iface-modem-3gpp-ussd.h" #include "mm-iface-modem-location.h" #include "mm-iface-modem-messaging.h" @@ -46,14 +47,15 @@ # include "mm-shared-qmi.h" #endif -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface); -static void iface_modem_location_init (MMIfaceModemLocation *iface); -static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); -static void iface_modem_signal_init (MMIfaceModemSignal *iface); +static void iface_modem_init (MMIfaceModem *iface); +static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); +static void iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface); +static void iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface); +static void iface_modem_location_init (MMIfaceModemLocation *iface); +static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); +static void iface_modem_signal_init (MMIfaceModemSignal *iface); #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED -static void shared_qmi_init (MMSharedQmi *iface); +static void shared_qmi_init (MMSharedQmi *iface); #endif #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED @@ -64,6 +66,7 @@ static MMIfaceModemSignal *iface_modem_signal_parent; G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbim, mm_broadband_modem_mbim, MM_TYPE_BROADBAND_MODEM, 0, G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP_PROFILE_MANAGER, iface_modem_3gpp_profile_manager_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP_USSD, iface_modem_3gpp_ussd_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init) @@ -84,6 +87,7 @@ typedef enum { PROCESS_NOTIFICATION_FLAG_PCO = 1 << 6, PROCESS_NOTIFICATION_FLAG_USSD = 1 << 7, PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS = 1 << 8, + PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS = 1 << 9, } ProcessNotificationFlag; #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED @@ -106,6 +110,7 @@ struct _MMBroadbandModemMbimPrivate { gchar *caps_hardware_info; /* Supported features */ + gboolean is_profile_management_supported; gboolean is_pco_supported; gboolean is_lte_attach_status_supported; gboolean is_ussd_supported; @@ -2339,6 +2344,16 @@ query_device_services_ready (MbimDevice *device, service = mbim_uuid_to_service (&device_services[i]->device_service_id); + if (service == MBIM_SERVICE_BASIC_CONNECT) { + for (j = 0; j < device_services[i]->cids_count; j++) { + if (device_services[i]->cids[j] == MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS) { + mm_obj_dbg (self, "Profile management is supported"); + self->priv->is_profile_management_supported = TRUE; + } + } + continue; + } + if (service == MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS) { for (j = 0; j < device_services[i]->cids_count; j++) { if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PCO) { @@ -3421,6 +3436,15 @@ basic_connect_notification_packet_service (MMBroadbandModemMbim *self, update_access_technologies (self); } +static void +basic_connect_notification_provisioned_contexts (MMBroadbandModemMbim *self, + MbimMessage *notification) +{ + /* We don't even attempt to parse the indication, we just need to notify that + * something changed to the upper layers */ + mm_iface_modem_3gpp_profile_manager_updated (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self)); +} + static void add_sms_part (MMBroadbandModemMbim *self, const MbimSmsPduReadRecord *pdu); @@ -3476,6 +3500,9 @@ basic_connect_notification (MMBroadbandModemMbim *self, if (self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE) basic_connect_notification_packet_service (self, notification); break; + case MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS: + if (self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS) + basic_connect_notification_provisioned_contexts (self, notification); default: /* Ignore */ break; @@ -3740,7 +3767,9 @@ common_setup_cleanup_unsolicited_events_sync (MMBroadbandModemMbim *self, if (!device) return; - mm_obj_dbg (self, "supported notifications: signal (%s), registration (%s), sms (%s), connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), lte attach status (%s)", + mm_obj_dbg (self, "supported notifications: signal (%s), registration (%s), sms (%s), " + "connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), " + "lte attach status (%s), provisioned contexts (%s)", self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY ? "yes" : "no", self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_REGISTRATION_UPDATES ? "yes" : "no", self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_SMS_READ ? "yes" : "no", @@ -3749,7 +3778,8 @@ common_setup_cleanup_unsolicited_events_sync (MMBroadbandModemMbim *self, self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE ? "yes" : "no", self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PCO ? "yes" : "no", self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_USSD ? "yes" : "no", - self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS ? "yes" : "no"); + self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS ? "yes" : "no", + self->priv->setup_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS ? "yes" : "no"); if (setup) { /* Don't re-enable it if already there */ @@ -3914,7 +3944,9 @@ common_enable_disable_unsolicited_events (MMBroadbandModemMbim *self, if (!peek_device (self, &device, callback, user_data)) return; - mm_obj_dbg (self, "enabled notifications: signal (%s), registration (%s), sms (%s), connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), lte attach status (%s)", + mm_obj_dbg (self, "enabled notifications: signal (%s), registration (%s), sms (%s), " + "connect (%s), subscriber (%s), packet (%s), pco (%s), ussd (%s), " + "lte attach status (%s), provisioned contexts (%s)", self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY ? "yes" : "no", self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_REGISTRATION_UPDATES ? "yes" : "no", self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_SMS_READ ? "yes" : "no", @@ -3923,7 +3955,8 @@ common_enable_disable_unsolicited_events (MMBroadbandModemMbim *self, self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE ? "yes" : "no", self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PCO ? "yes" : "no", self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_USSD ? "yes" : "no", - self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS ? "yes" : "no"); + self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_LTE_ATTACH_STATUS ? "yes" : "no", + self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS ? "yes" : "no"); entries = g_new0 (MbimEventEntry *, 5); @@ -3932,11 +3965,12 @@ common_enable_disable_unsolicited_events (MMBroadbandModemMbim *self, self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_REGISTRATION_UPDATES || self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_CONNECT || self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO || - self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE) { + self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE || + self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS) { entries[n_entries] = g_new (MbimEventEntry, 1); memcpy (&(entries[n_entries]->device_service_id), MBIM_UUID_BASIC_CONNECT, sizeof (MbimUuid)); entries[n_entries]->cids_count = 0; - entries[n_entries]->cids = g_new0 (guint32, 5); + entries[n_entries]->cids = g_new0 (guint32, 6); if (self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY) entries[n_entries]->cids[entries[n_entries]->cids_count++] = MBIM_CID_BASIC_CONNECT_SIGNAL_STATE; if (self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_REGISTRATION_UPDATES) @@ -3947,6 +3981,8 @@ common_enable_disable_unsolicited_events (MMBroadbandModemMbim *self, entries[n_entries]->cids[entries[n_entries]->cids_count++] = MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS; if (self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE) entries[n_entries]->cids[entries[n_entries]->cids_count++] = MBIM_CID_BASIC_CONNECT_PACKET_SERVICE; + if (self->priv->enable_flags & PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS) + entries[n_entries]->cids[entries[n_entries]->cids_count++] = MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS; n_entries++; } @@ -4845,6 +4881,445 @@ modem_signal_load_values (MMIfaceModemSignal *self, } /*****************************************************************************/ +/* Check support (3GPP profile management interface) */ + +static gboolean +modem_3gpp_profile_manager_check_support_finish (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +modem_3gpp_profile_manager_check_support (MMIfaceModem3gppProfileManager *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + + if (mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self)) && self->priv->is_profile_management_supported) + g_task_return_boolean (task, TRUE); + else + g_task_return_boolean (task, FALSE); + g_object_unref (task); +} + +/*****************************************************************************/ +/* Setup/Cleanup unsolicited event handlers (3gppProfileManager interface) */ + +static gboolean +common_setup_cleanup_unsolicited_events_3gpp_profile_manager_finish (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GError **error) +{ + return common_setup_cleanup_unsolicited_events_finish (MM_BROADBAND_MODEM_MBIM (self), res, error); +} + +static void +cleanup_unsolicited_events_3gpp_profile_manager (MMIfaceModem3gppProfileManager *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + + self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS; + common_setup_cleanup_unsolicited_events (self, FALSE, callback, user_data); +} + +static void +setup_unsolicited_events_3gpp_profile_manager (MMIfaceModem3gppProfileManager *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + + self->priv->setup_flags |= PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS; + common_setup_cleanup_unsolicited_events (self, TRUE, callback, user_data); +} + +/*****************************************************************************/ +/* Enable/Disable unsolicited event handlers (3gppProfileManager interface) */ + +static gboolean +common_enable_disable_unsolicited_events_3gpp_profile_manager_finish (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GError **error) +{ + return common_enable_disable_unsolicited_events_finish (MM_BROADBAND_MODEM_MBIM (self), res, error); +} + +static void +disable_unsolicited_events_3gpp_profile_manager (MMIfaceModem3gppProfileManager *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + + self->priv->enable_flags &= ~PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS; + common_enable_disable_unsolicited_events (self, callback, user_data); +} + +static void +enable_unsolicited_events_3gpp_profile_manager (MMIfaceModem3gppProfileManager *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + + self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_PROVISIONED_CONTEXTS; + common_enable_disable_unsolicited_events (self, callback, user_data); +} + +/*****************************************************************************/ +/* Check format (3gppProfileManager interface) */ + +static gboolean +modem_3gpp_profile_manager_check_format_finish (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + gboolean *new_id, + gint *min_profile_id, + gint *max_profile_id, + GEqualFunc *apn_cmp, + MM3gppProfileCmpFlags *profile_cmp_flags, + GError **error) +{ + if (!g_task_propagate_boolean (G_TASK (res), error)) { + g_assert_not_reached (); + return FALSE; + } + + if (new_id) + *new_id = TRUE; + if (min_profile_id) + *min_profile_id = 1; + if (max_profile_id) + *max_profile_id = G_MAXINT - 1; + /* use default string comparison method */ + if (apn_cmp) + *apn_cmp = NULL; + /* we don't support IP type in the profiles */ + if (profile_cmp_flags) + *profile_cmp_flags = MM_3GPP_PROFILE_CMP_FLAGS_NO_IP_TYPE; + return TRUE; +} + +static void +modem_3gpp_profile_manager_check_format (MMIfaceModem3gppProfileManager *self, + MMBearerIpFamily ip_type, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +/*****************************************************************************/ +/* List profiles (3GPP profile management interface) */ + +typedef struct { + GList *profiles; +} ListProfilesContext; + +static void +list_profiles_context_free (ListProfilesContext *ctx) +{ + mm_3gpp_profile_list_free (ctx->profiles); + g_slice_free (ListProfilesContext, ctx); +} + +static gboolean +modem_3gpp_profile_manager_list_profiles_finish (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GList **out_profiles, + GError **error) +{ + ListProfilesContext *ctx; + + if (!g_task_propagate_boolean (G_TASK (res), error)) + return FALSE; + + ctx = g_task_get_task_data (G_TASK (res)); + if (out_profiles) + *out_profiles = g_steal_pointer (&ctx->profiles); + return TRUE; +} + +static MM3gppProfile * +provisioned_context_element_to_3gpp_profile (MbimProvisionedContextElement *element) +{ + MM3gppProfile *profile; + MMBearerApnType apn_type; + + apn_type = mm_bearer_apn_type_from_mbim_context_type (mbim_uuid_to_context_type (&element->context_type)); + if (apn_type == MM_BEARER_APN_TYPE_NONE) + return NULL; + + profile = mm_3gpp_profile_new (); + mm_3gpp_profile_set_profile_id (profile, element->context_id); + mm_3gpp_profile_set_apn (profile, element->access_string); + mm_3gpp_profile_set_apn_type (profile, apn_type); + mm_3gpp_profile_set_user (profile, element->user_name); + mm_3gpp_profile_set_password (profile, element->password); + mm_3gpp_profile_set_allowed_auth (profile, (mm_bearer_allowed_auth_from_mbim_auth_protocol (element->auth_protocol))); + /* compression unused, and ip-type not provided */ + return profile; +} + +static void +profile_manager_provisioned_contexts_query_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + ListProfilesContext *ctx; + GError *error = NULL; + guint32 provisioned_contexts_count = 0; + g_autoptr(MbimMessage) response = NULL; + g_autoptr(MbimProvisionedContextElementArray) provisioned_contexts = NULL; + + ctx = g_slice_new0 (ListProfilesContext); + g_task_set_task_data (task, ctx, (GDestroyNotify) list_profiles_context_free); + + response = mbim_device_command_finish (device, res, &error); + if (response && + mbim_message_response_get_result (response, + MBIM_MESSAGE_TYPE_COMMAND_DONE, + &error) && + mbim_message_provisioned_contexts_response_parse (response, + &provisioned_contexts_count, + &provisioned_contexts, + &error)) { + guint i; + + for (i = 0; i < provisioned_contexts_count; i++) { + MM3gppProfile *profile; + + profile = provisioned_context_element_to_3gpp_profile (provisioned_contexts[i]); + if (profile) + ctx->profiles = g_list_append (ctx->profiles, profile); + } + g_task_return_boolean (task, TRUE); + } else + g_task_return_error (task, error); + g_object_unref (task); +} + +static void +modem_3gpp_profile_manager_list_profiles (MMIfaceModem3gppProfileManager *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MbimDevice *device; + GTask *task; + g_autoptr(MbimMessage) message = NULL; + + if (!peek_device (self, &device, callback, user_data)) + return; + + task = g_task_new (self, NULL, callback, user_data); + + mm_obj_dbg (self, "querying provisioned contexts..."); + message = mbim_message_provisioned_contexts_query_new (NULL); + + mbim_device_command (device, + message, + 10, + NULL, + (GAsyncReadyCallback)profile_manager_provisioned_contexts_query_ready, + task); +} + +/*****************************************************************************/ +/* Store profile (3GPP profile management interface) */ + +static gint +modem_3gpp_profile_manager_store_profile_finish (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GError **error) +{ + if (!g_task_propagate_boolean (G_TASK (res), error)) + return MM_3GPP_PROFILE_ID_UNKNOWN; + + return GPOINTER_TO_INT (g_task_get_task_data (G_TASK (res))); +} + +static void +profile_manager_provisioned_contexts_set_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + g_autoptr(MbimMessage) response = NULL; + + response = mbim_device_command_finish (device, res, &error); + if (response && mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); + g_object_unref (task); +} + +static void +modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, + MM3gppProfile *profile, + GAsyncReadyCallback callback, + gpointer user_data) +{ + 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; + const MbimUuid *context_type_uuid; + const gchar *apn; + const gchar *user; + const gchar *password; + g_autofree gchar *apn_type_str = NULL; + g_autoptr(MbimMessage) message = NULL; + + if (!peek_device (self, &device, callback, user_data)) + return; + + 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); + + apn = mm_3gpp_profile_get_apn (profile); + + apn_type = mm_3gpp_profile_get_apn_type (profile); + context_type = mm_bearer_apn_type_to_mbim_context_type (apn_type, self, &error); + if (error) { + 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); + + 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); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + } + + 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); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + mbim_device_command (device, + message, + 10, + NULL, + (GAsyncReadyCallback)profile_manager_provisioned_contexts_set_ready, + task); +} + +/*****************************************************************************/ +/* Delete profile (3GPP profile management interface) */ + +static gboolean +modem_3gpp_profile_manager_delete_profile_finish (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +profile_manager_provisioned_contexts_reset_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + g_autoptr(MbimMessage) response = NULL; + + response = mbim_device_command_finish (device, res, &error); + if (response && mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); + g_object_unref (task); +} + +static void +modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *self, + MM3gppProfile *profile, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MbimDevice *device; + GTask *task; + GError *error = NULL; + gint profile_id; + g_autoptr(MbimMessage) message = NULL; + + if (!peek_device (self, &device, callback, user_data)) + return; + + 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); + + 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); + return; + } + + mbim_device_command (device, + message, + 10, + NULL, + (GAsyncReadyCallback)profile_manager_provisioned_contexts_reset_ready, + task); +} + +/*****************************************************************************/ /* Check if USSD supported (3GPP/USSD interface) */ static gboolean @@ -5888,6 +6363,40 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface) } static void +iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface) +{ + /* Initialization steps */ + iface->check_support = modem_3gpp_profile_manager_check_support; + iface->check_support_finish = modem_3gpp_profile_manager_check_support_finish; + + /* Enabling steps */ + iface->setup_unsolicited_events = setup_unsolicited_events_3gpp_profile_manager; + iface->setup_unsolicited_events_finish = common_setup_cleanup_unsolicited_events_3gpp_profile_manager_finish; + iface->enable_unsolicited_events = enable_unsolicited_events_3gpp_profile_manager; + iface->enable_unsolicited_events_finish = common_enable_disable_unsolicited_events_3gpp_profile_manager_finish; + + /* Disabling steps */ + iface->cleanup_unsolicited_events = cleanup_unsolicited_events_3gpp_profile_manager; + iface->cleanup_unsolicited_events_finish = common_setup_cleanup_unsolicited_events_3gpp_profile_manager_finish; + iface->disable_unsolicited_events = disable_unsolicited_events_3gpp_profile_manager; + iface->disable_unsolicited_events_finish = common_enable_disable_unsolicited_events_3gpp_profile_manager_finish; + + /* Additional actions */ + iface->list_profiles = modem_3gpp_profile_manager_list_profiles; + iface->list_profiles_finish = modem_3gpp_profile_manager_list_profiles_finish; + iface->check_format = modem_3gpp_profile_manager_check_format; + iface->check_format_finish = modem_3gpp_profile_manager_check_format_finish; + iface->check_activated_profile = NULL; + iface->check_activated_profile_finish = NULL; + iface->deactivate_profile = NULL; + iface->deactivate_profile_finish = NULL; + iface->store_profile = modem_3gpp_profile_manager_store_profile; + iface->store_profile_finish = modem_3gpp_profile_manager_store_profile_finish; + iface->delete_profile = modem_3gpp_profile_manager_delete_profile; + iface->delete_profile_finish = modem_3gpp_profile_manager_delete_profile_finish; +} + +static void iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface) { /* Initialization steps */ diff --git a/src/mm-modem-helpers-mbim.c b/src/mm-modem-helpers-mbim.c index e418969f..c907b22e 100644 --- a/src/mm-modem-helpers-mbim.c +++ b/src/mm-modem-helpers-mbim.c @@ -408,6 +408,70 @@ mm_bearer_allowed_auth_to_mbim_auth_protocol (MMBearerAllowedAuth bearer_auth, /*****************************************************************************/ +MMBearerApnType +mm_bearer_apn_type_from_mbim_context_type (MbimContextType context_type) +{ + switch (context_type) { + case MBIM_CONTEXT_TYPE_INTERNET: + return MM_BEARER_APN_TYPE_DEFAULT; + case MBIM_CONTEXT_TYPE_VPN: + return MM_BEARER_APN_TYPE_PRIVATE; + case MBIM_CONTEXT_TYPE_VOICE: + return MM_BEARER_APN_TYPE_VOICE; + case MBIM_CONTEXT_TYPE_PURCHASE: + return MM_BEARER_APN_TYPE_MANAGEMENT; + case MBIM_CONTEXT_TYPE_IMS: + return MM_BEARER_APN_TYPE_IMS; + case MBIM_CONTEXT_TYPE_MMS: + return MM_BEARER_APN_TYPE_MMS; + case MBIM_CONTEXT_TYPE_INVALID: + case MBIM_CONTEXT_TYPE_NONE: + case MBIM_CONTEXT_TYPE_LOCAL: + case MBIM_CONTEXT_TYPE_VIDEO_SHARE: + /* some types unused right now */ + default: + return MM_BEARER_APN_TYPE_NONE; + } +} + +MbimContextType +mm_bearer_apn_type_to_mbim_context_type (MMBearerApnType apn_type, + gpointer log_object, + GError **error) +{ + g_autofree gchar *str = NULL; + + /* NOTE: the input is a BITMASK, so we try to find a "best match" */ + + if (apn_type == MM_BEARER_APN_TYPE_NONE) { + mm_obj_dbg (log_object, "using default (internet) APN type"); + return MBIM_CONTEXT_TYPE_INTERNET; + } + + if (apn_type & MM_BEARER_APN_TYPE_DEFAULT) + return MBIM_CONTEXT_TYPE_INTERNET; + if (apn_type & MM_BEARER_APN_TYPE_IMS) + return MBIM_CONTEXT_TYPE_IMS; + if (apn_type & MM_BEARER_APN_TYPE_MMS) + return MBIM_CONTEXT_TYPE_MMS; + if (apn_type &MM_BEARER_APN_TYPE_MANAGEMENT) + return MBIM_CONTEXT_TYPE_PURCHASE; + if (apn_type & MM_BEARER_APN_TYPE_VOICE) + return MBIM_CONTEXT_TYPE_VOICE; + if (apn_type & MM_BEARER_APN_TYPE_PRIVATE) + return MBIM_CONTEXT_TYPE_VPN; + + str = mm_bearer_apn_type_build_string_from_mask (apn_type); + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Unsupported APN types (%s)", + str); + return MBIM_CONTEXT_TYPE_NONE; +} + +/*****************************************************************************/ + MMBearerIpFamily mm_bearer_ip_family_from_mbim_context_ip_type (MbimContextIpType ip_type) { diff --git a/src/mm-modem-helpers-mbim.h b/src/mm-modem-helpers-mbim.h index 9cebe95f..c01c7532 100644 --- a/src/mm-modem-helpers-mbim.h +++ b/src/mm-modem-helpers-mbim.h @@ -47,6 +47,10 @@ MbimAuthProtocol mm_bearer_allowed_auth_to_mbim_auth_protocol (MMBearerAllo MMBearerIpFamily mm_bearer_ip_family_from_mbim_context_ip_type (MbimContextIpType ip_type); MbimContextIpType mm_bearer_ip_family_to_mbim_context_ip_type (MMBearerIpFamily ip_family, GError **error); +MMBearerApnType mm_bearer_apn_type_from_mbim_context_type (MbimContextType context_type); +MbimContextType mm_bearer_apn_type_to_mbim_context_type (MMBearerApnType apn_type, + gpointer log_object, + GError **error); /*****************************************************************************/ /* MBIM/SMS to MM translations */ |