summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekka Pessi <Pekka.Pessi@nokia.com>2010-11-04 22:35:39 +0200
committerPekka Pessi <Pekka.Pessi@nokia.com>2010-11-05 16:08:53 +0200
commit0bf275a61322262bace7f6b65ee34e54cc6d114d (patch)
treea5ec2c3a7add6d7f986acb797741c4193e34a141
parenta6f0222cca3e4293286fbff48511e63987bced78 (diff)
modem/modem: derive Modem from ModemOface
New functions: - modem_list_interfaces () - modem_has_imsi () - modem_has_imei () New signals: - "interface-added" - "interface-removed" - "imsi-added"
-rw-r--r--modem/modem.c500
-rw-r--r--modem/modem.h16
2 files changed, 403 insertions, 113 deletions
diff --git a/modem/modem.c b/modem/modem.c
index fb813c4..ae15490 100644
--- a/modem/modem.c
+++ b/modem/modem.c
@@ -2,7 +2,9 @@
* modem/modem.c - oFono modem
*
* Copyright (C) 2009, 2010 Nokia Corporation
- * @author Pekka Pessi <first.surname@nokia.com>
+ *
+ * @author Pekka Pessi <first.surname@nokia.com>
+ * @author Kai Vehmanen <first.surname@nokia.com>
*
* This work is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,8 +29,13 @@
#include "modem/modem.h"
#include "modem/request-private.h"
+#include "modem/oface.h"
#include "modem/ofono.h"
+#include "modem/call.h"
+#include "modem/sim.h"
+#include "modem/sms.h"
#include "modem/errors.h"
+#include "modem/oface.h"
#include <dbus/dbus-glib.h>
@@ -48,49 +55,59 @@
/* ------------------------------------------------------------------------ */
-G_DEFINE_TYPE (Modem, modem, G_TYPE_OBJECT);
+G_DEFINE_TYPE (Modem, modem, MODEM_TYPE_OFACE);
enum
{
- PROP_OBJECT_PATH = 1,
+ PROP_NONE,
PROP_POWERED,
PROP_ONLINE,
PROP_NAME,
PROP_MANUFACTURER,
PROP_MODEL,
PROP_REVISION,
- PROP_SERIAL,
+ PROP_IMEI,
PROP_FEATURES,
PROP_INTERFACES,
N_PROPS
};
+enum
+{
+ SIGNAL_INTERFACE_ADDED,
+ SIGNAL_INTERFACE_REMOVED,
+ SIGNAL_IMSI_ADDED,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
/* private data */
struct _ModemPrivate
{
- DBusGProxy *proxy;
-
/* Properties */
- gchar *object_path;
gboolean powered;
gboolean online;
gchar *name;
gchar *manufacturer;
gchar *model;
gchar *revision;
- gchar *serial;
+ gchar *imei;
gchar **features;
gchar **interfaces;
- unsigned dispose_has_run:1;
- unsigned :0;
+ GHashTable *ifhash;
+ GHashTable *connecting;
+ GHashTable *ofaces;
};
/* ------------------------------------------------------------------------ */
/* Local functions */
-static void on_modem_property_changed (DBusGProxy *, char const *,
- GValue const *, gpointer);
+static void on_notify_interfaces (Modem *, GParamSpec *, Modem *);
+static void modem_update_interfaces (Modem *);
+static void on_sim_notify_imsi (ModemSIMService *, GParamSpec *, Modem *);
+static void on_oface_connected (ModemOface *, gboolean, Modem *);
/* ------------------------------------------------------------------------ */
@@ -101,41 +118,24 @@ modem_init (Modem *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
MODEM_TYPE_MODEM, ModemPrivate);
+
+ self->priv->ifhash = g_hash_table_new (g_str_hash, g_str_equal);
+ self->priv->connecting = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
+ self->priv->ofaces = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
}
static void
modem_constructed (GObject *object)
{
- Modem *self = MODEM_MODEM (object);
- ModemPrivate *priv = self->priv;
-
- priv->proxy = modem_ofono_proxy (priv->object_path, OFONO_IFACE_MODEM);
-
- if (priv->proxy)
- {
- modem_ofono_proxy_connect_to_property_changed (priv->proxy,
- on_modem_property_changed, self);
- }
- else
- g_error ("Unable to proxy oFono modem %s", priv->object_path);
+ if (G_OBJECT_CLASS (modem_parent_class)->constructed)
+ G_OBJECT_CLASS (modem_parent_class)->constructed (object);
}
static void
modem_dispose (GObject *object)
{
- Modem *self = MODEM_MODEM (object);
- ModemPrivate *priv = self->priv;
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- modem_ofono_proxy_disconnect_from_property_changed (priv->proxy,
- on_modem_property_changed, self);
-
- g_object_run_dispose (G_OBJECT (priv->proxy));
-
if (G_OBJECT_CLASS (modem_parent_class)->dispose)
G_OBJECT_CLASS (modem_parent_class)->dispose (object);
}
@@ -150,17 +150,18 @@ modem_finalize (GObject *object)
/* Free any data held directly by the object here */
- g_object_unref (priv->proxy);
-
- g_free (priv->object_path);
g_free (priv->name);
g_free (priv->manufacturer);
g_free (priv->model);
g_free (priv->revision);
- g_free (priv->serial);
+ g_free (priv->imei);
g_strfreev (priv->features);
g_strfreev (priv->interfaces);
+ g_hash_table_destroy (priv->ifhash);
+ g_hash_table_destroy (priv->ofaces);
+ g_hash_table_destroy (priv->connecting);
+
G_OBJECT_CLASS (modem_parent_class)->finalize (object);
}
@@ -175,11 +176,6 @@ modem_set_property (GObject *obj,
switch (property_id)
{
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_boxed (value);
- break;
-
case PROP_POWERED:
priv->powered = g_value_get_boolean (value);
break;
@@ -208,9 +204,9 @@ modem_set_property (GObject *obj,
priv->revision = g_value_dup_string (value);
break;
- case PROP_SERIAL:
- g_free (priv->serial);
- priv->serial = g_value_dup_string (value);
+ case PROP_IMEI:
+ g_free (priv->imei);
+ priv->imei = g_value_dup_string (value);
break;
case PROP_FEATURES:
@@ -240,10 +236,6 @@ modem_get_property (GObject *obj,
switch (property_id)
{
- case PROP_OBJECT_PATH:
- g_value_set_boxed (value, priv->object_path);
- break;
-
case PROP_POWERED:
g_value_set_boolean (value, priv->powered);
break;
@@ -268,8 +260,8 @@ modem_get_property (GObject *obj,
g_value_set_string (value, priv->revision);
break;
- case PROP_SERIAL:
- g_value_set_string (value, priv->serial);
+ case PROP_IMEI:
+ g_value_set_string (value, priv->imei);
break;
case PROP_FEATURES:
@@ -286,10 +278,84 @@ modem_get_property (GObject *obj,
}
}
+/* ------------------------------------------------------------------------- */
+
+/** Maps properties of org.ofono.Modem to matching Modem properties */
+char const *
+modem_property_mapper (char const *name)
+{
+ if (!strcmp (name, "Powered"))
+ return "powered";
+ if (!strcmp (name, "Online"))
+ return "online";
+ if (!strcmp (name, "Name"))
+ return "name";
+ if (!strcmp (name, "Manufacturer"))
+ return "manufacturer";
+ if (!strcmp (name, "Model"))
+ return "model";
+ if (!strcmp (name, "Revision"))
+ return "revision";
+ if (!strcmp (name, "Serial"))
+ return "imei";
+ if (!strcmp (name, "Features"))
+ return "features";
+ if (!strcmp (name, "Interfaces"))
+ return "interfaces";
+ return NULL;
+}
+
+static void
+modem_connect (ModemOface *_self)
+{
+ DEBUG ("(%p): enter", _self);
+
+ modem_oface_connect_properties (_self, FALSE);
+
+ g_signal_connect (_self, "notify::interfaces",
+ G_CALLBACK(on_notify_interfaces), _self);
+
+ modem_update_interfaces ( MODEM_MODEM(_self) );
+}
+
+static void
+modem_disconnect (ModemOface *_self)
+{
+ DEBUG ("(%p): enter", _self);
+
+ Modem *self = MODEM_MODEM (_self);
+ ModemPrivate *priv = self->priv;
+ GHashTableIter iter[1];
+ char *interface;
+ ModemOface *oface;
+
+ g_signal_handlers_disconnect_by_func (_self,
+ G_CALLBACK(on_notify_interfaces), _self);
+
+ for (g_hash_table_iter_init (iter, priv->connecting);
+ g_hash_table_iter_next (iter, (gpointer)&interface, (gpointer)&oface);)
+ {
+ g_signal_handlers_disconnect_by_func (oface,
+ on_oface_connected, self);
+ }
+
+ for (g_hash_table_iter_init (iter, priv->ofaces);
+ g_hash_table_iter_next (iter, (gpointer)&interface, (gpointer)&oface);)
+ {
+ g_signal_handlers_disconnect_by_func (oface,
+ on_oface_connected, self);
+
+ if (MODEM_IS_SIM_SERVICE (oface))
+ g_signal_handlers_disconnect_by_func (oface,
+ on_sim_notify_imsi, self);
+ }
+}
+
static void
modem_class_init (ModemClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ModemOfaceClass *oface_class = MODEM_OFACE_CLASS (klass);
DEBUG ("enter");
@@ -299,14 +365,35 @@ modem_class_init (ModemClass *klass)
object_class->get_property = modem_get_property;
object_class->set_property = modem_set_property;
+ oface_class->property_mapper = modem_property_mapper;
+ oface_class->connect = modem_connect;
+ oface_class->disconnect = modem_disconnect;
+
g_type_class_add_private (klass, sizeof (ModemPrivate));
- g_object_class_install_property (object_class, PROP_OBJECT_PATH,
- g_param_spec_boxed ("object-path",
- "Object Path",
- "Object path of the modem on oFono",
- DBUS_TYPE_G_OBJECT_PATH,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+ signals[SIGNAL_INTERFACE_ADDED] = g_signal_new ("interface-added",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ signals[SIGNAL_INTERFACE_REMOVED] = g_signal_new ("interface-removed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ signals[SIGNAL_IMSI_ADDED] = g_signal_new ("imsi-added",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
g_object_class_install_property (object_class, PROP_POWERED,
g_param_spec_boolean ("powered",
@@ -350,10 +437,10 @@ modem_class_init (ModemClass *klass)
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (object_class, PROP_SERIAL,
- g_param_spec_string ("serial",
+ g_object_class_install_property (object_class, PROP_IMEI,
+ g_param_spec_string ("imei",
"Serial",
- "The serial number (IMEI) of the modem device.",
+ "The IMEI (serial number) of the modem device.",
"",
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
@@ -365,6 +452,7 @@ modem_class_init (ModemClass *klass)
G_TYPE_STRV,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /* XXX/KV: should this be removed as this is oFono-specific */
g_object_class_install_property (object_class, PROP_INTERFACES,
g_param_spec_boxed ("interfaces",
"Interfaces",
@@ -376,53 +464,190 @@ modem_class_init (ModemClass *klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
-
/* -------------------------------------------------------------------------- */
-/* modem interface */
-char const *
-modem_property_name_by_ofono_name (char const *name)
+static void
+on_sim_notify_imsi (ModemSIMService *sim,
+ GParamSpec *dummy,
+ Modem *self)
{
- if (!strcmp (name, "Powered"))
- return "powered";
- if (!strcmp (name, "Online"))
- return "online";
- if (!strcmp (name, "Name"))
- return "name";
- if (!strcmp (name, "Manufacturer"))
- return "manufacturer";
- if (!strcmp (name, "Model"))
- return "model";
- if (!strcmp (name, "Revision"))
- return "revision";
- if (!strcmp (name, "Serial"))
- return "serial";
- if (!strcmp (name, "Features"))
- return "features";
- if (!strcmp (name, "Interfaces"))
- return "interfaces";
- return NULL;
+ gchar *imsi = NULL;
+
+ DEBUG ("enter");
+
+ g_object_get (sim, "imsi", &imsi, NULL);
+ if (imsi == NULL)
+ return;
+
+ if (strlen (imsi))
+ {
+ DEBUG ("emitting imsi-added \"%s\" for %s", imsi,
+ modem_oface_object_path (MODEM_OFACE (sim)));
+ g_signal_emit (self, signals[SIGNAL_IMSI_ADDED], 0, imsi);
+ }
+
+ g_free (imsi);
}
static void
-on_modem_property_changed (DBusGProxy *proxy,
- char const *property,
- GValue const *value,
- gpointer _self)
+on_oface_connected (ModemOface *oface,
+ gboolean connected,
+ Modem *self)
{
- property = modem_property_name_by_ofono_name (property);
+ ModemPrivate *priv = self->priv;
+ char *interface;
+
+ DEBUG ("enter");
+
+ g_object_get (oface, "interface", &interface, NULL);
+
+ DEBUG ("%s %s interface = %s, oface = %p",
+ connected ? "connected" : "disconnected",
+ modem_oface_object_path (oface),
+ interface, oface);
- if (property)
- g_object_set_property (G_OBJECT (_self), property, value);
+ if (!connected)
+ {
+ g_signal_handlers_disconnect_by_func (oface,
+ on_oface_connected, self);
+
+ if (MODEM_IS_SIM_SERVICE (oface))
+ g_signal_handlers_disconnect_by_func (oface,
+ on_sim_notify_imsi, self);
+
+ if (g_hash_table_lookup (priv->connecting, interface))
+ {
+ g_hash_table_remove (priv->connecting, interface);
+ }
+ else if (g_hash_table_lookup (priv->ofaces, interface))
+ {
+ DEBUG("emitting interface-removed for %s", interface);
+ g_signal_emit (self, signals[SIGNAL_INTERFACE_REMOVED], 0, oface);
+ g_hash_table_remove (priv->ofaces, interface);
+ }
+
+ g_free (interface);
+
+ return;
+ }
+
+ g_hash_table_insert (priv->ofaces, interface, g_object_ref (oface));
+ g_hash_table_remove (priv->connecting, interface);
+
+ DEBUG ("emitting interface-added for %s", interface);
+
+ g_signal_emit (self, signals[SIGNAL_INTERFACE_ADDED], 0, oface);
+
+ if (MODEM_IS_SIM_SERVICE (oface))
+ {
+ g_signal_connect (oface, "notify::imsi",
+ G_CALLBACK(on_sim_notify_imsi), self);
+ on_sim_notify_imsi (MODEM_SIM_SERVICE (oface), NULL, self);
+ }
}
+static void
+modem_update_interfaces (Modem *self)
+{
+ ModemPrivate *priv = self->priv;
+ ModemOface *oface;
+ ModemOface *already;
+ GHashTableIter iter[1];
+ char const *object_path;
+ GHashTable *prev_ifhash;
+ char *interface;
+ guint i;
+
+ DEBUG ("enter");
+
+ prev_ifhash = priv->ifhash;
+ priv->ifhash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0; priv->interfaces[i]; i++)
+ {
+ interface = g_strdup (priv->interfaces[i]);
+ g_hash_table_insert (priv->ifhash, interface, GUINT_TO_POINTER(1));
+ }
+
+ object_path = modem_oface_object_path (MODEM_OFACE (self));
+
+ for (i = 0; priv->interfaces[i]; i++)
+ {
+ interface = priv->interfaces[i];
+
+ if (g_hash_table_lookup (priv->ofaces, interface))
+ continue;
+ if (g_hash_table_lookup (prev_ifhash, interface))
+ continue;
+
+ oface = modem_oface_new (interface, object_path);
+ if (oface == NULL) {
+ DEBUG("Modem %s ignoring interface %s", object_path, interface);
+ continue;
+ }
+
+ DEBUG("Modem %s adding interface %s", object_path, interface);
+
+ already = g_hash_table_lookup (priv->connecting, interface);
+ if (already)
+ {
+ /* interface was added, removed and added before it got connected */
+ g_signal_handlers_disconnect_by_func (already,
+ on_oface_connected, self);
+ }
+
+ g_hash_table_insert (priv->connecting, g_strdup (interface), oface);
+
+ g_signal_connect (oface, "connected",
+ G_CALLBACK (on_oface_connected), self);
+
+ modem_oface_connect (oface);
+ }
+
+ g_hash_table_unref (prev_ifhash);
+
+ DEBUG("All modem %s interfaces added", object_path);
+
+ redo_connecting:
+
+ for (g_hash_table_iter_init (iter, priv->connecting);
+ g_hash_table_iter_next (iter, (gpointer)&interface, (gpointer)&oface);)
+ {
+ if (g_hash_table_lookup (priv->ifhash, interface) == NULL)
+ {
+ modem_oface_disconnect (oface);
+ goto redo_connecting;
+ }
+ }
+
+ redo_ofaces:
+
+ for (g_hash_table_iter_init (iter, priv->ofaces);
+ g_hash_table_iter_next (iter, (gpointer)&interface, (gpointer)&oface);)
+ {
+ if (g_hash_table_lookup (priv->ifhash, interface) == NULL)
+ {
+ modem_oface_disconnect (oface);
+ goto redo_ofaces;
+ }
+ }
+}
+
+static void
+on_notify_interfaces (Modem *self,
+ GParamSpec *dummy1,
+ Modem *dummy2)
+{
+ modem_update_interfaces (self);
+}
+
+/* -------------------------------------------------------------------------- */
+/* modem interface */
+
char const *
modem_get_modem_path (Modem const *self)
{
- if (!MODEM_IS_MODEM (self))
- return NULL;
-
- return dbus_g_proxy_get_path (self->priv->proxy);
+ return modem_oface_object_path (MODEM_OFACE (self));
}
gboolean
@@ -441,37 +666,96 @@ modem_is_online (Modem const *self)
return self->priv->online;
}
+ModemOface *
+modem_get_interface (Modem const *self, char const *interface)
+{
+ g_return_val_if_fail (MODEM_IS_MODEM (self), FALSE);
+
+ return g_hash_table_lookup (self->priv->ofaces, interface);
+}
+
gboolean
modem_has_interface (Modem const *self, char const *interface)
{
- guint i;
-
g_return_val_if_fail (MODEM_IS_MODEM (self), FALSE);
- if (!self->priv->interfaces)
+ if (!self->priv->ifhash)
return FALSE;
- for (i = 0; self->priv->interfaces[i]; i++)
- if (!strcmp (self->priv->interfaces[i], interface))
- return TRUE;
+ return g_hash_table_lookup (self->priv->ifhash, interface) != NULL;
+}
+
+ModemOface **
+modem_list_interfaces (Modem const *self)
+{
+ ModemPrivate *priv;
+ GPtrArray *array;
+ char *key;
+ ModemOface *oface;
+ GHashTableIter iter[1];
+
+ g_return_val_if_fail (MODEM_IS_MODEM (self), g_new (ModemOface *, 1));
- return FALSE;
+ priv = self->priv;
+ array = g_ptr_array_sized_new (g_hash_table_size (priv->ofaces) + 1);
+
+ for (g_hash_table_iter_init (iter, priv->ofaces);
+ g_hash_table_iter_next (iter, (gpointer)&key, (gpointer)&oface);)
+ {
+ g_ptr_array_add(array, oface);
+ }
+
+ g_ptr_array_add (array, NULL);
+
+ return (ModemOface **)g_ptr_array_free (array, FALSE);
}
gboolean
modem_supports_sim (Modem const *self)
{
- return modem_has_interface (self, OFONO_IFACE_SIM);
+ return modem_get_interface (self, OFONO_IFACE_SIM) != NULL;
}
gboolean
modem_supports_call (Modem const *self)
{
- return modem_has_interface (self, OFONO_IFACE_CALL_MANAGER);
+ return modem_get_interface (self, OFONO_IFACE_CALL_MANAGER) != NULL;
}
gboolean
modem_supports_sms (Modem const *self)
{
- return modem_has_interface (self, OFONO_IFACE_SMS);
+ return modem_get_interface (self, OFONO_IFACE_SMS) != NULL;
+}
+
+gboolean
+modem_has_imsi (Modem const *self, gchar const *imsi)
+{
+ ModemSIMService *sim;
+ gchar *sim_imsi;
+ gboolean match;
+
+ g_return_val_if_fail (MODEM_IS_MODEM (self), FALSE);
+ g_return_val_if_fail (imsi != NULL, FALSE);
+
+ sim = (ModemSIMService *)modem_get_interface (self, OFONO_IFACE_SIM);
+ if (sim == NULL)
+ return FALSE;
+
+ g_object_get(sim, "imsi", &sim_imsi, NULL);
+
+ match = strcmp(sim_imsi, imsi) == 0;
+
+ g_free(sim_imsi);
+
+ return match;
+}
+
+gboolean
+modem_has_imei (Modem const *self, gchar const *imei)
+{
+ g_return_val_if_fail (MODEM_IS_MODEM (self), FALSE);
+ g_return_val_if_fail (imei != NULL, FALSE);
+
+ return g_strcmp0(self->priv->imei, imei) == 0;
}
diff --git a/modem/modem.h b/modem/modem.h
index e907b18..4cad466 100644
--- a/modem/modem.h
+++ b/modem/modem.h
@@ -1,7 +1,7 @@
/*
* modem/modem.h - Interface towards oFono modem instance
*
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009,2010 Nokia Corporation
* @author Pekka Pessi <first.surname@nokia.com>
*
* This work is free software; you can redistribute it and/or
@@ -24,6 +24,7 @@
#include <glib-object.h>
#include <modem/request.h>
+#include <modem/oface.h>
G_BEGIN_DECLS
@@ -32,11 +33,11 @@ typedef struct _ModemClass ModemClass;
typedef struct _ModemPrivate ModemPrivate;
struct _ModemClass {
- GObjectClass parent_class;
+ ModemOfaceClass parent_class;
};
struct _Modem {
- GObject parent;
+ ModemOface parent;
ModemPrivate *priv;
};
@@ -57,17 +58,22 @@ GType modem_get_type (void);
/* ---------------------------------------------------------------------- */
-char const *modem_property_name_by_ofono_name (char const *name);
-
char const *modem_get_modem_path (Modem const *self);
gboolean modem_is_powered (Modem const *self);
gboolean modem_is_online (Modem const *self);
gboolean modem_has_interface (Modem const *self, char const *interface);
+
+ModemOface **modem_list_interfaces (Modem const *self);
+
gboolean modem_supports_sim (Modem const *self);
gboolean modem_supports_call (Modem const *self);
gboolean modem_supports_sms (Modem const *self);
+gboolean modem_has_imsi (Modem const *self, gchar const *imsi);
+
+gboolean modem_has_imei (Modem const *self, gchar const *imei);
+
G_END_DECLS
#endif /* #ifndef _MODEM_MODEM_H_*/