bearer-mbim: log available provisioned contexts during connection

This commit is contained in:
Aleksander Morgado
2013-04-14 09:31:19 +02:00
parent 0e9a0eb4c7
commit 3c4a26cb91

View File

@@ -26,6 +26,7 @@
#define _LIBMM_INSIDE_MM #define _LIBMM_INSIDE_MM
#include <libmm-glib.h> #include <libmm-glib.h>
#include "mm-serial-enums-types.h"
#include "mm-bearer-mbim.h" #include "mm-bearer-mbim.h"
#include "mm-log.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 * MMBearer *
mm_bearer_mbim_new (MMBroadbandModemMbim *modem, mm_bearer_mbim_new (MMBroadbandModemMbim *modem,
MMBearerProperties *config) MMBearerProperties *config)
@@ -76,9 +353,13 @@ static void
mm_bearer_mbim_class_init (MMBearerMbimClass *klass) mm_bearer_mbim_class_init (MMBearerMbimClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
MMBearerClass *bearer_class = MM_BEARER_CLASS (klass);
g_type_class_add_private (object_class, sizeof (MMBearerMbimPrivate)); g_type_class_add_private (object_class, sizeof (MMBearerMbimPrivate));
/* Virtual methods */ /* Virtual methods */
object_class->dispose = dispose; object_class->dispose = dispose;
bearer_class->connect = _connect;
bearer_class->connect_finish = connect_finish;
} }