From 3c4a26cb918a2a4b0835a82003b69af4bda7a5df Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Sun, 14 Apr 2013 09:31:19 +0200 Subject: bearer-mbim: log available provisioned contexts during connection --- src/mm-bearer-mbim.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) diff --git a/src/mm-bearer-mbim.c b/src/mm-bearer-mbim.c index 5389cfa5..c164fae8 100644 --- a/src/mm-bearer-mbim.c +++ b/src/mm-bearer-mbim.c @@ -26,6 +26,7 @@ #define _LIBMM_INSIDE_MM #include +#include "mm-serial-enums-types.h" #include "mm-bearer-mbim.h" #include "mm-log.h" @@ -37,6 +38,282 @@ struct _MMBearerMbimPrivate { /*****************************************************************************/ +static gboolean +peek_ports (gpointer self, + MbimDevice **o_device, + MMPort **o_data, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBaseModem *modem = NULL; + + g_object_get (G_OBJECT (self), + MM_BEARER_MODEM, &modem, + NULL); + g_assert (MM_IS_BASE_MODEM (modem)); + + if (o_device) { + MMMbimPort *port; + + port = mm_base_modem_peek_port_mbim (modem); + if (!port) { + g_simple_async_report_error_in_idle (G_OBJECT (self), + callback, + user_data, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't peek MBIM port"); + g_object_unref (modem); + return FALSE; + } + + *o_device = mm_mbim_port_peek_device (port); + } + + if (o_data) { + MMPort *port; + + /* Grab a data port */ + port = mm_base_modem_peek_best_data_port (modem, MM_PORT_TYPE_NET); + if (!port) { + g_simple_async_report_error_in_idle (G_OBJECT (self), + callback, + user_data, + MM_CORE_ERROR, + MM_CORE_ERROR_NOT_FOUND, + "No valid data port found to launch connection"); + g_object_unref (modem); + return FALSE; + } + + *o_data = port; + } + + g_object_unref (modem); + return TRUE; +} + +/*****************************************************************************/ +/* Connect */ + +typedef enum { + CONNECT_STEP_FIRST, + CONNECT_STEP_PROVISIONED_CONTEXTS, + CONNECT_STEP_LAST +} ConnectStep; + +typedef struct { + MMBearerMbim *self; + MbimDevice *device; + GSimpleAsyncResult *result; + GCancellable *cancellable; + MMBearerProperties *properties; + ConnectStep step; + MMPort *data; +} ConnectContext; + +static void +connect_context_complete_and_free (ConnectContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->result); + g_object_unref (ctx->data); + g_object_unref (ctx->cancellable); + g_object_unref (ctx->device); + g_object_unref (ctx->self); + g_slice_free (ConnectContext, ctx); +} + +static MMBearerConnectResult * +connect_finish (MMBearer *self, + GAsyncResult *res, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return NULL; + + return mm_bearer_connect_result_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); +} + +static void connect_context_step (ConnectContext *ctx); + +static void +provisioned_contexts_query (MbimDevice *device, + GAsyncResult *res, + ConnectContext *ctx) +{ + GError *error = NULL; + MbimMessage *response; + guint32 provisioned_contexts_count; + MbimProvisionedContextElement **provisioned_contexts; + + response = mbim_device_command_finish (device, res, &error); + if (response && + mbim_message_command_done_get_result (response, &error) && + mbim_message_provisioned_contexts_response_parse ( + response, + &provisioned_contexts_count, + &provisioned_contexts, + &error)) { + guint32 i; + + mm_dbg ("Provisioned contexts found (%u):", provisioned_contexts_count); + for (i = 0; i < provisioned_contexts_count; i++) { + MbimProvisionedContextElement *el = provisioned_contexts[i]; + gchar *uuid_str; + + uuid_str = mbim_uuid_get_printable (&el->context_type); + mm_dbg ("[%u] context type: %s", el->context_id, mbim_context_type_get_string (mbim_uuid_to_context_type (&el->context_type))); + mm_dbg (" uuid: %s", uuid_str); + mm_dbg (" access string: %s", el->access_string ? el->access_string : ""); + mm_dbg (" username: %s", el->user_name ? el->user_name : ""); + mm_dbg (" password: %s", el->password ? el->password : ""); + mm_dbg (" compression: %s", mbim_compression_get_string (el->compression)); + mm_dbg (" auth: %s", mbim_auth_protocol_get_string (el->auth_protocol)); + g_free (uuid_str); + } + + mbim_provisioned_context_element_array_free (provisioned_contexts); + } else { + mm_dbg ("Error listing provisioned contexts: %s", error->message); + g_error_free (error); + } + + /* Keep on */ + ctx->step++; + connect_context_step (ctx); +} + +static void +connect_context_step (ConnectContext *ctx) +{ + /* If cancelled, complete */ + if (g_cancellable_is_cancelled (ctx->cancellable)) { + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_CANCELLED, + "Connection setup operation has been cancelled"); + connect_context_complete_and_free (ctx); + return; + } + + switch (ctx->step) { + case CONNECT_STEP_FIRST: + /* Fall down */ + ctx->step++; + + case CONNECT_STEP_PROVISIONED_CONTEXTS: { + MbimMessage *message; + + message = mbim_message_provisioned_contexts_query_new (NULL); + mbim_device_command (ctx->device, + message, + 10, + NULL, + (GAsyncReadyCallback)provisioned_contexts_query, + ctx); + mbim_message_unref (message); + return; + } + + case CONNECT_STEP_LAST: + /* /\* If one of IPv4 or IPv6 succeeds, we're connected *\/ */ + /* if (ctx->packet_data_handle_ipv4 || ctx->packet_data_handle_ipv6) { */ + /* MMBearerIpConfig *config; */ + + /* /\* Port is connected; update the state *\/ */ + /* mm_port_set_connected (MM_PORT (ctx->data), TRUE); */ + + /* /\* Keep connection related data *\/ */ + /* g_assert (ctx->self->priv->data == NULL); */ + /* ctx->self->priv->data = g_object_ref (ctx->data); */ + + /* g_assert (ctx->self->priv->packet_data_handle_ipv4 == 0); */ + /* g_assert (ctx->self->priv->client_ipv4 == NULL); */ + /* if (ctx->packet_data_handle_ipv4) { */ + /* ctx->self->priv->packet_data_handle_ipv4 = ctx->packet_data_handle_ipv4; */ + /* ctx->self->priv->client_ipv4 = g_object_ref (ctx->client_ipv4); */ + /* } */ + + /* g_assert (ctx->self->priv->packet_data_handle_ipv6 == 0); */ + /* g_assert (ctx->self->priv->client_ipv6 == NULL); */ + /* if (ctx->packet_data_handle_ipv6) { */ + /* ctx->self->priv->packet_data_handle_ipv6 = ctx->packet_data_handle_ipv6; */ + /* ctx->self->priv->client_ipv6 = g_object_ref (ctx->client_ipv6); */ + /* } */ + + /* /\* Build IP config; always DHCP based *\/ */ + /* config = mm_bearer_ip_config_new (); */ + /* mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); */ + + /* /\* Set operation result *\/ */ + /* g_simple_async_result_set_op_res_gpointer ( */ + /* ctx->result, */ + /* mm_bearer_connect_result_new ( */ + /* ctx->data, */ + /* ctx->packet_data_handle_ipv4 ? config : NULL, */ + /* ctx->packet_data_handle_ipv6 ? config : NULL), */ + /* (GDestroyNotify)mm_bearer_connect_result_unref); */ + /* g_object_unref (config); */ + /* } else { */ + /* GError *error; */ + + /* /\* No connection, set error. If both set, IPv4 error preferred *\/ */ + /* if (ctx->error_ipv4) { */ + /* error = ctx->error_ipv4; */ + /* ctx->error_ipv4 = NULL; */ + /* } else { */ + /* error = ctx->error_ipv6; */ + /* ctx->error_ipv6 = NULL; */ + /* } */ + + /* g_simple_async_result_take_error (ctx->result, error); */ + /* } */ + + g_simple_async_result_set_error (ctx->result, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Oops"); + connect_context_complete_and_free (ctx); + return; + } +} + +static void +_connect (MMBearer *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + ConnectContext *ctx; + MMPort *data; + MbimDevice *device; + + if (!peek_ports (self, &device, &data, callback, user_data)) + return; + + mm_dbg ("Launching connection with data port (%s/%s)", + mm_port_subsys_get_string (mm_port_get_subsys (data)), + mm_port_get_device (data)); + + ctx = g_slice_new0 (ConnectContext); + ctx->self = g_object_ref (self); + ctx->device = g_object_ref (device);; + ctx->data = g_object_ref (data); + ctx->cancellable = g_object_ref (cancellable); + ctx->step = CONNECT_STEP_FIRST; + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + _connect); + + g_object_get (self, + MM_BEARER_CONFIG, &ctx->properties, + NULL); + + /* Run! */ + connect_context_step (ctx); +} + +/*****************************************************************************/ + MMBearer * mm_bearer_mbim_new (MMBroadbandModemMbim *modem, MMBearerProperties *config) @@ -76,9 +353,13 @@ static void mm_bearer_mbim_class_init (MMBearerMbimClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMBearerClass *bearer_class = MM_BEARER_CLASS (klass); g_type_class_add_private (object_class, sizeof (MMBearerMbimPrivate)); /* Virtual methods */ object_class->dispose = dispose; + + bearer_class->connect = _connect; + bearer_class->connect_finish = connect_finish; } -- cgit v1.2.3