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) 2008 - 2009 Novell, Inc.
|
||||||
* Copyright (C) 2009 - 2012 Red Hat, 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) 2015 Marco Bascetta <marco.bascetta@sadel.it>
|
||||||
* Copyright (C) 2019 Purism SPC
|
* Copyright (C) 2019 Purism SPC
|
||||||
|
* Copyright (C) 2011 - 2021 Google, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@@ -10097,6 +10097,554 @@ modem_signal_load_values (MMIfaceModemSignal *self,
|
|||||||
user_data);
|
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[] = {
|
static const gchar *primary_init_sequence[] = {
|
||||||
@@ -12579,8 +13127,22 @@ static void
|
|||||||
iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface)
|
iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface)
|
||||||
{
|
{
|
||||||
/* Initialization steps */
|
/* Initialization steps */
|
||||||
iface->check_support = NULL;
|
iface->check_support = modem_3gpp_profile_manager_check_support;
|
||||||
iface->check_support_finish = NULL;
|
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
|
static void
|
||||||
|
Reference in New Issue
Block a user