aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTambet Ingo <tambet@gmail.com>2009-04-14 11:42:00 +0300
committerTambet Ingo <tambet@gmail.com>2009-04-14 11:43:26 +0300
commit8eb9fa50b40658d267da8763e7eef3680cad4b0b (patch)
tree00ceb2af7e02e5887d8771dacf3ec384f5cee2e2 /src
parentb79a3c0a6533092a82da49bffc603fbd84536cf0 (diff)
Handle cases where HAL is not running/disappears/reappears.
Diffstat (limited to 'src')
-rw-r--r--src/main.c156
-rw-r--r--src/mm-manager.c99
-rw-r--r--src/mm-manager.h9
3 files changed, 206 insertions, 58 deletions
diff --git a/src/main.c b/src/main.c
index 854166ab..629b10ed 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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 */