diff options
author | Tambet Ingo <tambet@gmail.com> | 2009-04-14 11:42:00 +0300 |
---|---|---|
committer | Tambet Ingo <tambet@gmail.com> | 2009-04-14 11:43:26 +0300 |
commit | 8eb9fa50b40658d267da8763e7eef3680cad4b0b (patch) | |
tree | 00ceb2af7e02e5887d8771dacf3ec384f5cee2e2 /src | |
parent | b79a3c0a6533092a82da49bffc603fbd84536cf0 (diff) |
Handle cases where HAL is not running/disappears/reappears.
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 156 | ||||
-rw-r--r-- | src/mm-manager.c | 99 | ||||
-rw-r--r-- | src/mm-manager.h | 9 |
3 files changed, 206 insertions, 58 deletions
@@ -2,10 +2,15 @@ #include <signal.h> #include <syslog.h> +#include <string.h> #include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include <libhal.h> #include "mm-manager.h" #include "mm-options.h" +#define HAL_DBUS_SERVICE "org.freedesktop.Hal" + static void mm_signal_handler (int signo) { @@ -90,24 +95,14 @@ destroy_cb (DBusGProxy *proxy, gpointer user_data) g_main_loop_quit (loop); } -static gboolean -dbus_init (GMainLoop *loop) +static DBusGProxy * +create_dbus_proxy (DBusGConnection *bus) { - DBusGConnection *connection; DBusGProxy *proxy; GError *err = NULL; int request_name_result; - connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); - if (!connection) { - g_warning ("Could not get the system bus. Make sure " - "the message bus daemon is running! Message: %s", - err->message); - g_error_free (err); - return FALSE; - } - - proxy = dbus_g_proxy_new_for_name (connection, + proxy = dbus_g_proxy_new_for_name (bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); @@ -120,33 +115,117 @@ dbus_init (GMainLoop *loop) G_TYPE_INVALID)) { g_warning ("Could not acquire the %s service.\n" " Message: '%s'", MM_DBUS_SERVICE, err->message); - g_error_free (err); - goto err; - } - if (request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error_free (err); + g_object_unref (proxy); + proxy = NULL; + } else if (request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { g_warning ("Could not acquire the " MM_DBUS_SERVICE " service as it is already taken. Return: %d", request_name_result); - goto err; + + g_object_unref (proxy); + proxy = NULL; + } else { + dbus_g_proxy_add_signal (proxy, "NameOwnerChanged", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); } - g_signal_connect (proxy, "destroy", G_CALLBACK (destroy_cb), loop); + return proxy; +} + +static void +hal_init (MMManager *manager) +{ + LibHalContext *hal_ctx; + DBusError dbus_error; - return TRUE; + hal_ctx = libhal_ctx_new (); + if (!hal_ctx) { + g_warning ("Could not get connection to the HAL service."); + } - err: - dbus_g_connection_unref (connection); - g_object_unref (proxy); + libhal_ctx_set_dbus_connection (hal_ctx, dbus_g_connection_get_connection (mm_manager_get_bus (manager))); - return FALSE; + dbus_error_init (&dbus_error); + if (!libhal_ctx_init (hal_ctx, &dbus_error)) { + g_warning ("libhal_ctx_init() failed: %s", dbus_error.message); + dbus_error_free (&dbus_error); + } + + mm_manager_set_hal_ctx (manager, hal_ctx); +} + +static void +hal_deinit (MMManager *manager) +{ + LibHalContext *hal_ctx; + + hal_ctx = mm_manager_get_hal_ctx (manager); + if (hal_ctx) { + libhal_ctx_shutdown (hal_ctx, NULL); + libhal_ctx_free (hal_ctx); + mm_manager_set_hal_ctx (manager, NULL); + } +} + +static gboolean +hal_on_bus (DBusGProxy *proxy) +{ + GError *err = NULL; + gboolean has_owner = FALSE; + + if (!dbus_g_proxy_call (proxy, + "NameHasOwner", &err, + G_TYPE_STRING, HAL_DBUS_SERVICE, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &has_owner, + G_TYPE_INVALID)) { + g_warning ("Error on NameHasOwner DBUS call: %s", err->message); + g_error_free (err); + } + + return has_owner; +} + +static void +name_owner_changed (DBusGProxy *proxy, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + MMManager *manager; + gboolean old_owner_good; + gboolean new_owner_good; + + /* Only care about signals from HAL */ + if (strcmp (name, HAL_DBUS_SERVICE)) + return; + + manager = MM_MANAGER (user_data); + old_owner_good = (old_owner && (strlen (old_owner) > 0)); + new_owner_good = (new_owner && (strlen (new_owner) > 0)); + + if (!old_owner_good && new_owner_good) { + g_message ("HAL appeared"); + hal_init (manager); + } else if (old_owner_good && !new_owner_good) { + /* HAL went away. Bad HAL. */ + g_message ("HAL disappeared"); + hal_deinit (manager); + } } int main (int argc, char *argv[]) { + DBusGConnection *bus; + DBusGProxy *proxy; GMainLoop *loop; MMManager *manager; + GError *err = NULL; mm_options_parse (argc, argv); g_type_init (); @@ -156,16 +235,39 @@ main (int argc, char *argv[]) if (!mm_options_debug ()) logging_setup (); - loop = g_main_loop_new (NULL, FALSE); + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); + if (!bus) { + g_warning ("Could not get the system bus. Make sure " + "the message bus daemon is running! Message: %s", + err->message); + g_error_free (err); + return -1; + } - if (!dbus_init (loop)) + proxy = create_dbus_proxy (bus); + if (!proxy) return -1; - manager = mm_manager_new (); + manager = mm_manager_new (bus); + + dbus_g_proxy_connect_signal (proxy, + "NameOwnerChanged", + G_CALLBACK (name_owner_changed), + manager, NULL); + + if (hal_on_bus (proxy)) + hal_init (manager); + + loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (proxy, "destroy", G_CALLBACK (destroy_cb), loop); g_main_loop_run (loop); + hal_deinit (manager); g_object_unref (manager); + g_object_unref (proxy); + dbus_g_connection_unref (bus); + logging_shutdown (); return 0; diff --git a/src/mm-manager.c b/src/mm-manager.c index 35fcd533..a19c9446 100644 --- a/src/mm-manager.c +++ b/src/mm-manager.c @@ -2,7 +2,6 @@ #include <string.h> #include <gmodule.h> -#include <libhal.h> #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-lowlevel.h> #include "mm-manager.h" @@ -129,9 +128,23 @@ load_plugins (MMManager *manager) } MMManager * -mm_manager_new (void) +mm_manager_new (DBusGConnection *bus) { - return g_object_new (MM_TYPE_MANAGER, NULL); + MMManager *manager; + + g_return_val_if_fail (bus != NULL, NULL); + + manager = (MMManager *) g_object_new (MM_TYPE_MANAGER, NULL); + if (manager) { + MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager); + + priv->connection = bus; + dbus_g_connection_register_g_object (priv->connection, + MM_DBUS_PATH, + G_OBJECT (manager)); + } + + return manager; } static char * @@ -362,43 +375,68 @@ device_new_capability (LibHalContext *ctx, const char *udi, const char *capabili device_added (ctx, udi); } -static void -mm_manager_init (MMManager *manager) + +DBusGConnection * +mm_manager_get_bus (MMManager *manager) { - MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager); - GError *err = NULL; - DBusError dbus_error; + g_return_val_if_fail (MM_IS_MANAGER (manager), NULL); - priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + return MM_MANAGER_GET_PRIVATE (manager)->connection; +} - priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); - if (!priv->connection) - g_error ("Could not connect to system bus."); +static gboolean +remove_one (gpointer key, + gpointer value, + gpointer user_data) +{ + const char *udi = (char *) key; + MMModem *modem = MM_MODEM (value); + MMManager *manager = MM_MANAGER (user_data); - dbus_g_connection_register_g_object (priv->connection, - MM_DBUS_PATH, - G_OBJECT (manager)); + g_debug ("Removed modem %s", udi); + g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem); - priv->hal_ctx = libhal_ctx_new (); - if (!priv->hal_ctx) - g_error ("Could not get connection to the HAL service."); + return TRUE; +} - libhal_ctx_set_dbus_connection (priv->hal_ctx, dbus_g_connection_get_connection (priv->connection)); +void +mm_manager_set_hal_ctx (MMManager *manager, + LibHalContext *hal_ctx) +{ + MMManagerPrivate *priv; - dbus_error_init (&dbus_error); - if (!libhal_ctx_init (priv->hal_ctx, &dbus_error)) - g_error ("libhal_ctx_init() failed: %s\n" - "Make sure the hal daemon is running?", - dbus_error.message); + g_return_if_fail (MM_IS_MANAGER (manager)); - load_plugins (manager); + priv = MM_MANAGER_GET_PRIVATE (manager); + priv->hal_ctx = hal_ctx; + + if (hal_ctx) { + libhal_ctx_set_user_data (hal_ctx, manager); + libhal_ctx_set_device_added (hal_ctx, device_added); + libhal_ctx_set_device_removed (hal_ctx, device_removed); + libhal_ctx_set_device_new_capability (hal_ctx, device_new_capability); + + create_initial_modems (manager); + } else { + g_hash_table_foreach_remove (priv->modems, remove_one, manager); + } +} + +LibHalContext * +mm_manager_get_hal_ctx (MMManager *manager) +{ + g_return_val_if_fail (MM_IS_MANAGER (manager), NULL); - libhal_ctx_set_user_data (priv->hal_ctx, manager); - libhal_ctx_set_device_added (priv->hal_ctx, device_added); - libhal_ctx_set_device_removed (priv->hal_ctx, device_removed); - libhal_ctx_set_device_new_capability (priv->hal_ctx, device_new_capability); + return MM_MANAGER_GET_PRIVATE (manager)->hal_ctx; +} - create_initial_modems (manager); +static void +mm_manager_init (MMManager *manager) +{ + MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager); + + priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + load_plugins (manager); } static void @@ -412,6 +450,7 @@ finalize (GObject *object) g_slist_free (priv->plugins); if (priv->hal_ctx) { + mm_manager_set_hal_ctx (MM_MANAGER (object), NULL); libhal_ctx_shutdown (priv->hal_ctx, NULL); libhal_ctx_free (priv->hal_ctx); } diff --git a/src/mm-manager.h b/src/mm-manager.h index ecb7f408..4426d0f1 100644 --- a/src/mm-manager.h +++ b/src/mm-manager.h @@ -5,6 +5,8 @@ #include <glib/gtypes.h> #include <glib-object.h> +#include <dbus/dbus-glib.h> +#include <libhal.h> #include "mm-modem.h" #define MM_TYPE_MANAGER (mm_manager_get_type ()) @@ -31,6 +33,11 @@ typedef struct { GType mm_manager_get_type (void); -MMManager *mm_manager_new (void); +MMManager *mm_manager_new (DBusGConnection *bus); +DBusGConnection *mm_manager_get_bus (MMManager *manager); +void mm_manager_set_hal_ctx (MMManager *manager, + LibHalContext *hal_ctx); + +LibHalContext *mm_manager_get_hal_ctx (MMManager *manager); #endif /* MM_MANAGER_H */ |