From d6a3eb003a41db98f536b6c253df42fa8be02d57 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 11 Jun 2009 20:49:22 -0400 Subject: [PATCH] libnm-glib: make nm_device_update_description() use libgudev not HAL You'll want latest udev-extras to get the ID_*_FROM_DATABASE rules. --- libnm-glib/Makefile.am | 56 ++++----- libnm-glib/nm-device.c | 259 +++++++++++++++++------------------------ 2 files changed, 135 insertions(+), 180 deletions(-) diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index dabf941b95..480abd768e 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -22,19 +22,19 @@ BUILT_SOURCES = \ lib_LTLIBRARIES = libnm_glib.la libnm_glib_vpn.la -libnm_glib_la_CFLAGS = \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(GCONF_CFLAGS) \ - $(GNOME_KEYRING_CFLAGS) +libnm_glib_la_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(GCONF_CFLAGS) \ + $(GUDEV_CFLAGS) libnmincludedir = $(includedir)/libnm-glib libnminclude_HEADERS = \ - libnm_glib.h \ - nm-object.h \ - nm-client.h \ - nm-device.h \ + libnm_glib.h \ + nm-object.h \ + nm-client.h \ + nm-device.h \ nm-device-ethernet.h \ nm-device-wifi.h \ nm-access-point.h \ @@ -54,23 +54,23 @@ libnminclude_HEADERS = \ nm-dhcp4-config.h libnm_glib_la_SOURCES = \ - libnm_glib.c \ - nm-object.c \ + libnm_glib.c \ + nm-object.c \ nm-object-private.h \ - nm-client.c \ - nm-dbus-utils.c \ - nm-dbus-utils.h \ - nm-device.c \ - nm-device-private.h \ + nm-client.c \ + nm-dbus-utils.c \ + nm-dbus-utils.h \ + nm-device.c \ + nm-device-private.h \ nm-device-ethernet.c \ nm-device-wifi.c \ - nm-access-point.c \ - nm-ip4-config.c \ - nm-settings.c \ - nm-gsm-device.c \ - nm-cdma-device.c \ + nm-access-point.c \ + nm-ip4-config.c \ + nm-settings.c \ + nm-gsm-device.c \ + nm-cdma-device.c \ nm-serial-device.c \ - nm-vpn-connection.c \ + nm-vpn-connection.c \ nm-types.c \ nm-types-private.h \ nm-object-cache.c \ @@ -82,12 +82,12 @@ libnm_glib_la_SOURCES = \ nm-dhcp4-config.c libnm_glib_la_LIBADD = \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(top_builddir)/marshallers/libmarshallers.la \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) \ - $(GCONF_LIBS) \ - $(GNOME_KEYRING_LIBS) + $(top_builddir)/libnm-util/libnm-util.la \ + $(top_builddir)/marshallers/libmarshallers.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) \ + $(GCONF_LIBS) \ + $(GUDEV_LIBS) libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm_glib.ver \ -version-info "1:0:1" diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 84cabcea42..5cb568c273 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -23,6 +23,9 @@ #include +#define G_UDEV_API_IS_SUBJECT_TO_CHANGE +#include + #include "NetworkManager.h" #include "nm-device-ethernet.h" #include "nm-device-wifi.h" @@ -54,6 +57,8 @@ typedef struct { NMDHCP4Config *dhcp4_config; gboolean null_dhcp4_config; NMDeviceState state; + + GUdevClient *client; char *product; char *vendor; } NMDevicePrivate; @@ -89,7 +94,6 @@ nm_device_init (NMDevice *device) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); priv->state = NM_DEVICE_STATE_UNKNOWN; - priv->disposed = FALSE; } static gboolean @@ -267,6 +271,8 @@ dispose (GObject *object) g_object_unref (priv->ip4_config); if (priv->dhcp4_config) g_object_unref (priv->dhcp4_config); + if (priv->client) + g_object_unref (priv->client); G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); } @@ -361,13 +367,13 @@ nm_device_class_init (NMDeviceClass *device_class) /** * NMDevice:udi: * - * The HAL UDI of the device. + * The Unique Device Identifier of the device. **/ g_object_class_install_property (object_class, PROP_UDI, g_param_spec_string (NM_DEVICE_UDI, "UDI", - "HAL UDI", + "Unique Device Identifier", NULL, G_PARAM_READABLE)); @@ -596,10 +602,11 @@ nm_device_get_iface (NMDevice *device) * nm_device_get_udi: * @device: a #NMDevice * - * Gets the HAL UDI of the #NMDevice. + * Gets the Unique Device Identifier of the #NMDevice. * - * Returns: the HAL UDI of the device. This is the internal string used by the - * device, and must not be modified. + * Returns: the Unique Device Identifier of the device. This identifier may be + * used to gather more information about the device from various operating + * system services like udev or sysfs. **/ const char * nm_device_get_udi (NMDevice *device) @@ -788,179 +795,127 @@ nm_device_get_state (NMDevice *device) return priv->state; } -static char * -get_ancestor_device (NMDevice *device, - DBusGConnection *connection, - const char *udi, - gboolean want_origdev) +/* From hostap, Copyright (c) 2002-2005, Jouni Malinen */ + +static int hex2num (char c) { - DBusGProxy *proxy; - GError *err = NULL; - char *parent = NULL; + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} - g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (udi != NULL, NULL); +static int hex2byte (const char *hex) +{ + int a, b; + a = hex2num(*hex++); + if (a < 0) + return -1; + b = hex2num(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} - proxy = dbus_g_proxy_new_for_name (connection, "org.freedesktop.Hal", udi, "org.freedesktop.Hal.Device"); - if (!proxy) +/* End from hostap */ + +static char * +get_decoded_property (GUdevDevice *device, const char *property) +{ + const char *orig, *p; + char *unescaped, *n; + guint len; + + p = orig = g_udev_device_get_property (device, property); + if (!orig) return NULL; - if (want_origdev) { - gboolean serial = FALSE; - - if (NM_IS_GSM_DEVICE (device) || NM_IS_CDMA_DEVICE (device)) - serial = TRUE; - - dbus_g_proxy_call (proxy, "GetPropertyString", NULL, - G_TYPE_STRING, serial ? "serial.originating_device" : "net.originating_device", - G_TYPE_INVALID, - G_TYPE_STRING, &parent, - G_TYPE_INVALID); - - if (!parent) { - /* Older HAL uses 'physical_device' */ - dbus_g_proxy_call (proxy, "GetPropertyString", &err, - G_TYPE_STRING, serial ? "serial.physical_device" : "net.physical_device", - G_TYPE_INVALID, - G_TYPE_STRING, &parent, - G_TYPE_INVALID); + len = strlen (orig); + n = unescaped = g_malloc0 (len + 1); + while (*p) { + if ((len >= 4) && (*p == '\\') && (*(p+1) == 'x')) { + *n++ = (char) hex2byte (p + 2); + p += 4; + len -= 4; + } else { + *n++ = *p++; + len--; } - - if (err || !parent) { - g_warning ("Error getting originating device info from HAL: %s", - err ? err->message : "unknown error"); - if (err) - g_error_free (err); - } - } else { - if (!dbus_g_proxy_call (proxy, "GetPropertyString", &err, - G_TYPE_STRING, "info.parent", - G_TYPE_INVALID, - G_TYPE_STRING, &parent, - G_TYPE_INVALID)) { - g_warning ("Error getting parent device info from HAL: %s", err->message); - g_error_free (err); - } } - g_object_unref (proxy); - return parent; -} - -static char * -proxy_get_string (DBusGProxy *proxy, - const char *property, - gboolean warn) -{ - GError *error = NULL; - char *result = NULL; - - g_return_val_if_fail (proxy != NULL, NULL); - g_return_val_if_fail (property != NULL, NULL); - - if (dbus_g_proxy_call (proxy, "GetPropertyString", &error, - G_TYPE_STRING, property, G_TYPE_INVALID, - G_TYPE_STRING, &result, G_TYPE_INVALID)) - return result; - - if (warn) { - g_warning ("Error getting HAL property '%s' from device '%s': %s", - property, dbus_g_proxy_get_path (proxy), - error ? error->message : "unknown"); - } - g_error_free (error); - return NULL; -} - -static gboolean -get_product_and_vendor (DBusGConnection *connection, - const char *udi, - char **product, - char **vendor) -{ - DBusGProxy *proxy; - char *tmp_product = NULL; - char *tmp_vendor = NULL; - char *subsys = NULL; - gboolean product_fallback = TRUE, vendor_fallback = TRUE; - gboolean warn = FALSE; - - g_return_val_if_fail (connection != NULL, FALSE); - g_return_val_if_fail (udi != NULL, FALSE); - - g_return_val_if_fail (product != NULL, FALSE); - g_return_val_if_fail (*product == NULL, FALSE); - - g_return_val_if_fail (vendor != NULL, FALSE); - g_return_val_if_fail (*vendor == NULL, FALSE); - - proxy = dbus_g_proxy_new_for_name (connection, "org.freedesktop.Hal", udi, "org.freedesktop.Hal.Device"); - if (!proxy) - return FALSE; - - subsys = proxy_get_string (proxy, "info.subsystem", warn); - if (subsys && !strcmp (subsys, "pci")) { - tmp_product = proxy_get_string (proxy, "pci.subsys_product", warn); - if (tmp_product) - product_fallback = FALSE; - - tmp_vendor = proxy_get_string (proxy, "pci.subsys_vendor", warn); - if (tmp_vendor) - vendor_fallback = FALSE; - } - g_free (subsys); - - if (product_fallback) - tmp_product = proxy_get_string (proxy, "info.product", warn); - if (vendor_fallback) - tmp_vendor = proxy_get_string (proxy, "info.vendor", warn); - - if (tmp_product && tmp_vendor) { - *product = tmp_product; - *vendor = tmp_vendor; - } else { - g_free (tmp_product); - g_free (tmp_vendor); - } - g_object_unref (proxy); - - return (*product && *vendor) ? TRUE : FALSE; + return unescaped; } static void nm_device_update_description (NMDevice *device) { NMDevicePrivate *priv; - DBusGConnection *connection; - const char *udi; - char *orig_dev_udi = NULL; - char *parent_udi = NULL; + const char *subsys[3] = { "net", "tty", NULL }; + GUdevDevice *udev_device = NULL, *tmpdev; + const char *ifname; + guint32 count = 0; + const char *vendor, *model; g_return_if_fail (NM_IS_DEVICE (device)); priv = NM_DEVICE_GET_PRIVATE (device); + if (!priv->client) { + priv->client = g_udev_client_new (subsys); + if (!priv->client) + return; + } + + ifname = nm_device_get_iface (device); + if (!ifname) + return; + + if (NM_IS_DEVICE_ETHERNET (device) || NM_IS_DEVICE_WIFI (device)) + udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname); + else if (NM_IS_GSM_DEVICE (device) || NM_IS_CDMA_DEVICE (device)) + udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname); + if (!udev_device) + return; + g_free (priv->product); priv->product = NULL; g_free (priv->vendor); priv->vendor = NULL; - connection = nm_object_get_connection (NM_OBJECT (device)); - g_return_if_fail (connection != NULL); + /* Walk up the chain of the device and its parents a few steps to grab + * vendor and device ID information off it. + */ + tmpdev = udev_device; + while ((count++ < 3) && tmpdev && (!priv->vendor || !priv->product)) { + if (!priv->vendor) + priv->vendor = get_decoded_property (tmpdev, "ID_VENDOR_ENC"); - /* First, get the udi of the originating device */ - udi = nm_device_get_udi (device); - orig_dev_udi = get_ancestor_device (device, connection, udi, TRUE); + if (!priv->product) + priv->product = get_decoded_property (tmpdev, "ID_MODEL_ENC"); - /* Get product and vendor off the originating device if possible */ - if (!get_product_and_vendor (connection, orig_dev_udi, &priv->product, &priv->vendor)) { - /* Try the parent of the originating device */ - parent_udi = get_ancestor_device (device, connection, orig_dev_udi, FALSE); - if (parent_udi) - get_product_and_vendor (connection, parent_udi, &priv->product, &priv->vendor); - g_free (parent_udi); + tmpdev = g_udev_device_get_parent (tmpdev); } - g_free (orig_dev_udi); + /* If we didn't get strings directly from the device, try database strings */ + tmpdev = udev_device; + count = 0; + while ((count++ < 3) && tmpdev && (!priv->vendor || !priv->product)) { + if (!priv->vendor) { + vendor = g_udev_device_get_property (tmpdev, "ID_VENDOR_FROM_DATABASE"); + if (vendor) + priv->vendor = g_strdup (vendor); + } + + if (!priv->product) { + model = g_udev_device_get_property (tmpdev, "ID_MODEL_FROM_DATABASE"); + if (model) + priv->product = g_strdup (model); + } + + tmpdev = g_udev_device_get_parent (tmpdev); + } _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_VENDOR); _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_PRODUCT);