diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2011-11-22 18:16:17 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-15 14:14:23 +0100 |
commit | e40d32ac94382361b0c0e18cd81cc98ebb38bc44 (patch) | |
tree | 74d88f5b3f4a252494e8e96cf9f839a22017d2ec | |
parent | 1453f352bca34f8592a33954d628acfec66d4336 (diff) |
core: new MMSim object, inherits from MmGdbusSim
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/mm-sim.c | 352 | ||||
-rw-r--r-- | src/mm-sim.h | 63 |
3 files changed, 417 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 15aa2fd6..595de664 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -110,6 +110,8 @@ modem_manager_SOURCES = \ mm-manager.h \ mm-plugin-manager.c \ mm-plugin-manager.h \ + mm-sim.h \ + mm-sim.c \ mm-base-modem.h \ mm-base-modem.c \ mm-iface-modem.h \ diff --git a/src/mm-sim.c b/src/mm-sim.c new file mode 100644 index 00000000..1b47a027 --- /dev/null +++ b/src/mm-sim.c @@ -0,0 +1,352 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2008 - 2009 Novell, Inc. + * Copyright (C) 2009 - 2011 Red Hat, Inc. + * Copyright (C) 2011 Google, Inc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> + +#include <ModemManager.h> + +#include <mm-enums-types.h> +#include <mm-errors-types.h> +#include <mm-gdbus-sim.h> +#include <mm-marshal.h> + +#include "mm-iface-modem.h" +#include "mm-at.h" +#include "mm-sim.h" +#include "mm-base-modem.h" +#include "mm-utils.h" +#include "mm-errors.h" +#include "mm-log.h" +#include "mm-modem-helpers.h" + +typedef struct _InitAsyncContext InitAsyncContext; +static void interface_initialization_step (InitAsyncContext *ctx); +static void async_initable_iface_init (GAsyncInitableIface *iface); + +G_DEFINE_TYPE_EXTENDED (MMSim, mm_sim, MM_GDBUS_TYPE_SIM_SKELETON, 0, + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, + async_initable_iface_init)); + +enum { + PROP_0, + PROP_PATH, + PROP_CONNECTION, + PROP_MODEM, + PROP_LAST +}; + +static GParamSpec *properties[PROP_LAST]; + +struct _MMSimPrivate { + /* The connection to the system bus */ + GDBusConnection *connection; + /* The modem which owns this SIM */ + MMBaseModem *modem; + /* The path where the SIM object is exported */ + gchar *path; +}; + +static void +mm_sim_export (MMSim *self) +{ + GError *error = NULL; + + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self), + self->priv->connection, + self->priv->path, + &error)) { + mm_warn ("couldn't export SIM at '%s': '%s'", + self->priv->path, + error->message); + g_error_free (error); + } +} + +static void +mm_sim_unexport (MMSim *self) +{ + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self)); +} + +/*****************************************************************************/ + +typedef enum { + INITIALIZATION_STEP_FIRST, + INITIALIZATION_STEP_LAST +} InitializationStep; + +struct _InitAsyncContext { + GSimpleAsyncResult *result; + GCancellable *cancellable; + MMSim *self; + InitializationStep step; + guint sim_identifier_tries; + MMAtSerialPort *port; +}; + +static void +init_async_context_free (InitAsyncContext *ctx, + gboolean close_port) +{ + if (close_port) + mm_serial_port_close (MM_SERIAL_PORT (ctx->port)); + g_object_unref (ctx->self); + g_object_unref (ctx->result); + if (ctx->cancellable) + g_object_unref (ctx->cancellable); + g_free (ctx); +} + +MMSim * +mm_sim_new_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error) +{ + return MM_SIM (g_async_initable_new_finish (initable, res, error)); +} + +static gboolean +initable_init_finish (GAsyncInitable *initable, + GAsyncResult *result, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + return TRUE; +} + +static void +interface_initialization_step (InitAsyncContext *ctx) +{ + switch (ctx->step) { + case INITIALIZATION_STEP_FIRST: + break; + + case INITIALIZATION_STEP_LAST: + /* We are done without errors! */ + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + g_simple_async_result_complete_in_idle (ctx->result); + init_async_context_free (ctx, TRUE); + return; + } + + /* Go on to next step */ + ctx->step++; + interface_initialization_step (ctx); +} + + +static void +initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + InitAsyncContext *ctx; + GError *error = NULL; + + mm_gdbus_sim_set_sim_identifier (MM_GDBUS_SIM (initable), NULL); + mm_gdbus_sim_set_imsi (MM_GDBUS_SIM (initable), NULL); + mm_gdbus_sim_set_operator_identifier (MM_GDBUS_SIM (initable), NULL); + mm_gdbus_sim_set_operator_name (MM_GDBUS_SIM (initable), NULL); + + ctx = g_new (InitAsyncContext, 1); + ctx->self = g_object_ref (initable); + ctx->result = g_simple_async_result_new (G_OBJECT (initable), + callback, + user_data, + initable_init_async); + ctx->cancellable = (cancellable ? + g_object_ref (cancellable) : + NULL); + ctx->step = INITIALIZATION_STEP_FIRST; + ctx->sim_identifier_tries = 0; + + ctx->port = mm_base_modem_get_port_primary (ctx->self->priv->modem); + if (!mm_serial_port_open (MM_SERIAL_PORT (ctx->port), &error)) { + g_simple_async_result_take_error (ctx->result, error); + g_simple_async_result_complete_in_idle (ctx->result); + init_async_context_free (ctx, FALSE); + return; + } + + interface_initialization_step (ctx); +} + +void +mm_sim_new (MMBaseModem *modem, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + gchar *path; + static guint32 id = 0; + + /* Build the unique path for the SIM, and create the object */ + path = g_strdup_printf (MM_DBUS_PATH"/SIMs/%d", id++); + g_async_initable_new_async (MM_TYPE_SIM, + G_PRIORITY_DEFAULT, + cancellable, + callback, + user_data, + MM_SIM_PATH, path, + MM_SIM_MODEM, modem, + NULL); + g_free (path); +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MMSim *self = MM_SIM (object); + + switch (prop_id) { + case PROP_PATH: + g_free (self->priv->path); + self->priv->path = g_value_dup_string (value); + break; + case PROP_CONNECTION: + if (self->priv->connection) + g_object_unref (self->priv->connection); + self->priv->connection = g_value_dup_object (value); + + /* Export when we get a DBus connection */ + if (self->priv->connection) + mm_sim_export (self); + else + mm_sim_unexport (self); + break; + case PROP_MODEM: + if (self->priv->modem) + g_object_unref (self->priv->modem); + self->priv->modem = g_value_dup_object (value); + if (self->priv->modem) { + /* Bind the modem's connection (which is set when it is exported, + * and unset when unexported) to the SIM's connection */ + g_object_bind_property (self->priv->modem, MM_BASE_MODEM_CONNECTION, + self, MM_SIM_CONNECTION, + G_BINDING_DEFAULT); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MMSim *self = MM_SIM (object); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, self->priv->path); + break; + case PROP_CONNECTION: + g_value_set_object (value, self->priv->connection); + break; + case PROP_MODEM: + g_value_set_object (value, self->priv->modem); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mm_sim_init (MMSim *self) +{ + /* Initialize private data */ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), + MM_TYPE_SIM, + MMSimPrivate); +} + +static void +dispose (GObject *object) +{ + MMSim *self = MM_SIM (object); + + if (self->priv->connection) + g_clear_object (&self->priv->connection); + + if (self->priv->modem) + g_clear_object (&self->priv->modem); + + G_OBJECT_CLASS (mm_sim_parent_class)->dispose (object); +} + +static void +async_initable_iface_init (GAsyncInitableIface *iface) +{ + iface->init_async = initable_init_async; + iface->init_finish = initable_init_finish; +} + +static void +mm_sim_class_init (MMSimClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (MMSimPrivate)); + + /* Virtual methods */ + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + + properties[PROP_CONNECTION] = + g_param_spec_object (MM_SIM_CONNECTION, + "Connection", + "GDBus connection to the system bus.", + G_TYPE_DBUS_CONNECTION, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_CONNECTION, properties[PROP_CONNECTION]); + + properties[PROP_PATH] = + g_param_spec_string (MM_SIM_PATH, + "Path", + "DBus path of the SIM", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (object_class, PROP_PATH, properties[PROP_PATH]); + + properties[PROP_MODEM] = + g_param_spec_object (MM_SIM_MODEM, + "Modem", + "The Modem which owns this SIM", + MM_TYPE_BASE_MODEM, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_MODEM, properties[PROP_MODEM]); +} + diff --git a/src/mm-sim.h b/src/mm-sim.h new file mode 100644 index 00000000..5a3c0712 --- /dev/null +++ b/src/mm-sim.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Author: Aleksander Morgado <aleksander@lanedo.com> + * + * Copyright (C) 2011 Google, Inc. + */ + +#ifndef MM_SIM_H +#define MM_SIM_H + +#include <glib.h> +#include <glib-object.h> + +#include <mm-gdbus-sim.h> +#include "mm-base-modem.h" + +#define MM_TYPE_SIM (mm_sim_get_type ()) +#define MM_SIM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM, MMSim)) +#define MM_SIM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM, MMSimClass)) +#define MM_IS_SIM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM)) +#define MM_IS_SIM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM)) +#define MM_SIM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM, MMSimClass)) + +typedef struct _MMSim MMSim; +typedef struct _MMSimClass MMSimClass; +typedef struct _MMSimPrivate MMSimPrivate; + +#define MM_SIM_PATH "sim-path" +#define MM_SIM_CONNECTION "sim-connection" +#define MM_SIM_MODEM "sim-modem" + +struct _MMSim { + MmGdbusSimSkeleton parent; + MMSimPrivate *priv; +}; + +struct _MMSimClass { + MmGdbusSimSkeletonClass parent; +}; + +GType mm_sim_get_type (void); + +void mm_sim_new (MMBaseModem *modem, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +MMSim *mm_sim_new_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error); + + +#endif /* MM_SIM_H */ + |