aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-bearer.c545
-rw-r--r--src/mm-broadband-bearer.h13
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,