diff options
Diffstat (limited to 'src/mm-modem-base.c')
-rw-r--r-- | src/mm-modem-base.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c new file mode 100644 index 0000000..3d82f8e --- /dev/null +++ b/src/mm-modem-base.c @@ -0,0 +1,341 @@ +/* -*- 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "mm-modem-base.h" +#include "mm-modem.h" +#include "mm-serial-port.h" +#include "mm-errors.h" +#include "mm-options.h" +#include "mm-properties-changed-signal.h" + +static void modem_init (MMModem *modem_class); + +G_DEFINE_TYPE_EXTENDED (MMModemBase, mm_modem_base, + G_TYPE_OBJECT, + G_TYPE_FLAG_VALUE_ABSTRACT, + G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init)) + +#define MM_MODEM_BASE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_BASE, MMModemBasePrivate)) + +typedef struct { + char *driver; + char *plugin; + char *device; + guint32 ip_method; + gboolean valid; + MMModemState state; + + GHashTable *ports; +} MMModemBasePrivate; + + +static char * +get_hash_key (const char *subsys, const char *name) +{ + return g_strdup_printf ("%s%s", subsys, name); +} + +MMPort * +mm_modem_base_get_port (MMModemBase *self, + const char *subsys, + const char *name) +{ + MMPort *port; + char *key; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (subsys != NULL, NULL); + + g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), NULL); + + key = get_hash_key (subsys, name); + port = g_hash_table_lookup (MM_MODEM_BASE_GET_PRIVATE (self)->ports, key); + g_free (key); + return port; +} + +static void +find_primary (gpointer key, gpointer data, gpointer user_data) +{ + MMPort **found = user_data; + MMPort *port = MM_PORT (data); + + if (!*found && (mm_port_get_port_type (port) == MM_PORT_TYPE_PRIMARY)) + *found = port; +} + +MMPort * +mm_modem_base_add_port (MMModemBase *self, + const char *subsys, + const char *name, + MMPortType ptype) +{ + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + MMPort *port = NULL; + char *key; + + g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); + g_return_val_if_fail (subsys != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL); + + g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), NULL); + + key = get_hash_key (subsys, name); + port = g_hash_table_lookup (priv->ports, key); + g_free (key); + g_return_val_if_fail (port == NULL, NULL); + + if (ptype == MM_PORT_TYPE_PRIMARY) { + g_hash_table_foreach (priv->ports, find_primary, &port); + g_return_val_if_fail (port == NULL, FALSE); + } + + if (!strcmp (subsys, "tty")) + port = MM_PORT (mm_serial_port_new (name, ptype)); + else if (!strcmp (subsys, "net")) { + port = MM_PORT (g_object_new (MM_TYPE_PORT, + MM_PORT_DEVICE, name, + MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET, + MM_PORT_TYPE, ptype, + NULL)); + } + + if (!port) + return NULL; + + key = get_hash_key (subsys, name); + g_hash_table_insert (priv->ports, key, port); + return port; +} + +gboolean +mm_modem_base_remove_port (MMModemBase *self, MMPort *port) +{ + g_return_val_if_fail (MM_IS_MODEM_BASE (self), FALSE); + g_return_val_if_fail (port != NULL, FALSE); + + return g_hash_table_remove (MM_MODEM_BASE_GET_PRIVATE (self)->ports, port); +} + +void +mm_modem_base_set_valid (MMModemBase *self, gboolean new_valid) +{ + MMModemBasePrivate *priv; + + g_return_if_fail (MM_IS_MODEM_BASE (self)); + + priv = MM_MODEM_BASE_GET_PRIVATE (self); + + if (priv->valid != new_valid) { + priv->valid = new_valid; + + /* Modem starts off in disabled state, and jumps to disabled when + * it's no longer valid. + */ + mm_modem_set_state (MM_MODEM (self), + MM_MODEM_STATE_DISABLED, + MM_MODEM_STATE_REASON_NONE); + + g_object_notify (G_OBJECT (self), MM_MODEM_VALID); + } +} + +gboolean +mm_modem_base_get_valid (MMModemBase *self) +{ + g_return_val_if_fail (MM_IS_MODEM_BASE (self), FALSE); + + return MM_MODEM_BASE_GET_PRIVATE (self)->valid; +} + +/*****************************************************************************/ + +static void +mm_modem_base_init (MMModemBase *self) +{ + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + + priv->ports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_ENABLED, + MM_MODEM_DBUS_INTERFACE); +} + +static void +modem_init (MMModem *modem_class) +{ +} + +static gboolean +is_enabled (MMModemState state) +{ + return (state >= MM_MODEM_STATE_ENABLED); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (object); + gboolean old_enabled; + + switch (prop_id) { + case MM_MODEM_PROP_STATE: + /* Ensure we update the 'enabled' property when the state changes */ + old_enabled = is_enabled (priv->state); + priv->state = g_value_get_uint (value); + if (old_enabled != is_enabled (priv->state)) + g_object_notify (object, MM_MODEM_ENABLED); + break; + case MM_MODEM_PROP_DRIVER: + /* Construct only */ + priv->driver = g_value_dup_string (value); + break; + case MM_MODEM_PROP_PLUGIN: + /* Construct only */ + priv->plugin = g_value_dup_string (value); + break; + case MM_MODEM_PROP_MASTER_DEVICE: + /* Construct only */ + priv->device = g_value_dup_string (value); + break; + case MM_MODEM_PROP_IP_METHOD: + priv->ip_method = g_value_get_uint (value); + break; + case MM_MODEM_PROP_VALID: + case MM_MODEM_PROP_TYPE: + case MM_MODEM_PROP_ENABLED: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (object); + + switch (prop_id) { + case MM_MODEM_PROP_STATE: + g_value_set_uint (value, priv->state); + break; + case MM_MODEM_PROP_MASTER_DEVICE: + g_value_set_string (value, priv->device); + break; + case MM_MODEM_PROP_DATA_DEVICE: + g_value_set_string (value, NULL); + break; + case MM_MODEM_PROP_DRIVER: + g_value_set_string (value, priv->driver); + break; + case MM_MODEM_PROP_PLUGIN: + g_value_set_string (value, priv->plugin); + break; + case MM_MODEM_PROP_TYPE: + g_value_set_uint (value, MM_MODEM_TYPE_UNKNOWN); + break; + case MM_MODEM_PROP_IP_METHOD: + g_value_set_uint (value, priv->ip_method); + break; + case MM_MODEM_PROP_VALID: + g_value_set_boolean (value, priv->valid); + break; + case MM_MODEM_PROP_ENABLED: + g_value_set_boolean (value, is_enabled (priv->state)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + MMModemBase *self = MM_MODEM_BASE (object); + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + + g_hash_table_destroy (priv->ports); + g_free (priv->driver); + g_free (priv->plugin); + g_free (priv->device); + + G_OBJECT_CLASS (mm_modem_base_parent_class)->finalize (object); +} + +static void +mm_modem_base_class_init (MMModemBaseClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (MMModemBasePrivate)); + + /* Virtual methods */ + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + g_object_class_override_property (object_class, + MM_MODEM_PROP_STATE, + MM_MODEM_STATE); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_MASTER_DEVICE, + MM_MODEM_MASTER_DEVICE); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_DATA_DEVICE, + MM_MODEM_DATA_DEVICE); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_DRIVER, + MM_MODEM_DRIVER); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_PLUGIN, + MM_MODEM_PLUGIN); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_TYPE, + MM_MODEM_TYPE); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_IP_METHOD, + MM_MODEM_IP_METHOD); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_VALID, + MM_MODEM_VALID); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_ENABLED, + MM_MODEM_ENABLED); + + mm_properties_changed_signal_new (object_class); +} + |