mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-31 21:50:11 +01:00
devices: rework device plugin interface to be more flexible
In preparation for making WWAN and Bluetooth plugins, rework the device plugin interface to meet those plugins' needs and port WiMAX over in the process.
This commit is contained in:
parent
8e9b9fe423
commit
2a04df856b
9 changed files with 472 additions and 154 deletions
|
|
@ -80,6 +80,7 @@ nm_sources = \
|
|||
devices/nm-device-bt.h \
|
||||
devices/nm-device-ethernet.c \
|
||||
devices/nm-device-ethernet.h \
|
||||
devices/nm-device-factory.c \
|
||||
devices/nm-device-factory.h \
|
||||
devices/nm-device-generic.c \
|
||||
devices/nm-device-generic.h \
|
||||
|
|
|
|||
|
|
@ -588,22 +588,22 @@ modem_removed_cb (NMModem *modem, gpointer user_data)
|
|||
modem_cleanup (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_device_bt_modem_added (NMDeviceBt *self,
|
||||
NMModem *modem,
|
||||
const char *driver)
|
||||
static gboolean
|
||||
component_added (NMDevice *device, GObject *component)
|
||||
{
|
||||
NMDeviceBtPrivate *priv;
|
||||
NMDeviceBt *self = NM_DEVICE_BT (device);
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
|
||||
NMModem *modem;
|
||||
const gchar *modem_data_port;
|
||||
const gchar *modem_control_port;
|
||||
char *base;
|
||||
NMDeviceState state;
|
||||
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE);
|
||||
g_return_val_if_fail (NM_IS_MODEM (modem), FALSE);
|
||||
if (!NM_IS_MODEM (component))
|
||||
return FALSE;
|
||||
modem = NM_MODEM (component);
|
||||
|
||||
priv = NM_DEVICE_BT_GET_PRIVATE (self);
|
||||
modem_data_port = nm_modem_get_data_port (modem);
|
||||
modem_control_port = nm_modem_get_control_port (modem);
|
||||
g_return_val_if_fail (modem_data_port != NULL || modem_control_port != NULL, FALSE);
|
||||
|
|
@ -1207,6 +1207,7 @@ nm_device_bt_class_init (NMDeviceBtClass *klass)
|
|||
device_class->check_connection_available = check_connection_available;
|
||||
device_class->complete_connection = complete_connection;
|
||||
device_class->is_available = is_available;
|
||||
device_class->component_added = component_added;
|
||||
|
||||
device_class->state_changed = device_state_changed;
|
||||
|
||||
|
|
|
|||
114
src/devices/nm-device-factory.c
Normal file
114
src/devices/nm-device-factory.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "nm-device-factory.h"
|
||||
|
||||
enum {
|
||||
DEVICE_ADDED,
|
||||
COMPONENT_ADDED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
gboolean
|
||||
nm_device_factory_emit_component_added (NMDeviceFactory *factory, GObject *component)
|
||||
{
|
||||
gboolean consumed = FALSE;
|
||||
|
||||
g_signal_emit (factory, signals[COMPONENT_ADDED], 0, component, &consumed);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void
|
||||
interface_init (gpointer g_iface)
|
||||
{
|
||||
GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
if (G_LIKELY (initialized))
|
||||
return;
|
||||
|
||||
g_object_interface_install_property
|
||||
(g_iface,
|
||||
g_param_spec_uint (NM_DEVICE_FACTORY_DEVICE_TYPE,
|
||||
"Device type",
|
||||
"Device type",
|
||||
0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
/* Signals */
|
||||
signals[DEVICE_ADDED] = g_signal_new (NM_DEVICE_FACTORY_DEVICE_ADDED,
|
||||
iface_type,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMDeviceFactory, device_added),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, NM_TYPE_DEVICE);
|
||||
|
||||
signals[COMPONENT_ADDED] = g_signal_new (NM_DEVICE_FACTORY_COMPONENT_ADDED,
|
||||
iface_type,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (NMDeviceFactory, component_added),
|
||||
g_signal_accumulator_true_handled, NULL, NULL,
|
||||
G_TYPE_BOOLEAN, 1, G_TYPE_OBJECT);
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
GType
|
||||
nm_device_factory_get_type (void)
|
||||
{
|
||||
static GType device_factory_type = 0;
|
||||
|
||||
if (!device_factory_type) {
|
||||
const GTypeInfo device_factory_info = {
|
||||
sizeof (NMDeviceFactory), /* class_size */
|
||||
interface_init, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
NULL,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0, /* n_preallocs */
|
||||
NULL
|
||||
};
|
||||
|
||||
device_factory_type = g_type_register_static (G_TYPE_INTERFACE,
|
||||
"NMDeviceFactory",
|
||||
&device_factory_info,
|
||||
0);
|
||||
g_type_interface_add_prerequisite (device_factory_type, G_TYPE_OBJECT);
|
||||
}
|
||||
|
||||
return device_factory_type;
|
||||
}
|
||||
|
||||
NMDevice *
|
||||
nm_device_factory_new_link (NMDeviceFactory *factory,
|
||||
NMPlatformLink *plink,
|
||||
GError **error)
|
||||
{
|
||||
g_return_if_fail (factory != NULL);
|
||||
g_return_if_fail (plink != NULL);
|
||||
|
||||
if (NM_DEVICE_FACTORY_GET_INTERFACE (factory)->new_link)
|
||||
return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->new_link (factory, plink, error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2007 - 2011 Red Hat, Inc.
|
||||
* Copyright (C) 2007 - 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef NM_DEVICE_FACTORY_H
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "NetworkManager.h"
|
||||
#include "nm-platform.h"
|
||||
#include "nm-device.h"
|
||||
|
||||
/* WARNING: this file is private API between NetworkManager and its internal
|
||||
* device plugins. Its API can change at any time and is not guaranteed to be
|
||||
|
|
@ -33,52 +34,106 @@
|
|||
* not meant to enable third-party plugins.
|
||||
*/
|
||||
|
||||
typedef struct _NMDeviceFactory NMDeviceFactory;
|
||||
|
||||
/**
|
||||
* nm_device_factory_create_device:
|
||||
* @devpath: sysfs path of the device
|
||||
* @ifname: interface name of the device
|
||||
* @driver: driver of the device
|
||||
* @error: error for failure information
|
||||
* nm_device_factory_create:
|
||||
* @error: an error if creation of the factory failed, or %NULL
|
||||
*
|
||||
* Creates a #NMDevice subclass if the given information represents a device
|
||||
* the factory is capable of creating. If the information does represent a
|
||||
* device the factory is capable of creating, but the device could not be
|
||||
* created, %NULL should be returned and @error should be set. If the
|
||||
* factory is not capable of creating a device with the given information
|
||||
* (ie, the factory creates Ethernet devices but the information represents
|
||||
* a WiFi device) it should return %NULL and leave @error untouched.
|
||||
* Creates a #GObject that implements the #NMDeviceFactory interface. This
|
||||
* function must not emit any signals or perform any actions that would cause
|
||||
* devices or components to be created immediately. Instead these should be
|
||||
* deferred to an idle handler.
|
||||
*
|
||||
* Returns: the device object (a subclass of #NMDevice) or %NULL
|
||||
* Returns: the #GObject implementing #NMDeviceFactory or %NULL
|
||||
*/
|
||||
GObject *nm_device_factory_create_device (NMPlatformLink *platform_device,
|
||||
NMDeviceFactory *nm_device_factory_create (GError **error);
|
||||
|
||||
/* Should match nm_device_factory_create() */
|
||||
typedef NMDeviceFactory * (*NMDeviceFactoryCreateFunc) (GError **error);
|
||||
|
||||
/**
|
||||
* nm_device_factory_get_device_type:
|
||||
*
|
||||
* Returns: the #NMDeviceType that this plugin creates
|
||||
*/
|
||||
NMDeviceType nm_device_factory_get_device_type (void);
|
||||
|
||||
/* Should match nm_device_factory_get_device_type() */
|
||||
typedef NMDeviceType (*NMDeviceFactoryDeviceTypeFunc) (void);
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#define NM_TYPE_DEVICE_FACTORY (nm_device_factory_get_type ())
|
||||
#define NM_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_FACTORY, NMDeviceFactory))
|
||||
#define NM_IS_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_FACTORY))
|
||||
#define NM_DEVICE_FACTORY_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_DEVICE_FACTORY, NMDeviceFactory))
|
||||
|
||||
/* properties */
|
||||
#define NM_DEVICE_FACTORY_DEVICE_TYPE "device-type"
|
||||
|
||||
/* signals */
|
||||
#define NM_DEVICE_FACTORY_COMPONENT_ADDED "component-added"
|
||||
#define NM_DEVICE_FACTORY_DEVICE_ADDED "device-added"
|
||||
|
||||
struct _NMDeviceFactory {
|
||||
GTypeInterface g_iface;
|
||||
|
||||
/**
|
||||
* new_link:
|
||||
* @factory: the #NMDeviceFactory
|
||||
* @link: the new link
|
||||
* @error: error if the link could be claimed but an error occurred
|
||||
*
|
||||
* The NetworkManager core was notified of a new link which the plugin
|
||||
* may want to claim and create a #NMDevice subclass for. If the link
|
||||
* represents a device the factory is capable of claiming, but the device
|
||||
* could not be created, %NULL should be returned and @error should be set.
|
||||
* %NULL should always be returned and @error should never be set if the
|
||||
* factory cannot create devices for the type which @link represents.
|
||||
*
|
||||
* Returns: the #NMDevice if the link was claimed and created, %NULL if not
|
||||
*/
|
||||
NMDevice * (*new_link) (NMDeviceFactory *factory,
|
||||
NMPlatformLink *plink,
|
||||
GError **error);
|
||||
|
||||
/* Signals */
|
||||
|
||||
/**
|
||||
* device_added:
|
||||
* @factory: the #NMDeviceFactory
|
||||
* @device: the new #NMDevice subclass
|
||||
*
|
||||
* The factory emits this signal if it finds a new device by itself.
|
||||
*/
|
||||
void (*device_added) (NMDeviceFactory *factory, NMDevice *device);
|
||||
|
||||
/**
|
||||
* component_added:
|
||||
* @factory: the #NMDeviceFactory
|
||||
* @component: a new component which existing devices may wish to claim
|
||||
*
|
||||
* The factory emits this signal when it finds a new component. For example,
|
||||
* the WWAN factory may indicate that a new modem is available, which an
|
||||
* existing Bluetooth device may wish to claim. If no device claims the
|
||||
* component, the plugin is allowed to create a new #NMDevice instance for
|
||||
* that component and emit the "device-added" signal.
|
||||
*
|
||||
* Returns: %TRUE if the component was claimed by a device, %FALSE if not
|
||||
*/
|
||||
gboolean (*component_added) (NMDeviceFactory *factory, GObject *component);
|
||||
};
|
||||
|
||||
GType nm_device_factory_get_type (void);
|
||||
|
||||
NMDevice * nm_device_factory_new_link (NMDeviceFactory *factory,
|
||||
NMPlatformLink *plink,
|
||||
GError **error);
|
||||
|
||||
/* Should match nm_device_factory() */
|
||||
typedef GObject * (*NMDeviceFactoryCreateFunc) (NMPlatformLink *platform_device,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* nm_device_factory_get_priority:
|
||||
*
|
||||
* Returns the priority of this plugin. Higher numbers mean a higher priority.
|
||||
*
|
||||
* Returns: plugin priority
|
||||
*/
|
||||
guint32 nm_device_factory_get_priority (void);
|
||||
|
||||
typedef guint32 (*NMDeviceFactoryPriorityFunc) (void);
|
||||
|
||||
/**
|
||||
* nm_device_factory_get_type:
|
||||
*
|
||||
* Returns the type of device this factory can create. Only one factory for
|
||||
* each type of device is allowed.
|
||||
*
|
||||
* Returns: the %NMDeviceType
|
||||
*/
|
||||
NMDeviceType nm_device_factory_get_type (void);
|
||||
|
||||
typedef NMDeviceType (*NMDeviceFactoryTypeFunc) (void);
|
||||
/* For use by implementations */
|
||||
gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory,
|
||||
GObject *component);
|
||||
|
||||
#endif /* NM_DEVICE_FACTORY_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -212,6 +212,15 @@ nm_device_modem_get_modem (NMDeviceModem *self)
|
|||
return NM_DEVICE_MODEM_GET_PRIVATE (self)->modem;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
owns_iface (NMDevice *device, const char *iface)
|
||||
{
|
||||
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
|
||||
|
||||
g_assert (priv->modem);
|
||||
return nm_modem_owns_port (priv->modem, iface);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -492,6 +501,7 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass)
|
|||
device_class->ip4_config_pre_commit = ip4_config_pre_commit;
|
||||
device_class->get_enabled = get_enabled;
|
||||
device_class->set_enabled = set_enabled;
|
||||
device_class->owns_iface = owns_iface;
|
||||
|
||||
device_class->state_changed = device_state_changed;
|
||||
|
||||
|
|
|
|||
|
|
@ -1193,6 +1193,48 @@ link_changed (NMDevice *device, NMPlatformLink *info)
|
|||
nm_device_set_carrier (device, info->connected);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_notify_component_added():
|
||||
* @device: the #NMDevice
|
||||
* @component: the component being added by a plugin
|
||||
*
|
||||
* Called by the manager to notify the device that a new component has
|
||||
* been found. The device implementation should return %TRUE if it
|
||||
* wishes to claim the component, or %FALSE if it cannot.
|
||||
*
|
||||
* Returns: %TRUE to claim the component, %FALSE if the component cannot be
|
||||
* claimed.
|
||||
*/
|
||||
gboolean
|
||||
nm_device_notify_component_added (NMDevice *device, GObject *component)
|
||||
{
|
||||
if (NM_DEVICE_GET_CLASS (device)->component_added)
|
||||
return NM_DEVICE_GET_CLASS (device)->component_added (device, component);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_owns_iface():
|
||||
* @device: the #NMDevice
|
||||
* @iface: an interface name
|
||||
*
|
||||
* Called by the manager to ask if the device or any of its components owns
|
||||
* @iface. For example, a WWAN implementation would return %TRUE for an
|
||||
* ethernet interface name that was owned by the WWAN device's modem component,
|
||||
* because that ethernet interface is controlled by the WWAN device and cannot
|
||||
* be used independently of the WWAN device.
|
||||
*
|
||||
* Returns: %TRUE if @device or it's components owns the interface name,
|
||||
* %FALSE if not
|
||||
*/
|
||||
gboolean
|
||||
nm_device_owns_iface (NMDevice *device, const char *iface)
|
||||
{
|
||||
if (NM_DEVICE_GET_CLASS (device)->owns_iface)
|
||||
return NM_DEVICE_GET_CLASS (device)->owns_iface (device, iface);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
check_carrier (NMDevice *device)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -196,6 +196,10 @@ typedef struct {
|
|||
|
||||
gboolean (* have_any_ready_slaves) (NMDevice *self,
|
||||
const GSList *slaves);
|
||||
|
||||
gboolean (* component_added) (NMDevice *self, GObject *component);
|
||||
|
||||
gboolean (* owns_iface) (NMDevice *self, const char *iface);
|
||||
} NMDeviceClass;
|
||||
|
||||
|
||||
|
|
@ -332,6 +336,10 @@ guint32 nm_device_get_mtu (NMDevice *device);
|
|||
|
||||
gboolean nm_device_connection_is_available (NMDevice *device, NMConnection *connection);
|
||||
|
||||
gboolean nm_device_notify_component_added (NMDevice *device, GObject *component);
|
||||
|
||||
gboolean nm_device_owns_iface (NMDevice *device, const char *iface);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
/* For testing only */
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
* Copyright (C) 2011 - 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include <gmodule.h>
|
||||
|
|
@ -23,28 +23,92 @@
|
|||
#include "nm-device-factory.h"
|
||||
#include "nm-device-wimax.h"
|
||||
|
||||
G_MODULE_EXPORT GObject *
|
||||
nm_device_factory_create_device (NMPlatformLink *platform_device,
|
||||
GError **error)
|
||||
#define NM_TYPE_WIMAX_FACTORY (nm_wimax_factory_get_type ())
|
||||
#define NM_WIMAX_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_WIMAX_FACTORY, NMWimaxFactory))
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
} NMWimaxFactory;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
} NMWimaxFactoryClass;
|
||||
|
||||
static GType nm_wimax_factory_get_type (void);
|
||||
|
||||
static void device_factory_interface_init (NMDeviceFactory *factory_iface);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (NMWimaxFactory, nm_wimax_factory, G_TYPE_OBJECT, 0,
|
||||
G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init))
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
#define PLUGIN_TYPE NM_DEVICE_TYPE_WIMAX
|
||||
|
||||
G_MODULE_EXPORT NMDeviceFactory *
|
||||
nm_device_factory_create (GError **error)
|
||||
{
|
||||
return (NMDeviceFactory *) g_object_new (NM_TYPE_WIMAX_FACTORY, NULL);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT NMDeviceType
|
||||
nm_device_factory_get_device_type (void)
|
||||
{
|
||||
return PLUGIN_TYPE;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static NMDevice *
|
||||
new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
|
||||
{
|
||||
/* FIXME: check udev 'DEVTYPE' instead; but since we only support Intel
|
||||
* WiMAX devices for now this is appropriate.
|
||||
*/
|
||||
if (g_strcmp0 (platform_device->driver, "i2400m_usb") != 0)
|
||||
if (g_strcmp0 (plink->driver, "i2400m_usb") != 0)
|
||||
return NULL; /* unsupported */
|
||||
|
||||
return (GObject *) nm_device_wimax_new (platform_device);
|
||||
return (NMDevice *) nm_device_wimax_new (plink);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT guint32
|
||||
nm_device_factory_get_priority (void)
|
||||
enum {
|
||||
PROP_0 = 0x1000,
|
||||
PROP_DEVICE_TYPE,
|
||||
};
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
return 0;
|
||||
switch (prop) {
|
||||
case PROP_DEVICE_TYPE:
|
||||
g_value_set_uint (value, PLUGIN_TYPE);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT NMDeviceType
|
||||
nm_device_factory_get_type (void)
|
||||
static void
|
||||
device_factory_interface_init (NMDeviceFactory *factory_iface)
|
||||
{
|
||||
return NM_DEVICE_TYPE_WIMAX;
|
||||
factory_iface->new_link = new_link;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_wimax_factory_init (NMWimaxFactory *factory)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
nm_wimax_factory_class_init (NMWimaxFactoryClass *wf_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (wf_class);
|
||||
|
||||
object_class->get_property = get_property;
|
||||
|
||||
g_object_class_override_property (object_class,
|
||||
PROP_DEVICE_TYPE,
|
||||
NM_DEVICE_FACTORY_DEVICE_TYPE);
|
||||
}
|
||||
|
||||
|
|
|
|||
209
src/nm-manager.c
209
src/nm-manager.c
|
|
@ -551,27 +551,12 @@ modem_added (NMModemManager *modem_manager,
|
|||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
NMDevice *device = NULL;
|
||||
const char *modem_iface;
|
||||
GSList *iter, *remove = NULL;
|
||||
|
||||
/* Remove ethernet devices that are actually owned by the modem, since
|
||||
* they cannot be used as normal ethernet.
|
||||
*/
|
||||
for (iter = priv->devices; iter; iter = iter->next) {
|
||||
if (nm_device_get_device_type (iter->data) == NM_DEVICE_TYPE_ETHERNET) {
|
||||
if (nm_modem_owns_port (modem, nm_device_get_ip_iface (iter->data)))
|
||||
remove = g_slist_prepend (remove, iter->data);
|
||||
}
|
||||
}
|
||||
for (iter = remove; iter; iter = iter->next)
|
||||
remove_device (self, NM_DEVICE (iter->data), FALSE);
|
||||
g_slist_free (remove);
|
||||
GSList *iter;
|
||||
|
||||
/* Give Bluetooth DUN devices first chance to claim the modem */
|
||||
for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
|
||||
if (nm_device_get_device_type (iter->data) == NM_DEVICE_TYPE_BT) {
|
||||
if (nm_device_bt_modem_added (NM_DEVICE_BT (iter->data), modem, driver))
|
||||
return;
|
||||
}
|
||||
for (iter = priv->devices; iter; iter = iter->next) {
|
||||
if (nm_device_notify_component_added (device, G_OBJECT (modem)))
|
||||
return;
|
||||
}
|
||||
|
||||
/* If it was a Bluetooth modem and no bluetooth device claimed it, ignore
|
||||
|
|
@ -589,8 +574,10 @@ modem_added (NMModemManager *modem_manager,
|
|||
|
||||
/* Make the new modem device */
|
||||
device = nm_device_modem_new (modem, driver);
|
||||
if (device)
|
||||
if (device) {
|
||||
add_device (self, device, FALSE);
|
||||
g_object_unref (device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1182,6 +1169,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection)
|
|||
if (device) {
|
||||
nm_device_set_is_nm_owned (device, TRUE);
|
||||
add_device (self, device, FALSE);
|
||||
g_object_unref (device);
|
||||
}
|
||||
|
||||
g_signal_handlers_unblock_by_func (nm_platform_get (), G_CALLBACK (platform_link_added_cb), self);
|
||||
|
|
@ -1792,6 +1780,15 @@ get_existing_connection (NMManager *manager, NMDevice *device)
|
|||
return added ? NM_CONNECTION (added) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* add_device:
|
||||
* @self: the #NMManager
|
||||
* @device: the #NMDevice to add
|
||||
* @generate_con: %TRUE if existing connection (if any) should be assumed
|
||||
*
|
||||
* If successful, this function will increase the references count of @device.
|
||||
* Callers should decrease the reference count.
|
||||
*/
|
||||
static void
|
||||
add_device (NMManager *self, NMDevice *device, gboolean generate_con)
|
||||
{
|
||||
|
|
@ -1804,26 +1801,31 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con)
|
|||
gboolean enabled = FALSE;
|
||||
RfKillType rtype;
|
||||
NMDeviceType devtype;
|
||||
|
||||
iface = nm_device_get_ip_iface (device);
|
||||
g_assert (iface);
|
||||
GSList *iter, *remove = NULL;
|
||||
|
||||
devtype = nm_device_get_device_type (device);
|
||||
|
||||
/* Ignore the device if we already know about it. But some modems will
|
||||
* provide pseudo-ethernet devices that NM has already claimed while
|
||||
* ModemManager is still detecting the modem's serial ports, so when the
|
||||
* MM modem object finally shows up it may have the same IP interface as the
|
||||
* ethernet interface we've already detected. In this case we skip the
|
||||
* check for an existing device with the same IP interface name and kill
|
||||
* the ethernet device later in favor of the modem device.
|
||||
*/
|
||||
if ((devtype != NM_DEVICE_TYPE_MODEM) && find_device_by_ip_iface (self, iface)) {
|
||||
g_object_unref (device);
|
||||
/* No duplicates */
|
||||
if (nm_manager_get_device_by_udi (self, nm_device_get_udi (device)))
|
||||
return;
|
||||
}
|
||||
|
||||
priv->devices = g_slist_append (priv->devices, device);
|
||||
/* Remove existing devices owned by the new device; eg remove ethernet
|
||||
* ports that are owned by a WWAN modem, since udev may announce them
|
||||
* before the modem is fully discovered.
|
||||
*
|
||||
* FIXME: use parent/child device relationships instead of removing
|
||||
* the child NMDevice entirely
|
||||
*/
|
||||
for (iter = priv->devices; iter; iter = iter->next) {
|
||||
iface = nm_device_get_ip_iface (iter->data);
|
||||
if (nm_device_owns_iface (device, iface))
|
||||
remove = g_slist_prepend (remove, iter->data);
|
||||
}
|
||||
for (iter = remove; iter; iter = iter->next)
|
||||
remove_device (self, NM_DEVICE (iter->data), FALSE);
|
||||
g_slist_free (remove);
|
||||
|
||||
priv->devices = g_slist_append (priv->devices, g_object_ref (device));
|
||||
|
||||
g_signal_connect (device, "state-changed",
|
||||
G_CALLBACK (manager_device_state_changed),
|
||||
|
|
@ -1874,6 +1876,9 @@ add_device (NMManager *self, NMDevice *device, gboolean generate_con)
|
|||
nm_device_set_enabled (device, enabled);
|
||||
}
|
||||
|
||||
iface = nm_device_get_iface (device);
|
||||
g_assert (iface);
|
||||
|
||||
type_desc = nm_device_get_type_desc (device);
|
||||
g_assert (type_desc);
|
||||
driver = nm_device_get_driver (device);
|
||||
|
|
@ -1983,6 +1988,7 @@ bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr,
|
|||
has_nap ? "NAP" : "");
|
||||
|
||||
add_device (manager, device, FALSE);
|
||||
g_object_unref (device);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2050,25 +2056,31 @@ find_device_by_ifindex (NMManager *self, guint32 ifindex)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#define PLUGIN_PREFIX "libnm-device-plugin-"
|
||||
|
||||
typedef struct {
|
||||
NMDeviceType t;
|
||||
guint priority;
|
||||
NMDeviceFactoryCreateFunc create_func;
|
||||
} PluginInfo;
|
||||
|
||||
static gint
|
||||
plugin_sort (PluginInfo *a, PluginInfo *b)
|
||||
static void
|
||||
factory_device_added_cb (NMDeviceFactory *factory,
|
||||
NMDevice *device,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* Higher priority means sort earlier in the list (ie, return -1) */
|
||||
if (a->priority > b->priority)
|
||||
return -1;
|
||||
else if (a->priority < b->priority)
|
||||
return 1;
|
||||
return 0;
|
||||
add_device (NM_MANAGER (user_data), device, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
factory_component_added_cb (NMDeviceFactory *factory,
|
||||
GObject *component,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMManager *self = NM_MANAGER (user_data);
|
||||
GSList *iter;
|
||||
|
||||
for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) {
|
||||
if (nm_device_notify_component_added (NM_DEVICE (iter->data), component))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define PLUGIN_PREFIX "libnm-device-plugin-"
|
||||
|
||||
static void
|
||||
load_device_factories (NMManager *self)
|
||||
{
|
||||
|
|
@ -2077,7 +2089,7 @@ load_device_factories (NMManager *self)
|
|||
GError *error = NULL;
|
||||
const char *item;
|
||||
char *path;
|
||||
GSList *list = NULL, *iter;
|
||||
GSList *iter;
|
||||
|
||||
dir = g_dir_open (NMPLUGINDIR, 0, &error);
|
||||
if (!dir) {
|
||||
|
|
@ -2090,11 +2102,11 @@ load_device_factories (NMManager *self)
|
|||
|
||||
while ((item = g_dir_read_name (dir))) {
|
||||
GModule *plugin;
|
||||
NMDeviceFactory *factory;
|
||||
NMDeviceFactoryCreateFunc create_func;
|
||||
NMDeviceFactoryPriorityFunc priority_func;
|
||||
NMDeviceFactoryTypeFunc type_func;
|
||||
PluginInfo *info = NULL;
|
||||
NMDeviceType plugin_type;
|
||||
NMDeviceFactoryDeviceTypeFunc type_func;
|
||||
NMDeviceType dev_type;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if (!g_str_has_prefix (item, PLUGIN_PREFIX))
|
||||
continue;
|
||||
|
|
@ -2109,60 +2121,63 @@ load_device_factories (NMManager *self)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (plugin, "nm_device_factory_get_type", (gpointer) (&type_func))) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to find device factory: %s", item, g_module_error ());
|
||||
if (!g_module_symbol (plugin, "nm_device_factory_get_device_type", (gpointer) &type_func)) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to find device factory type: %s", item, g_module_error ());
|
||||
g_module_close (plugin);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Make sure we don't double-load plugins */
|
||||
plugin_type = type_func ();
|
||||
for (iter = list; iter; iter = g_slist_next (iter)) {
|
||||
PluginInfo *candidate = iter->data;
|
||||
dev_type = type_func ();
|
||||
for (iter = priv->factories; iter; iter = iter->next) {
|
||||
NMDeviceType t = NM_DEVICE_TYPE_UNKNOWN;
|
||||
|
||||
if (plugin_type == candidate->t) {
|
||||
info = candidate;
|
||||
g_object_get (G_OBJECT (iter->data),
|
||||
NM_DEVICE_FACTORY_DEVICE_TYPE, &t,
|
||||
NULL);
|
||||
if (dev_type == t) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (info) {
|
||||
if (found) {
|
||||
g_module_close (plugin);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (plugin, "nm_device_factory_create_device", (gpointer) (&create_func))) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to find device creator: %s", item, g_module_error ());
|
||||
if (!g_module_symbol (plugin, "nm_device_factory_create", (gpointer) &create_func)) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to find device factory creator: %s", item, g_module_error ());
|
||||
g_module_close (plugin);
|
||||
continue;
|
||||
}
|
||||
|
||||
info = g_malloc0 (sizeof (*info));
|
||||
info->create_func = create_func;
|
||||
info->t = plugin_type;
|
||||
|
||||
/* Grab priority; higher number equals higher priority */
|
||||
if (g_module_symbol (plugin, "nm_device_factory_get_priority", (gpointer) (&priority_func)))
|
||||
info->priority = priority_func ();
|
||||
else {
|
||||
nm_log_dbg (LOGD_HW, "(%s): failed to find device factory priority func: %s",
|
||||
item, g_module_error ());
|
||||
factory = create_func (&error);
|
||||
if (!factory) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to initialize device factory: %s",
|
||||
item, error ? error->message : "unknown");
|
||||
g_clear_error (&error);
|
||||
g_module_close (plugin);
|
||||
continue;
|
||||
}
|
||||
g_clear_error (&error);
|
||||
|
||||
g_module_make_resident (plugin);
|
||||
list = g_slist_insert_sorted (list, info, (GCompareFunc) plugin_sort);
|
||||
priv->factories = g_slist_prepend (priv->factories, factory);
|
||||
|
||||
nm_log_info (LOGD_HW, "Loaded device factory: %s", g_module_name (plugin));
|
||||
g_signal_connect (factory,
|
||||
NM_DEVICE_FACTORY_DEVICE_ADDED,
|
||||
G_CALLBACK (factory_device_added_cb),
|
||||
self);
|
||||
g_signal_connect (factory,
|
||||
NM_DEVICE_FACTORY_COMPONENT_ADDED,
|
||||
G_CALLBACK (factory_component_added_cb),
|
||||
self);
|
||||
|
||||
nm_log_info (LOGD_HW, "Loaded device plugin: %s", g_module_name (plugin));
|
||||
};
|
||||
g_dir_close (dir);
|
||||
|
||||
/* Ditch the priority info and copy the factory functions to our private data */
|
||||
for (iter = list; iter; iter = g_slist_next (iter)) {
|
||||
PluginInfo *info = iter->data;
|
||||
|
||||
priv->factories = g_slist_append (priv->factories, info->create_func);
|
||||
g_free (info);
|
||||
}
|
||||
g_slist_free (list);
|
||||
priv->factories = g_slist_reverse (priv->factories);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2184,11 +2199,10 @@ platform_link_added_cb (NMPlatform *platform,
|
|||
return;
|
||||
|
||||
/* Try registered device factories */
|
||||
for (iter = priv->factories; iter; iter = g_slist_next (iter)) {
|
||||
NMDeviceFactoryCreateFunc create_func = iter->data;
|
||||
for (iter = priv->factories; iter; iter = iter->next) {
|
||||
NMDeviceFactory *factory = NM_DEVICE_FACTORY (iter->data);
|
||||
|
||||
g_clear_error (&error);
|
||||
device = (NMDevice *) create_func (plink, &error);
|
||||
device = nm_device_factory_new_link (factory, plink, &error);
|
||||
if (device && NM_IS_DEVICE (device)) {
|
||||
g_assert_no_error (error);
|
||||
break; /* success! */
|
||||
|
|
@ -2281,8 +2295,10 @@ platform_link_added_cb (NMPlatform *platform,
|
|||
}
|
||||
}
|
||||
|
||||
if (device)
|
||||
if (device) {
|
||||
add_device (self, device, plink->type != NM_LINK_TYPE_LOOPBACK);
|
||||
g_object_unref (device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -4807,6 +4823,8 @@ nm_manager_new (NMSettings *settings,
|
|||
*/
|
||||
rfkill_change_wifi (priv->radio_states[RFKILL_TYPE_WLAN].desc, initial_wifi_enabled);
|
||||
|
||||
load_device_factories (singleton);
|
||||
|
||||
return singleton;
|
||||
}
|
||||
|
||||
|
|
@ -4917,8 +4935,6 @@ nm_manager_init (NMManager *manager)
|
|||
KERNEL_FIRMWARE_DIR);
|
||||
}
|
||||
|
||||
load_device_factories (manager);
|
||||
|
||||
/* Update timestamps in active connections */
|
||||
priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, manager);
|
||||
}
|
||||
|
|
@ -5046,6 +5062,7 @@ dispose (GObject *object)
|
|||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
||||
DBusGConnection *bus;
|
||||
DBusConnection *dbus_connection;
|
||||
GSList *iter;
|
||||
|
||||
g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref);
|
||||
priv->auth_chains = NULL;
|
||||
|
|
@ -5116,6 +5133,12 @@ dispose (GObject *object)
|
|||
g_clear_object (&priv->fw_monitor);
|
||||
}
|
||||
|
||||
for (iter = priv->factories; iter; iter = iter->next) {
|
||||
NMDeviceFactory *factory = iter->data;
|
||||
|
||||
g_signal_handlers_disconnect_matched (factory, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager);
|
||||
g_object_unref (factory);
|
||||
}
|
||||
g_clear_pointer (&priv->factories, g_slist_free);
|
||||
|
||||
if (priv->timestamp_update_id) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue