aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-iface-modem-simple.c164
1 files changed, 155 insertions, 9 deletions
diff --git a/src/mm-iface-modem-simple.c b/src/mm-iface-modem-simple.c
index bd276f6d..245ae660 100644
--- a/src/mm-iface-modem-simple.c
+++ b/src/mm-iface-modem-simple.c
@@ -210,6 +210,152 @@ register_in_3gpp_or_cdma_network (MMIfaceModemSimple *self,
}
/*****************************************************************************/
+/* Packet service attach in 3GPP network */
+
+typedef enum {
+ PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_FIRST,
+ PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_WAIT_BEFORE,
+ PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_SET,
+ PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_WAIT_AFTER,
+ PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_LAST,
+} PacketServiceAttachIn3gppNetworkStep;
+
+typedef struct {
+ PacketServiceAttachIn3gppNetworkStep step;
+ GError *error;
+} PacketServiceAttachIn3gppNetworkContext;
+
+static void
+packet_service_attach_in_3gpp_network_context_free (PacketServiceAttachIn3gppNetworkContext *ctx)
+{
+ g_assert (!ctx->error);
+ g_slice_free (PacketServiceAttachIn3gppNetworkContext, ctx);
+}
+
+static gboolean
+packet_service_attach_in_3gpp_network_finish (MMIfaceModemSimple *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void packet_service_attach_in_3gpp_network_step (GTask *task);
+
+static void
+set_packet_service_state_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ PacketServiceAttachIn3gppNetworkContext *ctx;
+ g_autoptr(GError) error = NULL;
+
+ ctx = g_task_get_task_data (task);
+ g_assert (ctx->error);
+
+ if (!mm_iface_modem_3gpp_set_packet_service_state_finish (self, res, &error)) {
+ /* On an unsupported error, return the original wait failure; otherwise
+ * return the set error. */
+ if (!g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED)) {
+ g_error_free (ctx->error);
+ ctx->error = g_steal_pointer (&error);
+ }
+ /* Failures in the set are always fatal right away */
+ ctx->step = PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_LAST;
+ } else {
+ /* Retry if possible */
+ g_clear_error (&ctx->error);
+ ctx->step++;
+ }
+ packet_service_attach_in_3gpp_network_step (task);
+}
+
+static void
+wait_for_packet_service_state_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ PacketServiceAttachIn3gppNetworkContext *ctx;
+
+ ctx = g_task_get_task_data (task);
+ g_assert (!ctx->error);
+
+ if (!mm_iface_modem_3gpp_wait_for_packet_service_state_finish (self, res, &ctx->error))
+ ctx->step++;
+ else
+ ctx->step = PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_LAST;
+ packet_service_attach_in_3gpp_network_step (task);
+}
+
+static void
+packet_service_attach_in_3gpp_network_step (GTask *task)
+{
+ PacketServiceAttachIn3gppNetworkContext *ctx;
+ MMIfaceModemSimple *self;
+
+ self = g_task_get_source_object (task);
+ ctx = g_task_get_task_data (task);
+
+ switch (ctx->step) {
+ case PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_FIRST:
+ ctx->step++;
+ /* fall through */
+
+ case PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_WAIT_BEFORE:
+ g_assert (!ctx->error);
+ mm_iface_modem_3gpp_wait_for_packet_service_state (MM_IFACE_MODEM_3GPP (self),
+ MM_MODEM_3GPP_PACKET_SERVICE_STATE_ATTACHED,
+ (GAsyncReadyCallback)wait_for_packet_service_state_ready,
+ task);
+ return;
+
+ case PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_SET:
+ /* An explicit set will only be attempted if the packet service state wait failed */
+ g_assert (ctx->error);
+ mm_iface_modem_3gpp_set_packet_service_state (MM_IFACE_MODEM_3GPP (self),
+ MM_MODEM_3GPP_PACKET_SERVICE_STATE_ATTACHED,
+ (GAsyncReadyCallback)set_packet_service_state_ready,
+ task);
+ return;
+
+ case PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_WAIT_AFTER:
+ g_assert (!ctx->error);
+ mm_iface_modem_3gpp_wait_for_packet_service_state (MM_IFACE_MODEM_3GPP (self),
+ MM_MODEM_3GPP_PACKET_SERVICE_STATE_ATTACHED,
+ (GAsyncReadyCallback)wait_for_packet_service_state_ready,
+ task);
+ return;
+
+ case PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_LAST:
+ if (ctx->error)
+ g_task_return_error (task, g_steal_pointer (&ctx->error));
+ else
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ return;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+packet_service_attach_in_3gpp_network (MMIfaceModemSimple *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ PacketServiceAttachIn3gppNetworkContext *ctx;
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+ ctx = g_slice_new0 (PacketServiceAttachIn3gppNetworkContext);
+ ctx->step = PACKET_SERVICE_ATTACH_IN_3GPP_NETWORK_STEP_FIRST;
+ g_task_set_task_data (task, ctx, (GDestroyNotify)packet_service_attach_in_3gpp_network_context_free);
+
+ packet_service_attach_in_3gpp_network_step (task);
+}
+
+/*****************************************************************************/
typedef enum {
CONNECTION_STEP_FIRST,
@@ -317,14 +463,14 @@ create_bearer_ready (MMIfaceModem *self,
}
static void
-wait_for_packet_service_state_ready (MMIfaceModem3gpp *self,
- GAsyncResult *res,
- ConnectionContext *ctx)
+packet_service_attach_in_3gpp_network_ready (MMIfaceModemSimple *self,
+ GAsyncResult *res,
+ ConnectionContext *ctx)
{
GError *error = NULL;
- if (!mm_iface_modem_3gpp_wait_for_packet_service_state_finish (self, res, &error)) {
- mm_obj_warn (ctx->self, "couldn't attach packet service: %s", error->message);
+ if (!packet_service_attach_in_3gpp_network_finish (self, res, &error)) {
+ mm_obj_warn (ctx->self, "packet service attach in 3GPP network failed: %s", error->message);
g_dbus_method_invocation_take_error (ctx->invocation, error);
connection_context_free (ctx);
return;
@@ -629,10 +775,10 @@ connection_step (ConnectionContext *ctx)
mm_obj_msg (ctx->self, "simple connect state (%d/%d): wait to get packet service state attached",
ctx->step, CONNECTION_STEP_LAST);
if (mm_iface_modem_is_3gpp (MM_IFACE_MODEM (ctx->self))) {
- mm_iface_modem_3gpp_wait_for_packet_service_state (MM_IFACE_MODEM_3GPP (ctx->self),
- MM_MODEM_3GPP_PACKET_SERVICE_STATE_ATTACHED,
- (GAsyncReadyCallback)wait_for_packet_service_state_ready,
- ctx);
+ packet_service_attach_in_3gpp_network (
+ ctx->self,
+ (GAsyncReadyCallback)packet_service_attach_in_3gpp_network_ready,
+ ctx);
return;
}
/* If not 3GPP, just go on */