broadband-modem: implement profile management support
Using AT+CGDCONT for profile settings management (querying, updating, reseting), AT+CGDEL for profile deletion, and AT+CGACT for activation status management (check, deactivate).
This commit is contained in:
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* Copyright (C) 2008 - 2009 Novell, Inc.
|
||||
* Copyright (C) 2009 - 2012 Red Hat, Inc.
|
||||
* Copyright (C) 2011 - 2012 Google, Inc.
|
||||
* Copyright (C) 2015 Marco Bascetta <marco.bascetta@sadel.it>
|
||||
* Copyright (C) 2019 Purism SPC
|
||||
* Copyright (C) 2011 - 2021 Google, Inc.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -10097,6 +10097,554 @@ modem_signal_load_values (MMIfaceModemSignal *self,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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
|
||||
profile_manager_cgdcont_test_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
mm_base_modem_at_command_finish (self, res, &error);
|
||||
if (error)
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_3gpp_profile_manager_check_support (MMIfaceModem3gppProfileManager *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
if (!mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self))) {
|
||||
g_task_return_boolean (task, FALSE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Query with CGDCONT=? */
|
||||
mm_base_modem_at_command (
|
||||
MM_BASE_MODEM (self),
|
||||
"+CGDCONT=?",
|
||||
3,
|
||||
TRUE, /* allow caching, it's a test command */
|
||||
(GAsyncReadyCallback)profile_manager_cgdcont_test_ready,
|
||||
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 void
|
||||
profile_manager_cgdcont_query_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
ListProfilesContext *ctx;
|
||||
const gchar *response;
|
||||
GError *error = NULL;
|
||||
GList *pdp_context_list;
|
||||
|
||||
response = mm_base_modem_at_command_finish (self, res, &error);
|
||||
if (!response) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
/* may return NULL without error if response is empty */
|
||||
pdp_context_list = mm_3gpp_parse_cgdcont_read_response (response, &error);
|
||||
if (error) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = g_slice_new0 (ListProfilesContext);
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify) list_profiles_context_free);
|
||||
ctx->profiles = mm_3gpp_profile_list_new_from_pdp_context_list (pdp_context_list);
|
||||
|
||||
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)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
/* Query with CGDCONT? */
|
||||
mm_base_modem_at_command (
|
||||
MM_BASE_MODEM (self),
|
||||
"+CGDCONT?",
|
||||
3,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback)profile_manager_cgdcont_query_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Check format (3GPP profile management interface) */
|
||||
|
||||
typedef struct {
|
||||
MMBearerIpFamily ip_type;
|
||||
guint min_profile_id;
|
||||
guint max_profile_id;
|
||||
} CheckFormatContext;
|
||||
|
||||
static void
|
||||
check_format_context_free (CheckFormatContext *ctx)
|
||||
{
|
||||
g_slice_free (CheckFormatContext, ctx);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
CheckFormatContext *ctx;
|
||||
|
||||
if (!g_task_propagate_boolean (G_TASK (res), error))
|
||||
return FALSE;
|
||||
|
||||
ctx = g_task_get_task_data (G_TASK (res));
|
||||
if (new_id)
|
||||
*new_id = TRUE;
|
||||
if (min_profile_id)
|
||||
*min_profile_id = (gint) ctx->min_profile_id;
|
||||
if (max_profile_id)
|
||||
*max_profile_id = (gint) ctx->max_profile_id;
|
||||
if (apn_cmp)
|
||||
*apn_cmp = (GEqualFunc) mm_3gpp_cmp_apn_name;
|
||||
if (profile_cmp_flags)
|
||||
*profile_cmp_flags = (MM_3GPP_PROFILE_CMP_FLAGS_NO_AUTH | MM_3GPP_PROFILE_CMP_FLAGS_NO_APN_TYPE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
check_format_cgdcont_test_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
CheckFormatContext *ctx;
|
||||
const gchar *response;
|
||||
GList *format_list = NULL;
|
||||
g_autofree gchar *ip_family_str = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
gboolean checked = FALSE;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
ip_family_str = mm_bearer_ip_family_build_string_from_mask (ctx->ip_type);
|
||||
|
||||
response = mm_base_modem_at_command_full_finish (self, res, &error);
|
||||
if (!response)
|
||||
mm_obj_dbg (self, "failed checking context definition format: %s", error->message);
|
||||
else {
|
||||
format_list = mm_3gpp_parse_cgdcont_test_response (response, self, &error);
|
||||
if (error)
|
||||
mm_obj_dbg (self, "error parsing +CGDCONT test response: %s", error->message);
|
||||
else if (mm_3gpp_pdp_context_format_list_find_range (format_list, ctx->ip_type,
|
||||
&ctx->min_profile_id, &ctx->max_profile_id))
|
||||
checked = TRUE;
|
||||
}
|
||||
|
||||
if (!checked) {
|
||||
ctx->min_profile_id = 1;
|
||||
ctx->max_profile_id = G_MAXINT-1;
|
||||
mm_obj_dbg (self, "unknown +CGDCONT format details for PDP type '%s', using defaults: minimum %d, maximum %d",
|
||||
ip_family_str, ctx->min_profile_id, ctx->max_profile_id);
|
||||
} else
|
||||
mm_obj_dbg (self, "+CGDCONT format details for PDP type '%s': minimum %d, maximum %d",
|
||||
ip_family_str, ctx->min_profile_id, ctx->max_profile_id);
|
||||
|
||||
mm_3gpp_pdp_context_format_list_free (format_list);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_3gpp_profile_manager_check_format (MMIfaceModem3gppProfileManager *self,
|
||||
MMBearerIpFamily ip_type,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
CheckFormatContext *ctx;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
ctx = g_slice_new0 (CheckFormatContext);
|
||||
ctx->ip_type = ip_type;
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify)check_format_context_free);
|
||||
|
||||
mm_base_modem_at_command (MM_BASE_MODEM (self),
|
||||
"+CGDCONT=?",
|
||||
3,
|
||||
TRUE, /* cached */
|
||||
(GAsyncReadyCallback)check_format_cgdcont_test_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_cgdcont_reset_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gint profile_id;
|
||||
|
||||
profile_id = GPOINTER_TO_INT (g_task_get_task_data (task));
|
||||
|
||||
if (!mm_base_modem_at_command_finish (self, res, &error)) {
|
||||
mm_obj_dbg (self, "attempting to reset context with id '%d' failed: %s", profile_id, error->message);
|
||||
g_task_return_error (task, error);
|
||||
} else {
|
||||
mm_obj_dbg (self, "reseted context with profile id '%d'", profile_id);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
profile_manager_cgdel_set_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autofree gchar *cmd = NULL;
|
||||
gint profile_id;
|
||||
|
||||
profile_id = GPOINTER_TO_INT (g_task_get_task_data (task));
|
||||
|
||||
if (mm_base_modem_at_command_finish (self, res, &error)) {
|
||||
mm_obj_dbg (self, "deleted context with profile id '%d'", profile_id);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
mm_obj_dbg (self, "attempting to delete context with id '%d' failed: %s", profile_id, error->message);
|
||||
|
||||
/* From 3GPP TS 27.007 (v16.3.0):
|
||||
* A special form of the set command, +CGDCONT=<cid> causes the values for
|
||||
* context number <cid> to become undefined.
|
||||
*/
|
||||
cmd = g_strdup_printf ("+CGDCONT=%d", profile_id);
|
||||
mm_base_modem_at_command (
|
||||
MM_BASE_MODEM (self),
|
||||
cmd,
|
||||
3,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback)profile_manager_cgdcont_reset_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_3gpp_profile_manager_delete_profile (MMIfaceModem3gppProfileManager *self,
|
||||
MM3gppProfile *profile,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autofree gchar *cmd = NULL;
|
||||
GTask *task;
|
||||
gint profile_id;
|
||||
|
||||
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);
|
||||
|
||||
cmd = g_strdup_printf ("+CGDEL=%d", profile_id);
|
||||
|
||||
mm_base_modem_at_command (
|
||||
MM_BASE_MODEM (self),
|
||||
cmd,
|
||||
3,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback)profile_manager_cgdel_set_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Deactivate profile (3GPP profile management interface) */
|
||||
|
||||
static gboolean
|
||||
modem_3gpp_profile_manager_check_activated_profile_finish (MMIfaceModem3gppProfileManager *self,
|
||||
GAsyncResult *res,
|
||||
gboolean *out_activated,
|
||||
GError **error)
|
||||
{
|
||||
GError *inner_error = NULL;
|
||||
gboolean result;
|
||||
|
||||
result = g_task_propagate_boolean (G_TASK (res), &inner_error);
|
||||
if (inner_error) {
|
||||
g_propagate_error (error, inner_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (out_activated)
|
||||
*out_activated = result;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
check_activated_profile_cgact_query_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
MM3gppProfile *profile;
|
||||
const gchar *response;
|
||||
GError *error = NULL;
|
||||
GList *pdp_context_active_list = NULL;
|
||||
GList *l;
|
||||
gint profile_id;
|
||||
gboolean activated = FALSE;
|
||||
g_autofree gchar *cmd = NULL;
|
||||
|
||||
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
|
||||
if (response)
|
||||
pdp_context_active_list = mm_3gpp_parse_cgact_read_response (response, &error);
|
||||
|
||||
if (error) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
profile = g_task_get_task_data (task);
|
||||
profile_id = mm_3gpp_profile_get_profile_id (profile);
|
||||
|
||||
for (l = pdp_context_active_list; l; l = g_list_next (l)) {
|
||||
MM3gppPdpContextActive *iter = l->data;
|
||||
|
||||
if ((gint)iter->cid == profile_id) {
|
||||
activated = iter->active;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mm_3gpp_pdp_context_active_list_free (pdp_context_active_list);
|
||||
|
||||
if (!l)
|
||||
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND,
|
||||
"Profile '%d' not found in CGACT? response",
|
||||
profile_id);
|
||||
else
|
||||
g_task_return_boolean (task, activated);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_3gpp_profile_manager_check_activated_profile (MMIfaceModem3gppProfileManager *self,
|
||||
MM3gppProfile *profile,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
gint profile_id;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
g_task_set_task_data (task, g_object_ref (profile), g_object_unref);
|
||||
|
||||
profile_id = mm_3gpp_profile_get_profile_id (profile);
|
||||
|
||||
mm_obj_dbg (self, "checking if profile with id '%d' is already activated...", profile_id);
|
||||
mm_base_modem_at_command (
|
||||
MM_BASE_MODEM (self),
|
||||
"+CGACT?",
|
||||
3,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback)check_activated_profile_cgact_query_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Deactivate profile (3GPP profile management interface) */
|
||||
|
||||
static gboolean
|
||||
modem_3gpp_profile_manager_deactivate_profile_finish (MMIfaceModem3gppProfileManager *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
deactivate_profile_cgact_set_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error))
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_3gpp_profile_manager_deactivate_profile (MMIfaceModem3gppProfileManager *self,
|
||||
MM3gppProfile *profile,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
gint profile_id;
|
||||
g_autofree gchar *cmd = NULL;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
profile_id = mm_3gpp_profile_get_profile_id (profile);
|
||||
mm_obj_dbg (self, "deactivating profile with id '%d'...", profile_id);
|
||||
|
||||
cmd = g_strdup_printf ("+CGACT=0,%d", profile_id);
|
||||
mm_base_modem_at_command (
|
||||
MM_BASE_MODEM (self),
|
||||
cmd,
|
||||
MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback)deactivate_profile_cgact_set_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
|
||||
store_profile_cgdcont_set_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error))
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self,
|
||||
MM3gppProfile *profile,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
gint profile_id;
|
||||
MMBearerIpFamily ip_type;
|
||||
const gchar *apn;
|
||||
const gchar *pdp_type;
|
||||
g_autofree gchar *ip_type_str = NULL;
|
||||
g_autofree gchar *quoted_apn = NULL;
|
||||
g_autofree gchar *cmd = NULL;
|
||||
|
||||
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);
|
||||
|
||||
ip_type = mm_3gpp_profile_get_ip_type (profile);
|
||||
g_assert (ip_type != MM_BEARER_IP_FAMILY_NONE);
|
||||
g_assert (ip_type != MM_BEARER_IP_FAMILY_ANY);
|
||||
ip_type_str = mm_bearer_ip_family_build_string_from_mask (ip_type);
|
||||
pdp_type = mm_3gpp_get_pdp_type_from_ip_family (ip_type);
|
||||
g_assert (pdp_type);
|
||||
|
||||
apn = mm_3gpp_profile_get_apn (profile);
|
||||
quoted_apn = mm_port_serial_at_quote_string (apn);
|
||||
|
||||
mm_obj_dbg (self, "storing profile '%d': apn '%s', ip type '%s'",
|
||||
profile_id, apn, ip_type_str);
|
||||
|
||||
cmd = g_strdup_printf ("+CGDCONT=%d,\"%s\",%s", profile_id, pdp_type, quoted_apn);
|
||||
mm_base_modem_at_command (MM_BASE_MODEM (self),
|
||||
cmd,
|
||||
3,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback) store_profile_cgdcont_set_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const gchar *primary_init_sequence[] = {
|
||||
@@ -12579,8 +13127,22 @@ static void
|
||||
iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface)
|
||||
{
|
||||
/* Initialization steps */
|
||||
iface->check_support = NULL;
|
||||
iface->check_support_finish = NULL;
|
||||
iface->check_support = modem_3gpp_profile_manager_check_support;
|
||||
iface->check_support_finish = modem_3gpp_profile_manager_check_support_finish;
|
||||
|
||||
/* User actions */
|
||||
iface->list_profiles = modem_3gpp_profile_manager_list_profiles;
|
||||
iface->list_profiles_finish = modem_3gpp_profile_manager_list_profiles_finish;
|
||||
iface->delete_profile = modem_3gpp_profile_manager_delete_profile;
|
||||
iface->delete_profile_finish = modem_3gpp_profile_manager_delete_profile_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 = modem_3gpp_profile_manager_check_activated_profile;
|
||||
iface->check_activated_profile_finish = modem_3gpp_profile_manager_check_activated_profile_finish;
|
||||
iface->deactivate_profile = modem_3gpp_profile_manager_deactivate_profile;
|
||||
iface->deactivate_profile_finish = modem_3gpp_profile_manager_deactivate_profile_finish;
|
||||
iface->store_profile = modem_3gpp_profile_manager_store_profile;
|
||||
iface->store_profile_finish = modem_3gpp_profile_manager_store_profile_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
|
Reference in New Issue
Block a user