diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-08-07 11:45:25 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-10-12 11:29:52 +0200 |
commit | b117321980c39c2dcc50789058017fa3201e7003 (patch) | |
tree | 966eebd0053ded66391cd675fde02de8e1984f40 /src | |
parent | 30772ffc2609e070306f6fd75c0d787d3ea0153a (diff) |
broadband-bearer: allow subclassing the CID selection step in the 3GPP sequence
Instead of relying always on CGDCONT to look for a matching PDP context or
creating a new one, we allow plugins to apply their own logic.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-bearer.c | 545 | ||||
-rw-r--r-- | src/mm-broadband-bearer.h | 13 |
2 files changed, 326 insertions, 232 deletions
diff --git a/src/mm-broadband-bearer.c b/src/mm-broadband-bearer.c index d8c8c884..24e36b82 100644 --- a/src/mm-broadband-bearer.c +++ b/src/mm-broadband-bearer.c @@ -69,6 +69,26 @@ mm_broadband_bearer_get_3gpp_cid (MMBroadbandBearer *self) } /*****************************************************************************/ + +static MMBearerIpFamily +select_bearer_ip_family (MMBroadbandBearer *self) +{ + MMBearerIpFamily ip_family; + + ip_family = mm_bearer_properties_get_ip_type (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); + if (ip_family == MM_BEARER_IP_FAMILY_NONE || ip_family == MM_BEARER_IP_FAMILY_ANY) { + gchar *default_family; + + ip_family = mm_base_bearer_get_default_ip_family (MM_BASE_BEARER (self)); + default_family = mm_bearer_ip_family_build_string_from_mask (ip_family); + mm_dbg ("No specific IP family requested, defaulting to %s", default_family); + g_free (default_family); + } + + return ip_family; +} + +/*****************************************************************************/ /* Detailed connect context, used in both CDMA and 3GPP sequences */ typedef struct { @@ -83,9 +103,6 @@ typedef struct { gboolean close_data_on_exit; /* 3GPP-specific */ - guint cid; - guint max_cid; - gboolean use_existing_cid; MMBearerIpFamily ip_family; } DetailedConnectContext; @@ -167,16 +184,7 @@ detailed_connect_context_new (MMBroadbandBearer *self, user_data, detailed_connect_context_new); - ctx->ip_family = mm_bearer_properties_get_ip_type (mm_base_bearer_peek_config (MM_BASE_BEARER (self))); - if (ctx->ip_family == MM_BEARER_IP_FAMILY_NONE || - ctx->ip_family == MM_BEARER_IP_FAMILY_ANY) { - gchar *default_family; - - ctx->ip_family = mm_base_bearer_get_default_ip_family (MM_BASE_BEARER (self)); - default_family = mm_bearer_ip_family_build_string_from_mask (ctx->ip_family); - mm_dbg ("No specific IP family requested, defaulting to %s", default_family); - g_free (default_family); - } + ctx->ip_family = select_bearer_ip_family (self); /* NOTE: * We don't currently support cancelling AT commands, so we'll just check @@ -620,219 +628,107 @@ dial_3gpp (MMBroadbandBearer *self, } /*****************************************************************************/ -/* 3GPP CONNECT - * - * 3GPP connection procedure of a bearer involves several steps: - * 1) Get data port from the modem. Default implementation will have only - * one single possible data port, but plugins may have more. - * 2) Decide which PDP context to use - * 2.1) Look for an already existing PDP context with the same APN. - * 2.2) If none found with the same APN, try to find a PDP context without any - * predefined APN. - * 2.3) If none found, look for the highest available CID, and use that one. - * 3) Activate PDP context. - * 4) Initiate call. - */ - -static void -get_ip_config_3gpp_ready (MMBroadbandModem *modem, - GAsyncResult *res, - DetailedConnectContext *ctx) -{ - MMBearerIpConfig *ipv4_config = NULL; - MMBearerIpConfig *ipv6_config = NULL; - GError *error = NULL; +/* 3GPP cid selection (sub-step of the 3GPP Connection sequence) */ - if (!MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->get_ip_config_3gpp_finish (ctx->self, - res, - &ipv4_config, - &ipv6_config, - &error)) { - g_simple_async_result_take_error (ctx->result, error); - detailed_connect_context_complete_and_free (ctx); - return; - } - - /* Keep port open during connection */ - if (MM_IS_PORT_SERIAL_AT (ctx->data)) - ctx->close_data_on_exit = FALSE; - - g_simple_async_result_set_op_res_gpointer ( - ctx->result, - mm_bearer_connect_result_new (ctx->data, ipv4_config, ipv6_config), - (GDestroyNotify)mm_bearer_connect_result_unref); - detailed_connect_context_complete_and_free (ctx); - - if (ipv4_config) - g_object_unref (ipv4_config); - if (ipv6_config) - g_object_unref (ipv6_config); -} +typedef struct { + MMBroadbandBearer *self; + MMBaseModem *modem; + MMPortSerialAt *primary; + GCancellable *cancellable; + guint cid; + guint max_cid; + gboolean use_existing_cid; + MMBearerIpFamily ip_family; +} CidSelection3gppContext; static void -dial_3gpp_ready (MMBroadbandModem *modem, - GAsyncResult *res, - DetailedConnectContext *ctx) +cid_selection_3gpp_context_free (CidSelection3gppContext *ctx) { - MMBearerIpMethod ip_method = MM_BEARER_IP_METHOD_UNKNOWN; - MMBearerIpConfig *ipv4_config = NULL; - MMBearerIpConfig *ipv6_config = NULL; - GError *error = NULL; - - ctx->data = MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->dial_3gpp_finish (ctx->self, res, &error); - if (!ctx->data) { - /* Clear CID when it failed to connect. */ - ctx->self->priv->cid = 0; - g_simple_async_result_take_error (ctx->result, error); - detailed_connect_context_complete_and_free (ctx); - return; - } - - /* If the dialling operation used an AT port, it is assumed to have an extra - * open() count. */ - if (MM_IS_PORT_SERIAL_AT (ctx->data)) - ctx->close_data_on_exit = TRUE; - - if (MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->get_ip_config_3gpp && - MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->get_ip_config_3gpp_finish) { - /* Launch specific IP config retrieval */ - MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->get_ip_config_3gpp ( - ctx->self, - MM_BROADBAND_MODEM (ctx->modem), - ctx->primary, - ctx->secondary, - ctx->data, - ctx->cid, - ctx->ip_family, - (GAsyncReadyCallback)get_ip_config_3gpp_ready, - ctx); - return; - } - - /* Yuhu! */ - - /* Keep port open during connection */ - if (MM_IS_PORT_SERIAL_AT (ctx->data)) - ctx->close_data_on_exit = FALSE; - - /* If no specific IP retrieval requested, set the default implementation - * (PPP if data port is AT, DHCP otherwise) */ - ip_method = MM_IS_PORT_SERIAL_AT (ctx->data) ? - MM_BEARER_IP_METHOD_PPP : - MM_BEARER_IP_METHOD_DHCP; - - if (ctx->ip_family & MM_BEARER_IP_FAMILY_IPV4 || - ctx->ip_family & MM_BEARER_IP_FAMILY_IPV4V6) { - ipv4_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (ipv4_config, ip_method); - } - if (ctx->ip_family & MM_BEARER_IP_FAMILY_IPV6 || - ctx->ip_family & MM_BEARER_IP_FAMILY_IPV4V6) { - ipv6_config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (ipv6_config, ip_method); - } - g_assert (ipv4_config || ipv6_config); - - g_simple_async_result_set_op_res_gpointer ( - ctx->result, - mm_bearer_connect_result_new (ctx->data, ipv4_config, ipv6_config), - (GDestroyNotify)mm_bearer_connect_result_unref); - detailed_connect_context_complete_and_free (ctx); - - g_clear_object (&ipv4_config); - g_clear_object (&ipv6_config); + g_object_unref (ctx->self); + g_object_unref (ctx->modem); + g_object_unref (ctx->primary); + g_object_unref (ctx->cancellable); + g_slice_free (CidSelection3gppContext, ctx); } -static void -start_3gpp_dial (DetailedConnectContext *ctx) +static guint +cid_selection_3gpp_finish (MMBroadbandBearer *self, + GAsyncResult *res, + GError **error) { - /* Keep CID around after initializing the PDP context in order to - * handle corresponding unsolicited PDP activation responses. */ - ctx->self->priv->cid = ctx->cid; - MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->dial_3gpp (ctx->self, - ctx->modem, - ctx->primary, - ctx->cid, - ctx->cancellable, - (GAsyncReadyCallback)dial_3gpp_ready, - ctx); + gssize cid; + + /* We return 0 as an invalid CID, not -1 */ + cid = g_task_propagate_int (G_TASK (res), error); + return (guint) (cid < 0 ? 0 : cid); } static void -initialize_pdp_context_ready (MMBaseModem *modem, +initialize_pdp_context_ready (MMBaseModem *modem, GAsyncResult *res, - DetailedConnectContext *ctx) + GTask *task) { - GError *error = NULL; - - /* If cancelled, complete */ - if (detailed_connect_context_complete_and_free_if_cancelled (ctx)) - return; + CidSelection3gppContext *ctx; + GError *error = NULL; + ctx = (CidSelection3gppContext *) g_task_get_task_data (task); mm_base_modem_at_command_full_finish (modem, res, &error); if (error) { - mm_warn ("Couldn't initialize PDP context with our APN: '%s'", - error->message); - g_simple_async_result_take_error (ctx->result, error); - detailed_connect_context_complete_and_free (ctx); - return; - } - - start_3gpp_dial (ctx); + mm_warn ("Couldn't initialize PDP context with our APN: '%s'", error->message); + g_task_return_error (task, error); + } else + g_task_return_int (task, (gssize) ctx->cid); + g_object_unref (task); } static void -find_cid_ready (MMBaseModem *modem, +find_cid_ready (MMBaseModem *modem, GAsyncResult *res, - DetailedConnectContext *ctx) + GTask *task) { - GVariant *result; - gchar *apn, *command; - GError *error = NULL; - const gchar *pdp_type; + gchar *apn; + gchar *command; + GError *error = NULL; + const gchar *pdp_type; + CidSelection3gppContext *ctx; - result = mm_base_modem_at_sequence_full_finish (modem, res, NULL, &error); - if (!result) { + ctx = (CidSelection3gppContext *) g_task_get_task_data (task); + + mm_base_modem_at_sequence_full_finish (modem, res, NULL, &error); + if (error) { mm_warn ("Couldn't find best CID to use: '%s'", error->message); - g_simple_async_result_take_error (ctx->result, error); - detailed_connect_context_complete_and_free (ctx); + g_task_return_error (task, error); + g_object_unref (task); return; } - /* If cancelled, complete. Normally, we would get the cancellation error - * already when finishing the sequence, but we may still get cancelled - * between last command result parsing in the sequence and the ready(). */ - if (detailed_connect_context_complete_and_free_if_cancelled (ctx)) - return; - + /* Validate requested PDP type */ pdp_type = mm_3gpp_get_pdp_type_from_ip_family (ctx->ip_family); if (!pdp_type) { gchar * str; str = mm_bearer_ip_family_build_string_from_mask (ctx->ip_family); - g_simple_async_result_set_error (ctx->result, - MM_CORE_ERROR, - MM_CORE_ERROR_INVALID_ARGS, - "Unsupported IP type requested: '%s'", - str); + g_task_return_new_error (task, + MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Unsupported IP type requested: '%s'", str); + g_object_unref (task); g_free (str); - detailed_connect_context_complete_and_free (ctx); return; } - ctx->cid = g_variant_get_uint32 (result); + + /* If no error reported, we must have a valid CID to be used */ + g_assert (ctx->cid != 0); /* If there's already a PDP context defined, just use it */ if (ctx->use_existing_cid) { - start_3gpp_dial (ctx); + g_task_return_int (task, (gssize) ctx->cid); + g_object_unref (task); return; } /* Otherwise, initialize a new PDP context with our APN */ apn = mm_port_serial_at_quote_string (mm_bearer_properties_get_apn (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)))); - command = g_strdup_printf ("+CGDCONT=%u,\"%s\",%s", - ctx->cid, - pdp_type, - apn); + command = g_strdup_printf ("+CGDCONT=%u,\"%s\",%s", ctx->cid, pdp_type, apn); g_free (apn); mm_base_modem_at_command_full (ctx->modem, ctx->primary, @@ -841,33 +737,36 @@ find_cid_ready (MMBaseModem *modem, FALSE, FALSE, /* raw */ NULL, /* cancellable */ - (GAsyncReadyCallback)initialize_pdp_context_ready, - ctx); + (GAsyncReadyCallback) initialize_pdp_context_ready, + task); g_free (command); } static gboolean -parse_cid_range (MMBaseModem *modem, - DetailedConnectContext *ctx, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) +parse_cid_range (MMBaseModem *modem, + CidSelection3gppContext *ctx, + const gchar *command, + const gchar *response, + gboolean last_command, + const GError *error, + GVariant **result, + GError **result_error) { GError *inner_error = NULL; - GList *formats, *l; - guint cid; + GList *formats, *l; + guint cid; /* If cancelled, set result error */ - if (detailed_connect_context_set_error_if_cancelled (ctx, result_error)) + if (g_cancellable_is_cancelled (ctx->cancellable)) { + g_set_error (result_error, MM_CORE_ERROR, MM_CORE_ERROR_CANCELLED, + "Connection setup operation has been cancelled"); return FALSE; + } if (error) { mm_dbg ("Unexpected +CGDCONT error: '%s'", error->message); mm_dbg ("Defaulting to CID=1"); - *result = g_variant_new_uint32 (1); + ctx->cid = 1; return TRUE; } @@ -876,7 +775,7 @@ parse_cid_range (MMBaseModem *modem, mm_dbg ("Error parsing +CGDCONT test response: '%s'", inner_error->message); mm_dbg ("Defaulting to CID=1"); g_error_free (inner_error); - *result = g_variant_new_uint32 (1); + ctx->cid = 1; return TRUE; } @@ -902,19 +801,19 @@ parse_cid_range (MMBaseModem *modem, } else mm_dbg ("Using CID %u", cid); - *result = g_variant_new_uint32 (cid); + ctx->cid = cid; return TRUE; } static gboolean -parse_pdp_list (MMBaseModem *modem, - DetailedConnectContext *ctx, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) +parse_pdp_list (MMBaseModem *modem, + CidSelection3gppContext *ctx, + const gchar *command, + const gchar *response, + gboolean last_command, + const GError *error, + GVariant **result, + GError **result_error) { GError *inner_error = NULL; GList *pdp_list; @@ -922,10 +821,11 @@ parse_pdp_list (MMBaseModem *modem, guint cid; /* If cancelled, set result error */ - if (detailed_connect_context_set_error_if_cancelled (ctx, result_error)) + if (g_cancellable_is_cancelled (ctx->cancellable)) { + g_set_error (result_error, MM_CORE_ERROR, MM_CORE_ERROR_CANCELLED, + "Connection setup operation has been cancelled"); return FALSE; - - ctx->max_cid = 0; + } /* Some Android phones don't support querying existing PDP contexts, * but will accept setting the APN. So if CGDCONT? isn't supported, @@ -1007,7 +907,7 @@ parse_pdp_list (MMBaseModem *modem, mm_3gpp_pdp_context_list_free (pdp_list); if (cid > 0) { - *result = g_variant_new_uint32 (cid); + ctx->cid = cid; return TRUE; } @@ -1015,24 +915,208 @@ parse_pdp_list (MMBaseModem *modem, } static const MMBaseModemAtCommand find_cid_sequence[] = { - { "+CGDCONT?", 3, FALSE, (MMBaseModemAtResponseProcessor)parse_pdp_list }, - { "+CGDCONT=?", 3, TRUE, (MMBaseModemAtResponseProcessor)parse_cid_range }, + { "+CGDCONT?", 3, FALSE, (MMBaseModemAtResponseProcessor) parse_pdp_list }, + { "+CGDCONT=?", 3, TRUE, (MMBaseModemAtResponseProcessor) parse_cid_range }, { NULL } }; static void -connect_3gpp (MMBroadbandBearer *self, - MMBroadbandModem *modem, - MMPortSerialAt *primary, - MMPortSerialAt *secondary, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +cid_selection_3gpp (MMBroadbandBearer *self, + MMBaseModem *modem, + MMPortSerialAt *primary, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + CidSelection3gppContext *ctx; + + ctx = g_slice_new0 (CidSelection3gppContext); + ctx->self = g_object_ref (self); + ctx->modem = g_object_ref (modem); + ctx->primary = g_object_ref (primary); + ctx->cancellable = g_object_ref (cancellable); + ctx->ip_family = select_bearer_ip_family (self); + + task = g_task_new (self, cancellable, callback, user_data); + g_task_set_task_data (task, ctx, (GDestroyNotify) cid_selection_3gpp_context_free); + + mm_dbg ("Looking for best CID..."); + mm_base_modem_at_sequence_full (ctx->modem, + ctx->primary, + find_cid_sequence, + ctx, /* also passed as response processor context */ + NULL, /* response_processor_context_free */ + NULL, /* cancellable */ + (GAsyncReadyCallback) find_cid_ready, + task); +} + +/*****************************************************************************/ +/* 3GPP CONNECT + * + * 3GPP connection procedure of a bearer involves several steps: + * 1) Get data port from the modem. Default implementation will have only + * one single possible data port, but plugins may have more. + * 2) Decide which PDP context to use + * 2.1) Look for an already existing PDP context with the same APN. + * 2.2) If none found with the same APN, try to find a PDP context without any + * predefined APN. + * 2.3) If none found, look for the highest available CID, and use that one. + * 3) Activate PDP context. + * 4) Initiate call. + */ + +static void +get_ip_config_3gpp_ready (MMBroadbandModem *modem, + GAsyncResult *res, + DetailedConnectContext *ctx) +{ + MMBearerIpConfig *ipv4_config = NULL; + MMBearerIpConfig *ipv6_config = NULL; + GError *error = NULL; + + if (!MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->get_ip_config_3gpp_finish (ctx->self, + res, + &ipv4_config, + &ipv6_config, + &error)) { + g_simple_async_result_take_error (ctx->result, error); + detailed_connect_context_complete_and_free (ctx); + return; + } + + /* Keep port open during connection */ + if (MM_IS_PORT_SERIAL_AT (ctx->data)) + ctx->close_data_on_exit = FALSE; + + g_simple_async_result_set_op_res_gpointer ( + ctx->result, + mm_bearer_connect_result_new (ctx->data, ipv4_config, ipv6_config), + (GDestroyNotify)mm_bearer_connect_result_unref); + detailed_connect_context_complete_and_free (ctx); + + if (ipv4_config) + g_object_unref (ipv4_config); + if (ipv6_config) + g_object_unref (ipv6_config); +} + +static void +dial_3gpp_ready (MMBroadbandModem *modem, + GAsyncResult *res, + DetailedConnectContext *ctx) +{ + MMBearerIpMethod ip_method = MM_BEARER_IP_METHOD_UNKNOWN; + MMBearerIpConfig *ipv4_config = NULL; + MMBearerIpConfig *ipv6_config = NULL; + GError *error = NULL; + + ctx->data = MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->dial_3gpp_finish (ctx->self, res, &error); + if (!ctx->data) { + /* Clear CID when it failed to connect. */ + ctx->self->priv->cid = 0; + g_simple_async_result_take_error (ctx->result, error); + detailed_connect_context_complete_and_free (ctx); + return; + } + + /* If the dialling operation used an AT port, it is assumed to have an extra + * open() count. */ + if (MM_IS_PORT_SERIAL_AT (ctx->data)) + ctx->close_data_on_exit = TRUE; + + if (MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->get_ip_config_3gpp && + MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->get_ip_config_3gpp_finish) { + /* Launch specific IP config retrieval */ + MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->get_ip_config_3gpp ( + ctx->self, + MM_BROADBAND_MODEM (ctx->modem), + ctx->primary, + ctx->secondary, + ctx->data, + ctx->self->priv->cid, + ctx->ip_family, + (GAsyncReadyCallback)get_ip_config_3gpp_ready, + ctx); + return; + } + + /* Yuhu! */ + + /* Keep port open during connection */ + if (MM_IS_PORT_SERIAL_AT (ctx->data)) + ctx->close_data_on_exit = FALSE; + + /* If no specific IP retrieval requested, set the default implementation + * (PPP if data port is AT, DHCP otherwise) */ + ip_method = MM_IS_PORT_SERIAL_AT (ctx->data) ? + MM_BEARER_IP_METHOD_PPP : + MM_BEARER_IP_METHOD_DHCP; + + if (ctx->ip_family & MM_BEARER_IP_FAMILY_IPV4 || + ctx->ip_family & MM_BEARER_IP_FAMILY_IPV4V6) { + ipv4_config = mm_bearer_ip_config_new (); + mm_bearer_ip_config_set_method (ipv4_config, ip_method); + } + if (ctx->ip_family & MM_BEARER_IP_FAMILY_IPV6 || + ctx->ip_family & MM_BEARER_IP_FAMILY_IPV4V6) { + ipv6_config = mm_bearer_ip_config_new (); + mm_bearer_ip_config_set_method (ipv6_config, ip_method); + } + g_assert (ipv4_config || ipv6_config); + + g_simple_async_result_set_op_res_gpointer ( + ctx->result, + mm_bearer_connect_result_new (ctx->data, ipv4_config, ipv6_config), + (GDestroyNotify)mm_bearer_connect_result_unref); + detailed_connect_context_complete_and_free (ctx); + + g_clear_object (&ipv4_config); + g_clear_object (&ipv6_config); +} + +static void +cid_selection_3gpp_ready (MMBroadbandModem *modem, + GAsyncResult *res, + DetailedConnectContext *ctx) +{ + GError *error = NULL; + + /* Keep CID around after initializing the PDP context in order to + * handle corresponding unsolicited PDP activation responses. */ + ctx->self->priv->cid = MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->cid_selection_3gpp_finish (ctx->self, res, &error); + if (!ctx->self->priv->cid) { + g_simple_async_result_take_error (ctx->result, error); + detailed_connect_context_complete_and_free (ctx); + return; + } + + MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->dial_3gpp (ctx->self, + ctx->modem, + ctx->primary, + ctx->self->priv->cid, + ctx->cancellable, + (GAsyncReadyCallback) dial_3gpp_ready, + ctx); +} + +static void +connect_3gpp (MMBroadbandBearer *self, + MMBroadbandModem *modem, + MMPortSerialAt *primary, + MMPortSerialAt *secondary, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { DetailedConnectContext *ctx; g_assert (primary != NULL); + /* Clear CID on every connection attempt */ + self->priv->cid = 0; + ctx = detailed_connect_context_new (self, modem, primary, @@ -1041,15 +1125,12 @@ connect_3gpp (MMBroadbandBearer *self, callback, user_data); - mm_dbg ("Looking for best CID..."); - mm_base_modem_at_sequence_full (ctx->modem, - ctx->primary, - find_cid_sequence, - ctx, /* also passed as response processor context */ - NULL, /* response_processor_context_free */ - NULL, /* cancellable */ - (GAsyncReadyCallback)find_cid_ready, - ctx); + MM_BROADBAND_BEARER_GET_CLASS (ctx->self)->cid_selection_3gpp (ctx->self, + ctx->modem, + ctx->primary, + ctx->cancellable, + (GAsyncReadyCallback)cid_selection_3gpp_ready, + ctx); } /*****************************************************************************/ @@ -2108,6 +2189,8 @@ mm_broadband_bearer_class_init (MMBroadbandBearerClass *klass) klass->connect_3gpp_finish = detailed_connect_finish; klass->dial_3gpp = dial_3gpp; klass->dial_3gpp_finish = dial_3gpp_finish; + klass->cid_selection_3gpp = cid_selection_3gpp; + klass->cid_selection_3gpp_finish = cid_selection_3gpp_finish; klass->connect_cdma = connect_cdma; klass->connect_cdma_finish = detailed_connect_finish; diff --git a/src/mm-broadband-bearer.h b/src/mm-broadband-bearer.h index a3e9b165..bee2c521 100644 --- a/src/mm-broadband-bearer.h +++ b/src/mm-broadband-bearer.h @@ -47,7 +47,7 @@ struct _MMBroadbandBearer { struct _MMBroadbandBearerClass { MMBaseBearerClass parent; - /* Full 3GPP connection sequence */ + /* Full 3GPP connection sequence (cid selection, dial, get ip config) */ void (* connect_3gpp) (MMBroadbandBearer *self, MMBroadbandModem *modem, MMPortSerialAt *primary, @@ -59,6 +59,17 @@ struct _MMBroadbandBearerClass { GAsyncResult *res, GError **error); + /* CID selection sub-part of 3GPP connection */ + void (* cid_selection_3gpp) (MMBroadbandBearer *self, + MMBaseModem *modem, + MMPortSerialAt *primary, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + guint (* cid_selection_3gpp_finish) (MMBroadbandBearer *self, + GAsyncResult *res, + GError **error); + /* Dialing sub-part of 3GPP connection */ void (* dial_3gpp) (MMBroadbandBearer *self, MMBaseModem *modem, |