diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 351 | ||||
-rw-r--r-- | src/mm-broadband-modem-mbim.h | 43 |
2 files changed, 290 insertions, 104 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 034d5ef5..ce27e3a3 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -4324,13 +4324,33 @@ modem_3gpp_load_initial_eps_bearer_settings (MMIfaceModem3gpp *_self, } /*****************************************************************************/ -/* Set initial EPS bearer settings - * - * The logic to set the EPS bearer settings requires us to first load the current - * settings from the module, because we are only going to change the settings - * associated to the HOME slot, we will leave untouched the PARTNER and NON-PARTNER - * slots. - */ +/* Set initial EPS bearer settings */ + +typedef struct { + MMBroadbandModemMbimSetInitialEpsBearerSettingsFlag mask; + MbimDevice *device; + MbimLteAttachConfiguration home; + MbimLteAttachConfiguration partner; + MbimLteAttachConfiguration non_partner; +} SetInitialEpsBearerSettingsContext; + +static void +clear_lte_attach_configuration (MbimLteAttachConfiguration *config) +{ + g_free (config->access_string); + g_free (config->user_name); + g_free (config->password); +} + +static void +set_initial_eps_bearer_settings_context_free (SetInitialEpsBearerSettingsContext *ctx) +{ + clear_lte_attach_configuration (&ctx->home); + clear_lte_attach_configuration (&ctx->partner); + clear_lte_attach_configuration (&ctx->non_partner); + g_object_unref (ctx->device); + g_slice_free (SetInitialEpsBearerSettingsContext, ctx); +} static gboolean modem_3gpp_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, @@ -4341,12 +4361,12 @@ modem_3gpp_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, } static void -set_lte_attach_configuration_set_ready (MbimDevice *device, - GAsyncResult *res, - GTask *task) +lte_attach_configuration_set_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) { - MbimMessage *response; - GError *error = NULL; + g_autoptr(MbimMessage) response = NULL; + GError *error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) @@ -4354,27 +4374,135 @@ set_lte_attach_configuration_set_ready (MbimDevice *device, else g_task_return_boolean (task, TRUE); g_object_unref (task); +} - if (response) - mbim_message_unref (response); +static void +lte_attach_configuration_set (GTask *task) +{ + g_autoptr(MbimMessage) request = NULL; + SetInitialEpsBearerSettingsContext *ctx; + guint32 n_configurations = 0; + MbimLteAttachConfiguration *configurations[3]; + + ctx = g_task_get_task_data (task); + + /* Home always added */ + g_assert (ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_HOME); + g_assert (ctx->home.roaming == MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_HOME); + configurations[n_configurations++] = &ctx->home; + + /* Partner and non-partner optional */ + if (!(ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_SKIP_PARTNER)) { + g_assert (ctx->partner.roaming == MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_PARTNER); + configurations[n_configurations++] = &ctx->partner; + } + if (!(ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_SKIP_NON_PARTNER)) { + g_assert (ctx->non_partner.roaming == MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_NON_PARTNER); + configurations[n_configurations++] = &ctx->non_partner; + } + + request = mbim_message_ms_basic_connect_extensions_lte_attach_configuration_set_new ( + MBIM_LTE_ATTACH_CONTEXT_OPERATION_DEFAULT, + n_configurations, + (const MbimLteAttachConfiguration * const*)configurations, + NULL); + mbim_device_command (ctx->device, + request, + 10, + NULL, + (GAsyncReadyCallback)lte_attach_configuration_set_ready, + task); } static void -before_set_lte_attach_configuration_query_ready (MbimDevice *device, - GAsyncResult *res, - GTask *task) +update_lte_attach_configuration (MMBroadbandModemMbim *self, + MbimLteAttachContextRoamingControl roaming_control, + MbimLteAttachConfiguration *config, + const MbimLteAttachConfiguration *previous_config, + const MbimLteAttachConfiguration *new_config) { - MMBroadbandModemMbim *self; - MbimMessage *request; - MbimMessage *response; - GError *error = NULL; - MMBearerProperties *config; - guint32 n_configurations = 0; - MbimLteAttachConfiguration **configurations = NULL; - guint i; + guint n_updates = 0; + + /* Log differences between previous and new */ + + mm_obj_dbg (self, "updates in the %s LTE attach configuration settings:", + mbim_lte_attach_context_roaming_control_get_string (roaming_control)); + + if (!previous_config && !new_config) { + mm_obj_dbg (self, " none (skipped)"); + return; + } + + /* ignore source and compression on purpose, as we don't care about their values */ + + if (!previous_config || !new_config || g_strcmp0 (previous_config->access_string, new_config->access_string)) { + mm_obj_dbg (self, " access string: '%s' -> '%s'", + (previous_config && previous_config->access_string) ? previous_config->access_string : "", + (new_config && new_config->access_string) ? new_config->access_string : ""); + n_updates++; + } + + if (!previous_config || !new_config || (previous_config->ip_type != new_config->ip_type)) { + mm_obj_dbg (self, " ip type: '%s' -> '%s'", + previous_config ? mbim_context_ip_type_get_string (previous_config->ip_type) : "", + new_config ? mbim_context_ip_type_get_string (new_config->ip_type) : ""); + n_updates++; + } + + if (!previous_config || !new_config || (previous_config->auth_protocol != new_config->auth_protocol)) { + mm_obj_dbg (self, " auth protocol: '%s' -> '%s'", + previous_config ? mbim_auth_protocol_get_string (previous_config->auth_protocol) : "", + new_config ? mbim_auth_protocol_get_string (new_config->auth_protocol) : ""); + n_updates++; + } + + if (!previous_config || !new_config || g_strcmp0 (previous_config->user_name, new_config->user_name)) { + mm_obj_dbg (self, " user name: '%s' -> '%s'", + (previous_config && previous_config->user_name) ? mm_log_str_personal_info (previous_config->user_name) : "", + (new_config && new_config->user_name) ? mm_log_str_personal_info (new_config->user_name) : ""); + n_updates++; + } + + if (!previous_config || !new_config || g_strcmp0 (previous_config->password, new_config->password)) { + mm_obj_dbg (self, " password: '%s' -> '%s'", + (previous_config && previous_config->password) ? mm_log_str_personal_info (previous_config->password) : "", + (new_config && new_config->password) ? mm_log_str_personal_info (new_config->password) : ""); + n_updates++; + } + + if (!n_updates) + mm_obj_dbg (self, " none"); + + /* Copy config from the new one, if any */ + if (config && new_config) { + config->roaming = roaming_control; + config->source = new_config->source; + config->compression = new_config->compression; + config->ip_type = new_config->ip_type; + config->access_string = g_strdup (new_config->access_string); + config->user_name = g_strdup (new_config->user_name); + config->password = g_strdup (new_config->password); + config->auth_protocol = new_config->auth_protocol; + } +} + +static void +lte_attach_configuration_reload_before_set_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemMbim *self; + g_autoptr(MbimMessage) response = NULL; + SetInitialEpsBearerSettingsContext *ctx; + guint32 n_configurations = 0; + g_autoptr(MbimLteAttachConfigurationArray) configurations = NULL; + GError *error = NULL; + const MbimLteAttachConfiguration *previous_home = NULL; + const MbimLteAttachConfiguration *previous_partner = NULL; + const MbimLteAttachConfiguration *previous_non_partner = NULL; - self = g_task_get_source_object (task); - config = g_task_get_task_data (task); + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); response = mbim_device_command_finish (device, res, &error); if (!response || @@ -4384,83 +4512,94 @@ before_set_lte_attach_configuration_query_ready (MbimDevice *device, &n_configurations, &configurations, &error)) { + g_prefix_error (&error, "Failed to load LTE attach configuration before updating: "); g_task_return_error (task, error); g_object_unref (task); - goto out; + return; } - /* We should always receive 3 configurations but the MBIM API doesn't force - * that so we'll just assume we don't get always the same fixed number */ - for (i = 0; i < n_configurations; i++) { - MMBearerIpFamily ip_family; - MMBearerAllowedAuth auth; + /* Lookup the home settings, which are the ones we always control via the MM API, but also + * detect existing partner and non-partner settings */ + previous_home = lte_attach_configuration_response_detect_home_settings (self, + (const MbimLteAttachConfiguration *const *)configurations, + n_configurations, + &previous_partner, + &previous_non_partner, + NULL); - /* We only support configuring the HOME settings */ - if (configurations[i]->roaming != MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_HOME) - continue; + /* Log differences, no need to update anything as the target settings are already set */ + update_lte_attach_configuration (self, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_HOME, NULL, previous_home, &ctx->home); - ip_family = mm_bearer_properties_get_ip_type (config); - if (ip_family == MM_BEARER_IP_FAMILY_NONE || ip_family == MM_BEARER_IP_FAMILY_ANY) - configurations[i]->ip_type = MBIM_CONTEXT_IP_TYPE_DEFAULT; - else { - configurations[i]->ip_type = mm_bearer_ip_family_to_mbim_context_ip_type (ip_family, &error); - if (error) { - configurations[i]->ip_type = MBIM_CONTEXT_IP_TYPE_DEFAULT; - mm_obj_warn (self, "unexpected IP type settings requested: %s", error->message); - g_clear_error (&error); - } - } + if (ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_SKIP_PARTNER) { + /* Partner settings need to be skipped */ + g_assert (!(ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_PARTNER)); + update_lte_attach_configuration (self, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_PARTNER, NULL, previous_partner, NULL); + } else if (ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_PARTNER) { + /* Partner settings need to be updated to be equal to home */ + update_lte_attach_configuration (self, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_PARTNER, &ctx->partner, previous_partner, &ctx->home); + } else { + /* Partner settings need to be same as they were before */ + update_lte_attach_configuration (self, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_PARTNER, &ctx->partner, previous_partner, previous_partner); + } - g_clear_pointer (&(configurations[i]->access_string), g_free); - configurations[i]->access_string = g_strdup (mm_bearer_properties_get_apn (config)); + if (ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_SKIP_NON_PARTNER) { + /* Non partner settings need to be skipped */ + g_assert (!(ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_NON_PARTNER)); + update_lte_attach_configuration (self, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_NON_PARTNER, NULL, previous_non_partner, NULL); + } else if (ctx->mask & MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_NON_PARTNER) { + /* Non partner settings need to be updated to be equal to home */ + update_lte_attach_configuration (self, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_NON_PARTNER, &ctx->non_partner, previous_non_partner, &ctx->home); + } else { + /* Non partner settings need to be same as they were before */ + update_lte_attach_configuration (self, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_NON_PARTNER, &ctx->non_partner, previous_non_partner, previous_non_partner); + } - g_clear_pointer (&(configurations[i]->user_name), g_free); - configurations[i]->user_name = g_strdup (mm_bearer_properties_get_user (config)); + lte_attach_configuration_set (task); +} - g_clear_pointer (&(configurations[i]->password), g_free); - configurations[i]->password = g_strdup (mm_bearer_properties_get_password (config)); +static void +init_lte_attach_configuration_from_bearer_properties (MMBroadbandModemMbim *self, + MbimLteAttachConfiguration *lte_attach_config, + MbimLteAttachContextRoamingControl roaming_control, + MMBearerProperties *bearer_properties) +{ + GError *error = NULL; + MMBearerIpFamily ip_family; + MMBearerAllowedAuth auth; - auth = mm_bearer_properties_get_allowed_auth (config); - if ((auth != MM_BEARER_ALLOWED_AUTH_UNKNOWN) || configurations[i]->user_name || configurations[i]->password) { - configurations[i]->auth_protocol = mm_bearer_allowed_auth_to_mbim_auth_protocol (auth, self, &error); - if (error) { - configurations[i]->auth_protocol = MBIM_AUTH_PROTOCOL_NONE; - mm_obj_warn (self, "unexpected auth settings requested: %s", error->message); - g_clear_error (&error); - } - } else { - configurations[i]->auth_protocol = MBIM_AUTH_PROTOCOL_NONE; - } + g_assert (lte_attach_config); - configurations[i]->source = MBIM_CONTEXT_SOURCE_USER; - configurations[i]->compression = MBIM_COMPRESSION_NONE; - break; - } + lte_attach_config->roaming = roaming_control; + lte_attach_config->source = MBIM_CONTEXT_SOURCE_USER; + lte_attach_config->compression = MBIM_COMPRESSION_NONE; - request = mbim_message_ms_basic_connect_extensions_lte_attach_configuration_set_new ( - MBIM_LTE_ATTACH_CONTEXT_OPERATION_DEFAULT, - n_configurations, - (const MbimLteAttachConfiguration *const *)configurations, - &error); - if (!request) { - g_task_return_error (task, error); - g_object_unref (task); - goto out; + ip_family = mm_bearer_properties_get_ip_type (bearer_properties); + if (ip_family == MM_BEARER_IP_FAMILY_NONE || ip_family == MM_BEARER_IP_FAMILY_ANY) + lte_attach_config->ip_type = MBIM_CONTEXT_IP_TYPE_DEFAULT; + else { + lte_attach_config->ip_type = mm_bearer_ip_family_to_mbim_context_ip_type (ip_family, &error); + if (error) { + lte_attach_config->ip_type = MBIM_CONTEXT_IP_TYPE_DEFAULT; + mm_obj_warn (self, "unexpected IP type settings requested: %s", error->message); + g_clear_error (&error); + } } - mbim_device_command (device, - request, - 10, - NULL, - (GAsyncReadyCallback)set_lte_attach_configuration_set_ready, - task); - mbim_message_unref (request); - out: - if (configurations) - mbim_lte_attach_configuration_array_free (configurations); + lte_attach_config->access_string = g_strdup (mm_bearer_properties_get_apn (bearer_properties)); + lte_attach_config->user_name = g_strdup (mm_bearer_properties_get_user (bearer_properties)); + lte_attach_config->password = g_strdup (mm_bearer_properties_get_password (bearer_properties)); - if (response) - mbim_message_unref (response); + auth = mm_bearer_properties_get_allowed_auth (bearer_properties); + if ((auth != MM_BEARER_ALLOWED_AUTH_UNKNOWN) || lte_attach_config->user_name || lte_attach_config->password) { + lte_attach_config->auth_protocol = mm_bearer_allowed_auth_to_mbim_auth_protocol (auth, self, &error); + if (error) { + lte_attach_config->auth_protocol = MBIM_AUTH_PROTOCOL_NONE; + mm_obj_warn (self, "unexpected auth settings requested: %s", error->message); + g_clear_error (&error); + } + } else { + lte_attach_config->auth_protocol = MBIM_AUTH_PROTOCOL_NONE; + } } static void @@ -4469,10 +4608,11 @@ modem_3gpp_set_initial_eps_bearer_settings (MMIfaceModem3gpp *_self, GAsyncReadyCallback callback, gpointer user_data) { - MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); - GTask *task; - MbimDevice *device; - MbimMessage *message; + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + MbimDevice *device; + GTask *task; + SetInitialEpsBearerSettingsContext *ctx; + g_autoptr(MbimMessage) request = NULL; if (!peek_device (self, &device, callback, user_data)) return; @@ -4486,16 +4626,29 @@ modem_3gpp_set_initial_eps_bearer_settings (MMIfaceModem3gpp *_self, return; } - g_task_set_task_data (task, g_object_ref (config), g_object_unref); + ctx = g_slice_new0 (SetInitialEpsBearerSettingsContext); + ctx->device = g_object_ref (device); + ctx->mask = MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_DEFAULT; + g_task_set_task_data (task, ctx, (GDestroyNotify)set_initial_eps_bearer_settings_context_free); + + /* Load custom settings to use in the operation */ + if (MM_BROADBAND_MODEM_MBIM_GET_CLASS (self)->load_set_initial_eps_bearer_settings_mask) + ctx->mask = MM_BROADBAND_MODEM_MBIM_GET_CLASS (self)->load_set_initial_eps_bearer_settings_mask (self); - message = mbim_message_ms_basic_connect_extensions_lte_attach_configuration_query_new (NULL); - mbim_device_command (device, - message, + /* Initialize home settings from the config. Home settings will always be unconditionally updated */ + init_lte_attach_configuration_from_bearer_properties (self, + &ctx->home, + MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_HOME, + config); + + /* Reload existing settings, so that we can log about the changes before the set operation */ + request = mbim_message_ms_basic_connect_extensions_lte_attach_configuration_query_new (NULL); + mbim_device_command (ctx->device, + request, 10, NULL, - (GAsyncReadyCallback)before_set_lte_attach_configuration_query_ready, + (GAsyncReadyCallback)lte_attach_configuration_reload_before_set_ready, task); - mbim_message_unref (message); } /*****************************************************************************/ diff --git a/src/mm-broadband-modem-mbim.h b/src/mm-broadband-modem-mbim.h index 0edd8818..43ee96ca 100644 --- a/src/mm-broadband-modem-mbim.h +++ b/src/mm-broadband-modem-mbim.h @@ -33,6 +33,37 @@ typedef struct _MMBroadbandModemMbimPrivate MMBroadbandModemMbimPrivate; #define MM_BROADBAND_MODEM_MBIM_QMI_UNSUPPORTED "broadband-modem-mbim-qmi-unsupported" #define MM_BROADBAND_MODEM_MBIM_INTEL_FIRMWARE_UPDATE_UNSUPPORTED "broadband-modem-mbim-intel-firmware-update-unsupported" +/* Flags to modify the behavior of the generic initial EPS bearer settings + * operation, given that different modules may end up having different needs at + * different times. + * + * The "home" section is always included and always updated. + * + * The "update partner" and "update non partner" flags control which settings are + * used for the given section. If the flag is given, the section receives the same + * settings as "home", otherwise the section receives the same settings it already + * had before. + * + * The "skip" partner and "skip non partner" flags control whether the given section + * is included in the list of configurations given to the device. If any of the + * section is flagged to be skipped, the "update" flag for that section is irrelevant. + * + * By default for now all 3 sections are included, but partner and non partner are not + * updated. + */ +typedef enum { + MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_NONE, + MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_HOME = 1 << 0, + MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_PARTNER = 1 << 1, + MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_NON_PARTNER = 1 << 2, + MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_SKIP_PARTNER = 1 << 3, + MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_SKIP_NON_PARTNER = 1 << 4, +} MMBroadbandModemMbimSetInitialEpsBearerSettingsFlag; + +/* By default: provide home/partner/non-partner but only update home */ +#define MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_DEFAULT \ + MM_BROADBAND_MODEM_MBIM_SET_INITIAL_EPS_BEARER_SETTINGS_FLAG_UPDATE_HOME + struct _MMBroadbandModemMbim { MMBroadbandModem parent; MMBroadbandModemMbimPrivate *priv; @@ -41,11 +72,13 @@ struct _MMBroadbandModemMbim { struct _MMBroadbandModemMbimClass{ MMBroadbandModemClass parent; - MMPortMbim * (* peek_port_mbim_for_data) (MMBroadbandModemMbim *self, - MMPort *data, - GError **error); - guint32 (* normalize_nw_error) (MMBroadbandModemMbim *self, - guint32 nw_error); + MMPortMbim * (* peek_port_mbim_for_data) (MMBroadbandModemMbim *self, + MMPort *data, + GError **error); + guint32 (* normalize_nw_error) (MMBroadbandModemMbim *self, + guint32 nw_error); + MMBroadbandModemMbimSetInitialEpsBearerSettingsFlag + (* load_set_initial_eps_bearer_settings_mask) (MMBroadbandModemMbim *self); }; GType mm_broadband_modem_mbim_get_type (void); |