diff options
-rw-r--r-- | src/mm-iface-modem-simple.c | 400 |
1 files changed, 41 insertions, 359 deletions
diff --git a/src/mm-iface-modem-simple.c b/src/mm-iface-modem-simple.c index ef66c88b..de74b529 100644 --- a/src/mm-iface-modem-simple.c +++ b/src/mm-iface-modem-simple.c @@ -25,8 +25,6 @@ #include "mm-iface-modem-3gpp.h" #include "mm-iface-modem-cdma.h" #include "mm-iface-modem-simple.h" -#include "mm-bearer-3gpp.h" -#include "mm-bearer-cdma.h" #include "mm-log.h" /*****************************************************************************/ @@ -169,314 +167,6 @@ register_in_3gpp_or_cdma_network (MMIfaceModemSimple *self, /*****************************************************************************/ -typedef struct { - GSimpleAsyncResult *result; - MMIfaceModemSimple *self; - MMCommonBearerProperties *bearer_properties; - gboolean create_cdma_bearer; - gboolean create_3gpp_bearer; - GList *list; -} CreateBearersContext; - -static void -create_bearers_context_complete_and_free (CreateBearersContext *ctx) -{ - g_simple_async_result_complete_in_idle (ctx->result); - g_list_free_full (ctx->list, (GDestroyNotify)g_object_unref); - g_object_unref (ctx->bearer_properties); - g_object_unref (ctx->result); - g_object_unref (ctx->self); - g_free (ctx); -} - -static GList * -create_3gpp_and_cdma_bearers_finish (MMIfaceModemSimple *self, - GAsyncResult *res, - GError **error) -{ - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) - return NULL; - - /* We return the list itself. Note that there was no GDestroyNotify given when - * the result was set, as we know that this finish() is always executed */ - return (GList *) g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); -} - -static void create_next_bearer (CreateBearersContext *ctx); - -static void -create_bearer_ready (MMIfaceModem *self, - GAsyncResult *res, - CreateBearersContext *ctx) -{ - GError *error = NULL; - MMBearer *bearer; - - bearer = mm_iface_modem_create_bearer_finish (self, res, &error); - if (!bearer) { - g_simple_async_result_take_error (ctx->result, error); - create_bearers_context_complete_and_free (ctx); - return; - } - - /* Keep the new bearer */ - ctx->list = g_list_prepend (ctx->list, bearer); - - /* And see if we need to create a new one */ - create_next_bearer (ctx); -} - -static void -create_next_bearer (CreateBearersContext *ctx) -{ - /* Create 3GPP bearer if needed */ - if (ctx->create_3gpp_bearer) { - ctx->create_3gpp_bearer = FALSE; - mm_iface_modem_create_bearer (MM_IFACE_MODEM (ctx->self), - ctx->bearer_properties, - (GAsyncReadyCallback)create_bearer_ready, - ctx); - return; - } - - /* Create CDMA bearer if needed */ - if (ctx->create_cdma_bearer) { - MMCommonBearerProperties *cdma_properties = NULL; - - ctx->create_cdma_bearer = FALSE; - - /* If the bearer properties has 'apn', we need to remove that before - * trying to create the bearer. */ - if (mm_common_bearer_properties_get_apn (ctx->bearer_properties)) { - cdma_properties = mm_common_bearer_properties_dup (ctx->bearer_properties); - mm_common_bearer_properties_set_apn (cdma_properties, NULL); - } - - mm_iface_modem_create_bearer ( - MM_IFACE_MODEM (ctx->self), - (cdma_properties ? cdma_properties : ctx->bearer_properties), - (GAsyncReadyCallback)create_bearer_ready, - ctx); - - if (cdma_properties) - g_object_unref (cdma_properties); - return; - } - - /* If no more bearers to create, we're done. - * NOTE: we won't provide a GDestroyNotify to clear the gpointer passed as - * result, as we know that finish() will ALWAYS be executed. */ - g_assert (ctx->list != NULL); - g_simple_async_result_set_op_res_gpointer (ctx->result, ctx->list, NULL); - ctx->list = NULL; - create_bearers_context_complete_and_free (ctx); -} - -static void -create_3gpp_and_cdma_bearers (MMIfaceModemSimple *self, - MMCommonBearerProperties *bearer_properties, - GAsyncReadyCallback callback, - gpointer user_data) -{ - guint n_bearers_needed; - MMBearerList *list = NULL; - CreateBearersContext *ctx; - - /* The implementation of this async method requires a valid callback, so - * that we ensure that finish() will always be called. */ - g_assert (callback != NULL); - - ctx = g_new0 (CreateBearersContext, 1); - ctx->self = g_object_ref (self); - ctx->bearer_properties = g_object_ref (bearer_properties); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - create_3gpp_and_cdma_bearers); - - /* 3GPP-only modems... */ - if (mm_iface_modem_is_3gpp_only (MM_IFACE_MODEM (ctx->self))) - ctx->create_3gpp_bearer = TRUE; - /* CDMA-only modems... */ - else if (mm_iface_modem_is_cdma_only (MM_IFACE_MODEM (ctx->self))) - ctx->create_cdma_bearer = TRUE; - /* Mixed CDMA+3GPP modems */ - else { - /* If we have APN, we'll create both 3GPP and CDMA bearers. - * Otherwise we'll only create a CDMA bearer. */ - if (mm_common_bearer_properties_get_apn (ctx->bearer_properties)) { - ctx->create_3gpp_bearer = TRUE; - } - ctx->create_cdma_bearer = TRUE; - } - - n_bearers_needed = ctx->create_3gpp_bearer + ctx->create_cdma_bearer; - if (n_bearers_needed == 0) - g_assert_not_reached (); - - g_object_get (self, - MM_IFACE_MODEM_BEARER_LIST, &list, - NULL); - - /* TODO: check if the bearers we want to create are already in the list */ - - /* If we don't have enough space to create all needed bearers, try to remove - * all existing ones first BUT only if that will give us enough space. */ - if (mm_bearer_list_get_max (list) < (mm_bearer_list_get_count (list) + - n_bearers_needed)) { - if (mm_bearer_list_get_max (list) < n_bearers_needed) { - g_simple_async_result_set_error ( - ctx->result, - MM_CORE_ERROR, - MM_CORE_ERROR_TOO_MANY, - "Cannot create bearers: need %u but only %u allowed", - n_bearers_needed, - mm_bearer_list_get_max (list)); - create_bearers_context_complete_and_free (ctx); - g_object_unref (list); - return; - } - - /* We are told to force the creation of the new bearer. - * We'll remove all existing bearers, and then go on creating the new one */ - mm_bearer_list_delete_all_bearers (list); - } - - create_next_bearer (ctx); - g_object_unref (list); -} - -/*****************************************************************************/ - -typedef struct { - MMIfaceModemSimple *self; - GSimpleAsyncResult *result; - GList *bearers; - MMBearer *current; -} ConnectBearerContext; - -static void -connect_bearer_context_complete_and_free (ConnectBearerContext *ctx) -{ - g_simple_async_result_complete_in_idle (ctx->result); - if (ctx->current) - g_object_unref (ctx->current); - g_list_free_full (ctx->bearers, (GDestroyNotify)g_object_unref); - g_object_unref (ctx->result); - g_object_unref (ctx->self); - g_free (ctx); -} - -static MMBearer * -connect_3gpp_or_cdma_bearer_finish (MMIfaceModemSimple *self, - GAsyncResult *res, - GError **error) -{ - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) - return NULL; - - return MM_BEARER (g_object_ref (g_simple_async_result_get_op_res_gpointer ( - G_SIMPLE_ASYNC_RESULT (res)))); -} - -static void connect_next_bearer (ConnectBearerContext *ctx); - -static void -connect_bearer_ready (MMBearer *bearer, - GAsyncResult *res, - ConnectBearerContext *ctx) -{ - GError *error = NULL; - - if (!mm_bearer_connect_finish (bearer, res, &error)) { - mm_dbg ("Couldn't connect bearer: '%s'", error->message); - g_error_free (error); - /* We'll try with the next one */ - connect_next_bearer (ctx); - return; - } - - /* We got connected! */ - g_simple_async_result_set_op_res_gpointer (ctx->result, - g_object_ref (ctx->current), - (GDestroyNotify)g_object_unref); - connect_bearer_context_complete_and_free (ctx); -} - -static void -connect_next_bearer (ConnectBearerContext *ctx) -{ - GList *l; - - g_clear_object (&ctx->current); - - /* First, look for 3GPP bearers */ - for (l = ctx->bearers; l; l = g_list_next (l)) { - if (MM_IS_BEARER_3GPP (l->data)) { - /* Try to connect the current bearer. If the modem is not yet - * registered in the 3GPP network, connection won't succeed. - * Steal the reference from the list. */ - ctx->current = MM_BEARER (l->data); - ctx->bearers = g_list_delete_link (ctx->bearers, l); - mm_bearer_connect (MM_BEARER (ctx->current), - NULL, /* no number given */ - (GAsyncReadyCallback)connect_bearer_ready, - ctx); - return; - } - } - - /* Then, we look for CDMA bearers */ - for (l = ctx->bearers; l; l = g_list_next (l)) { - if (MM_IS_BEARER_CDMA (l->data)) { - /* Try to connect the current bearer. If the modem is not yet - * registered in the 3GPP network, connection won't succeed. - * Steal the reference from the list. */ - ctx->current = MM_BEARER (l->data); - ctx->bearers = g_list_delete_link (ctx->bearers, l); - mm_bearer_connect (MM_BEARER (ctx->current), - NULL, /* no number given */ - (GAsyncReadyCallback)connect_bearer_ready, - ctx); - return; - } - } - - /* Here we shouldn't have any remaining bearer. - * POTS modem not yet supported */ - - /* If we got here, we didn't get connected :-/ */ - g_simple_async_result_set_error (ctx->result, - MM_CORE_ERROR, - MM_CORE_ERROR_UNAUTHORIZED, - "Cannot connect any bearer"); - connect_bearer_context_complete_and_free (ctx); -} - -static void -connect_3gpp_or_cdma_bearer (MMIfaceModemSimple *self, - GList *bearers, - GAsyncReadyCallback callback, - gpointer user_data) -{ - ConnectBearerContext *ctx; - - g_assert (bearers != NULL); - - ctx = g_new0 (ConnectBearerContext, 1); - ctx->self = g_object_ref (self); - ctx->result = g_simple_async_result_new (G_OBJECT (self), - callback, - user_data, - connect_3gpp_or_cdma_bearer); - ctx->bearers = g_list_copy (bearers); - g_list_foreach (ctx->bearers, (GFunc)g_object_ref, NULL); - - connect_next_bearer (ctx); -} - -/*****************************************************************************/ - typedef enum { CONNECTION_STEP_FIRST, CONNECTION_STEP_UNLOCK_CHECK, @@ -499,16 +189,13 @@ typedef struct { MMCommonConnectProperties *properties; /* Results to set */ - GList *bearers; - MMBearer *connected_bearer; + MMBearer *bearer; } ConnectionContext; static void connection_context_free (ConnectionContext *ctx) { - g_list_free_full (ctx->bearers, (GDestroyNotify)g_object_unref); - if (ctx->connected_bearer) - g_object_unref (ctx->connected_bearer); + g_object_unref (ctx->bearer); g_object_unref (ctx->properties); g_object_unref (ctx->skeleton); g_object_unref (ctx->invocation); @@ -519,14 +206,14 @@ connection_context_free (ConnectionContext *ctx) static void connection_step (ConnectionContext *ctx); static void -connect_3gpp_or_cdma_bearer_ready (MMIfaceModemSimple *self, - GAsyncResult *res, - ConnectionContext *ctx) +connect_bearer_ready (MMBearer *bearer, + GAsyncResult *res, + ConnectionContext *ctx) { GError *error = NULL; - ctx->connected_bearer = connect_3gpp_or_cdma_bearer_finish (self, res, &error); - if (!ctx->connected_bearer) { + if (!mm_bearer_connect_finish (bearer, res, &error)) { + mm_dbg ("Couldn't connect bearer: '%s'", error->message); g_dbus_method_invocation_take_error (ctx->invocation, error); connection_context_free (ctx); return; @@ -538,21 +225,21 @@ connect_3gpp_or_cdma_bearer_ready (MMIfaceModemSimple *self, } static void -create_3gpp_and_cdma_bearers_ready (MMIfaceModemSimple *self, - GAsyncResult *res, - ConnectionContext *ctx) +create_bearer_ready (MMIfaceModem *self, + GAsyncResult *res, + ConnectionContext *ctx) { GError *error = NULL; - /* List ownership for the caller */ - ctx->bearers = create_3gpp_and_cdma_bearers_finish (self, res, &error); - if (!ctx->bearers) { + /* ownership for the caller */ + ctx->bearer = mm_iface_modem_create_bearer_finish (self, res, &error); + if (!ctx->bearer) { g_dbus_method_invocation_take_error (ctx->invocation, error); connection_context_free (ctx); return; } - /* Bearers available! */ + /* Bearer available! */ ctx->step++; connection_step (ctx); } @@ -804,50 +491,45 @@ connection_step (ConnectionContext *ctx) * So, fall down to next step */ ctx->step++; - case CONNECTION_STEP_BEARER: + case CONNECTION_STEP_BEARER: { + MMBearerList *list = NULL; + MMCommonBearerProperties *bearer_properties; + mm_info ("Simple connect state (%d/%d): Bearer", ctx->step, CONNECTION_STEP_LAST); - if (mm_iface_modem_is_3gpp (MM_IFACE_MODEM (ctx->self)) || - mm_iface_modem_is_cdma (MM_IFACE_MODEM (ctx->self))) { - MMCommonBearerProperties *bearer_properties; + g_object_get (ctx->self, + MM_IFACE_MODEM_BEARER_LIST, &list, + NULL); - bearer_properties = (mm_common_connect_properties_get_bearer_properties ( - ctx->properties)); - /* 3GPP and/or CDMA bearer creation */ - create_3gpp_and_cdma_bearers ( - ctx->self, - bearer_properties, - (GAsyncReadyCallback)create_3gpp_and_cdma_bearers_ready, - ctx); + /* TODO: check if the bearer we want to create is already in the list */ - g_object_unref (bearer_properties); - return; + /* If we don't have enough space to create the, try to remove + * all existing ones first BUT only if that will give us enough space. */ + if (mm_bearer_list_get_max (list) == mm_bearer_list_get_count (list)) { + /* We'll remove all existing bearers, and then go on creating the new one */ + mm_bearer_list_delete_all_bearers (list); } - /* If not 3GPP and not CDMA, this will possibly be a POTS modem, - * currently unsupported. So, just abort. */ - g_assert_not_reached (); + bearer_properties = (mm_common_connect_properties_get_bearer_properties ( + ctx->properties)); + mm_iface_modem_create_bearer (MM_IFACE_MODEM (ctx->self), + bearer_properties, + (GAsyncReadyCallback)create_bearer_ready, + ctx); + + g_object_unref (list); + g_object_unref (bearer_properties); return; + } case CONNECTION_STEP_CONNECT: mm_info ("Simple connect state (%d/%d): Connect", ctx->step, CONNECTION_STEP_LAST); - if (mm_iface_modem_is_3gpp (MM_IFACE_MODEM (ctx->self)) || - mm_iface_modem_is_cdma (MM_IFACE_MODEM (ctx->self))) { - /* 3GPP or CDMA bearer connection */ - connect_3gpp_or_cdma_bearer ( - ctx->self, - ctx->bearers, - (GAsyncReadyCallback)connect_3gpp_or_cdma_bearer_ready, - ctx); - return; - } - - /* If not 3GPP and not CDMA, this will possibly be a POTS modem, - * currently unsupported. So, just abort. */ - g_assert_not_reached (); + mm_bearer_connect (ctx->bearer, + (GAsyncReadyCallback)connect_bearer_ready, + ctx); return; case CONNECTION_STEP_LAST: @@ -857,7 +539,7 @@ connection_step (ConnectionContext *ctx) mm_gdbus_modem_simple_complete_connect ( ctx->skeleton, ctx->invocation, - mm_bearer_get_path (ctx->connected_bearer)); + mm_bearer_get_path (ctx->bearer)); connection_context_free (ctx); return; } |