[gnome-disk-utility/new-ui] Show port number of device, if available



commit 7bc36f0f887c74ebfdf3298befdbc955aa3b0989
Author: David Zeuthen <davidz redhat com>
Date:   Sat Nov 28 14:40:35 2009 -0500

    Show port number of device, if available

 src/gdu/Makefile.am                |    8 +-
 src/gdu/gdu-adapter.c              |   23 +++-
 src/gdu/gdu-adapter.h              |    2 +
 src/gdu/gdu-device.c               |   10 ++
 src/gdu/gdu-device.h               |    1 +
 src/gdu/gdu-pool.c                 |  236 +++++++++++++++++++++++++++-
 src/gdu/gdu-pool.h                 |   13 ++-
 src/gdu/gdu-port.c                 |  314 ++++++++++++++++++++++++++++++++++++
 src/gdu/gdu-port.h                 |   75 +++++++++
 src/gdu/gdu-private.h              |    7 +-
 src/gdu/gdu-types.h                |    1 +
 src/gdu/gdu.h                      |    1 +
 src/palimpsest/gdu-section-drive.c |   37 +++++
 13 files changed, 719 insertions(+), 9 deletions(-)
---
diff --git a/src/gdu/Makefile.am b/src/gdu/Makefile.am
index b873e46..7594045 100644
--- a/src/gdu/Makefile.am
+++ b/src/gdu/Makefile.am
@@ -4,6 +4,7 @@ BUILT_SOURCES =                                         	\
         devkit-disks-daemon-glue.h                      	\
         devkit-disks-device-glue.h				\
         devkit-disks-adapter-glue.h				\
+        devkit-disks-port-glue.h				\
 	gdu-marshal.h			gdu-marshal.c
 
 gdu-marshal.h: gdu-marshal.list
@@ -21,6 +22,9 @@ devkit-disks-device-glue.h: /usr/share/dbus-1/interfaces/org.freedesktop.DeviceK
 devkit-disks-adapter-glue.h: /usr/share/dbus-1/interfaces/org.freedesktop.DeviceKit.Disks.Adapter.xml Makefile.am
 	dbus-binding-tool --prefix=devkit_disks_daemon --mode=glib-client --output=devkit-disks-adapter-glue.h /usr/share/dbus-1/interfaces/org.freedesktop.DeviceKit.Disks.Adapter.xml
 
+devkit-disks-port-glue.h: /usr/share/dbus-1/interfaces/org.freedesktop.DeviceKit.Disks.Port.xml Makefile.am
+	dbus-binding-tool --prefix=devkit_disks_daemon --mode=glib-client --output=devkit-disks-port-glue.h /usr/share/dbus-1/interfaces/org.freedesktop.DeviceKit.Disks.Port.xml
+
 lib_LTLIBRARIES=libgdu.la
 
 libgduincludedir=$(includedir)/gnome-disk-utility/gdu
@@ -30,7 +34,8 @@ libgduinclude_HEADERS =              			\
 	gdu-types.h					\
 	gdu-callbacks.h					\
 	gdu-device.h					\
-	gdu-adapter.h				\
+	gdu-adapter.h					\
+	gdu-port.h					\
 	gdu-drive.h					\
 	gdu-linux-md-drive.h				\
 	gdu-error.h					\
@@ -52,6 +57,7 @@ libgdu_la_SOURCES =                                					\
 	gdu-pool.c				gdu-pool.h				\
 	gdu-device.c				gdu-device.h				\
 	gdu-adapter.c				gdu-adapter.h				\
+	gdu-port.c				gdu-port.h				\
 	gdu-drive.c				gdu-drive.h				\
 	gdu-linux-md-drive.c			gdu-linux-md-drive.h			\
 	gdu-volume.c				gdu-volume.h				\
diff --git a/src/gdu/gdu-adapter.c b/src/gdu/gdu-adapter.c
index 6290ac1..22b5e78 100644
--- a/src/gdu/gdu-adapter.c
+++ b/src/gdu/gdu-adapter.c
@@ -48,6 +48,8 @@ typedef struct
         gchar *vendor;
         gchar *model;
         gchar *driver;
+        gchar *fabric;
+        guint num_ports;
 } AdapterProperties;
 
 static void
@@ -64,6 +66,10 @@ collect_props (const char *key, const GValue *value, AdapterProperties *props)
                 props->model = g_value_dup_string (value);
         else if (strcmp (key, "Driver") == 0)
                 props->driver = g_value_dup_string (value);
+        else if (strcmp (key, "Fabric") == 0)
+                props->fabric = g_value_dup_string (value);
+        else if (strcmp (key, "NumPorts") == 0)
+                props->num_ports = g_value_get_uint (value);
         else
                 handled = FALSE;
 
@@ -78,6 +84,7 @@ adapter_properties_free (AdapterProperties *props)
         g_free (props->vendor);
         g_free (props->model);
         g_free (props->driver);
+        g_free (props->fabric);
         g_free (props);
 }
 
@@ -119,12 +126,14 @@ adapter_properties_get (DBusGConnection *bus,
 
         g_hash_table_unref (hash_table);
 
-#if 0
+#if 1
         g_print ("----------------------------------------------------------------------\n");
         g_print ("native_path: %s\n", props->native_path);
         g_print ("vendor:      %s\n", props->vendor);
         g_print ("model:       %s\n", props->model);
         g_print ("driver:      %s\n", props->driver);
+        g_print ("fabric:      %s\n", props->fabric);
+        g_print ("num_ports:   %d\n", props->num_ports);
 #endif
 
 out:
@@ -313,3 +322,15 @@ gdu_adapter_get_driver (GduAdapter *adapter)
 {
         return adapter->priv->props->driver;
 }
+
+const gchar *
+gdu_adapter_get_fabric (GduAdapter *adapter)
+{
+        return adapter->priv->props->fabric;
+}
+
+guint
+gdu_adapter_get_num_ports (GduAdapter *adapter)
+{
+        return adapter->priv->props->num_ports;
+}
diff --git a/src/gdu/gdu-adapter.h b/src/gdu/gdu-adapter.h
index eb69307..fd57b5b 100644
--- a/src/gdu/gdu-adapter.h
+++ b/src/gdu/gdu-adapter.h
@@ -69,6 +69,8 @@ const gchar *gdu_adapter_get_native_path       (GduAdapter   *adapter);
 const gchar *gdu_adapter_get_vendor            (GduAdapter   *adapter);
 const gchar *gdu_adapter_get_model             (GduAdapter   *adapter);
 const gchar *gdu_adapter_get_driver            (GduAdapter   *adapter);
+const gchar *gdu_adapter_get_fabric            (GduAdapter   *adapter);
+guint        gdu_adapter_get_num_ports         (GduAdapter   *adapter);
 
 G_END_DECLS
 
diff --git a/src/gdu/gdu-device.c b/src/gdu/gdu-device.c
index dd0ecda..88b977c 100644
--- a/src/gdu/gdu-device.c
+++ b/src/gdu/gdu-device.c
@@ -124,6 +124,7 @@ typedef struct
         guint    drive_rotation_rate;
         char    *drive_write_cache;
         char    *drive_adapter;
+        char    *drive_port;
 
         gboolean optical_disc_is_blank;
         gboolean optical_disc_is_appendable;
@@ -321,6 +322,8 @@ collect_props (const char *key, const GValue *value, DeviceProperties *props)
                 props->drive_write_cache = g_strdup (g_value_get_string (value));
         else if (strcmp (key, "DriveAdapter") == 0)
                 props->drive_adapter = g_strdup (g_value_get_boxed (value));
+        else if (strcmp (key, "DrivePort") == 0)
+                props->drive_port = g_strdup (g_value_get_boxed (value));
 
         else if (strcmp (key, "OpticalDiscIsBlank") == 0)
                 props->optical_disc_is_blank = g_value_get_boolean (value);
@@ -442,6 +445,7 @@ device_properties_free (DeviceProperties *props)
         g_free (props->drive_media);
         g_free (props->drive_write_cache);
         g_free (props->drive_adapter);
+        g_free (props->drive_port);
 
         g_free (props->drive_ata_smart_status);
         g_free (props->drive_ata_smart_blob);
@@ -1092,6 +1096,12 @@ gdu_device_drive_get_adapter (GduDevice *device)
         return device->priv->props->drive_adapter;
 }
 
+const char *
+gdu_device_drive_get_port (GduDevice *device)
+{
+        return device->priv->props->drive_port;
+}
+
 gboolean
 gdu_device_drive_get_is_media_ejectable (GduDevice *device)
 {
diff --git a/src/gdu/gdu-device.h b/src/gdu/gdu-device.h
index d294450..78d9855 100644
--- a/src/gdu/gdu-device.h
+++ b/src/gdu/gdu-device.h
@@ -145,6 +145,7 @@ gboolean gdu_device_drive_get_is_rotational (GduDevice *device);
 guint    gdu_device_drive_get_rotation_rate (GduDevice *device);
 const char *gdu_device_drive_get_write_cache (GduDevice *device);
 const char *gdu_device_drive_get_adapter (GduDevice *device);
+const char *gdu_device_drive_get_port (GduDevice *device);
 
 gboolean gdu_device_optical_disc_get_is_blank (GduDevice *device);
 gboolean gdu_device_optical_disc_get_is_appendable (GduDevice *device);
diff --git a/src/gdu/gdu-pool.c b/src/gdu/gdu-pool.c
index a4b232d..69c1c5f 100644
--- a/src/gdu/gdu-pool.c
+++ b/src/gdu/gdu-pool.c
@@ -28,6 +28,7 @@
 #include "gdu-presentable.h"
 #include "gdu-device.h"
 #include "gdu-adapter.h"
+#include "gdu-port.h"
 #include "gdu-drive.h"
 #include "gdu-linux-md-drive.h"
 #include "gdu-volume.h"
@@ -54,6 +55,9 @@ enum {
         ADAPTER_ADDED,
         ADAPTER_REMOVED,
         ADAPTER_CHANGED,
+        PORT_ADDED,
+        PORT_REMOVED,
+        PORT_CHANGED,
         PRESENTABLE_ADDED,
         PRESENTABLE_REMOVED,
         PRESENTABLE_CHANGED,
@@ -79,8 +83,11 @@ struct _GduPoolPrivate
         /* the current set of devices we know about */
         GHashTable *object_path_to_device;
 
-        /* the current set of devices we know about */
+        /* the current set of adapters we know about */
         GHashTable *object_path_to_adapter;
+
+        /* the current set of ports we know about */
+        GHashTable *object_path_to_port;
 };
 
 G_DEFINE_TYPE (GduPool, gdu_pool, G_TYPE_OBJECT);
@@ -100,6 +107,8 @@ gdu_pool_finalize (GduPool *pool)
 
         g_hash_table_unref (pool->priv->object_path_to_adapter);
 
+        g_hash_table_unref (pool->priv->object_path_to_port);
+
         g_list_foreach (pool->priv->presentables, (GFunc) g_object_unref, NULL);
         g_list_free (pool->priv->presentables);
 
@@ -239,6 +248,58 @@ gdu_pool_class_init (GduPoolClass *klass)
                               G_TYPE_NONE, 1,
                               GDU_TYPE_ADAPTER);
 
+        /**
+         * GduPool::port-added
+         * @pool: The #GduPool emitting the signal.
+         * @port: The #GduPort that was added.
+         *
+         * Emitted when @port is added to @pool.
+         **/
+        signals[PORT_ADDED] =
+                g_signal_new ("port-added",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GduPoolClass, port_added),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE, 1,
+                              GDU_TYPE_PORT);
+
+        /**
+         * GduPool::port-removed
+         * @pool: The #GduPool emitting the signal.
+         * @port: The #GduPort that was removed.
+         *
+         * Emitted when @port is removed from @pool. Recipients
+         * should release references to @port.
+         **/
+        signals[PORT_REMOVED] =
+                g_signal_new ("port-removed",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GduPoolClass, port_removed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE, 1,
+                              GDU_TYPE_PORT);
+
+        /**
+         * GduPool::port-changed
+         * @pool: The #GduPool emitting the signal.
+         * @port: A #GduPort.
+         *
+         * Emitted when @port is changed.
+         **/
+        signals[PORT_CHANGED] =
+                g_signal_new ("port-changed",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GduPoolClass, port_changed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE, 1,
+                              GDU_TYPE_PORT);
+
 
         /**
          * GduPool::presentable-added
@@ -356,6 +417,11 @@ gdu_pool_init (GduPool *pool)
                                                                        g_str_equal,
                                                                        NULL,
                                                                        g_object_unref);
+
+        pool->priv->object_path_to_port = g_hash_table_new_full (g_str_hash,
+                                                                 g_str_equal,
+                                                                 NULL,
+                                                                 g_object_unref);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -1183,6 +1249,96 @@ adapter_changed_signal_handler (DBusGProxy *proxy, const char *object_path, gpoi
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static void
+port_changed_signal_handler (DBusGProxy *proxy, const char *object_path, gpointer user_data);
+
+static void
+port_added_signal_handler (DBusGProxy *proxy, const char *object_path, gpointer user_data)
+{
+        GduPool *pool;
+        GduPort *port;
+
+        pool = GDU_POOL (user_data);
+
+        port = gdu_pool_get_port_by_object_path (pool, object_path);
+        if (port != NULL) {
+                g_object_unref (port);
+                g_warning ("Treating add for previously added port %s as change", object_path);
+                port_changed_signal_handler (proxy, object_path, user_data);
+                goto out;
+        }
+
+        port = _gdu_port_new_from_object_path (pool, object_path);
+        if (port == NULL)
+                goto out;
+
+        g_hash_table_insert (pool->priv->object_path_to_port,
+                             (gpointer) gdu_port_get_object_path (port),
+                             port);
+        g_signal_emit (pool, signals[PORT_ADDED], 0, port);
+        //g_debug ("Added port %s", object_path);
+
+        recompute_presentables (pool);
+
+ out:
+        ;
+}
+
+static void
+port_removed_signal_handler (DBusGProxy *proxy, const char *object_path, gpointer user_data)
+{
+        GduPool *pool;
+        GduPort *port;
+
+        pool = GDU_POOL (user_data);
+
+        port = gdu_pool_get_port_by_object_path (pool, object_path);
+        if (port == NULL) {
+                g_warning ("No port to remove for remove %s", object_path);
+                goto out;
+        }
+
+        g_hash_table_remove (pool->priv->object_path_to_port,
+                             gdu_port_get_object_path (port));
+        g_signal_emit (pool, signals[PORT_REMOVED], 0, port);
+        g_signal_emit_by_name (port, "removed");
+        g_object_unref (port);
+        g_debug ("Removed port %s", object_path);
+
+        recompute_presentables (pool);
+
+ out:
+        ;
+}
+
+static void
+port_changed_signal_handler (DBusGProxy *proxy, const char *object_path, gpointer user_data)
+{
+        GduPool *pool;
+        GduPort *port;
+
+        pool = GDU_POOL (user_data);
+
+        port = gdu_pool_get_port_by_object_path (pool, object_path);
+        if (port == NULL) {
+                g_warning ("Ignoring change event on non-existant port %s", object_path);
+                goto out;
+        }
+
+        if (_gdu_port_changed (port)) {
+                g_signal_emit (pool, signals[PORT_CHANGED], 0, port);
+                g_signal_emit_by_name (port, "changed");
+        }
+        g_object_unref (port);
+
+        recompute_presentables (pool);
+
+ out:
+        ;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 static gboolean
 get_properties (GduPool *pool)
 {
@@ -1264,6 +1420,7 @@ gdu_pool_new (void)
         int n;
         GPtrArray *devices;
         GPtrArray *adapters;
+        GPtrArray *ports;
         GduPool *pool;
         GError *error;
 
@@ -1324,6 +1481,16 @@ gdu_pool_new (void)
         dbus_g_proxy_connect_signal (pool->priv->proxy, "AdapterChanged",
                                      G_CALLBACK (adapter_changed_signal_handler), pool, NULL);
 
+        dbus_g_proxy_add_signal (pool->priv->proxy, "PortAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+        dbus_g_proxy_add_signal (pool->priv->proxy, "PortRemoved", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+        dbus_g_proxy_add_signal (pool->priv->proxy, "PortChanged", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+        dbus_g_proxy_connect_signal (pool->priv->proxy, "PortAdded",
+                                     G_CALLBACK (port_added_signal_handler), pool, NULL);
+        dbus_g_proxy_connect_signal (pool->priv->proxy, "PortRemoved",
+                                     G_CALLBACK (port_removed_signal_handler), pool, NULL);
+        dbus_g_proxy_connect_signal (pool->priv->proxy, "PortChanged",
+                                     G_CALLBACK (port_changed_signal_handler), pool, NULL);
+
         /* get the properties on the daemon object at / */
         if (!get_properties (pool)) {
                 g_warning ("Couldn't get daemon properties");
@@ -1377,6 +1544,28 @@ gdu_pool_new (void)
         g_ptr_array_foreach (adapters, (GFunc) g_free, NULL);
         g_ptr_array_free (adapters, TRUE);
 
+        /* prime the list of ports */
+        error = NULL;
+        if (!org_freedesktop_DeviceKit_Disks_enumerate_ports (pool->priv->proxy, &ports, &error)) {
+                g_warning ("Couldn't enumerate ports: %s", error->message);
+                g_error_free (error);
+                goto error;
+        }
+        for (n = 0; n < (int) ports->len; n++) {
+                const char *object_path;
+                GduPort *port;
+
+                object_path = ports->pdata[n];
+
+                port = _gdu_port_new_from_object_path (pool, object_path);
+
+                g_hash_table_insert (pool->priv->object_path_to_port,
+                                     (gpointer) gdu_port_get_object_path (port),
+                                     port);
+        }
+        g_ptr_array_foreach (ports, (GFunc) g_free, NULL);
+        g_ptr_array_free (ports, TRUE);
+
         /* and finally compute all presentables */
         recompute_presentables (pool);
 
@@ -1432,6 +1621,28 @@ gdu_pool_get_adapter_by_object_path (GduPool *pool, const char *object_path)
 }
 
 /**
+ * gdu_pool_get_by_object_path:
+ * @pool: the pool
+ * @object_path: the D-Bus object path
+ *
+ * Looks up #GduPort object for @object_path.
+ *
+ * Returns: A #GduPort object for @object_path, otherwise
+ * #NULL. Caller must unref this object using g_object_unref().
+ **/
+GduPort *
+gdu_pool_get_port_by_object_path (GduPool *pool, const char *object_path)
+{
+        GduPort *ret;
+
+        ret = g_hash_table_lookup (pool->priv->object_path_to_port, object_path);
+        if (ret != NULL) {
+                g_object_ref (ret);
+        }
+        return ret;
+}
+
+/**
  * gdu_pool_get_by_device_file:
  * @pool: the device pool
  * @device_file: the UNIX block special device file, e.g. /dev/sda1.
@@ -1617,7 +1828,7 @@ gdu_pool_get_devices (GduPool *pool)
  * gdu_pool_get_adapters:
  * @pool: A #GduPool.
  *
- * Get a list of all adapters. 
+ * Get a list of all adapters.
  *
  * Returns: A #GList of #GduAdapter objects. Caller must free this
  * (unref all objects, then use g_list_free()).
@@ -1635,6 +1846,27 @@ gdu_pool_get_adapters (GduPool *pool)
 }
 
 /**
+ * gdu_pool_get_ports:
+ * @pool: A #GduPool.
+ *
+ * Get a list of all ports.
+ *
+ * Returns: A #GList of #GduPort objects. Caller must free this
+ * (unref all objects, then use g_list_free()).
+ **/
+GList *
+gdu_pool_get_ports (GduPool *pool)
+{
+        GList *ret;
+
+        ret = NULL;
+
+        ret = g_hash_table_get_values (pool->priv->object_path_to_port);
+        g_list_foreach (ret, (GFunc) g_object_ref, NULL);
+        return ret;
+}
+
+/**
  * gdu_pool_get_presentables:
  * @pool: A #GduPool
  *
diff --git a/src/gdu/gdu-pool.h b/src/gdu/gdu-pool.h
index ea2ac84..a44a500 100644
--- a/src/gdu/gdu-pool.h
+++ b/src/gdu/gdu-pool.h
@@ -59,9 +59,13 @@ struct _GduPoolClass
         void (*device_changed) (GduPool *pool, GduDevice *device);
         void (*device_job_changed) (GduPool *pool, GduDevice *device);
 
-        void (*adapter_added) (GduPool *pool, GduDevice *device);
-        void (*adapter_removed) (GduPool *pool, GduDevice *device);
-        void (*adapter_changed) (GduPool *pool, GduDevice *device);
+        void (*adapter_added) (GduPool *pool, GduAdapter *adapter);
+        void (*adapter_removed) (GduPool *pool, GduAdapter *adapter);
+        void (*adapter_changed) (GduPool *pool, GduAdapter *adapter);
+
+        void (*port_added) (GduPool *pool, GduPort *port);
+        void (*port_removed) (GduPool *pool, GduPort *port);
+        void (*port_changed) (GduPool *pool, GduPort *port);
 
         void (*presentable_added) (GduPool *pool, GduPresentable *presentable);
         void (*presentable_removed) (GduPool *pool, GduPresentable *presentable);
@@ -94,6 +98,9 @@ GList      *gdu_pool_get_enclosed_presentables (GduPool *pool, GduPresentable *p
 GduAdapter *gdu_pool_get_adapter_by_object_path (GduPool *pool, const char *object_path);
 GList      *gdu_pool_get_adapters               (GduPool *pool);
 
+GduPort    *gdu_pool_get_port_by_object_path (GduPool *pool, const char *object_path);
+GList      *gdu_pool_get_ports               (GduPool *pool);
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 void gdu_pool_op_linux_md_start (GduPool *pool,
diff --git a/src/gdu/gdu-port.c b/src/gdu/gdu-port.c
new file mode 100644
index 0000000..c02c28f
--- /dev/null
+++ b/src/gdu/gdu-port.c
@@ -0,0 +1,314 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-port.c
+ *
+ * Copyright (C) 2009 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <dbus/dbus-glib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "gdu-private.h"
+#include "gdu-pool.h"
+#include "gdu-port.h"
+#include "devkit-disks-port-glue.h"
+
+/* --- SUCKY CODE BEGIN --- */
+
+/* This totally sucks; dbus-bindings-tool and dbus-glib should be able
+ * to do this for us.
+ *
+ * TODO: keep in sync with code in tools/devkit-disks in DeviceKit-disks.
+ */
+
+typedef struct
+{
+        gchar *native_path;
+
+        gchar *adapter;
+        gchar *parent;
+        gint number;
+} PortProperties;
+
+static void
+collect_props (const char *key, const GValue *value, PortProperties *props)
+{
+        gboolean handled = TRUE;
+
+        if (strcmp (key, "NativePath") == 0)
+                props->native_path = g_strdup (g_value_get_string (value));
+
+        else if (strcmp (key, "Adapter") == 0)
+                props->adapter = g_value_dup_boxed (value);
+        else if (strcmp (key, "Parent") == 0)
+                props->parent = g_value_dup_boxed (value);
+        else if (strcmp (key, "Number") == 0)
+                props->number = g_value_get_int (value);
+        else
+                handled = FALSE;
+
+        if (!handled)
+                g_warning ("unhandled property '%s'", key);
+}
+
+static void
+port_properties_free (PortProperties *props)
+{
+        g_free (props->native_path);
+        g_free (props->adapter);
+        g_free (props->parent);
+        g_free (props);
+}
+
+static PortProperties *
+port_properties_get (DBusGConnection *bus,
+                     const char *object_path)
+{
+        PortProperties *props;
+        GError *error;
+        GHashTable *hash_table;
+        DBusGProxy *prop_proxy;
+        const char *ifname = "org.freedesktop.DeviceKit.Disks.Port";
+
+        props = g_new0 (PortProperties, 1);
+
+	prop_proxy = dbus_g_proxy_new_for_name (bus,
+                                                "org.freedesktop.DeviceKit.Disks",
+                                                object_path,
+                                                "org.freedesktop.DBus.Properties");
+        error = NULL;
+        if (!dbus_g_proxy_call (prop_proxy,
+                                "GetAll",
+                                &error,
+                                G_TYPE_STRING,
+                                ifname,
+                                G_TYPE_INVALID,
+                                dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+                                &hash_table,
+                                G_TYPE_INVALID)) {
+                g_warning ("Couldn't call GetAll() to get properties for %s: %s", object_path, error->message);
+                g_error_free (error);
+
+                port_properties_free (props);
+                props = NULL;
+                goto out;
+        }
+
+        g_hash_table_foreach (hash_table, (GHFunc) collect_props, props);
+
+        g_hash_table_unref (hash_table);
+
+#if 0
+        g_print ("----------------------------------------------------------------------\n");
+        g_print ("native_path:  %s\n", props->native_path);
+        g_print ("adapter:      %s\n", props->adapter);
+        g_print ("parent:       %s\n", props->parent);
+        g_print ("number:       %d\n", props->number);
+#endif
+
+out:
+        g_object_unref (prop_proxy);
+        return props;
+}
+
+/* --- SUCKY CODE END --- */
+
+struct _GduPortPrivate
+{
+        DBusGConnection *bus;
+        DBusGProxy *proxy;
+        GduPool *pool;
+
+        char *object_path;
+
+        PortProperties *props;
+};
+
+enum {
+        CHANGED,
+        REMOVED,
+        LAST_SIGNAL,
+};
+
+static GObjectClass *parent_class = NULL;
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GduPort, gdu_port, G_TYPE_OBJECT);
+
+GduPool *
+gdu_port_get_pool (GduPort *port)
+{
+        return g_object_ref (port->priv->pool);
+}
+
+static void
+gdu_port_finalize (GduPort *port)
+{
+        g_debug ("##### finalized port %s",
+                 port->priv->props != NULL ? port->priv->props->native_path : port->priv->object_path);
+
+        dbus_g_connection_unref (port->priv->bus);
+        g_free (port->priv->object_path);
+        if (port->priv->proxy != NULL)
+                g_object_unref (port->priv->proxy);
+        if (port->priv->pool != NULL)
+                g_object_unref (port->priv->pool);
+        if (port->priv->props != NULL)
+                port_properties_free (port->priv->props);
+
+        if (G_OBJECT_CLASS (parent_class)->finalize)
+                (* G_OBJECT_CLASS (parent_class)->finalize) (G_OBJECT (port));
+}
+
+static void
+gdu_port_class_init (GduPortClass *klass)
+{
+        GObjectClass *obj_class = (GObjectClass *) klass;
+
+        parent_class = g_type_class_peek_parent (klass);
+
+        obj_class->finalize = (GObjectFinalizeFunc) gdu_port_finalize;
+
+        g_type_class_add_private (klass, sizeof (GduPortPrivate));
+
+        signals[CHANGED] =
+                g_signal_new ("changed",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GduPortClass, changed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE, 0);
+        signals[REMOVED] =
+                g_signal_new ("removed",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GduPortClass, removed),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE, 0);
+}
+
+static void
+gdu_port_init (GduPort *port)
+{
+        port->priv = G_TYPE_INSTANCE_GET_PRIVATE (port, GDU_TYPE_PORT, GduPortPrivate);
+}
+
+static gboolean
+update_info (GduPort *port)
+{
+        PortProperties *new_properties;
+
+        new_properties = port_properties_get (port->priv->bus, port->priv->object_path);
+        if (new_properties != NULL) {
+                if (port->priv->props != NULL)
+                        port_properties_free (port->priv->props);
+                port->priv->props = new_properties;
+                return TRUE;
+        } else {
+                return FALSE;
+        }
+}
+
+
+GduPort *
+_gdu_port_new_from_object_path (GduPool *pool, const char *object_path)
+{
+        GError *error;
+        GduPort *port;
+
+        port = GDU_PORT (g_object_new (GDU_TYPE_PORT, NULL));
+        port->priv->object_path = g_strdup (object_path);
+        port->priv->pool = g_object_ref (pool);
+
+        error = NULL;
+        port->priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (port->priv->bus == NULL) {
+                g_warning ("Couldn't connect to system bus: %s", error->message);
+                g_error_free (error);
+                goto error;
+        }
+
+	port->priv->proxy = dbus_g_proxy_new_for_name (port->priv->bus,
+                                                         "org.freedesktop.DeviceKit.Disks",
+                                                         port->priv->object_path,
+                                                         "org.freedesktop.DeviceKit.Disks.Port");
+        dbus_g_proxy_set_default_timeout (port->priv->proxy, INT_MAX);
+        dbus_g_proxy_add_signal (port->priv->proxy, "Changed", G_TYPE_INVALID);
+
+        /* TODO: connect signals */
+
+        if (!update_info (port))
+                goto error;
+
+        g_debug ("_gdu_port_new_from_object_path: %s", port->priv->props->native_path);
+
+        return port;
+error:
+        g_object_unref (port);
+        return NULL;
+}
+
+gboolean
+_gdu_port_changed (GduPort *port)
+{
+        g_debug ("_gdu_port_changed: %s", port->priv->props->native_path);
+        if (update_info (port)) {
+                g_signal_emit (port, signals[CHANGED], 0);
+                return TRUE;
+        } else {
+                return FALSE;
+        }
+}
+
+const gchar *
+gdu_port_get_object_path (GduPort *port)
+{
+        return port->priv->object_path;
+}
+
+
+const gchar *
+gdu_port_get_native_path (GduPort *port)
+{
+        return port->priv->props->native_path;
+}
+
+const gchar *
+gdu_port_get_adapter (GduPort *port)
+{
+        return port->priv->props->adapter;
+}
+
+const gchar *
+gdu_port_get_parent (GduPort *port)
+{
+        return port->priv->props->parent;
+}
+
+gint
+gdu_port_get_number (GduPort *port)
+{
+        return port->priv->props->number;
+}
diff --git a/src/gdu/gdu-port.h b/src/gdu/gdu-port.h
new file mode 100644
index 0000000..39c3ccc
--- /dev/null
+++ b/src/gdu/gdu-port.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-port.h
+ *
+ * Copyright (C) 2009 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#if !defined (__GDU_INSIDE_GDU_H) && !defined (GDU_COMPILATION)
+#error "Only <gdu/gdu.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __GDU_PORT_H
+#define __GDU_PORT_H
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <gdu/gdu-types.h>
+#include <gdu/gdu-callbacks.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_PORT           (gdu_port_get_type ())
+#define GDU_PORT(o)             (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_PORT, GduPort))
+#define GDU_PORT_CLASS(k)       (G_TYPE_CHECK_CLASS_CAST ((k), GDU_PORT,  GduPortClass))
+#define GDU_IS_PORT(o)          (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_PORT))
+#define GDU_IS_PORT_CLASS(k)    (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_PORT))
+#define GDU_PORT_GET_CLASS(k)   (G_TYPE_INSTANCE_GET_CLASS ((k), GDU_TYPE_PORT, GduPortClass))
+
+typedef struct _GduPortClass    GduPortClass;
+typedef struct _GduPortPrivate  GduPortPrivate;
+
+struct _GduPort
+{
+        GObject parent;
+
+        /* private */
+        GduPortPrivate *priv;
+};
+
+struct _GduPortClass
+{
+        GObjectClass parent_class;
+
+        /* signals */
+        void (*changed)     (GduPort *port);
+        void (*removed)     (GduPort *port);
+};
+
+GType        gdu_port_get_type              (void);
+const char  *gdu_port_get_object_path       (GduPort   *port);
+GduPool     *gdu_port_get_pool              (GduPort   *port);
+
+const gchar *gdu_port_get_native_path       (GduPort   *port);
+const gchar *gdu_port_get_adapter           (GduPort   *port);
+const gchar *gdu_port_get_parent            (GduPort   *port);
+gint         gdu_port_get_number            (GduPort   *port);
+
+G_END_DECLS
+
+#endif /* __GDU_ADAPTER_H */
diff --git a/src/gdu/gdu-private.h b/src/gdu/gdu-private.h
index cc9166e..52bc2f5 100644
--- a/src/gdu/gdu-private.h
+++ b/src/gdu/gdu-private.h
@@ -105,8 +105,11 @@ void        _gdu_device_job_changed           (GduDevice   *device,
                                                double       job_percentage);
 
 GduAdapter *_gdu_adapter_new_from_object_path (GduPool *pool, const char *object_path);
-gboolean    _gdu_adapter_changed               (GduAdapter   *adapter);
-GduHba *_gdu_hba_new_from_adapter (GduPool *pool, GduAdapter *adapter);
+gboolean    _gdu_adapter_changed              (GduAdapter   *adapter);
+GduHba     *_gdu_hba_new_from_adapter         (GduPool *pool, GduAdapter *adapter);
+
+GduPort    *_gdu_port_new_from_object_path (GduPool *pool, const char *object_path);
+gboolean    _gdu_port_changed               (GduPort   *port);
 
 void _gdu_drive_rewrite_enclosing_presentable (GduDrive *drive);
 void _gdu_volume_rewrite_enclosing_presentable (GduVolume *volume);
diff --git a/src/gdu/gdu-types.h b/src/gdu/gdu-types.h
index cc5ba70..96ede57 100644
--- a/src/gdu/gdu-types.h
+++ b/src/gdu/gdu-types.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 typedef struct _GduPool                   GduPool;
 typedef struct _GduDevice                 GduDevice;
 typedef struct _GduAdapter                GduAdapter;
+typedef struct _GduPort                   GduPort;
 
 typedef struct _GduPresentable            GduPresentable; /* Dummy typedef */
 typedef struct _GduDrive                  GduDrive;
diff --git a/src/gdu/gdu.h b/src/gdu/gdu.h
index 656e8bb..7bd9dbc 100644
--- a/src/gdu/gdu.h
+++ b/src/gdu/gdu.h
@@ -32,6 +32,7 @@
 #include <gdu/gdu-linux-md-drive.h>
 #include <gdu/gdu-device.h>
 #include <gdu/gdu-adapter.h>
+#include <gdu/gdu-port.h>
 #include <gdu/gdu-drive.h>
 #include <gdu/gdu-error.h>
 #include <gdu/gdu-known-filesystem.h>
diff --git a/src/palimpsest/gdu-section-drive.c b/src/palimpsest/gdu-section-drive.c
index 0587487..42226cd 100644
--- a/src/palimpsest/gdu-section-drive.c
+++ b/src/palimpsest/gdu-section-drive.c
@@ -36,6 +36,8 @@ struct _GduSectionDrivePrivate
         GduDetailsElement *firmware_element;
         GduDetailsElement *serial_element;
         GduDetailsElement *wwn_element;
+        GduDetailsElement *port_number_element;
+        GduDetailsElement *device_element;
         GduDetailsElement *write_cache_element;
         GduDetailsElement *rotation_rate_element;
         GduDetailsElement *capacity_element;
@@ -102,6 +104,8 @@ gdu_section_drive_update (GduSection *_section)
         guint rotation_rate;
         gboolean is_rotational;
         GIcon *icon;
+        const gchar *port_object_path;
+        GduPort *port;
         gboolean show_cddvd_button;
         gboolean show_format_button;
         gboolean show_eject_button;
@@ -117,6 +121,7 @@ gdu_section_drive_update (GduSection *_section)
         show_benchmark_button = FALSE;
 
         d = NULL;
+        port = NULL;
         wwn = NULL;
         p = gdu_section_get_presentable (_section);
 
@@ -124,6 +129,30 @@ gdu_section_drive_update (GduSection *_section)
         if (d == NULL)
                 goto out;
 
+        port_object_path = gdu_device_drive_get_port (d);
+        if (port_object_path != NULL && strlen (port_object_path) > 1) {
+                GduPool *pool;
+                pool = gdu_device_get_pool (d);
+                port = gdu_pool_get_port_by_object_path (pool, port_object_path);
+                g_object_unref (pool);
+        }
+        if (port != NULL) {
+                gint port_number;
+
+                port_number = gdu_port_get_number (port);
+                if (port_number >= 0) {
+                        /* Start at 1 */
+                        s = g_strdup_printf ("%d", port_number + 1);
+                        gdu_details_element_set_text (section->priv->port_number_element, s);
+                        g_free (s);
+                } else {
+                        gdu_details_element_set_text (section->priv->port_number_element, "â??");
+                }
+        } else {
+                gdu_details_element_set_text (section->priv->port_number_element, "â??");
+        }
+        gdu_details_element_set_text (section->priv->device_element, gdu_device_get_device_file (d));
+
         model = gdu_device_drive_get_model (d);
         vendor = gdu_device_drive_get_vendor (d);
         if (vendor != NULL && strlen (vendor) == 0)
@@ -595,6 +624,14 @@ gdu_section_drive_constructed (GObject *object)
         g_ptr_array_add (elements, element);
         section->priv->wwn_element = element;
 
+        element = gdu_details_element_new (_("Port Number:"), NULL, NULL);
+        g_ptr_array_add (elements, element);
+        section->priv->port_number_element = element;
+
+        element = gdu_details_element_new (_("Device:"), NULL, NULL);
+        g_ptr_array_add (elements, element);
+        section->priv->device_element = element;
+
         element = gdu_details_element_new (_("Write Cache:"), NULL, NULL);
         g_ptr_array_add (elements, element);
         section->priv->write_cache_element = element;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]