core/libnm-glib: implement better missing firmware support (rh #594578)

Track missing firmware and ensure the device can't be used when firmware
is missing.  Add a property for missing firmware so that clients can do
something intelligent with this information.
This commit is contained in:
Dan Williams
2010-05-25 10:52:25 -07:00
parent ba17174798
commit fea6431a20
8 changed files with 134 additions and 40 deletions

View File

@@ -52,6 +52,12 @@
Whether or not this device is managed by NetworkManager. Whether or not this device is managed by NetworkManager.
</tp:docstring> </tp:docstring>
</property> </property>
<property name="FirmwareMissing" type="b" access="read">
<tp:docstring>
If TRUE, indicates the device is likely missing firmware necessary for
its operation.
</tp:docstring>
</property>
<property name="DeviceType" type="u" access="read" tp:type="NM_DEVICE_TYPE"> <property name="DeviceType" type="u" access="read" tp:type="NM_DEVICE_TYPE">
<tp:docstring> <tp:docstring>
The general type of the network device; ie Ethernet, WiFi, etc. The general type of the network device; ie Ethernet, WiFi, etc.

View File

@@ -132,7 +132,7 @@ libnm_glib_la_LIBADD = \
$(GUDEV_LIBS) $(GUDEV_LIBS)
libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \ libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \
-version-info "4:2:2" -version-info "5:0:3"
noinst_PROGRAMS = libnm-glib-test noinst_PROGRAMS = libnm-glib-test

View File

@@ -68,6 +68,7 @@ global:
nm_device_get_capabilities; nm_device_get_capabilities;
nm_device_get_dhcp4_config; nm_device_get_dhcp4_config;
nm_device_get_driver; nm_device_get_driver;
nm_device_get_firmware_missing;
nm_device_get_iface; nm_device_get_iface;
nm_device_get_ip4_config; nm_device_get_ip4_config;
nm_device_get_ip6_config; nm_device_get_ip6_config;

View File

@@ -18,7 +18,7 @@
* Boston, MA 02110-1301 USA. * Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2008 Red Hat, Inc. * Copyright (C) 2007 - 2010 Red Hat, Inc.
*/ */
#include <string.h> #include <string.h>
@@ -53,6 +53,7 @@ typedef struct {
char *driver; char *driver;
guint32 capabilities; guint32 capabilities;
gboolean managed; gboolean managed;
gboolean firmware_missing;
NMIP4Config *ip4_config; NMIP4Config *ip4_config;
gboolean null_ip4_config; gboolean null_ip4_config;
NMDHCP4Config *dhcp4_config; NMDHCP4Config *dhcp4_config;
@@ -75,6 +76,7 @@ enum {
PROP_DRIVER, PROP_DRIVER,
PROP_CAPABILITIES, PROP_CAPABILITIES,
PROP_MANAGED, PROP_MANAGED,
PROP_FIRMWARE_MISSING,
PROP_IP4_CONFIG, PROP_IP4_CONFIG,
PROP_DHCP4_CONFIG, PROP_DHCP4_CONFIG,
PROP_IP6_CONFIG, PROP_IP6_CONFIG,
@@ -268,15 +270,16 @@ register_for_property_changed (NMDevice *device)
{ {
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
const NMPropertiesChangedInfo property_changed_info[] = { const NMPropertiesChangedInfo property_changed_info[] = {
{ NM_DEVICE_UDI, _nm_object_demarshal_generic, &priv->udi }, { NM_DEVICE_UDI, _nm_object_demarshal_generic, &priv->udi },
{ NM_DEVICE_INTERFACE, _nm_object_demarshal_generic, &priv->iface }, { NM_DEVICE_INTERFACE, _nm_object_demarshal_generic, &priv->iface },
{ NM_DEVICE_DRIVER, _nm_object_demarshal_generic, &priv->driver }, { NM_DEVICE_DRIVER, _nm_object_demarshal_generic, &priv->driver },
{ NM_DEVICE_CAPABILITIES, _nm_object_demarshal_generic, &priv->capabilities }, { NM_DEVICE_CAPABILITIES, _nm_object_demarshal_generic, &priv->capabilities },
{ NM_DEVICE_MANAGED, _nm_object_demarshal_generic, &priv->managed }, { NM_DEVICE_MANAGED, _nm_object_demarshal_generic, &priv->managed },
{ NM_DEVICE_IP4_CONFIG, demarshal_ip4_config, &priv->ip4_config }, { NM_DEVICE_FIRMWARE_MISSING, _nm_object_demarshal_generic, &priv->firmware_missing },
{ NM_DEVICE_DHCP4_CONFIG, demarshal_dhcp4_config, &priv->dhcp4_config }, { NM_DEVICE_IP4_CONFIG, demarshal_ip4_config, &priv->ip4_config },
{ NM_DEVICE_IP6_CONFIG, demarshal_ip6_config, &priv->ip6_config }, { NM_DEVICE_DHCP4_CONFIG, demarshal_dhcp4_config, &priv->dhcp4_config },
{ NM_DEVICE_DHCP6_CONFIG, demarshal_dhcp6_config, &priv->dhcp6_config }, { NM_DEVICE_IP6_CONFIG, demarshal_ip6_config, &priv->ip6_config },
{ NM_DEVICE_DHCP6_CONFIG, demarshal_dhcp6_config, &priv->dhcp6_config },
{ NULL }, { NULL },
}; };
@@ -408,6 +411,9 @@ get_property (GObject *object,
case PROP_MANAGED: case PROP_MANAGED:
g_value_set_boolean (value, nm_device_get_managed (device)); g_value_set_boolean (value, nm_device_get_managed (device));
break; break;
case PROP_FIRMWARE_MISSING:
g_value_set_boolean (value, nm_device_get_firmware_missing (device));
break;
case PROP_IP4_CONFIG: case PROP_IP4_CONFIG:
g_value_set_object (value, nm_device_get_ip4_config (device)); g_value_set_object (value, nm_device_get_ip4_config (device));
break; break;
@@ -515,6 +521,20 @@ nm_device_class_init (NMDeviceClass *device_class)
FALSE, FALSE,
G_PARAM_READABLE)); G_PARAM_READABLE));
/**
* NMDevice:firmware-missing:
*
* When %TRUE indicates the device is likely missing firmware required
* for its operation.
**/
g_object_class_install_property
(object_class, PROP_FIRMWARE_MISSING,
g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING,
"FirmwareMissing",
"Firmware missing",
FALSE,
G_PARAM_READABLE));
/** /**
* NMDevice:ip4-config: * NMDevice:ip4-config:
* *
@@ -829,6 +849,33 @@ nm_device_get_managed (NMDevice *device)
return priv->managed; return priv->managed;
} }
/**
* nm_device_get_firmware_missing:
* @device: a #NMDevice
*
* Indicates that firmware required for the device's operation is likely
* to be missing.
*
* Returns: %TRUE if firmware required for the device's operation is likely
* to be missing.
**/
gboolean
nm_device_get_firmware_missing (NMDevice *device)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (device), 0);
priv = NM_DEVICE_GET_PRIVATE (device);
if (!priv->firmware_missing) {
priv->firmware_missing = _nm_object_get_boolean_property (NM_OBJECT (device),
NM_DBUS_INTERFACE_DEVICE,
"FirmwareMissing");
}
return priv->firmware_missing;
}
/** /**
* nm_device_get_ip4_config: * nm_device_get_ip4_config:
* @device: a #NMDevice * @device: a #NMDevice

View File

@@ -18,7 +18,7 @@
* Boston, MA 02110-1301 USA. * Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2008 Red Hat, Inc. * Copyright (C) 2007 - 2010 Red Hat, Inc.
*/ */
#ifndef NM_DEVICE_H #ifndef NM_DEVICE_H
@@ -49,6 +49,7 @@ G_BEGIN_DECLS
#define NM_DEVICE_DRIVER "driver" #define NM_DEVICE_DRIVER "driver"
#define NM_DEVICE_CAPABILITIES "capabilities" #define NM_DEVICE_CAPABILITIES "capabilities"
#define NM_DEVICE_MANAGED "managed" #define NM_DEVICE_MANAGED "managed"
#define NM_DEVICE_FIRMWARE_MISSING "firmware-missing"
#define NM_DEVICE_IP4_CONFIG "ip4-config" #define NM_DEVICE_IP4_CONFIG "ip4-config"
#define NM_DEVICE_DHCP4_CONFIG "dhcp4-config" #define NM_DEVICE_DHCP4_CONFIG "dhcp4-config"
#define NM_DEVICE_IP6_CONFIG "ip6-config" #define NM_DEVICE_IP6_CONFIG "ip6-config"
@@ -83,18 +84,19 @@ GType nm_device_get_type (void);
GObject * nm_device_new (DBusGConnection *connection, const char *path); GObject * nm_device_new (DBusGConnection *connection, const char *path);
const char * nm_device_get_iface (NMDevice *device); const char * nm_device_get_iface (NMDevice *device);
const char * nm_device_get_udi (NMDevice *device); const char * nm_device_get_udi (NMDevice *device);
const char * nm_device_get_driver (NMDevice *device); const char * nm_device_get_driver (NMDevice *device);
guint32 nm_device_get_capabilities (NMDevice *device); guint32 nm_device_get_capabilities (NMDevice *device);
gboolean nm_device_get_managed (NMDevice *device); gboolean nm_device_get_managed (NMDevice *device);
NMIP4Config * nm_device_get_ip4_config (NMDevice *device); gboolean nm_device_get_firmware_missing (NMDevice *device);
NMDHCP4Config * nm_device_get_dhcp4_config (NMDevice *device); NMIP4Config * nm_device_get_ip4_config (NMDevice *device);
NMIP6Config * nm_device_get_ip6_config (NMDevice *device); NMDHCP4Config * nm_device_get_dhcp4_config (NMDevice *device);
NMDHCP6Config * nm_device_get_dhcp6_config (NMDevice *device); NMIP6Config * nm_device_get_ip6_config (NMDevice *device);
NMDeviceState nm_device_get_state (NMDevice *device); NMDHCP6Config * nm_device_get_dhcp6_config (NMDevice *device);
const char * nm_device_get_product (NMDevice *device); NMDeviceState nm_device_get_state (NMDevice *device);
const char * nm_device_get_vendor (NMDevice *device); const char * nm_device_get_product (NMDevice *device);
const char * nm_device_get_vendor (NMDevice *device);
typedef void (*NMDeviceDeactivateFn) (NMDevice *device, GError *error, gpointer user_data); typedef void (*NMDeviceDeactivateFn) (NMDevice *device, GError *error, gpointer user_data);

View File

@@ -169,6 +169,13 @@ nm_device_interface_init (gpointer g_iface)
FALSE, FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_interface_install_property
(g_iface, g_param_spec_boolean (NM_DEVICE_INTERFACE_FIRMWARE_MISSING,
"FirmwareMissing",
"Firmware missing",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_interface_install_property g_object_interface_install_property
(g_iface, (g_iface,
g_param_spec_string (NM_DEVICE_INTERFACE_TYPE_DESC, g_param_spec_string (NM_DEVICE_INTERFACE_TYPE_DESC,

View File

@@ -16,7 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2008 Red Hat, Inc. * Copyright (C) 2007 - 2010 Red Hat, Inc.
*/ */
#ifndef NM_DEVICE_INTERFACE_H #ifndef NM_DEVICE_INTERFACE_H
@@ -45,21 +45,22 @@ typedef enum
#define NM_DEVICE_INTERFACE_ERROR (nm_device_interface_error_quark ()) #define NM_DEVICE_INTERFACE_ERROR (nm_device_interface_error_quark ())
#define NM_TYPE_DEVICE_INTERFACE_ERROR (nm_device_interface_error_get_type ()) #define NM_TYPE_DEVICE_INTERFACE_ERROR (nm_device_interface_error_get_type ())
#define NM_DEVICE_INTERFACE_UDI "udi" #define NM_DEVICE_INTERFACE_UDI "udi"
#define NM_DEVICE_INTERFACE_IFACE "interface" #define NM_DEVICE_INTERFACE_IFACE "interface"
#define NM_DEVICE_INTERFACE_DRIVER "driver" #define NM_DEVICE_INTERFACE_DRIVER "driver"
#define NM_DEVICE_INTERFACE_CAPABILITIES "capabilities" #define NM_DEVICE_INTERFACE_CAPABILITIES "capabilities"
#define NM_DEVICE_INTERFACE_IP4_ADDRESS "ip4-address" #define NM_DEVICE_INTERFACE_IP4_ADDRESS "ip4-address"
#define NM_DEVICE_INTERFACE_IP4_CONFIG "ip4-config" #define NM_DEVICE_INTERFACE_IP4_CONFIG "ip4-config"
#define NM_DEVICE_INTERFACE_DHCP4_CONFIG "dhcp4-config" #define NM_DEVICE_INTERFACE_DHCP4_CONFIG "dhcp4-config"
#define NM_DEVICE_INTERFACE_IP6_CONFIG "ip6-config" #define NM_DEVICE_INTERFACE_IP6_CONFIG "ip6-config"
#define NM_DEVICE_INTERFACE_DHCP6_CONFIG "dhcp6-config" #define NM_DEVICE_INTERFACE_DHCP6_CONFIG "dhcp6-config"
#define NM_DEVICE_INTERFACE_STATE "state" #define NM_DEVICE_INTERFACE_STATE "state"
#define NM_DEVICE_INTERFACE_DEVICE_TYPE "device-type" /* ugh */ #define NM_DEVICE_INTERFACE_DEVICE_TYPE "device-type" /* ugh */
#define NM_DEVICE_INTERFACE_MANAGED "managed" #define NM_DEVICE_INTERFACE_MANAGED "managed"
#define NM_DEVICE_INTERFACE_TYPE_DESC "type-desc" /* Internal only */ #define NM_DEVICE_INTERFACE_FIRMWARE_MISSING "firmware-missing"
#define NM_DEVICE_INTERFACE_RFKILL_TYPE "rfkill-type" /* Internal only */ #define NM_DEVICE_INTERFACE_TYPE_DESC "type-desc" /* Internal only */
#define NM_DEVICE_INTERFACE_IFINDEX "ifindex" /* Internal only */ #define NM_DEVICE_INTERFACE_RFKILL_TYPE "rfkill-type" /* Internal only */
#define NM_DEVICE_INTERFACE_IFINDEX "ifindex" /* Internal only */
typedef enum { typedef enum {
NM_DEVICE_INTERFACE_PROP_FIRST = 0x1000, NM_DEVICE_INTERFACE_PROP_FIRST = 0x1000,
@@ -76,6 +77,7 @@ typedef enum {
NM_DEVICE_INTERFACE_PROP_STATE, NM_DEVICE_INTERFACE_PROP_STATE,
NM_DEVICE_INTERFACE_PROP_DEVICE_TYPE, NM_DEVICE_INTERFACE_PROP_DEVICE_TYPE,
NM_DEVICE_INTERFACE_PROP_MANAGED, NM_DEVICE_INTERFACE_PROP_MANAGED,
NM_DEVICE_INTERFACE_PROP_FIRMWARE_MISSING,
NM_DEVICE_INTERFACE_PROP_TYPE_DESC, NM_DEVICE_INTERFACE_PROP_TYPE_DESC,
NM_DEVICE_INTERFACE_PROP_RFKILL_TYPE, NM_DEVICE_INTERFACE_PROP_RFKILL_TYPE,
NM_DEVICE_INTERFACE_PROP_IFINDEX, NM_DEVICE_INTERFACE_PROP_IFINDEX,

View File

@@ -92,6 +92,7 @@ typedef struct {
char * driver; char * driver;
gboolean managed; /* whether managed by NM or not */ gboolean managed; /* whether managed by NM or not */
RfKillType rfkill_type; RfKillType rfkill_type;
gboolean firmware_missing;
guint32 ip4_address; guint32 ip4_address;
@@ -492,6 +493,11 @@ nm_device_get_act_request (NMDevice *self)
gboolean gboolean
nm_device_is_available (NMDevice *self) nm_device_is_available (NMDevice *self)
{ {
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->firmware_missing)
return FALSE;
if (NM_DEVICE_GET_CLASS (self)->is_available) if (NM_DEVICE_GET_CLASS (self)->is_available)
return NM_DEVICE_GET_CLASS (self)->is_available (self); return NM_DEVICE_GET_CLASS (self)->is_available (self);
return TRUE; return TRUE;
@@ -3384,6 +3390,9 @@ set_property (GObject *object, guint prop_id,
case NM_DEVICE_INTERFACE_PROP_MANAGED: case NM_DEVICE_INTERFACE_PROP_MANAGED:
priv->managed = g_value_get_boolean (value); priv->managed = g_value_get_boolean (value);
break; break;
case NM_DEVICE_INTERFACE_PROP_FIRMWARE_MISSING:
priv->firmware_missing = g_value_get_boolean (value);
break;
case NM_DEVICE_INTERFACE_PROP_DEVICE_TYPE: case NM_DEVICE_INTERFACE_PROP_DEVICE_TYPE:
g_return_if_fail (priv->type == NM_DEVICE_TYPE_UNKNOWN); g_return_if_fail (priv->type == NM_DEVICE_TYPE_UNKNOWN);
priv->type = g_value_get_uint (value); priv->type = g_value_get_uint (value);
@@ -3471,6 +3480,9 @@ get_property (GObject *object, guint prop_id,
case NM_DEVICE_INTERFACE_PROP_MANAGED: case NM_DEVICE_INTERFACE_PROP_MANAGED:
g_value_set_boolean (value, priv->managed); g_value_set_boolean (value, priv->managed);
break; break;
case NM_DEVICE_INTERFACE_PROP_FIRMWARE_MISSING:
g_value_set_boolean (value, priv->firmware_missing);
break;
case NM_DEVICE_INTERFACE_PROP_TYPE_DESC: case NM_DEVICE_INTERFACE_PROP_TYPE_DESC:
g_value_set_string (value, priv->type_desc); g_value_set_string (value, priv->type_desc);
break; break;
@@ -3563,6 +3575,10 @@ nm_device_class_init (NMDeviceClass *klass)
NM_DEVICE_INTERFACE_PROP_MANAGED, NM_DEVICE_INTERFACE_PROP_MANAGED,
NM_DEVICE_INTERFACE_MANAGED); NM_DEVICE_INTERFACE_MANAGED);
g_object_class_override_property (object_class,
NM_DEVICE_INTERFACE_PROP_FIRMWARE_MISSING,
NM_DEVICE_INTERFACE_FIRMWARE_MISSING);
g_object_class_override_property (object_class, g_object_class_override_property (object_class,
NM_DEVICE_INTERFACE_PROP_TYPE_DESC, NM_DEVICE_INTERFACE_PROP_TYPE_DESC,
NM_DEVICE_INTERFACE_TYPE_DESC); NM_DEVICE_INTERFACE_TYPE_DESC);
@@ -3607,6 +3623,17 @@ unavailable_to_disconnected (gpointer user_data)
return FALSE; return FALSE;
} }
static void
set_firmware_missing (NMDevice *self, gboolean new_missing)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->firmware_missing != new_missing) {
priv->firmware_missing = new_missing;
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_FIRMWARE_MISSING);
}
}
void void
nm_device_state_changed (NMDevice *device, nm_device_state_changed (NMDevice *device,
NMDeviceState state, NMDeviceState state,
@@ -3639,6 +3666,7 @@ nm_device_state_changed (NMDevice *device,
*/ */
switch (state) { switch (state) {
case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNMANAGED:
set_firmware_missing (device, FALSE);
if (old_state > NM_DEVICE_STATE_UNMANAGED) if (old_state > NM_DEVICE_STATE_UNMANAGED)
nm_device_take_down (device, TRUE, reason); nm_device_take_down (device, TRUE, reason);
break; break;
@@ -3646,6 +3674,7 @@ nm_device_state_changed (NMDevice *device,
if (old_state == NM_DEVICE_STATE_UNMANAGED) { if (old_state == NM_DEVICE_STATE_UNMANAGED) {
if (!nm_device_bring_up (device, TRUE, &no_firmware) && no_firmware) { if (!nm_device_bring_up (device, TRUE, &no_firmware) && no_firmware) {
nm_log_warn (LOGD_HW, "%s: firmware may be missing.", nm_device_get_iface (device)); nm_log_warn (LOGD_HW, "%s: firmware may be missing.", nm_device_get_iface (device));
set_firmware_missing (device, TRUE);
} }
} }
/* Ensure the device gets deactivated in response to stuff like /* Ensure the device gets deactivated in response to stuff like