diff options
Diffstat (limited to 'plugins/icera/mm-broadband-modem-icera.c')
-rw-r--r-- | plugins/icera/mm-broadband-modem-icera.c | 973 |
1 files changed, 668 insertions, 305 deletions
diff --git a/plugins/icera/mm-broadband-modem-icera.c b/plugins/icera/mm-broadband-modem-icera.c index 730a79fb..e60d4bd5 100644 --- a/plugins/icera/mm-broadband-modem-icera.c +++ b/plugins/icera/mm-broadband-modem-icera.c @@ -25,27 +25,33 @@ #include "ModemManager.h" #include "mm-serial-parsers.h" -#include "mm-log.h" +#include "mm-log-object.h" #include "mm-modem-helpers.h" #include "mm-errors-types.h" #include "mm-iface-modem.h" #include "mm-iface-modem-3gpp.h" +#include "mm-iface-modem-3gpp-profile-manager.h" #include "mm-iface-modem-time.h" +#include "mm-common-helpers.h" #include "mm-base-modem-at.h" #include "mm-bearer-list.h" #include "mm-broadband-bearer-icera.h" #include "mm-broadband-modem-icera.h" +#include "mm-modem-helpers-icera.h" -static void iface_modem_init (MMIfaceModem *iface); -static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); -static void iface_modem_time_init (MMIfaceModemTime *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_time_init (MMIfaceModemTime *iface); -static MMIfaceModem *iface_modem_parent; -static MMIfaceModem3gpp *iface_modem_3gpp_parent; +static MMIfaceModem *iface_modem_parent; +static MMIfaceModem3gpp *iface_modem_3gpp_parent; +static MMIfaceModem3gppProfileManager *iface_modem_3gpp_profile_manager_parent; G_DEFINE_TYPE_EXTENDED (MMBroadbandModemIcera, mm_broadband_modem_icera, 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_TIME, iface_modem_time_init)) enum { @@ -71,38 +77,38 @@ struct _MMBroadbandModemIceraPrivate { /* Load supported modes (Modem interface) */ static void -add_supported_mode (GArray **combinations, - guint mode) +add_supported_mode (MMBroadbandModemIcera *self, + GArray **combinations, + guint mode) { MMModemModeCombination combination; switch (mode) { case 0: - mm_dbg ("Modem supports 2G-only mode"); + mm_obj_dbg (self, "2G-only mode supported"); combination.allowed = MM_MODEM_MODE_2G; combination.preferred = MM_MODEM_MODE_NONE; break; case 1: - mm_dbg ("Modem supports 3G-only mode"); + mm_obj_dbg (self, "3G-only mode supported"); combination.allowed = MM_MODEM_MODE_3G; combination.preferred = MM_MODEM_MODE_NONE; break; case 2: - mm_dbg ("Modem supports 2G/3G mode with 2G preferred"); + mm_obj_dbg (self, "2G/3G mode with 2G preferred supported"); combination.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); combination.preferred = MM_MODEM_MODE_2G; break; case 3: - mm_dbg ("Modem supports 2G/3G mode with 3G preferred"); + mm_obj_dbg (self, "2G/3G mode with 3G preferred supported"); combination.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); combination.preferred = MM_MODEM_MODE_3G; break; case 5: - mm_dbg ("Modem supports 'any', but not explicitly listing it"); /* Any, no need to add it to the list */ return; default: - mm_warn ("Unsupported Icera mode found: %u", mode); + mm_obj_warn (self, "unsupported mode found in %%IPSYS=?: %u", mode); return; } @@ -182,18 +188,18 @@ load_supported_modes_finish (MMIfaceModem *self, guint j; for (j = modefirst; j <= modelast; j++) - add_supported_mode (&combinations, j); + add_supported_mode (MM_BROADBAND_MODEM_ICERA (self), &combinations, j); } else - mm_warn ("Couldn't parse mode interval (%s) in %%IPSYS=? response", split[i]); + mm_obj_warn (self, "couldn't parse mode interval in %%IPSYS=? response: %s", split[i]); g_free (first); } else { guint mode; /* Add single */ if (mm_get_uint_from_str (split[i], &mode)) - add_supported_mode (&combinations, mode); + add_supported_mode (MM_BROADBAND_MODEM_ICERA (self), &combinations, mode); else - mm_warn ("Couldn't parse mode (%s) in %%IPSYS=? response", split[i]); + mm_obj_warn (self, "couldn't parse mode in %%IPSYS=? response: %s", split[i]); } } @@ -305,24 +311,24 @@ modem_set_current_modes_finish (MMIfaceModem *self, GAsyncResult *res, GError **error) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + return g_task_propagate_boolean (G_TASK (res), error); } static void allowed_mode_update_ready (MMBaseModem *self, GAsyncResult *res, - GSimpleAsyncResult *operation_result) + GTask *task) { GError *error = NULL; mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (error) /* Let the error be critical. */ - g_simple_async_result_take_error (operation_result, error); + g_task_return_error (task, error); else - g_simple_async_result_set_op_res_gboolean (operation_result, TRUE); - g_simple_async_result_complete (operation_result); - g_object_unref (operation_result); + g_task_return_boolean (task, TRUE); + + g_object_unref (task); } static void @@ -332,14 +338,11 @@ modem_set_current_modes (MMIfaceModem *self, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *result; + GTask *task; gchar *command; gint icera_mode = -1; - result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_set_current_modes); + task = g_task_new (self, NULL, callback, user_data); /* * The core has checked the following: @@ -366,18 +369,16 @@ modem_set_current_modes (MMIfaceModem *self, allowed_str = mm_modem_mode_build_string_from_mask (allowed); preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_simple_async_result_set_error (result, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); + g_task_return_new_error (task, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Requested mode (allowed: '%s', preferred: '%s') not " + "supported by the modem.", + allowed_str, + preferred_str); + g_object_unref (task); g_free (allowed_str); g_free (preferred_str); - - g_simple_async_result_complete_in_idle (result); - g_object_unref (result); return; } @@ -388,7 +389,7 @@ modem_set_current_modes (MMIfaceModem *self, 3, FALSE, (GAsyncReadyCallback)allowed_mode_update_ready, - result); + task); g_free (command); } @@ -404,12 +405,21 @@ static void bearer_list_report_status_foreach (MMBaseBearer *bearer, BearerListReportStatusForeachContext *ctx) { - if (mm_broadband_bearer_get_3gpp_cid (MM_BROADBAND_BEARER (bearer)) != ctx->cid) - return; + gint profile_id; + gint connecting_profile_id; if (!MM_IS_BROADBAND_BEARER_ICERA (bearer)) return; + /* The profile ID in the base bearer is set only once the modem is connected */ + profile_id = mm_base_bearer_get_profile_id (bearer); + + /* The profile ID in the icera bearer is available during the connecting phase */ + connecting_profile_id = mm_broadband_bearer_icera_get_connecting_profile_id (MM_BROADBAND_BEARER_ICERA (bearer)); + + if ((profile_id != (gint)ctx->cid) && (connecting_profile_id != (gint)ctx->cid)) + return; + mm_base_bearer_report_connection_status (bearer, ctx->status); } @@ -446,7 +456,7 @@ ipdpact_received (MMPortSerialAt *port, ctx.status = MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED; break; default: - mm_warn ("Unknown Icera connect status %d", status); + mm_obj_warn (self, "unknown %%IPDPACT connect status %d", status); break; } @@ -555,7 +565,7 @@ set_unsolicited_events_handlers (MMBroadbandModemIcera *self, ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); /* Enable unsolicited events in given port */ - for (i = 0; i < 2; i++) { + for (i = 0; i < G_N_ELEMENTS (ports); i++) { if (!ports[i]) continue; @@ -597,12 +607,16 @@ modem_load_access_technologies_finish (MMIfaceModem *self, guint *mask, GError **error) { - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + GError *inner_error = NULL; + gssize value; + + value = g_task_propagate_int (G_TASK (res), &inner_error); + if (inner_error) { + g_propagate_error (error, inner_error); return FALSE; + } - *access_technologies = ((MMModemAccessTechnology) GPOINTER_TO_UINT ( - g_simple_async_result_get_op_res_gpointer ( - G_SIMPLE_ASYNC_RESULT (res)))); + *access_technologies = (MMModemAccessTechnology) value; *mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; return TRUE; } @@ -610,26 +624,22 @@ modem_load_access_technologies_finish (MMIfaceModem *self, static void nwstate_query_ready (MMBroadbandModemIcera *self, GAsyncResult *res, - GSimpleAsyncResult *operation_result) + GTask *task) { GError *error = NULL; mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); - if (error) { - mm_dbg ("Couldn't query access technology: '%s'", error->message); - g_simple_async_result_take_error (operation_result, error); - } else { + if (error) + g_task_return_error (task, error); + else { /* * The unsolicited message handler will already have run and * removed the NWSTATE response, so we use the result from there. */ - g_simple_async_result_set_op_res_gpointer (operation_result, - GUINT_TO_POINTER (self->priv->last_act), - NULL); + g_task_return_int (task, self->priv->last_act); } - g_simple_async_result_complete (operation_result); - g_object_unref (operation_result); + g_object_unref (task); } static void @@ -637,12 +647,9 @@ modem_load_access_technologies (MMIfaceModem *self, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *result; + GTask *task; - result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_load_access_technologies); + task = g_task_new (self, NULL, callback, user_data); mm_base_modem_at_command ( MM_BASE_MODEM (self), @@ -650,7 +657,7 @@ modem_load_access_technologies (MMIfaceModem *self, 3, FALSE, (GAsyncReadyCallback)nwstate_query_ready, - result); + task); } /*****************************************************************************/ @@ -661,26 +668,24 @@ modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, GAsyncResult *res, GError **error) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + return g_task_propagate_boolean (G_TASK (res), error); } static void parent_setup_unsolicited_events_ready (MMIfaceModem3gpp *self, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { GError *error = NULL; if (!iface_modem_3gpp_parent->setup_unsolicited_events_finish (self, res, &error)) - g_simple_async_result_take_error (simple, error); + g_task_return_error (task, error); else { /* Our own setup now */ set_unsolicited_events_handlers (MM_BROADBAND_MODEM_ICERA (self), TRUE); - g_simple_async_result_set_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res), TRUE); + g_task_return_boolean (task, TRUE); } - - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_object_unref (task); } static void @@ -692,25 +697,21 @@ modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, iface_modem_3gpp_parent->setup_unsolicited_events ( self, (GAsyncReadyCallback)parent_setup_unsolicited_events_ready, - g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_setup_unsolicited_events)); + g_task_new (self, NULL, callback, user_data)); } static void parent_cleanup_unsolicited_events_ready (MMIfaceModem3gpp *self, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { GError *error = NULL; if (!iface_modem_3gpp_parent->cleanup_unsolicited_events_finish (self, res, &error)) - g_simple_async_result_take_error (simple, error); + g_task_return_error (task, error); else - g_simple_async_result_set_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res), TRUE); - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_boolean (task, TRUE); + g_object_unref (task); } static void @@ -718,13 +719,6 @@ modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *result; - - result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_cleanup_unsolicited_events); - /* Our own cleanup first */ set_unsolicited_events_handlers (MM_BROADBAND_MODEM_ICERA (self), FALSE); @@ -732,7 +726,7 @@ modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, iface_modem_3gpp_parent->cleanup_unsolicited_events ( self, (GAsyncReadyCallback)parent_cleanup_unsolicited_events_ready, - result); + g_task_new (self, NULL, callback, user_data)); } /*****************************************************************************/ @@ -743,35 +737,33 @@ modem_3gpp_enable_disable_unsolicited_events_finish (MMIfaceModem3gpp *self, GAsyncResult *res, GError **error) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + return g_task_propagate_boolean (G_TASK (res), error); } static void own_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { GError *error = NULL; if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) - g_simple_async_result_take_error (simple, error); + g_task_return_error (task, error); else - g_simple_async_result_set_op_res_gboolean (simple, TRUE); - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_boolean (task, TRUE); + g_object_unref (task); } static void parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { GError *error = NULL; if (!iface_modem_3gpp_parent->enable_unsolicited_events_finish (self, res, &error)) { - g_simple_async_result_take_error (simple, error); - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_error (task, error); + g_object_unref (task); return; } @@ -782,7 +774,7 @@ parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self, 3, FALSE, (GAsyncReadyCallback)own_enable_unsolicited_events_ready, - simple); + task); } static void @@ -794,38 +786,33 @@ modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self, iface_modem_3gpp_parent->enable_unsolicited_events ( self, (GAsyncReadyCallback)parent_enable_unsolicited_events_ready, - g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_enable_unsolicited_events)); + g_task_new (self, NULL, callback, user_data)); } static void parent_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { GError *error = NULL; if (!iface_modem_3gpp_parent->disable_unsolicited_events_finish (self, res, &error)) - g_simple_async_result_take_error (simple, error); + g_task_return_error (task, error); else - g_simple_async_result_set_op_res_gboolean (simple, TRUE); - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_boolean (task, TRUE); + g_object_unref (task); } static void own_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { GError *error = NULL; if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) { - g_simple_async_result_take_error (simple, error); - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_error (task, error); + g_object_unref (task); return; } @@ -833,7 +820,7 @@ own_disable_unsolicited_events_ready (MMIfaceModem3gpp *self, iface_modem_3gpp_parent->disable_unsolicited_events ( MM_IFACE_MODEM_3GPP (self), (GAsyncReadyCallback)parent_disable_unsolicited_events_ready, - simple); + task); } static void @@ -847,10 +834,7 @@ modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self, 3, FALSE, (GAsyncReadyCallback)own_disable_unsolicited_events_ready, - g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_3gpp_disable_unsolicited_events)); + g_task_new (self, NULL, callback, user_data)); } /*****************************************************************************/ @@ -861,84 +845,72 @@ modem_create_bearer_finish (MMIfaceModem *self, GAsyncResult *res, GError **error) { - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) - return NULL; - - return MM_BASE_BEARER (g_object_ref ( - g_simple_async_result_get_op_res_gpointer ( - G_SIMPLE_ASYNC_RESULT (res)))); + return g_task_propagate_pointer (G_TASK (res), error); } static void broadband_bearer_icera_new_ready (GObject *source, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { MMBaseBearer *bearer = NULL; GError *error = NULL; bearer = mm_broadband_bearer_icera_new_finish (res, &error); if (!bearer) - g_simple_async_result_take_error (simple, error); + g_task_return_error (task, error); else - g_simple_async_result_set_op_res_gpointer (simple, - bearer, - (GDestroyNotify)g_object_unref); - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_pointer (task, bearer, g_object_unref); + + g_object_unref (task); } static void broadband_bearer_new_ready (GObject *source, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { MMBaseBearer *bearer = NULL; GError *error = NULL; bearer = mm_broadband_bearer_new_finish (res, &error); if (!bearer) - g_simple_async_result_take_error (simple, error); + g_task_return_error (task, error); else - g_simple_async_result_set_op_res_gpointer (simple, - bearer, - (GDestroyNotify)g_object_unref); - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_pointer (task, bearer, g_object_unref); + + g_object_unref (task); } static void -modem_create_bearer (MMIfaceModem *self, - MMBearerProperties *properties, - GAsyncReadyCallback callback, - gpointer user_data) +modem_create_bearer (MMIfaceModem *self, + MMBearerProperties *props, + GAsyncReadyCallback callback, + gpointer user_data) { - GSimpleAsyncResult *result; + GTask *task; - result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_create_bearer); + task = g_task_new (self, NULL, callback, user_data); /* If we get a NET port, create Icera bearer */ if (mm_base_modem_peek_best_data_port (MM_BASE_MODEM (self), MM_PORT_TYPE_NET)) { mm_broadband_bearer_icera_new ( MM_BROADBAND_MODEM (self), MM_BROADBAND_MODEM_ICERA (self)->priv->default_ip_method, - properties, + props, NULL, /* cancellable */ (GAsyncReadyCallback)broadband_bearer_icera_new_ready, - result); + task); return; } /* Otherwise, plain generic broadband bearer */ mm_broadband_bearer_new ( MM_BROADBAND_MODEM (self), - properties, + props, NULL, /* cancellable */ (GAsyncReadyCallback)broadband_bearer_new_ready, - result); + task); } /*****************************************************************************/ @@ -949,13 +921,13 @@ modem_power_up_finish (MMIfaceModem *self, GAsyncResult *res, GError **error) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + return g_task_propagate_boolean (G_TASK (res), error); } static void cfun_enable_ready (MMBaseModem *self, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { GError *error = NULL; @@ -964,13 +936,14 @@ cfun_enable_ready (MMBaseModem *self, if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NOT_ALLOWED)) - g_simple_async_result_take_error (simple, error); - else + g_task_return_error (task, error); + else { g_error_free (error); + g_task_return_boolean (task, TRUE); + } } - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_object_unref (task); } static void @@ -978,19 +951,12 @@ modem_power_up (MMIfaceModem *self, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *result; - - result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_power_up); - mm_base_modem_at_command (MM_BASE_MODEM (self), "+CFUN=1", 10, FALSE, (GAsyncReadyCallback)cfun_enable_ready, - result); + g_task_new (self, NULL, callback, user_data)); } /*****************************************************************************/ @@ -1056,16 +1022,13 @@ modem_load_unlock_retries_finish (MMIfaceModem *self, GAsyncResult *res, GError **error) { - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) - return NULL; - return (MMUnlockRetries *) g_object_ref (g_simple_async_result_get_op_res_gpointer ( - G_SIMPLE_ASYNC_RESULT (res))); + return g_task_propagate_pointer (G_TASK (res), error); } static void load_unlock_retries_ready (MMBaseModem *self, GAsyncResult *res, - GSimpleAsyncResult *operation_result) + GTask *task) { const gchar *response; GError *error = NULL; @@ -1073,10 +1036,8 @@ load_unlock_retries_ready (MMBaseModem *self, response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (!response) { - mm_dbg ("Couldn't query unlock retries: '%s'", error->message); - g_simple_async_result_take_error (operation_result, error); - g_simple_async_result_complete (operation_result); - g_object_unref (operation_result); + g_task_return_error (task, error); + g_object_unref (task); return; } @@ -1088,18 +1049,15 @@ load_unlock_retries_ready (MMBaseModem *self, mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, puk1); mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, pin2); mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, puk2); - g_simple_async_result_set_op_res_gpointer (operation_result, - retries, - (GDestroyNotify)g_object_unref); + g_task_return_pointer (task, retries, g_object_unref); } else { - g_simple_async_result_set_error (operation_result, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Invalid unlock retries response: '%s'", - response); + g_task_return_new_error (task, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Invalid unlock retries response: '%s'", + response); } - g_simple_async_result_complete (operation_result); - g_object_unref (operation_result); + g_object_unref (task); } static void @@ -1113,10 +1071,7 @@ modem_load_unlock_retries (MMIfaceModem *self, 3, FALSE, (GAsyncReadyCallback)load_unlock_retries_ready, - g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_load_unlock_retries)); + g_task_new (self, NULL, callback, user_data)); } /*****************************************************************************/ @@ -1137,20 +1092,20 @@ band_free (Band *b) static const Band modem_bands[] = { /* Sort 3G first since it's preferred */ - { MM_MODEM_BAND_U2100, "FDD_BAND_I", FALSE }, - { MM_MODEM_BAND_U1900, "FDD_BAND_II", FALSE }, - { MM_MODEM_BAND_U1800, "FDD_BAND_III", FALSE }, - { MM_MODEM_BAND_U17IV, "FDD_BAND_IV", FALSE }, - { MM_MODEM_BAND_U800, "FDD_BAND_VI", FALSE }, - { MM_MODEM_BAND_U850, "FDD_BAND_V", FALSE }, - { MM_MODEM_BAND_U900, "FDD_BAND_VIII", FALSE }, + { MM_MODEM_BAND_UTRAN_1, (gchar *) "FDD_BAND_I", FALSE }, + { MM_MODEM_BAND_UTRAN_2, (gchar *) "FDD_BAND_II", FALSE }, + { MM_MODEM_BAND_UTRAN_3, (gchar *) "FDD_BAND_III", FALSE }, + { MM_MODEM_BAND_UTRAN_4, (gchar *) "FDD_BAND_IV", FALSE }, + { MM_MODEM_BAND_UTRAN_5, (gchar *) "FDD_BAND_V", FALSE }, + { MM_MODEM_BAND_UTRAN_6, (gchar *) "FDD_BAND_VI", FALSE }, + { MM_MODEM_BAND_UTRAN_8, (gchar *) "FDD_BAND_VIII", FALSE }, /* 2G second */ - { MM_MODEM_BAND_G850, "G850", FALSE }, - { MM_MODEM_BAND_DCS, "DCS", FALSE }, - { MM_MODEM_BAND_EGSM, "EGSM", FALSE }, - { MM_MODEM_BAND_PCS, "PCS", FALSE }, + { MM_MODEM_BAND_G850, (gchar *) "G850", FALSE }, + { MM_MODEM_BAND_DCS, (gchar *) "DCS", FALSE }, + { MM_MODEM_BAND_EGSM, (gchar *) "EGSM", FALSE }, + { MM_MODEM_BAND_PCS, (gchar *) "PCS", FALSE }, /* And ANY last since it's most inclusive */ - { MM_MODEM_BAND_ANY, "ANY", FALSE }, + { MM_MODEM_BAND_ANY, (gchar *) "ANY", FALSE }, }; static const guint modem_band_any_bit = 1 << (G_N_ELEMENTS (modem_bands) - 1); @@ -1158,7 +1113,7 @@ static const guint modem_band_any_bit = 1 << (G_N_ELEMENTS (modem_bands) - 1); static MMModemBand icera_band_to_mm (const char *icera) { - int i; + guint i; for (i = 0 ; i < G_N_ELEMENTS (modem_bands); i++) { if (g_strcmp0 (icera, modem_bands[i].name) == 0) @@ -1219,7 +1174,7 @@ parse_bands (const gchar *response, guint32 *out_len) /* Load supported bands (Modem interface) */ typedef struct { - MMBaseModemAtCommand *cmds; + MMBaseModemAtCommandAlloc *cmds; GSList *check_bands; GSList *enabled_bands; guint32 idx; @@ -1231,7 +1186,7 @@ supported_bands_context_free (SupportedBandsContext *ctx) guint i; for (i = 0; ctx->cmds[i].command; i++) - g_free (ctx->cmds[i].command); + mm_base_modem_at_command_alloc_clear (&ctx->cmds[i]); g_free (ctx->cmds); g_slist_free_full (ctx->check_bands, (GDestroyNotify) band_free); g_slist_free_full (ctx->enabled_bands, (GDestroyNotify) band_free); @@ -1243,17 +1198,13 @@ modem_load_supported_bands_finish (MMIfaceModem *self, GAsyncResult *res, GError **error) { - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) - return NULL; - - return (GArray *) g_array_ref (g_simple_async_result_get_op_res_gpointer ( - G_SIMPLE_ASYNC_RESULT (res))); + return g_task_propagate_pointer (G_TASK (res), error); } static void load_supported_bands_ready (MMBaseModem *self, GAsyncResult *res, - GSimpleAsyncResult *simple) + GTask *task) { GError *error = NULL; SupportedBandsContext *ctx = NULL; @@ -1262,7 +1213,7 @@ load_supported_bands_ready (MMBaseModem *self, mm_base_modem_at_sequence_finish (self, res, (gpointer) &ctx, &error); if (error) - g_simple_async_result_take_error (simple, error); + g_task_return_error (task, error); else { bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), ctx->idx); @@ -1282,26 +1233,26 @@ load_supported_bands_ready (MMBaseModem *self, g_array_prepend_val (bands, b->band); } - g_simple_async_result_set_op_res_gpointer (simple, - bands, - (GDestroyNotify) g_array_unref); + g_task_return_pointer (task, bands, (GDestroyNotify) g_array_unref); } - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_object_unref (task); } -static gboolean -load_supported_bands_response_processor (MMBaseModem *self, - gpointer context, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - SupportedBandsContext *ctx = context; - Band *b = g_slist_nth_data (ctx->check_bands, ctx->idx++); +static MMBaseModemAtResponseProcessorResult +load_supported_bands_response_processor (MMBaseModem *self, + gpointer context, + const gchar *command, + const gchar *response, + gboolean last_command, + const GError *error, + GVariant **result, + GError **result_error) +{ + SupportedBandsContext *ctx; + Band *b; + + ctx = context; + b = g_slist_nth_data (ctx->check_bands, ctx->idx++); /* If there was no error setting the band, that band is supported. We * abuse the 'enabled' item to mean supported/unsupported. @@ -1309,13 +1260,13 @@ load_supported_bands_response_processor (MMBaseModem *self, b->enabled = !error; /* Continue to next band */ - return FALSE; + return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; } static void load_supported_bands_get_current_bands_ready (MMIfaceModem *self, GAsyncResult *res, - GSimpleAsyncResult *operation_result) + GTask *task) { SupportedBandsContext *ctx; const gchar *response; @@ -1325,10 +1276,8 @@ load_supported_bands_get_current_bands_ready (MMIfaceModem *self, response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (!response) { - mm_dbg ("Couldn't query current bands: '%s'", error->message); - g_simple_async_result_take_error (operation_result, error); - g_simple_async_result_complete (operation_result); - g_object_unref (operation_result); + g_task_return_error (task, error); + g_object_unref (task); return; } @@ -1338,7 +1287,7 @@ load_supported_bands_get_current_bands_ready (MMIfaceModem *self, * to its current enabled/disabled state. */ iter = ctx->check_bands = parse_bands (response, &len); - ctx->cmds = g_new0 (MMBaseModemAtCommand, len + 1); + ctx->cmds = g_new0 (MMBaseModemAtCommandAlloc, len + 1); while (iter) { Band *b = iter->data; @@ -1362,11 +1311,11 @@ load_supported_bands_get_current_bands_ready (MMIfaceModem *self, } mm_base_modem_at_sequence (MM_BASE_MODEM (self), - ctx->cmds, + (const MMBaseModemAtCommand *)ctx->cmds, ctx, (GDestroyNotify) supported_bands_context_free, (GAsyncReadyCallback) load_supported_bands_ready, - operation_result); + task); } static void @@ -1385,10 +1334,7 @@ modem_load_supported_bands (MMIfaceModem *self, 3, FALSE, (GAsyncReadyCallback)load_supported_bands_get_current_bands_ready, - g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_load_supported_bands)); + g_task_new (self, NULL, callback, user_data)); } /*****************************************************************************/ @@ -1399,17 +1345,13 @@ modem_load_current_bands_finish (MMIfaceModem *self, GAsyncResult *res, GError **error) { - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) - return NULL; - - return (GArray *) g_array_ref (g_simple_async_result_get_op_res_gpointer ( - G_SIMPLE_ASYNC_RESULT (res))); + return g_task_propagate_pointer (G_TASK (res), error); } static void load_current_bands_ready (MMIfaceModem *self, GAsyncResult *res, - GSimpleAsyncResult *operation_result) + GTask *task) { GArray *bands; const gchar *response; @@ -1419,10 +1361,7 @@ load_current_bands_ready (MMIfaceModem *self, response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (!response) { - mm_dbg ("Couldn't query current bands: '%s'", error->message); - g_simple_async_result_take_error (operation_result, error); - g_simple_async_result_complete (operation_result); - g_object_unref (operation_result); + g_task_return_error (task, error); } else { /* Parse bands from Icera response into MM band numbers */ parsed = parse_bands (response, &len); @@ -1435,12 +1374,9 @@ load_current_bands_ready (MMIfaceModem *self, } g_slist_free_full (parsed, (GDestroyNotify) band_free); - g_simple_async_result_set_op_res_gpointer (operation_result, - bands, - (GDestroyNotify)g_array_unref); - g_simple_async_result_complete (operation_result); - g_object_unref (operation_result); + g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); } + g_object_unref (task); } static void @@ -1454,17 +1390,13 @@ modem_load_current_bands (MMIfaceModem *self, 3, FALSE, (GAsyncReadyCallback)load_current_bands_ready, - g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_load_current_bands)); + g_task_new (self, NULL, callback, user_data)); } /*****************************************************************************/ /* Set current bands (Modem interface) */ typedef struct { - GSimpleAsyncResult *result; guint bandbits; guint enablebits; guint disablebits; @@ -1482,43 +1414,37 @@ modem_set_current_bands_finish (MMIfaceModem *self, GAsyncResult *res, GError **error) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + return g_task_propagate_boolean (G_TASK (res), error); } -static void set_one_band (MMIfaceModem *self, SetCurrentBandsContext *ctx); - -static void -set_current_bands_context_complete_and_free (SetCurrentBandsContext *ctx) -{ - g_simple_async_result_complete (ctx->result); - g_object_unref (ctx->result); - g_slice_free (SetCurrentBandsContext, ctx); -} +static void set_one_band (MMIfaceModem *self, GTask *task); static void set_current_bands_next (MMIfaceModem *self, GAsyncResult *res, - SetCurrentBandsContext *ctx) + GTask *task) { GError *error = NULL; if (!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error)) { - mm_dbg ("Couldn't set current bands: '%s'", error->message); - g_simple_async_result_take_error (ctx->result, error); - set_current_bands_context_complete_and_free (ctx); + g_task_return_error (task, error); + g_object_unref (task); return; } - set_one_band (self, ctx); + set_one_band (self, task); } static void set_one_band (MMIfaceModem *self, - SetCurrentBandsContext *ctx) + GTask *task) { + SetCurrentBandsContext *ctx; guint enable, band; gchar *command; + ctx = g_task_get_task_data (task); + /* Find the next band to enable or disable, always doing enables first */ enable = 1; band = ffs (ctx->enablebits); @@ -1528,22 +1454,22 @@ set_one_band (MMIfaceModem *self, } if (band == 0) { /* Both enabling and disabling are done */ - g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); - set_current_bands_context_complete_and_free (ctx); + g_task_return_boolean (task, TRUE); + g_object_unref (task); return; } /* Note that ffs() returning 2 corresponds to 1 << 1, not 1 << 2 */ band--; - mm_dbg("1. enablebits %x disablebits %x band %d enable %d", - ctx->enablebits, ctx->disablebits, band, enable); + mm_obj_dbg (self, "preparing %%IPBM command (1/2): enablebits %x, disablebits %x, band %d, enable %d", + ctx->enablebits, ctx->disablebits, band, enable); if (enable) ctx->enablebits &= ~(1 << band); else ctx->disablebits &= ~(1 << band); - mm_dbg("2. enablebits %x disablebits %x", - ctx->enablebits, ctx->disablebits); + mm_obj_dbg (self, "preparing %%IPBM command (2/2): enablebits %x, disablebits %x", + ctx->enablebits, ctx->disablebits); command = g_strdup_printf ("%%IPBM=\"%s\",%d", modem_bands[band].name, @@ -1554,7 +1480,7 @@ set_one_band (MMIfaceModem *self, 10, FALSE, (GAsyncReadyCallback)set_current_bands_next, - ctx); + task); g_free (command); } @@ -1582,24 +1508,26 @@ band_array_to_bandbits (GArray *bands) static void set_current_bands_got_current_bands (MMIfaceModem *self, GAsyncResult *res, - SetCurrentBandsContext *ctx) + GTask *task) { + SetCurrentBandsContext *ctx; GArray *bands; GError *error = NULL; guint currentbits; bands = modem_load_current_bands_finish (self, res, &error); if (!bands) { - g_simple_async_result_take_error (ctx->result, error); - set_current_bands_context_complete_and_free (ctx); + g_task_return_error (task, error); + g_object_unref (task); return; } + ctx = g_task_get_task_data (task); currentbits = band_array_to_bandbits (bands); ctx->enablebits = ctx->bandbits & ~currentbits; ctx->disablebits = currentbits & ~ctx->bandbits; - set_one_band (self, ctx); + set_one_band (self, task); } static void @@ -1609,27 +1537,27 @@ modem_set_current_bands (MMIfaceModem *self, gpointer user_data) { SetCurrentBandsContext *ctx; + GTask *task; - ctx = g_slice_new0 (SetCurrentBandsContext); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_set_current_bands); + ctx = g_new0 (SetCurrentBandsContext, 1); ctx->bandbits = band_array_to_bandbits (bands_array); + task = g_task_new (self, NULL, callback, user_data); + g_task_set_task_data (task, ctx, g_free); + /* * If ANY is requested, simply enable ANY to activate all bands except for * those forbidden. */ if (ctx->bandbits & modem_band_any_bit) { ctx->enablebits = modem_band_any_bit; ctx->disablebits = 0; - set_one_band (self, ctx); + set_one_band (self, task); return; } modem_load_current_bands (self, (GAsyncReadyCallback)set_current_bands_got_current_bands, - ctx); + task); } /*****************************************************************************/ @@ -1763,6 +1691,424 @@ modem_time_load_network_timezone (MMIfaceModemTime *self, } /*****************************************************************************/ +/* 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_ipdpcfg_query_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) +{ + ListProfilesContext *ctx; + const gchar *response; + g_autoptr(GError) error = NULL; + + ctx = g_task_get_task_data (task); + + response = mm_base_modem_at_command_finish (self, res, &error); + if (!response) + mm_obj_warn (self, "couldn't load PDP context auth settings: %s", error->message); + else if (!mm_icera_parse_ipdpcfg_query_response (response, ctx->profiles, self, &error)) + mm_obj_warn (self, "couldn't update profile list with PDP context auth settings: %s", error->message); + + /* complete successfully anyway */ + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +profile_manager_parent_list_profiles_ready (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GTask *task) +{ + ListProfilesContext *ctx; + GError *error = NULL; + + ctx = g_slice_new0 (ListProfilesContext); + g_task_set_task_data (task, ctx, (GDestroyNotify) list_profiles_context_free); + + if (!iface_modem_3gpp_profile_manager_parent->list_profiles_finish (self, res, &ctx->profiles, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + if (!ctx->profiles) { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + mm_base_modem_at_command ( + MM_BASE_MODEM (self), + "%IPDPCFG?", + 3, + FALSE, + (GAsyncReadyCallback)profile_manager_ipdpcfg_query_ready, + 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); + + iface_modem_3gpp_profile_manager_parent->list_profiles ( + self, + (GAsyncReadyCallback)profile_manager_parent_list_profiles_ready, + task); +} + +typedef struct { + gboolean new_id; + gint min_profile_id; + gint max_profile_id; + GEqualFunc apn_cmp; + MM3gppProfileCmpFlags profile_cmp_flags; +} 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 = ctx->new_id; + 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 = ctx->apn_cmp; + if (profile_cmp_flags) + *profile_cmp_flags = ctx->profile_cmp_flags; + return TRUE; +} + +static void +profile_manager_parent_check_format_ready (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + CheckFormatContext *ctx; + + ctx = g_task_get_task_data (task); + + if (!iface_modem_3gpp_profile_manager_parent->check_format_finish (self, + res, + &ctx->new_id, + &ctx->min_profile_id, + &ctx->max_profile_id, + &ctx->apn_cmp, + &ctx->profile_cmp_flags, + &error)) { + g_task_return_error (task, error); + } else { + /* the icera implementation supports AUTH, so unset that cmp flag */ + ctx->profile_cmp_flags &= ~MM_3GPP_PROFILE_CMP_FLAGS_NO_AUTH; + 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); + g_task_set_task_data (task, ctx, (GDestroyNotify)check_format_context_free); + + iface_modem_3gpp_profile_manager_parent->check_format ( + self, + ip_type, + (GAsyncReadyCallback)profile_manager_parent_check_format_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_ipdpact_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; + g_autofree gchar *cmd = NULL; + gint profile_id; + + task = g_task_new (self, NULL, callback, user_data); + + profile_id = mm_3gpp_profile_get_profile_id (profile); + mm_obj_dbg (self, "deactivating profile '%d'...", profile_id); + + cmd = g_strdup_printf ("%%IPDPACT=%d,0", profile_id); + mm_base_modem_at_command ( + MM_BASE_MODEM (self), + cmd, + MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, + FALSE, + (GAsyncReadyCallback)deactivate_profile_ipdpact_set_ready, + task); +} + +/*****************************************************************************/ +/* Set profile (3GPP profile management interface) */ + +#define IPDPCFG_SET_MAX_ATTEMPTS 3 +#define IPDPCFG_SET_RETRY_TIMEOUT_SECS 1 + +typedef struct { + MM3gppProfile *profile; + gchar *cmd; + gint profile_id; + guint n_attempts; +} StoreProfileContext; + +static void +store_profile_context_free (StoreProfileContext *ctx) +{ + g_free (ctx->cmd); + g_clear_object (&ctx->profile); + g_slice_free (StoreProfileContext, ctx); +} + +static gint +modem_3gpp_profile_manager_store_profile_finish (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GError **error) +{ + StoreProfileContext *ctx; + + if (!g_task_propagate_boolean (G_TASK (res), error)) + return MM_3GPP_PROFILE_ID_UNKNOWN; + + ctx = g_task_get_task_data (G_TASK (res)); + return ctx->profile_id; +} + +static void profile_manager_store_profile_auth_settings (GTask *task); + +static gboolean +profile_manager_ipdpcfg_set_retry (GTask *task) +{ + profile_manager_store_profile_auth_settings (task); + return G_SOURCE_REMOVE; +} + +static void +profile_manager_ipdpcfg_set_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) +{ + StoreProfileContext *ctx; + g_autoptr(GError) error = NULL; + + ctx = g_task_get_task_data (task); + + if (!mm_base_modem_at_command_finish (self, res, &error)) { + /* Retry configuring the context. It sometimes fails with a 583 + * error ["a profile (CID) is currently active"] if a connect + * is attempted too soon after a disconnect. */ + if (ctx->n_attempts < IPDPCFG_SET_MAX_ATTEMPTS) { + mm_obj_dbg (self, "couldn't store auth settings in profile '%d': %s; retrying...", + ctx->profile_id, error->message); + g_timeout_add_seconds (IPDPCFG_SET_RETRY_TIMEOUT_SECS, (GSourceFunc)profile_manager_ipdpcfg_set_retry, task); + return; + } + g_task_return_error (task, g_steal_pointer (&error)); + } else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +profile_manager_store_profile_auth_settings (GTask *task) +{ + MMIfaceModem3gppProfileManager *self; + StoreProfileContext *ctx; + g_autofree gchar *cmd = NULL; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + if (!ctx->cmd) { + const gchar *user; + const gchar *password; + MMBearerAllowedAuth allowed_auth; + + user = mm_3gpp_profile_get_user (ctx->profile); + password = mm_3gpp_profile_get_password (ctx->profile); + allowed_auth = mm_3gpp_profile_get_allowed_auth (ctx->profile); + + /* Both user and password are required; otherwise firmware returns an error */ + if (!user || !password || allowed_auth == MM_BEARER_ALLOWED_AUTH_NONE) { + mm_obj_dbg (self, "not using authentication"); + ctx->cmd = g_strdup_printf ("%%IPDPCFG=%d,0,0,\"\",\"\"", ctx->profile_id); + } else { + g_autofree gchar *quoted_user = NULL; + g_autofree gchar *quoted_password = NULL; + guint icera_auth; + + if (allowed_auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN) { + mm_obj_dbg (self, "using default (CHAP) authentication method"); + icera_auth = 2; + } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_CHAP) { + mm_obj_dbg (self, "using CHAP authentication method"); + icera_auth = 2; + } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_PAP) { + mm_obj_dbg (self, "using PAP authentication method"); + icera_auth = 1; + } else { + g_autofree gchar *str = NULL; + + str = mm_bearer_allowed_auth_build_string_from_mask (allowed_auth); + g_task_return_new_error (task, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Cannot use any of the specified authentication methods (%s)", + str); + g_object_unref (task); + return; + } + + quoted_user = mm_port_serial_at_quote_string (user); + quoted_password = mm_port_serial_at_quote_string (password); + ctx->cmd = g_strdup_printf ("%%IPDPCFG=%d,0,%u,%s,%s", + ctx->profile_id, + icera_auth, + quoted_user, + quoted_password); + } + } + + ctx->n_attempts++; + mm_base_modem_at_command (MM_BASE_MODEM (self), + ctx->cmd, + 6, + FALSE, + (GAsyncReadyCallback)profile_manager_ipdpcfg_set_ready, + task); +} + +static void +profile_manager_parent_store_profile_ready (MMIfaceModem3gppProfileManager *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (iface_modem_3gpp_profile_manager_parent->store_profile_finish (self, res, &error) == MM_3GPP_PROFILE_ID_UNKNOWN) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + profile_manager_store_profile_auth_settings (task); +} + +static void +modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self, + MM3gppProfile *profile, + GAsyncReadyCallback callback, + gpointer user_data) +{ + StoreProfileContext *ctx; + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + ctx = g_slice_new0 (StoreProfileContext); + ctx->profile = g_object_ref (profile); + ctx->profile_id = mm_3gpp_profile_get_profile_id (ctx->profile); + g_assert (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN); + g_task_set_task_data (task, ctx, (GDestroyNotify) store_profile_context_free); + + iface_modem_3gpp_profile_manager_parent->store_profile ( + self, + profile, + (GAsyncReadyCallback)profile_manager_parent_store_profile_ready, + task); +} + +/*****************************************************************************/ /* Load network time (Time interface) */ static gchar * @@ -1801,11 +2147,7 @@ modem_time_check_support_finish (MMIfaceModemTime *self, GAsyncResult *res, GError **error) { - /* We assume Icera devices always support *TLTS, since they appear - * to return ERROR if the modem is not powered up, and thus we cannot - * check for *TLTS support during modem initialization. - */ - return TRUE; + return g_task_propagate_boolean (G_TASK (res), error); } static void @@ -1813,15 +2155,16 @@ modem_time_check_support (MMIfaceModemTime *self, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *result; + GTask *task; - result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - modem_time_check_support); + task = g_task_new (self, NULL, callback, user_data); - g_simple_async_result_complete_in_idle (result); - g_object_unref (result); + /* We assume Icera devices always support *TLTS, since they appear + * to return ERROR if the modem is not powered up, and thus we cannot + * check for *TLTS support during modem initialization. + */ + g_task_return_boolean (task, TRUE); + g_object_unref (task); } /*****************************************************************************/ @@ -1852,6 +2195,9 @@ mm_broadband_modem_icera_new (const gchar *device, MM_BASE_MODEM_PLUGIN, plugin, MM_BASE_MODEM_VENDOR_ID, vendor_id, MM_BASE_MODEM_PRODUCT_ID, product_id, + /* Generic bearer (AT) or Icera bearer (NET) supported */ + MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, + MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE, NULL); } @@ -1971,6 +2317,23 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface) } static void +iface_modem_3gpp_profile_manager_init (MMIfaceModem3gppProfileManager *iface) +{ + iface_modem_3gpp_profile_manager_parent = g_type_interface_peek_parent (iface); + + 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; + /* note: the parent check_activated_profile() implementation using +CGACT? seems to + * be perfectly valid. */ + 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 iface_modem_time_init (MMIfaceModemTime *iface) { iface->check_support = modem_time_check_support; |