Handle cases where HAL is not running/disappears/reappears.
This commit is contained in:
156
src/main.c
156
src/main.c
@@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <string.h>
|
||||||
#include <dbus/dbus-glib.h>
|
#include <dbus/dbus-glib.h>
|
||||||
|
#include <dbus/dbus-glib-lowlevel.h>
|
||||||
|
#include <libhal.h>
|
||||||
#include "mm-manager.h"
|
#include "mm-manager.h"
|
||||||
#include "mm-options.h"
|
#include "mm-options.h"
|
||||||
|
|
||||||
|
#define HAL_DBUS_SERVICE "org.freedesktop.Hal"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mm_signal_handler (int signo)
|
mm_signal_handler (int signo)
|
||||||
{
|
{
|
||||||
@@ -90,24 +95,14 @@ destroy_cb (DBusGProxy *proxy, gpointer user_data)
|
|||||||
g_main_loop_quit (loop);
|
g_main_loop_quit (loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static DBusGProxy *
|
||||||
dbus_init (GMainLoop *loop)
|
create_dbus_proxy (DBusGConnection *bus)
|
||||||
{
|
{
|
||||||
DBusGConnection *connection;
|
|
||||||
DBusGProxy *proxy;
|
DBusGProxy *proxy;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
int request_name_result;
|
int request_name_result;
|
||||||
|
|
||||||
connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
|
proxy = dbus_g_proxy_new_for_name (bus,
|
||||||
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,
|
|
||||||
"org.freedesktop.DBus",
|
"org.freedesktop.DBus",
|
||||||
"/org/freedesktop/DBus",
|
"/org/freedesktop/DBus",
|
||||||
"org.freedesktop.DBus");
|
"org.freedesktop.DBus");
|
||||||
@@ -120,33 +115,117 @@ dbus_init (GMainLoop *loop)
|
|||||||
G_TYPE_INVALID)) {
|
G_TYPE_INVALID)) {
|
||||||
g_warning ("Could not acquire the %s service.\n"
|
g_warning ("Could not acquire the %s service.\n"
|
||||||
" Message: '%s'", MM_DBUS_SERVICE, err->message);
|
" 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
|
g_warning ("Could not acquire the " MM_DBUS_SERVICE
|
||||||
" service as it is already taken. Return: %d",
|
" service as it is already taken. Return: %d",
|
||||||
request_name_result);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
static void
|
||||||
|
hal_init (MMManager *manager)
|
||||||
|
{
|
||||||
|
LibHalContext *hal_ctx;
|
||||||
|
DBusError dbus_error;
|
||||||
|
|
||||||
err:
|
hal_ctx = libhal_ctx_new ();
|
||||||
dbus_g_connection_unref (connection);
|
if (!hal_ctx) {
|
||||||
g_object_unref (proxy);
|
g_warning ("Could not get connection to the HAL service.");
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
libhal_ctx_set_dbus_connection (hal_ctx, dbus_g_connection_get_connection (mm_manager_get_bus (manager)));
|
||||||
|
|
||||||
|
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
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
DBusGConnection *bus;
|
||||||
|
DBusGProxy *proxy;
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
MMManager *manager;
|
MMManager *manager;
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
mm_options_parse (argc, argv);
|
mm_options_parse (argc, argv);
|
||||||
g_type_init ();
|
g_type_init ();
|
||||||
@@ -156,16 +235,39 @@ main (int argc, char *argv[])
|
|||||||
if (!mm_options_debug ())
|
if (!mm_options_debug ())
|
||||||
logging_setup ();
|
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;
|
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);
|
g_main_loop_run (loop);
|
||||||
|
|
||||||
|
hal_deinit (manager);
|
||||||
g_object_unref (manager);
|
g_object_unref (manager);
|
||||||
|
g_object_unref (proxy);
|
||||||
|
dbus_g_connection_unref (bus);
|
||||||
|
|
||||||
logging_shutdown ();
|
logging_shutdown ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
105
src/mm-manager.c
105
src/mm-manager.c
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
#include <libhal.h>
|
|
||||||
#include <dbus/dbus-glib.h>
|
#include <dbus/dbus-glib.h>
|
||||||
#include <dbus/dbus-glib-lowlevel.h>
|
#include <dbus/dbus-glib-lowlevel.h>
|
||||||
#include "mm-manager.h"
|
#include "mm-manager.h"
|
||||||
@@ -129,9 +128,23 @@ load_plugins (MMManager *manager)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MMManager *
|
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 *
|
static char *
|
||||||
@@ -362,43 +375,68 @@ device_new_capability (LibHalContext *ctx, const char *udi, const char *capabili
|
|||||||
device_added (ctx, udi);
|
device_added (ctx, udi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DBusGConnection *
|
||||||
|
mm_manager_get_bus (MMManager *manager)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MM_IS_MANAGER (manager), NULL);
|
||||||
|
|
||||||
|
return MM_MANAGER_GET_PRIVATE (manager)->connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
g_debug ("Removed modem %s", udi);
|
||||||
|
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mm_manager_set_hal_ctx (MMManager *manager,
|
||||||
|
LibHalContext *hal_ctx)
|
||||||
|
{
|
||||||
|
MMManagerPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (MM_IS_MANAGER (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);
|
||||||
|
|
||||||
|
return MM_MANAGER_GET_PRIVATE (manager)->hal_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mm_manager_init (MMManager *manager)
|
mm_manager_init (MMManager *manager)
|
||||||
{
|
{
|
||||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||||
GError *err = NULL;
|
|
||||||
DBusError dbus_error;
|
|
||||||
|
|
||||||
priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||||
|
|
||||||
priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
|
|
||||||
if (!priv->connection)
|
|
||||||
g_error ("Could not connect to system bus.");
|
|
||||||
|
|
||||||
dbus_g_connection_register_g_object (priv->connection,
|
|
||||||
MM_DBUS_PATH,
|
|
||||||
G_OBJECT (manager));
|
|
||||||
|
|
||||||
priv->hal_ctx = libhal_ctx_new ();
|
|
||||||
if (!priv->hal_ctx)
|
|
||||||
g_error ("Could not get connection to the HAL service.");
|
|
||||||
|
|
||||||
libhal_ctx_set_dbus_connection (priv->hal_ctx, dbus_g_connection_get_connection (priv->connection));
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
load_plugins (manager);
|
load_plugins (manager);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
create_initial_modems (manager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -412,6 +450,7 @@ finalize (GObject *object)
|
|||||||
g_slist_free (priv->plugins);
|
g_slist_free (priv->plugins);
|
||||||
|
|
||||||
if (priv->hal_ctx) {
|
if (priv->hal_ctx) {
|
||||||
|
mm_manager_set_hal_ctx (MM_MANAGER (object), NULL);
|
||||||
libhal_ctx_shutdown (priv->hal_ctx, NULL);
|
libhal_ctx_shutdown (priv->hal_ctx, NULL);
|
||||||
libhal_ctx_free (priv->hal_ctx);
|
libhal_ctx_free (priv->hal_ctx);
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <glib/gtypes.h>
|
#include <glib/gtypes.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <dbus/dbus-glib.h>
|
||||||
|
#include <libhal.h>
|
||||||
#include "mm-modem.h"
|
#include "mm-modem.h"
|
||||||
|
|
||||||
#define MM_TYPE_MANAGER (mm_manager_get_type ())
|
#define MM_TYPE_MANAGER (mm_manager_get_type ())
|
||||||
@@ -31,6 +33,11 @@ typedef struct {
|
|||||||
|
|
||||||
GType mm_manager_get_type (void);
|
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 */
|
#endif /* MM_MANAGER_H */
|
||||||
|
Reference in New Issue
Block a user