674 lines
20 KiB
C
674 lines
20 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details:
|
|
*
|
|
* Copyright (C) 2008 - 2009 Novell, Inc.
|
|
* Copyright (C) 2009 Red Hat, Inc.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <gmodule.h>
|
|
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
|
|
#include <gudev/gudev.h>
|
|
#include <dbus/dbus-glib.h>
|
|
#include <dbus/dbus-glib-lowlevel.h>
|
|
#include "mm-manager.h"
|
|
#include "mm-errors.h"
|
|
#include "mm-plugin.h"
|
|
|
|
static gboolean impl_manager_enumerate_devices (MMManager *manager,
|
|
GPtrArray **devices,
|
|
GError **err);
|
|
|
|
#include "mm-manager-glue.h"
|
|
|
|
G_DEFINE_TYPE (MMManager, mm_manager, G_TYPE_OBJECT)
|
|
|
|
enum {
|
|
DEVICE_ADDED,
|
|
DEVICE_REMOVED,
|
|
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
#define MM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MANAGER, MMManagerPrivate))
|
|
|
|
#define DBUS_PATH_TAG "dbus-path"
|
|
|
|
typedef struct {
|
|
DBusGConnection *connection;
|
|
GUdevClient *udev;
|
|
GSList *plugins;
|
|
GHashTable *modems;
|
|
|
|
GHashTable *supports;
|
|
} MMManagerPrivate;
|
|
|
|
static MMPlugin *
|
|
load_plugin (const char *path)
|
|
{
|
|
MMPlugin *plugin = NULL;
|
|
GModule *module;
|
|
MMPluginCreateFunc plugin_create_func;
|
|
int *major_plugin_version, *minor_plugin_version;
|
|
|
|
module = g_module_open (path, G_MODULE_BIND_LAZY);
|
|
if (!module) {
|
|
g_warning ("Could not load plugin %s: %s", path, g_module_error ());
|
|
return NULL;
|
|
}
|
|
|
|
if (!g_module_symbol (module, "mm_plugin_major_version", (gpointer *) &major_plugin_version)) {
|
|
g_warning ("Could not load plugin %s: Missing major version info", path);
|
|
goto out;
|
|
}
|
|
|
|
if (*major_plugin_version != MM_PLUGIN_MAJOR_VERSION) {
|
|
g_warning ("Could not load plugin %s: Plugin major version %d, %d is required",
|
|
path, *major_plugin_version, MM_PLUGIN_MAJOR_VERSION);
|
|
goto out;
|
|
}
|
|
|
|
if (!g_module_symbol (module, "mm_plugin_minor_version", (gpointer *) &minor_plugin_version)) {
|
|
g_warning ("Could not load plugin %s: Missing minor version info", path);
|
|
goto out;
|
|
}
|
|
|
|
if (*minor_plugin_version != MM_PLUGIN_MINOR_VERSION) {
|
|
g_warning ("Could not load plugin %s: Plugin minor version %d, %d is required",
|
|
path, *minor_plugin_version, MM_PLUGIN_MINOR_VERSION);
|
|
goto out;
|
|
}
|
|
|
|
if (!g_module_symbol (module, "mm_plugin_create", (gpointer *) &plugin_create_func)) {
|
|
g_warning ("Could not load plugin %s: %s", path, g_module_error ());
|
|
goto out;
|
|
}
|
|
|
|
plugin = (*plugin_create_func) ();
|
|
if (plugin) {
|
|
g_object_weak_ref (G_OBJECT (plugin), (GWeakNotify) g_module_close, module);
|
|
g_message ("Loaded plugin %s", mm_plugin_get_name (plugin));
|
|
} else
|
|
g_warning ("Could not load plugin %s: initialization failed", path);
|
|
|
|
out:
|
|
if (!plugin)
|
|
g_module_close (module);
|
|
|
|
return plugin;
|
|
}
|
|
|
|
static void
|
|
load_plugins (MMManager *manager)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
GDir *dir;
|
|
const char *fname;
|
|
MMPlugin *generic_plugin = NULL;
|
|
|
|
if (!g_module_supported ()) {
|
|
g_warning ("GModules are not supported on your platform!");
|
|
return;
|
|
}
|
|
|
|
dir = g_dir_open (PLUGINDIR, 0, NULL);
|
|
if (!dir) {
|
|
g_warning ("No plugins found");
|
|
return;
|
|
}
|
|
|
|
while ((fname = g_dir_read_name (dir)) != NULL) {
|
|
char *path;
|
|
MMPlugin *plugin;
|
|
|
|
if (!g_str_has_suffix (fname, G_MODULE_SUFFIX))
|
|
continue;
|
|
|
|
path = g_module_build_path (PLUGINDIR, fname);
|
|
plugin = load_plugin (path);
|
|
g_free (path);
|
|
|
|
if (plugin) {
|
|
if (!strcmp (mm_plugin_get_name (plugin), MM_PLUGIN_GENERIC_NAME))
|
|
generic_plugin = plugin;
|
|
else
|
|
priv->plugins = g_slist_append (priv->plugins, plugin);
|
|
}
|
|
}
|
|
|
|
/* Make sure the generic plugin is last */
|
|
if (generic_plugin)
|
|
priv->plugins = g_slist_append (priv->plugins, generic_plugin);
|
|
|
|
g_dir_close (dir);
|
|
}
|
|
|
|
MMManager *
|
|
mm_manager_new (DBusGConnection *bus)
|
|
{
|
|
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 = dbus_g_connection_ref (bus);
|
|
dbus_g_connection_register_g_object (priv->connection,
|
|
MM_DBUS_PATH,
|
|
G_OBJECT (manager));
|
|
}
|
|
|
|
return manager;
|
|
}
|
|
|
|
static void
|
|
remove_modem (MMManager *manager, MMModem *modem)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
char *device;
|
|
|
|
device = mm_modem_get_device (modem);
|
|
g_assert (device);
|
|
g_debug ("Removed modem %s", device);
|
|
|
|
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, modem);
|
|
g_hash_table_remove (priv->modems, device);
|
|
g_free (device);
|
|
}
|
|
|
|
static void
|
|
modem_valid (MMModem *modem, GParamSpec *pspec, gpointer user_data)
|
|
{
|
|
MMManager *manager = MM_MANAGER (user_data);
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
static guint32 id = 0;
|
|
char *path, *device;
|
|
|
|
if (mm_modem_get_valid (modem)) {
|
|
path = g_strdup_printf (MM_DBUS_PATH"/Modems/%d", id++);
|
|
dbus_g_connection_register_g_object (priv->connection, path, G_OBJECT (modem));
|
|
g_object_set_data_full (G_OBJECT (modem), DBUS_PATH_TAG, path, (GDestroyNotify) g_free);
|
|
|
|
device = mm_modem_get_device (modem);
|
|
g_assert (device);
|
|
g_debug ("Exported modem %s as %s", device, path);
|
|
g_free (device);
|
|
|
|
g_signal_emit (manager, signals[DEVICE_ADDED], 0, modem);
|
|
} else
|
|
remove_modem (manager, modem);
|
|
}
|
|
|
|
static void
|
|
add_modem (MMManager *manager, MMModem *modem)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
char *device;
|
|
gboolean valid = FALSE;
|
|
|
|
device = mm_modem_get_device (modem);
|
|
g_assert (device);
|
|
if (!g_hash_table_lookup (priv->modems, device)) {
|
|
g_hash_table_insert (priv->modems, g_strdup (device), modem);
|
|
g_debug ("Added modem %s", device);
|
|
g_signal_connect (modem, "notify::valid", G_CALLBACK (modem_valid), manager);
|
|
g_object_get (modem, MM_MODEM_VALID, &valid, NULL);
|
|
if (valid)
|
|
modem_valid (modem, NULL, manager);
|
|
}
|
|
g_free (device);
|
|
}
|
|
|
|
static void
|
|
enumerate_devices_cb (gpointer key, gpointer val, gpointer user_data)
|
|
{
|
|
MMModem *modem = MM_MODEM (val);
|
|
GPtrArray **devices = (GPtrArray **) user_data;
|
|
const char *path;
|
|
gboolean valid = FALSE;
|
|
|
|
g_object_get (G_OBJECT (modem), MM_MODEM_VALID, &valid, NULL);
|
|
if (valid) {
|
|
path = g_object_get_data (G_OBJECT (modem), DBUS_PATH_TAG);
|
|
g_return_if_fail (path != NULL);
|
|
g_ptr_array_add (*devices, g_strdup (path));
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
impl_manager_enumerate_devices (MMManager *manager,
|
|
GPtrArray **devices,
|
|
GError **err)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
*devices = g_ptr_array_sized_new (g_hash_table_size (priv->modems));
|
|
g_hash_table_foreach (priv->modems, enumerate_devices_cb, devices);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static MMModem *
|
|
find_modem_for_port (MMManager *manager, const char *subsys, const char *name)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
GHashTableIter iter;
|
|
gpointer key, value;
|
|
|
|
g_hash_table_iter_init (&iter, priv->modems);
|
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
MMModem *modem = MM_MODEM (value);
|
|
|
|
if (mm_modem_owns_port (modem, subsys, name))
|
|
return modem;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
typedef struct {
|
|
MMManager *manager;
|
|
char *subsys;
|
|
char *name;
|
|
GSList *plugins;
|
|
GSList *cur_plugin;
|
|
guint defer_id;
|
|
guint done_id;
|
|
|
|
guint32 best_level;
|
|
MMPlugin *best_plugin;
|
|
} SupportsInfo;
|
|
|
|
static SupportsInfo *
|
|
supports_info_new (MMManager *self, const char *subsys, const char *name)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (self);
|
|
SupportsInfo *info;
|
|
|
|
info = g_malloc0 (sizeof (SupportsInfo));
|
|
info->manager = self;
|
|
info->subsys = g_strdup (subsys);
|
|
info->name = g_strdup (name);
|
|
info->plugins = g_slist_copy (priv->plugins);
|
|
info->cur_plugin = info->plugins;
|
|
return info;
|
|
}
|
|
|
|
static void
|
|
supports_info_free (SupportsInfo *info)
|
|
{
|
|
/* Cancel any in-process operation on the first plugin */
|
|
if (info->cur_plugin)
|
|
mm_plugin_cancel_supports_port (MM_PLUGIN (info->cur_plugin->data), info->subsys, info->name);
|
|
|
|
if (info->defer_id)
|
|
g_source_remove (info->defer_id);
|
|
|
|
if (info->done_id)
|
|
g_source_remove (info->done_id);
|
|
|
|
g_free (info->subsys);
|
|
g_free (info->name);
|
|
g_slist_free (info->plugins);
|
|
memset (info, 0, sizeof (SupportsInfo));
|
|
g_free (info);
|
|
}
|
|
|
|
static char *
|
|
get_key (const char *subsys, const char *name)
|
|
{
|
|
return g_strdup_printf ("%s%s", subsys, name);
|
|
}
|
|
|
|
|
|
static void supports_callback (MMPlugin *plugin,
|
|
const char *subsys,
|
|
const char *name,
|
|
guint32 level,
|
|
gpointer user_data);
|
|
|
|
static void try_supports_port (MMManager *manager,
|
|
MMPlugin *plugin,
|
|
const char *subsys,
|
|
const char *name,
|
|
SupportsInfo *info);
|
|
|
|
static gboolean
|
|
supports_defer_timeout (gpointer user_data)
|
|
{
|
|
SupportsInfo *info = user_data;
|
|
|
|
g_debug ("(%s): re-checking support...", info->name);
|
|
try_supports_port (info->manager,
|
|
MM_PLUGIN (info->cur_plugin->data),
|
|
info->subsys,
|
|
info->name,
|
|
info);
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
try_supports_port (MMManager *manager,
|
|
MMPlugin *plugin,
|
|
const char *subsys,
|
|
const char *name,
|
|
SupportsInfo *info)
|
|
{
|
|
MMPluginSupportsResult result;
|
|
|
|
result = mm_plugin_supports_port (plugin, subsys, name, supports_callback, info);
|
|
|
|
switch (result) {
|
|
case MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED:
|
|
/* If the plugin knows it doesn't support the modem, just call the
|
|
* callback and indicate 0 support.
|
|
*/
|
|
supports_callback (plugin, subsys, name, 0, info);
|
|
break;
|
|
case MM_PLUGIN_SUPPORTS_PORT_DEFER:
|
|
g_debug ("(%s): (%s) deferring support check", mm_plugin_get_name (plugin), name);
|
|
if (info->defer_id)
|
|
g_source_remove (info->defer_id);
|
|
|
|
/* defer port detection for a bit as requested by the plugin */
|
|
info->defer_id = g_timeout_add (3000, supports_defer_timeout, info);
|
|
break;
|
|
case MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
do_grab_port (gpointer user_data)
|
|
{
|
|
SupportsInfo *info = user_data;
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (info->manager);
|
|
MMModem *modem;
|
|
GError *error = NULL;
|
|
char *key;
|
|
GSList *iter;
|
|
|
|
/* No more plugins to try */
|
|
if (info->best_plugin) {
|
|
/* Create the modem */
|
|
modem = mm_plugin_grab_port (info->best_plugin, info->subsys, info->name, &error);
|
|
if (modem) {
|
|
guint32 modem_type = MM_MODEM_TYPE_UNKNOWN;
|
|
const char *type_name = "UNKNOWN";
|
|
|
|
g_object_get (G_OBJECT (modem), MM_MODEM_TYPE, &modem_type, NULL);
|
|
if (modem_type == MM_MODEM_TYPE_GSM)
|
|
type_name = "GSM";
|
|
else if (modem_type == MM_MODEM_TYPE_CDMA)
|
|
type_name = "CDMA";
|
|
|
|
g_message ("(%s): %s modem %s claimed port %s",
|
|
mm_plugin_get_name (info->best_plugin),
|
|
type_name,
|
|
mm_modem_get_device (modem),
|
|
info->name);
|
|
|
|
add_modem (info->manager, modem);
|
|
} else {
|
|
g_warning ("%s: plugin '%s' claimed to support %s/%s but couldn't: (%d) %s",
|
|
__func__,
|
|
mm_plugin_get_name (info->best_plugin),
|
|
info->subsys,
|
|
info->name,
|
|
error ? error->code : -1,
|
|
(error && error->message) ? error->message : "(unknown)");
|
|
}
|
|
}
|
|
|
|
/* Tell each plugin to clean up any outstanding supports task */
|
|
for (iter = info->plugins; iter; iter = g_slist_next (iter))
|
|
mm_plugin_cancel_supports_port (MM_PLUGIN (iter->data), info->subsys, info->name);
|
|
g_slist_free (info->plugins);
|
|
info->cur_plugin = info->plugins = NULL;
|
|
|
|
key = get_key (info->subsys, info->name);
|
|
g_hash_table_remove (priv->supports, key);
|
|
g_free (key);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
supports_callback (MMPlugin *plugin,
|
|
const char *subsys,
|
|
const char *name,
|
|
guint32 level,
|
|
gpointer user_data)
|
|
{
|
|
SupportsInfo *info = user_data;
|
|
MMPlugin *next_plugin = NULL;
|
|
|
|
info->cur_plugin = info->cur_plugin->next;
|
|
if (info->cur_plugin)
|
|
next_plugin = MM_PLUGIN (info->cur_plugin->data);
|
|
|
|
/* Is this plugin's result better than any one we've tried before? */
|
|
if (level > info->best_level) {
|
|
info->best_level = level;
|
|
info->best_plugin = plugin;
|
|
}
|
|
|
|
/* Prevent the generic plugin from probing devices that are already supported
|
|
* by other plugins. For Huawei for example, secondary ports shouldn't
|
|
* be probed, but the generic plugin would happily do so if allowed to.
|
|
*/
|
|
if ( next_plugin
|
|
&& !strcmp (mm_plugin_get_name (next_plugin), MM_PLUGIN_GENERIC_NAME)
|
|
&& info->best_plugin)
|
|
next_plugin = NULL;
|
|
|
|
if (next_plugin) {
|
|
/* Try the next plugin */
|
|
try_supports_port (info->manager, next_plugin, info->subsys, info->name, info);
|
|
} else {
|
|
/* All done; let the best modem grab the port */
|
|
info->done_id = g_idle_add (do_grab_port, info);
|
|
}
|
|
}
|
|
|
|
static void
|
|
device_added (MMManager *manager, GUdevDevice *device)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
const char *subsys, *name;
|
|
SupportsInfo *info;
|
|
char *key;
|
|
gboolean found;
|
|
|
|
g_return_if_fail (device != NULL);
|
|
|
|
if (!g_slist_length (priv->plugins))
|
|
return;
|
|
|
|
subsys = g_udev_device_get_subsystem (device);
|
|
name = g_udev_device_get_name (device);
|
|
|
|
if (find_modem_for_port (manager, subsys, name))
|
|
return;
|
|
|
|
key = get_key (subsys, name);
|
|
found = !!g_hash_table_lookup (priv->supports, key);
|
|
if (found) {
|
|
g_free (key);
|
|
return;
|
|
}
|
|
|
|
info = supports_info_new (manager, subsys, name);
|
|
g_hash_table_insert (priv->supports, key, info);
|
|
|
|
try_supports_port (manager, MM_PLUGIN (info->cur_plugin->data), subsys, name, info);
|
|
}
|
|
|
|
static void
|
|
device_removed (MMManager *manager, GUdevDevice *device)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
MMModem *modem;
|
|
const char *subsys, *name;
|
|
char *key;
|
|
SupportsInfo *info;
|
|
|
|
g_return_if_fail (device != NULL);
|
|
|
|
if (!g_slist_length (priv->plugins))
|
|
return;
|
|
|
|
subsys = g_udev_device_get_subsystem (device);
|
|
name = g_udev_device_get_name (device);
|
|
modem = find_modem_for_port (manager, subsys, name);
|
|
if (modem) {
|
|
mm_modem_release_port (modem, subsys, name);
|
|
return;
|
|
}
|
|
|
|
/* Maybe a plugin is checking whether or not the port is supported */
|
|
key = get_key (subsys, name);
|
|
info = g_hash_table_lookup (priv->supports, key);
|
|
|
|
if (info) {
|
|
if (info->plugins)
|
|
mm_plugin_cancel_supports_port (MM_PLUGIN (info->plugins->data), subsys, name);
|
|
g_hash_table_remove (priv->supports, key);
|
|
}
|
|
|
|
g_free (key);
|
|
}
|
|
|
|
static void
|
|
handle_uevent (GUdevClient *client,
|
|
const char *action,
|
|
GUdevDevice *device,
|
|
gpointer user_data)
|
|
{
|
|
MMManager *self = MM_MANAGER (user_data);
|
|
const char *subsys;
|
|
|
|
g_return_if_fail (action != NULL);
|
|
|
|
/* A bit paranoid */
|
|
subsys = g_udev_device_get_subsystem (device);
|
|
g_return_if_fail (subsys != NULL);
|
|
|
|
g_return_if_fail (!strcmp (subsys, "tty") || !strcmp (subsys, "net"));
|
|
|
|
if (!strcmp (action, "add"))
|
|
device_added (self, device);
|
|
else if (!strcmp (action, "remove"))
|
|
device_removed (self, device);
|
|
}
|
|
|
|
void
|
|
mm_manager_start (MMManager *manager)
|
|
{
|
|
MMManagerPrivate *priv;
|
|
GList *devices, *iter;
|
|
|
|
g_return_if_fail (manager != NULL);
|
|
g_return_if_fail (MM_IS_MANAGER (manager));
|
|
|
|
priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
|
|
devices = g_udev_client_query_by_subsystem (priv->udev, "tty");
|
|
for (iter = devices; iter; iter = g_list_next (iter))
|
|
device_added (manager, G_UDEV_DEVICE (iter->data));
|
|
|
|
devices = g_udev_client_query_by_subsystem (priv->udev, "net");
|
|
for (iter = devices; iter; iter = g_list_next (iter))
|
|
device_added (manager, G_UDEV_DEVICE (iter->data));
|
|
}
|
|
|
|
static void
|
|
mm_manager_init (MMManager *manager)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
|
const char *subsys[3] = { "tty", "net", NULL };
|
|
|
|
priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
|
load_plugins (manager);
|
|
|
|
priv->supports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) supports_info_free);
|
|
|
|
priv->udev = g_udev_client_new (subsys);
|
|
g_assert (priv->udev);
|
|
g_signal_connect (priv->udev, "uevent", G_CALLBACK (handle_uevent), manager);
|
|
}
|
|
|
|
static void
|
|
finalize (GObject *object)
|
|
{
|
|
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (object);
|
|
|
|
g_hash_table_destroy (priv->supports);
|
|
g_hash_table_destroy (priv->modems);
|
|
|
|
g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL);
|
|
g_slist_free (priv->plugins);
|
|
|
|
if (priv->udev)
|
|
g_object_unref (priv->udev);
|
|
|
|
if (priv->connection)
|
|
dbus_g_connection_unref (priv->connection);
|
|
|
|
G_OBJECT_CLASS (mm_manager_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
mm_manager_class_init (MMManagerClass *manager_class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
|
|
|
|
g_type_class_add_private (object_class, sizeof (MMManagerPrivate));
|
|
|
|
/* Virtual methods */
|
|
object_class->finalize = finalize;
|
|
|
|
/* Signals */
|
|
signals[DEVICE_ADDED] =
|
|
g_signal_new ("device-added",
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (MMManagerClass, device_added),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__OBJECT,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_OBJECT);
|
|
|
|
signals[DEVICE_REMOVED] =
|
|
g_signal_new ("device-removed",
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (MMManagerClass, device_removed),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__OBJECT,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_OBJECT);
|
|
|
|
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (manager_class),
|
|
&dbus_glib_mm_manager_object_info);
|
|
|
|
dbus_g_error_domain_register (MM_SERIAL_ERROR, "org.freedesktop.ModemManager.Modem", MM_TYPE_SERIAL_ERROR);
|
|
dbus_g_error_domain_register (MM_MODEM_ERROR, "org.freedesktop.ModemManager.Modem", MM_TYPE_MODEM_ERROR);
|
|
dbus_g_error_domain_register (MM_MODEM_CONNECT_ERROR, "org.freedesktop.ModemManager.Modem", MM_TYPE_MODEM_CONNECT_ERROR);
|
|
dbus_g_error_domain_register (MM_MOBILE_ERROR, "org.freedesktop.ModemManager.Modem.Gsm", MM_TYPE_MOBILE_ERROR);
|
|
}
|
|
|