broadband-modem-mbim: support profile properties from MbimProvisionedContextElementV2

Microsoft defined a new extended version of the "provisioned contexts"
operation from the generic MBIM basic connect service. This extended
version adds several new settings that can be stored in the profile
(e.g. IP type, media type, roaming allowance...).

But this new version has a huge drawback; we cannot specify single
profiles via their unique id while we perform update/delete operations
in the modem. Instead, Microsoft explains that we should use the
context type to identify the target context; but this will ONLY work
if we have one context defined for each type. As soon as we have
multiple contexts of the same type, this operation may fail or
otherwise update multiple contexts at once.
This commit is contained in:
Aleksander Morgado
2021-11-27 22:59:29 +01:00
parent 6ba245cedc
commit b90d64192a
3 changed files with 576 additions and 57 deletions

View File

@@ -116,6 +116,7 @@ struct _MMBroadbandModemMbimPrivate {
/* Supported features */
gboolean is_profile_management_supported;
gboolean is_profile_management_ext_supported;
gboolean is_pco_supported;
gboolean is_lte_attach_info_supported;
gboolean is_nr5g_registration_settings_supported;
@@ -2632,6 +2633,9 @@ query_device_services_ready (MbimDevice *device,
} else if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS) {
mm_obj_dbg (self, "5GNR registration settings are supported");
self->priv->is_nr5g_registration_settings_supported = TRUE;
} else if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PROVISIONED_CONTEXTS) {
mm_obj_dbg (self, "Profile management extension is supported");
self->priv->is_profile_management_ext_supported = TRUE;
}
}
continue;
@@ -6036,7 +6040,7 @@ enable_unsolicited_events_3gpp_profile_manager (MMIfaceModem3gppProfileManager *
/* Check format (3gppProfileManager interface) */
static gboolean
modem_3gpp_profile_manager_check_format_finish (MMIfaceModem3gppProfileManager *self,
modem_3gpp_profile_manager_check_format_finish (MMIfaceModem3gppProfileManager *_self,
GAsyncResult *res,
gboolean *new_id,
gint *min_profile_id,
@@ -6045,6 +6049,8 @@ modem_3gpp_profile_manager_check_format_finish (MMIfaceModem3gppProfileManager
MM3gppProfileCmpFlags *profile_cmp_flags,
GError **error)
{
MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
if (!g_task_propagate_boolean (G_TASK (res), error)) {
g_assert_not_reached ();
return FALSE;
@@ -6059,11 +6065,17 @@ modem_3gpp_profile_manager_check_format_finish (MMIfaceModem3gppProfileManager
/* use default string comparison method */
if (apn_cmp)
*apn_cmp = NULL;
if (profile_cmp_flags)
*profile_cmp_flags = (MM_3GPP_PROFILE_CMP_FLAGS_NO_IP_TYPE |
MM_3GPP_PROFILE_CMP_FLAGS_NO_ACCESS_TYPE_PREFERENCE |
MM_3GPP_PROFILE_CMP_FLAGS_NO_ROAMING_ALLOWANCE |
MM_3GPP_PROFILE_CMP_FLAGS_NO_PROFILE_SOURCE);
if (profile_cmp_flags) {
if (!self->priv->is_profile_management_ext_supported)
*profile_cmp_flags = (MM_3GPP_PROFILE_CMP_FLAGS_NO_IP_TYPE |
MM_3GPP_PROFILE_CMP_FLAGS_NO_ACCESS_TYPE_PREFERENCE |
MM_3GPP_PROFILE_CMP_FLAGS_NO_ROAMING_ALLOWANCE |
MM_3GPP_PROFILE_CMP_FLAGS_NO_PROFILE_SOURCE);
else
/* when using the MS extensions, we support all IP type, access type
* preference, roaming allowance and profile source */
*profile_cmp_flags = 0;
}
return TRUE;
}
@@ -6132,6 +6144,60 @@ provisioned_context_element_to_3gpp_profile (MbimProvisionedContextElement *elem
return profile;
}
static MM3gppProfile *
provisioned_context_element_v2_to_3gpp_profile (MMBroadbandModemMbim *self,
MbimProvisionedContextElementV2 *element)
{
MM3gppProfile *profile;
MMBearerApnType apn_type;
GError *error = NULL;
gboolean enabled;
MMBearerRoamingAllowance roaming_allowance;
MMBearerAccessTypePreference access_type_preference;
MMBearerProfileSource profile_source;
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)));
if (!mm_boolean_from_mbim_context_state (element->state, &enabled, &error)) {
mm_obj_dbg (self, "ignoring enable setting: %s", error->message);
g_clear_error (&error);
} else
mm_3gpp_profile_set_enabled (profile, enabled);
roaming_allowance = mm_bearer_roaming_allowance_from_mbim_context_roaming_control (element->roaming, &error);
if (roaming_allowance == MM_BEARER_ROAMING_ALLOWANCE_NONE) {
mm_obj_dbg (self, "ignoring roaming allowance: %s", error->message);
g_clear_error (&error);
} else
mm_3gpp_profile_set_roaming_allowance (profile, roaming_allowance);
if (!mm_bearer_access_type_preference_from_mbim_context_media_type (element->media_type, &access_type_preference, &error)) {
mm_obj_dbg (self, "ignoring access type preference: %s", error->message);
g_clear_error (&error);
} else
mm_3gpp_profile_set_access_type_preference (profile, access_type_preference);
profile_source = mm_bearer_profile_source_from_mbim_context_source (element->source, &error);
if (profile_source == MM_BEARER_PROFILE_SOURCE_UNKNOWN) {
mm_obj_dbg (self, "ignoring profile source: %s", error->message);
g_clear_error (&error);
} else
mm_3gpp_profile_set_profile_source (profile, profile_source);
/* compression unused, and ip-type not provided */
return profile;
}
static void
profile_manager_provisioned_contexts_query_ready (MbimDevice *device,
GAsyncResult *res,
@@ -6139,42 +6205,84 @@ profile_manager_provisioned_contexts_query_ready (MbimDevice *device,
{
ListProfilesContext *ctx;
GError *error = NULL;
guint i;
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);
ctx = g_task_get_task_data (task);
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
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)) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
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);
g_object_unref (task);
}
static void
modem_3gpp_profile_manager_list_profiles (MMIfaceModem3gppProfileManager *self,
profile_manager_provisioned_contexts_v2_query_ready (MbimDevice *device,
GAsyncResult *res,
GTask *task)
{
MMBroadbandModemMbim *self;
ListProfilesContext *ctx;
GError *error = NULL;
guint i;
guint32 provisioned_contexts_count = 0;
g_autoptr(MbimMessage) response = NULL;
g_autoptr(MbimProvisionedContextElementV2Array) provisioned_contexts_v2 = NULL;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
response = mbim_device_command_finish (device, res, &error);
if (!response ||
!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) ||
!mbim_message_ms_basic_connect_extensions_provisioned_contexts_response_parse (response,
&provisioned_contexts_count,
&provisioned_contexts_v2,
&error)) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
for (i = 0; i < provisioned_contexts_count; i++) {
MM3gppProfile *profile;
profile = provisioned_context_element_v2_to_3gpp_profile (self, provisioned_contexts_v2[i]);
if (profile)
ctx->profiles = g_list_append (ctx->profiles, profile);
}
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
modem_3gpp_profile_manager_list_profiles (MMIfaceModem3gppProfileManager *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
ListProfilesContext *ctx;
MbimDevice *device;
GTask *task;
g_autoptr(MbimMessage) message = NULL;
@@ -6183,10 +6291,23 @@ modem_3gpp_profile_manager_list_profiles (MMIfaceModem3gppProfileManager *self,
return;
task = g_task_new (self, NULL, callback, user_data);
ctx = g_slice_new0 (ListProfilesContext);
g_task_set_task_data (task, ctx, (GDestroyNotify) list_profiles_context_free);
mm_obj_dbg (self, "querying provisioned contexts...");
message = mbim_message_provisioned_contexts_query_new (NULL);
if (self->priv->is_profile_management_ext_supported) {
message = mbim_message_ms_basic_connect_extensions_provisioned_contexts_query_new (NULL);
mbim_device_command (device,
message,
10,
NULL,
(GAsyncReadyCallback)profile_manager_provisioned_contexts_v2_query_ready,
task);
return;
}
message = mbim_message_provisioned_contexts_query_new (NULL);
mbim_device_command (device,
message,
10,
@@ -6226,25 +6347,26 @@ profile_manager_provisioned_contexts_set_ready (MbimDevice *device,
}
static void
modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self,
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;
MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
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;
@@ -6260,6 +6382,7 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self,
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_prefix_error (&error, "Failed to convert mbim context type from apn type: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
@@ -6275,24 +6398,87 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self,
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_prefix_error (&error, "Failed to convert mbim auth protocol from allowed auth: ");
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);
if (self->priv->is_profile_management_ext_supported) {
MbimContextIpType ip_type;
MbimContextState state;
MbimContextRoamingControl roaming;
MbimContextMediaType media_type;
MbimContextSource source;
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);
if (error) {
g_prefix_error (&error, "Failed to convert mbim context ip type from ip type: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
if (!mm_bearer_roaming_allowance_to_mbim_context_roaming_control (mm_3gpp_profile_get_roaming_allowance (profile), self, &roaming, &error)) {
g_prefix_error (&error, "Failed to convert mbim context roaming control from roaming allowance: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
if (!mm_bearer_access_type_preference_to_mbim_context_media_type (mm_3gpp_profile_get_access_type_preference (profile), self, &media_type, &error)) {
g_prefix_error (&error, "Failed to convert mbim context media type from access type preference: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
if (!mm_bearer_profile_source_to_mbim_context_source (mm_3gpp_profile_get_profile_source (profile), self, &source, &error)) {
g_prefix_error (&error, "Failed to convert mbim context source from profile source: ");
g_task_return_error (task, error);
g_object_unref (task);
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? */
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));
message = mbim_message_ms_basic_connect_extensions_provisioned_contexts_set_new (MBIM_CONTEXT_OPERATION_DEFAULT,
context_type_uuid,
ip_type,
state,
roaming,
media_type,
source,
apn ? apn : "",
user ? user : "",
password ? password : "",
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);
}
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);
@@ -6310,6 +6496,19 @@ 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,
@@ -6335,11 +6534,95 @@ profile_manager_provisioned_contexts_reset_ready (MbimDevice *device,
}
static void
modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *self,
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,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
MbimDevice *device;
GTask *task;
GError *error = NULL;
@@ -6354,8 +6637,21 @@ modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *self,
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);
if (self->priv->is_profile_management_ext_supported) {
DeleteProfileContext *ctx;
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);
modem_3gpp_profile_manager_list_profiles (_self,
(GAsyncReadyCallback)list_profiles_delete_ready,
task);
return;
}
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 */

View File

@@ -612,6 +612,202 @@ mm_bearer_ip_family_to_mbim_context_ip_type (MMBearerIpFamily ip_family,
/*****************************************************************************/
gboolean
mm_bearer_roaming_allowance_to_mbim_context_roaming_control (MMBearerRoamingAllowance mask,
gpointer log_object,
MbimContextRoamingControl *out_value,
GError **error)
{
if (mask == MM_BEARER_ROAMING_ALLOWANCE_NONE) {
mm_obj_dbg (log_object, "using default (all) roaming allowance");
*out_value = MBIM_CONTEXT_ROAMING_CONTROL_ALLOW_ALL;
} else if (mask == MM_BEARER_ROAMING_ALLOWANCE_HOME)
*out_value =MBIM_CONTEXT_ROAMING_CONTROL_HOME_ONLY;
else if (mask == MM_BEARER_ROAMING_ALLOWANCE_PARTNER)
*out_value =MBIM_CONTEXT_ROAMING_CONTROL_PARTNER_ONLY;
else if (mask == MM_BEARER_ROAMING_ALLOWANCE_NON_PARTNER)
*out_value =MBIM_CONTEXT_ROAMING_CONTROL_NON_PARTNER_ONLY;
else if (mask == (MM_BEARER_ROAMING_ALLOWANCE_HOME | MM_BEARER_ROAMING_ALLOWANCE_PARTNER))
*out_value =MBIM_CONTEXT_ROAMING_CONTROL_HOME_AND_PARTNER;
else if (mask == (MM_BEARER_ROAMING_ALLOWANCE_HOME | MM_BEARER_ROAMING_ALLOWANCE_NON_PARTNER))
*out_value =MBIM_CONTEXT_ROAMING_CONTROL_HOME_AND_NON_PARTNER;
else if (mask == (MM_BEARER_ROAMING_ALLOWANCE_PARTNER | MM_BEARER_ROAMING_ALLOWANCE_NON_PARTNER))
*out_value =MBIM_CONTEXT_ROAMING_CONTROL_PARTNER_AND_NON_PARTNER;
else if (mask == (MM_BEARER_ROAMING_ALLOWANCE_HOME | MM_BEARER_ROAMING_ALLOWANCE_PARTNER | MM_BEARER_ROAMING_ALLOWANCE_NON_PARTNER))
*out_value = MBIM_CONTEXT_ROAMING_CONTROL_ALLOW_ALL;
else {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported roaming allowance mask: 0x%x", mask);
return FALSE;
}
return TRUE;
}
MMBearerRoamingAllowance
mm_bearer_roaming_allowance_from_mbim_context_roaming_control (MbimContextRoamingControl value,
GError **error)
{
switch (value) {
case MBIM_CONTEXT_ROAMING_CONTROL_HOME_ONLY:
return MM_BEARER_ROAMING_ALLOWANCE_HOME;
case MBIM_CONTEXT_ROAMING_CONTROL_PARTNER_ONLY:
return MM_BEARER_ROAMING_ALLOWANCE_PARTNER;
case MBIM_CONTEXT_ROAMING_CONTROL_NON_PARTNER_ONLY:
return MM_BEARER_ROAMING_ALLOWANCE_NON_PARTNER;
case MBIM_CONTEXT_ROAMING_CONTROL_HOME_AND_PARTNER:
return (MM_BEARER_ROAMING_ALLOWANCE_HOME | MM_BEARER_ROAMING_ALLOWANCE_PARTNER);
case MBIM_CONTEXT_ROAMING_CONTROL_HOME_AND_NON_PARTNER:
return (MM_BEARER_ROAMING_ALLOWANCE_HOME | MM_BEARER_ROAMING_ALLOWANCE_NON_PARTNER);
case MBIM_CONTEXT_ROAMING_CONTROL_PARTNER_AND_NON_PARTNER:
return (MM_BEARER_ROAMING_ALLOWANCE_PARTNER | MM_BEARER_ROAMING_ALLOWANCE_NON_PARTNER);
case MBIM_CONTEXT_ROAMING_CONTROL_ALLOW_ALL:
return (MM_BEARER_ROAMING_ALLOWANCE_HOME | MM_BEARER_ROAMING_ALLOWANCE_PARTNER | MM_BEARER_ROAMING_ALLOWANCE_NON_PARTNER);
default:
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported roaming control value: 0x%x", value);
return MM_BEARER_ROAMING_ALLOWANCE_NONE;
}
}
/*****************************************************************************/
gboolean
mm_bearer_access_type_preference_to_mbim_context_media_type (MMBearerAccessTypePreference value,
gpointer log_object,
MbimContextMediaType *out_value,
GError **error)
{
switch (value) {
case MM_BEARER_ACCESS_TYPE_PREFERENCE_NONE:
mm_obj_dbg (log_object, "using default (cellular only) context media type");
*out_value = MBIM_CONTEXT_MEDIA_TYPE_CELLULAR_ONLY;
return TRUE;
case MM_BEARER_ACCESS_TYPE_PREFERENCE_3GPP_ONLY:
*out_value = MBIM_CONTEXT_MEDIA_TYPE_CELLULAR_ONLY;
return TRUE;
case MM_BEARER_ACCESS_TYPE_PREFERENCE_3GPP_PREFERRED:
*out_value = MBIM_CONTEXT_MEDIA_TYPE_ALL;
return TRUE;
case MM_BEARER_ACCESS_TYPE_PREFERENCE_NON_3GPP_ONLY:
*out_value = MBIM_CONTEXT_MEDIA_TYPE_WIFI_ONLY;
return TRUE;
default:
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported roaming control value: 0x%x", value);
return FALSE;
}
}
gboolean
mm_bearer_access_type_preference_from_mbim_context_media_type (MbimContextMediaType value,
MMBearerAccessTypePreference *out_value,
GError **error)
{
switch (value) {
case MBIM_CONTEXT_MEDIA_TYPE_CELLULAR_ONLY:
*out_value = MM_BEARER_ACCESS_TYPE_PREFERENCE_3GPP_ONLY;
return TRUE;
case MBIM_CONTEXT_MEDIA_TYPE_WIFI_ONLY:
*out_value = MM_BEARER_ACCESS_TYPE_PREFERENCE_NON_3GPP_ONLY;
return TRUE;
case MBIM_CONTEXT_MEDIA_TYPE_ALL:
*out_value = MM_BEARER_ACCESS_TYPE_PREFERENCE_3GPP_PREFERRED;
return TRUE;
default:
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported roaming control value: 0x%x", value);
return FALSE;
}
}
/*****************************************************************************/
gboolean
mm_boolean_from_mbim_context_state (MbimContextState value,
gboolean *out_value,
GError **error)
{
switch (value) {
case MBIM_CONTEXT_STATE_DISABLED:
*out_value = FALSE;
return TRUE;
case MBIM_CONTEXT_STATE_ENABLED:
*out_value = TRUE;
return TRUE;
default:
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported context state value: 0x%x", value);
return FALSE;
}
}
MbimContextState
mm_boolean_to_mbim_context_state (gboolean value)
{
return (value ? MBIM_CONTEXT_STATE_ENABLED: MBIM_CONTEXT_STATE_DISABLED);
}
/*****************************************************************************/
MMBearerProfileSource
mm_bearer_profile_source_from_mbim_context_source (MbimContextSource value,
GError **error)
{
switch (value) {
case MBIM_CONTEXT_SOURCE_ADMIN:
return MM_BEARER_PROFILE_SOURCE_ADMIN;
case MBIM_CONTEXT_SOURCE_USER:
return MM_BEARER_PROFILE_SOURCE_USER;
case MBIM_CONTEXT_SOURCE_OPERATOR:
return MM_BEARER_PROFILE_SOURCE_OPERATOR;
case MBIM_CONTEXT_SOURCE_MODEM:
return MM_BEARER_PROFILE_SOURCE_MODEM;
case MBIM_CONTEXT_SOURCE_DEVICE:
return MM_BEARER_PROFILE_SOURCE_DEVICE;
default:
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported context source value: 0x%x", value);
return MM_BEARER_PROFILE_SOURCE_UNKNOWN;
}
}
gboolean
mm_bearer_profile_source_to_mbim_context_source (MMBearerProfileSource value,
gpointer log_object,
MbimContextSource *out_value,
GError **error)
{
switch (value) {
case MM_BEARER_PROFILE_SOURCE_UNKNOWN:
mm_obj_dbg (log_object, "using default (admin) context source");
*out_value = MBIM_CONTEXT_SOURCE_ADMIN;
return TRUE;
case MM_BEARER_PROFILE_SOURCE_ADMIN:
*out_value = MBIM_CONTEXT_SOURCE_ADMIN;
return TRUE;
case MM_BEARER_PROFILE_SOURCE_USER:
*out_value = MBIM_CONTEXT_SOURCE_USER;
return TRUE;
case MM_BEARER_PROFILE_SOURCE_OPERATOR:
*out_value = MBIM_CONTEXT_SOURCE_OPERATOR;
return TRUE;
case MM_BEARER_PROFILE_SOURCE_MODEM:
*out_value = MBIM_CONTEXT_SOURCE_MODEM;
return TRUE;
case MM_BEARER_PROFILE_SOURCE_DEVICE:
*out_value = MBIM_CONTEXT_SOURCE_DEVICE;
return TRUE;
default:
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported profile source value: 0x%x", value);
return FALSE;
}
}
/*****************************************************************************/
/* index in the array is the code point (8 possible values), and the actual
* value is the lower limit of the error rate range. */
static const gdouble bit_error_rate_ranges[] = { 0.00, 0.20, 0.40, 0.80, 1.60, 3.20, 6.40, 12.80 };

View File

@@ -67,6 +67,33 @@ MbimContextType mm_bearer_apn_type_to_mbim_context_type (MMBearerApnT
gpointer log_object,
GError **error);
gboolean mm_bearer_roaming_allowance_to_mbim_context_roaming_control (MMBearerRoamingAllowance mask,
gpointer log_object,
MbimContextRoamingControl *out_value,
GError **error);
MMBearerRoamingAllowance mm_bearer_roaming_allowance_from_mbim_context_roaming_control (MbimContextRoamingControl value,
GError **error);
gboolean mm_bearer_access_type_preference_to_mbim_context_media_type (MMBearerAccessTypePreference value,
gpointer log_object,
MbimContextMediaType *out_value,
GError **error);
gboolean mm_bearer_access_type_preference_from_mbim_context_media_type (MbimContextMediaType value,
MMBearerAccessTypePreference *out_value,
GError **error);
gboolean mm_boolean_from_mbim_context_state (MbimContextState value,
gboolean *out_value,
GError **error);
MbimContextState mm_boolean_to_mbim_context_state (gboolean value);
MMBearerProfileSource mm_bearer_profile_source_from_mbim_context_source (MbimContextSource value,
GError **error);
gboolean mm_bearer_profile_source_to_mbim_context_source (MMBearerProfileSource value,
gpointer log_object,
MbimContextSource *out_value,
GError **error);
gboolean mm_signal_error_rate_percentage_from_coded_value (guint coded_value,
gdouble *out_percentage,
gboolean is_gsm,