From aa1eaedcb3ad687d18ab52faf704069222164d30 Mon Sep 17 00:00:00 2001 From: Pekka Pessi Date: Wed, 13 Oct 2010 02:35:55 +0300 Subject: modem/service: use Modem objects Provide simple interface to modems being added or removed. --- modem/ofono.c | 2 +- modem/service.c | 565 +++++++++++++++++---------------------------- modem/service.h | 19 +- modem/signals-marshal.list | 1 + 4 files changed, 222 insertions(+), 365 deletions(-) diff --git a/modem/ofono.c b/modem/ofono.c index 31fdc69..0d986b9 100644 --- a/modem/ofono.c +++ b/modem/ofono.c @@ -226,7 +226,7 @@ modem_ofono_debug_desc(char const *name, GValue *value; GHashTableIter iter[1]; - DEBUG("%s path %s", name, object_path); + DEBUG ("%s(\"%s\")", name, object_path); for (g_hash_table_iter_init(iter, properties); g_hash_table_iter_next(iter, (gpointer)&key, (gpointer)&value);) { diff --git a/modem/service.c b/modem/service.c index ba27f27..1e09f25 100644 --- a/modem/service.c +++ b/modem/service.c @@ -31,6 +31,7 @@ #include "modem/errors.h" #include +#include #include #include @@ -50,52 +51,33 @@ G_DEFINE_TYPE(ModemService, modem_service, G_TYPE_OBJECT); -/* Signals we send */ enum { - SIGNAL_CONNECTED, SIGNAL_MODEM_ADDED, SIGNAL_MODEM_REMOVED, N_SIGNALS }; -enum { - PROP_OBJECT_PATH = 1, - N_PROPS -}; - static guint signals[N_SIGNALS] = {0}; -/* private data */ struct _ModemServicePrivate { - struct { - ModemRequest *request; - GError *error; - } connecting; + ModemRequest *refresh; DBusGProxy *proxy; - DBusGProxy *modem; - gchar *object_path; + GHashTable *modems; - gchar **interfaces; - - unsigned dispose_has_run:1, connected:1, signals:1, disconnected:1; - unsigned modem_online:1; - unsigned have_call_manager:1; + unsigned dispose_has_run:1, signals:1, subscribed:1; unsigned :0; }; /* ------------------------------------------------------------------------ */ /* Local functions */ -static void reply_to_get_modems(gpointer _self, ModemRequest *request, +static void reply_to_get_modems (gpointer _self, ModemRequest *request, GPtrArray *modems, GError const *error, gpointer user_data); -static void on_modem_added(DBusGProxy *, char const *, GHashTable *, gpointer); -static void on_modem_removed(DBusGProxy *, char const *, gpointer); -static void modem_service_check_connected(ModemService *self); -static void on_modem_property_changed(DBusGProxy *, char const *, - GValue const *, gpointer); +static void on_modem_added (DBusGProxy *, char const *, GHashTable *, gpointer); +static void on_modem_removed (DBusGProxy *, char const *, gpointer); /* ------------------------------------------------------------------------ */ @@ -106,6 +88,9 @@ modem_service_init(ModemService *self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE( self, MODEM_TYPE_SERVICE, ModemServicePrivate); + + self->priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); } static void @@ -131,17 +116,13 @@ modem_service_dispose(GObject *object) return; priv->dispose_has_run = TRUE; - priv->disconnected = TRUE; - priv->connected = FALSE; priv->signals = FALSE; - if (priv->connecting.request) - modem_request_cancel(priv->connecting.request); - priv->connecting.request = NULL; + if (priv->refresh) + modem_request_cancel (priv->refresh); + priv->refresh = NULL; g_object_run_dispose(G_OBJECT(priv->proxy)); - if (priv->modem) - g_object_run_dispose(G_OBJECT(priv->modem)); if (G_OBJECT_CLASS(modem_service_parent_class)->dispose) G_OBJECT_CLASS(modem_service_parent_class)->dispose(object); @@ -157,57 +138,13 @@ modem_service_finalize(GObject *object) /* Free any data held directly by the object here */ - g_object_unref(priv->proxy); - if (priv->modem) - g_object_unref(priv->modem); + g_object_unref (priv->proxy); - if (priv->connecting.error) - g_clear_error(&priv->connecting.error); + g_hash_table_unref (priv->modems); G_OBJECT_CLASS(modem_service_parent_class)->finalize(object); } -static void -modem_service_set_property(GObject *obj, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - ModemService *self = MODEM_SERVICE(obj); - ModemServicePrivate *priv = self->priv; - - switch (property_id) { - case PROP_OBJECT_PATH: - g_free(priv->object_path); - priv->object_path = g_value_dup_boxed(value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec); - break; - } -} - -static void -modem_service_get_property(GObject *obj, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - ModemService *self = MODEM_SERVICE(obj); - ModemServicePrivate *priv = self->priv; - - switch (property_id) { - case PROP_OBJECT_PATH: - g_value_set_boxed(value, priv->object_path); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec); - break; - } -} - static void modem_service_class_init(ModemServiceClass *klass) { @@ -218,16 +155,22 @@ modem_service_class_init(ModemServiceClass *klass) object_class->constructed = modem_service_constructed; object_class->dispose = modem_service_dispose; object_class->finalize = modem_service_finalize; - object_class->get_property = modem_service_get_property; - object_class->set_property = modem_service_set_property; - signals[SIGNAL_CONNECTED] = g_signal_new("connected", + signals[SIGNAL_MODEM_ADDED] = g_signal_new ("modem-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, MODEM_TYPE_MODEM); + + signals[SIGNAL_MODEM_REMOVED] = g_signal_new ("modem-removed", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, MODEM_TYPE_MODEM); g_type_class_add_private(klass, sizeof (ModemServicePrivate)); @@ -239,14 +182,6 @@ modem_service_class_init(ModemServiceClass *klass) G_TYPE_NONE, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - 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)); - modem_error_domain_prefix(0); /* Init errors */ modem_ofono_init_quarks(); @@ -255,332 +190,248 @@ modem_service_class_init(ModemServiceClass *klass) /* ------------------------------------------------------------------------ */ /* modem_service interface */ -/* Connect to service */ -gboolean -modem_service_connect(ModemService *self) +ModemService *modem_service (void) { - ModemServicePrivate *priv = self->priv; + static ModemService *service; - DEBUG("enter"); + if (!service) + service = g_object_new (MODEM_TYPE_SERVICE, NULL); - if (self->priv->connected) { - DEBUG("already connected"); - return TRUE; - } + return service; +} - if (self->priv->disconnected) { - DEBUG("already disconnected"); - return TRUE; - } +Modem *modem_service_find_modem (ModemService *self, char const *object_path) +{ + ModemServicePrivate *priv; + char *key; + Modem *modem; + GHashTableIter iter[1]; - priv->signals = TRUE; + g_return_val_if_fail (MODEM_IS_SERVICE (self), NULL); - dbus_g_proxy_add_signal(priv->proxy, - "ModemAdded", DBUS_TYPE_G_OBJECT_PATH, MODEM_TYPE_DBUS_DICT, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->proxy, - "ModemAdded", G_CALLBACK(on_modem_added), self, NULL); + priv = self->priv; - dbus_g_proxy_add_signal(priv->proxy, - "ModemRemoved", DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->proxy, - "ModemRemoved", G_CALLBACK(on_modem_removed), self, NULL); + if (object_path) + return g_hash_table_lookup (priv->modems, object_path); - priv->connecting.request = modem_ofono_request_descs(self, - priv->proxy, "GetModems", - reply_to_get_modems, NULL); + for (g_hash_table_iter_init (iter, priv->modems); + g_hash_table_iter_next (iter, (gpointer)&key, (gpointer)&modem);) + { + if (modem_is_online (modem)) + return modem; + } - DEBUG("connecting"); + for (g_hash_table_iter_init (iter, priv->modems); + g_hash_table_iter_next (iter, (gpointer)&key, (gpointer)&modem);) + { + if (modem_is_powered (modem)) + return modem; + } - return TRUE; + return NULL; } -static void -reply_to_get_modems(gpointer _self, - ModemRequest *request, - GPtrArray *modem_list, - GError const *error, - gpointer user_data) +Modem **modem_service_get_modems(ModemService *self) { - ModemService *self = MODEM_SERVICE(_self); ModemServicePrivate *priv = self->priv; - guint i; + GPtrArray *array; + char *key; + Modem *modem; + GHashTableIter iter[1]; - DEBUG("enter"); + g_return_val_if_fail (MODEM_IS_SERVICE (self), NULL); - priv->connecting.request = NULL; + priv = self->priv; + array = g_ptr_array_sized_new (g_hash_table_size (priv->modems) + 1); - if (error) { - if (priv->connecting.error) - g_clear_error(&priv->connecting.error); - priv->connecting.error = g_error_copy(error); - priv->connected = TRUE; - g_signal_emit(self, signals[SIGNAL_CONNECTED], 0); - return; - } + for (g_hash_table_iter_init (iter, priv->modems); + g_hash_table_iter_next (iter, (gpointer)&key, (gpointer)&modem);) + { + g_ptr_array_add(array, modem); + } - for (i = 0; i < modem_list->len; i++) { - GValueArray *va = g_ptr_array_index(modem_list, i); - char const *path = g_value_get_boxed(va->values + 0); - GHashTable *properties = g_value_get_boxed(va->values + 1); + g_ptr_array_add (array, NULL); - on_modem_added(priv->proxy, path, properties, self); - } + return (Modem **)g_ptr_array_free (array, FALSE); } -static void -on_modem_added(DBusGProxy *proxy, - char const *object_path, - GHashTable *properties, - gpointer userdata) +void +modem_service_refresh (ModemService *self) { - ModemService *self = userdata; ModemServicePrivate *priv = self->priv; - GValue *value; - - if (DEBUGGING) - modem_ofono_debug_desc("Modem", object_path, properties); - if (priv->modem) - return; + DEBUG("enter"); - if (priv->object_path && strcmp(object_path, priv->object_path)) + if (!priv->signals) + { + priv->signals = TRUE; + + dbus_g_proxy_add_signal (priv->proxy, + "ModemAdded", DBUS_TYPE_G_OBJECT_PATH, MODEM_TYPE_DBUS_DICT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, + "ModemAdded", G_CALLBACK (on_modem_added), self, NULL); + + dbus_g_proxy_add_signal (priv->proxy, + "ModemRemoved", DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, + "ModemRemoved", G_CALLBACK (on_modem_removed), self, NULL); + } + + if (!priv->subscribed) + { + DBusConnection *bus = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + + /* Pre-subscribe to all interesting signals */ + + if (bus) + { + priv->subscribed = 1; + + dbus_bus_add_match (bus, + "type='signal'," + "sender='org.ofono'," + "interface='org.ofono.Modem'," + "member='PropertyChanged'", + NULL); + dbus_bus_add_match (bus, + "type='signal'," + "sender='org.ofono'," + "interface='org.ofono.SimManager'," + "member='PropertyChanged'", + NULL); + dbus_bus_add_match (bus, + "type='signal'," + "sender='org.ofono'," + "interface='org.ofono.MessageManager'," + "member='PropertyChanged'", + NULL); + dbus_bus_add_match (bus, + "type='signal'," + "sender='org.ofono'," + "interface='org.ofono.MessageManager'," + "member='MessageAdded'", + NULL); + dbus_bus_add_match (bus, + "type='signal'," + "sender='org.ofono'," + "interface='org.ofono.MessageManager'," + "member='MessageRemoved'", + NULL); + dbus_bus_add_match (bus, + "type='signal'," + "sender='org.ofono'," + "interface='org.ofono.VoiceCallManager'," + "member='PropertyChanged'", + NULL); + dbus_bus_add_match (bus, + "type='signal'," + "sender='org.ofono'," + "interface='org.ofono.VoiceCallManager'," + "member='CallAdded'", + NULL); + dbus_bus_add_match (bus, + "type='signal'," + "sender='org.ofono'," + "interface='org.ofono.VoiceCallManager'," + "member='CallRemoved'", + NULL); + } + } + + if (priv->refresh) return; - priv->modem = modem_ofono_proxy(object_path, OFONO_IFACE_MODEM); - - modem_ofono_proxy_connect_to_property_changed(priv->modem, - on_modem_property_changed, self); - - value = g_hash_table_lookup(properties, "Powered"); - if (value && !g_value_get_boolean(value)) { - GValue v[1]; - g_value_init (memset (v, 0, sizeof v), G_TYPE_BOOLEAN); - g_value_set_boolean (v, TRUE); - - modem_ofono_proxy_set_property(priv->modem, - "Powered", v, - NULL, NULL, NULL); - } - - value = g_hash_table_lookup(properties, "Interfaces"); - if (value) - priv->interfaces = g_value_dup_boxed(value); - - value = g_hash_table_lookup(properties, "Online"); - if (value) { - priv->modem_online = g_value_get_boolean(value); - - modem_service_check_connected(self); - } + priv->refresh = modem_ofono_request_descs (self, + priv->proxy, "GetModems", + reply_to_get_modems, NULL); } static void -on_modem_removed(DBusGProxy *proxy, - char const *object_path, - gpointer userdata) +reply_to_get_modems (gpointer _self, + ModemRequest *request, + GPtrArray *modem_list, + GError const *error, + gpointer user_data) { - ModemService *self = userdata; + ModemService *self = MODEM_SERVICE (_self); ModemServicePrivate *priv = self->priv; + guint i; - DEBUG("ModemRemoved(%s)", object_path); + DEBUG ("enter"); - if (priv->modem == NULL) - return; + priv->refresh = NULL; - if (strcmp(object_path, dbus_g_proxy_get_path(priv->modem))) + if (error) return; - if (modem_service_is_connecting(self)) { - modem_ofono_proxy_disconnect_from_property_changed(priv->modem, - on_modem_property_changed, self); - g_object_run_dispose(G_OBJECT(priv->modem)); - priv->modem = NULL; - - if (priv->connecting.request) - return; - - /* Try another? */ - priv->connecting.request = modem_ofono_request_descs(self, - priv->proxy, "GetModems", - reply_to_get_modems, NULL); + for (i = 0; i < modem_list->len; i++) { + GValueArray *va = g_ptr_array_index (modem_list, i); + char const *path = g_value_get_boxed (va->values + 0); + GHashTable *properties = g_value_get_boxed (va->values + 1); - DEBUG("re-connecting"); + on_modem_added (priv->proxy, path, properties, self); } - else if (priv->connected) - modem_service_disconnect(self); } static void -modem_service_check_connected(ModemService *self) +on_modem_added (DBusGProxy *proxy, + char const *object_path, + GHashTable *properties, + gpointer userdata) { + ModemService *self = userdata; ModemServicePrivate *priv = self->priv; + Modem *modem; + GHashTableIter iter[1]; + char *name; + GValue *value; - if (priv->connected || priv->disconnected) - return; - - if (modem_service_is_connecting(self)) - return; - - int i; - for (i = 0; priv->interfaces[i]; i++) - if (!strcmp(priv->interfaces[i], OFONO_IFACE_SIM)) - break; - - if (priv->interfaces[i]) - priv->connected = TRUE; - else - modem_service_disconnect(self); - - g_signal_emit(self, signals[SIGNAL_CONNECTED], 0); -} - -gboolean -modem_service_is_connected(ModemService *self) -{ - return MODEM_IS_SERVICE(self) - && self->priv->connected - && !self->priv->connecting.error; -} - -gboolean -modem_service_is_connecting(ModemService *self) -{ - ModemServicePrivate *priv; - - if (!MODEM_IS_SERVICE(self)) - return FALSE; - - priv = self->priv; - - if (priv->connected || priv->disconnected) - return FALSE; - - if (priv->connecting.request) - return TRUE; - - if (!priv->modem) - return TRUE; - - if (!priv->modem_online) - return TRUE; - - if (!priv->interfaces) - return TRUE; - - return FALSE; -} + if (DEBUGGING) + modem_ofono_debug_desc ("ModemAdded", object_path, properties); -void -modem_service_disconnect(ModemService *self) -{ - ModemServicePrivate *priv = self->priv; - int was_connected; + modem = g_hash_table_lookup (priv->modems, object_path); + if (modem) + { + DEBUG ("Modem %s already has object %p", object_path, (void *)modem); + return; + } - if (priv->disconnected) + modem = g_object_new (MODEM_TYPE_MODEM, "object-path", object_path, NULL); + if (!modem) return; - DEBUG("enter"); - - was_connected = priv->connected; - priv->disconnected = TRUE; - priv->connected = FALSE; + for (g_hash_table_iter_init (iter, properties); + g_hash_table_iter_next (iter, (gpointer)&name, (gpointer)&value);) + { + char const *property = modem_property_name_by_ofono_name (name); - if (priv->signals) { - dbus_g_proxy_disconnect_signal(priv->proxy, "ModemAdded", - G_CALLBACK(on_modem_added), self); - dbus_g_proxy_disconnect_signal(priv->proxy, "ModemRemoved", - G_CALLBACK(on_modem_removed), self); + if (property) + g_object_set_property (G_OBJECT (modem), property, value); + } - priv->signals = FALSE; - } - - if (priv->modem) { - modem_ofono_proxy_disconnect_from_property_changed(priv->modem, - on_modem_property_changed, self); - } + g_hash_table_insert (priv->modems, g_strdup (object_path), modem); - if (was_connected) - g_signal_emit(self, signals[SIGNAL_CONNECTED], 0); -} - -char const * -modem_service_get_modem_path(ModemService *self) -{ - g_return_val_if_fail(MODEM_IS_SERVICE(self), NULL); - - if (!self->priv->modem) - return NULL; - - return dbus_g_proxy_get_path(self->priv->modem); -} - -gboolean -modem_service_supports_call(ModemService *self) -{ - g_return_val_if_fail(MODEM_IS_SERVICE(self), FALSE); - - ModemServicePrivate *priv = self->priv; - int i; - - if (priv->interfaces == NULL) - return FALSE; - - for (i = 0; priv->interfaces[i]; i++) - if (!strcmp(priv->interfaces[i], OFONO_IFACE_CALL_MANAGER)) - return TRUE; - - return FALSE; -} - -gboolean -modem_service_supports_sms(ModemService *self) -{ - g_return_val_if_fail(MODEM_IS_SERVICE(self), FALSE); - - ModemServicePrivate *priv = self->priv; - int i; - - if (priv->interfaces == NULL) - return FALSE; - - for (i = 0; priv->interfaces[i]; i++) - if (!strcmp(priv->interfaces[i], OFONO_IFACE_SMS)) - return TRUE; - - return FALSE; + g_signal_emit (self, signals[SIGNAL_MODEM_ADDED], 0, modem); } static void -on_modem_property_changed(DBusGProxy *proxy, - char const *property, - GValue const *value, - gpointer _self) +on_modem_removed (DBusGProxy *proxy, + char const *object_path, + gpointer userdata) { - ModemService *self = MODEM_SERVICE(_self); + ModemService *self = userdata; ModemServicePrivate *priv = self->priv; + Modem *modem; - if (!strcmp(property, "Interfaces")) { - g_strfreev(priv->interfaces); - priv->interfaces = g_value_dup_boxed(value); - modem_service_check_connected(self); - return; - } - - if (!strcmp(property, "Powered")) { - gboolean powered = g_value_get_boolean(value); + DEBUG ("ModemRemoved(%s)", object_path); - DEBUG("Powered = %d", powered); - if (!powered) - modem_service_disconnect(self); + modem = g_hash_table_lookup (priv->modems, object_path); + if (!modem) return; - } - if (!strcmp(property, "Online")) { - priv->modem_online = g_value_get_boolean(value); + g_signal_emit (self, signals[SIGNAL_MODEM_REMOVED], 0, modem); - modem_service_check_connected(self); - return; - } + g_hash_table_remove (priv->modems, object_path); } diff --git a/modem/service.h b/modem/service.h index 151335d..ee04ece 100644 --- a/modem/service.h +++ b/modem/service.h @@ -24,6 +24,8 @@ #include +#include + G_BEGIN_DECLS typedef struct _ModemService ModemService; @@ -55,17 +57,20 @@ GType modem_service_get_type(void); #define MODEM_SERVICE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), MODEM_TYPE_SERVICE, ModemServiceClass)) +/* + * Signals: + * modem-added (modem) + * modem-removed (modem) + */ + /* ---------------------------------------------------------------------- */ -gboolean modem_service_connect(ModemService *self); -gboolean modem_service_is_connected(ModemService *self); -gboolean modem_service_is_connecting(ModemService *self); -void modem_service_disconnect(ModemService *self); +ModemService *modem_service(void); -char const *modem_service_get_modem_path(ModemService *self); +void modem_service_refresh(ModemService *self); -gboolean modem_service_supports_call(ModemService *self); -gboolean modem_service_supports_sms(ModemService *self); +Modem *modem_service_find_modem(ModemService *self, char const *object_path); +Modem **modem_service_get_modems(ModemService *self); G_END_DECLS diff --git a/modem/signals-marshal.list b/modem/signals-marshal.list index 5027f8d..d3d6f95 100644 --- a/modem/signals-marshal.list +++ b/modem/signals-marshal.list @@ -2,6 +2,7 @@ VOID:INT,STRING,STRING VOID:STRING,BOXED VOID:STRING,STRING VOID:STRING,STRING,STRING +VOID:OBJECT VOID:OBJECT,STRING VOID:BOXED,BOXED VOID:BOXED -- cgit v1.2.3