[gnome-battery-bench] system-info: pci device class, discover GPUs
- From: Christian Kellner <gicmo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-battery-bench] system-info: pci device class, discover GPUs
- Date: Wed, 5 Jul 2017 14:18:45 +0000 (UTC)
commit 9b2e3fa762cf70ad2ae6045f4200704a0f9a2a46
Author: Christian Kellner <gicmo gnome org>
Date: Thu Jun 8 18:56:29 2017 +0200
system-info: pci device class, discover GPUs
Introduce a GbbPciDevice abstraction and use it to discover gpus
in the system.
src/system-info.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/system-info.h | 18 +++
2 files changed, 359 insertions(+), 0 deletions(-)
---
diff --git a/src/system-info.c b/src/system-info.c
index 02bff26..7316b7e 100644
--- a/src/system-info.c
+++ b/src/system-info.c
@@ -14,10 +14,300 @@
#include <gdk/gdkx.h>
#endif
+#include "util-sysfs.h"
+
#include "power-supply.h"
#include "config.h"
+
+G_DEFINE_BOXED_TYPE (GbbPciClass, gbb_pci_class, gbb_pci_class_copy, gbb_pci_class_free)
+
+GbbPciClass *
+gbb_pci_class_copy(const GbbPciClass *klass)
+{
+ return g_slice_dup(GbbPciClass, klass);
+}
+
+void
+gbb_pci_class_free(GbbPciClass *klass)
+{
+ g_slice_free(GbbPciClass, klass);
+}
+
+struct _GbbPciDeviceClass
+{
+ GObjectClass parent_class;
+
+ gpointer padding[13];
+};
+
+
+typedef struct _GbbPciDevicePrivate {
+ GUdevDevice *udevice;
+
+ GbbPciClass class_id;
+
+ guint16 vendor_id;
+ guint16 device_id;
+
+ gboolean enabled;
+
+} GbbPciDevicePrivate;
+
+enum {
+ PROP_PCI_DEVICE_0,
+ PROP_UDEV_DEVICE,
+ PROP_CLASS,
+ PROP_VENDOR_ID,
+ PROP_VENDOR_NAME,
+ PROP_DEVICE_ID,
+ PROP_DEVICE_NAME,
+ PROP_ENABLED,
+ PROP_PCI_DEVICE_LAST
+};
+
+static GParamSpec *pcidev_props[PROP_PCI_DEVICE_LAST] = { NULL, };
+
+G_DEFINE_TYPE_WITH_PRIVATE(GbbPciDevice,
+ gbb_pci_device,
+ G_TYPE_OBJECT);
+
+#define PCIDEV_GET_PRIV(obj) \
+ ((GbbPciDevicePrivate *) gbb_pci_device_get_instance_private(GBB_PCI_DEVICE(obj)))
+
+static void gbb_pci_device_constructed(GObject *obj);
+
+static void
+gbb_pci_device_finalize(GObject *object)
+{
+ GbbPciDevice *dev = GBB_PCI_DEVICE(object);
+ GbbPciDevicePrivate *priv = PCIDEV_GET_PRIV(dev);
+
+ g_clear_object(&priv->udevice);
+}
+
+static void
+gbb_pci_device_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbbPciDevice *dev = GBB_PCI_DEVICE(object);
+ GbbPciDevicePrivate *priv = PCIDEV_GET_PRIV(dev);
+ GUdevDevice *udevice = priv->udevice;
+ guint ui;
+ const char *str;
+
+ switch (prop_id) {
+
+ case PROP_UDEV_DEVICE:
+ g_value_set_object(value, udevice);
+ break;
+
+ case PROP_CLASS:
+ g_value_set_boxed(value, &priv->class_id);
+ break;
+
+ case PROP_VENDOR_ID:
+ ui = priv->vendor_id;
+ g_value_set_uint(value, ui);
+ break;
+
+ case PROP_VENDOR_NAME:
+ str = g_udev_device_get_property (udevice, "ID_VENDOR_FROM_DATABASE");
+ g_value_set_string(value, str);
+ break;
+
+ case PROP_DEVICE_ID:
+ ui = priv->device_id;
+ g_value_set_uint(value, ui);
+ break;
+
+ case PROP_DEVICE_NAME:
+ str = g_udev_device_get_property (udevice, "ID_MODEL_FROM_DATABASE");
+ g_value_set_string(value, str);
+ break;
+
+ case PROP_ENABLED:
+ g_value_set_boolean(value, priv->enabled);
+ break;
+ }
+}
+
+static void
+gbb_pci_device_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbbPciDevice *dev = GBB_PCI_DEVICE(object);
+ GbbPciDevicePrivate *priv = PCIDEV_GET_PRIV(dev);
+
+ switch (prop_id) {
+ case PROP_UDEV_DEVICE:
+ priv->udevice = g_value_dup_object(value);
+ break;
+ }
+
+}
+
+static void
+gbb_pci_device_class_init(GbbPciDeviceClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = gbb_pci_device_finalize;
+ gobject_class->get_property = gbb_pci_device_get_property;
+ gobject_class->set_property = gbb_pci_device_set_property;
+ gobject_class->constructed = gbb_pci_device_constructed;
+
+ pcidev_props[PROP_UDEV_DEVICE] =
+ g_param_spec_object("udev-device",
+ NULL, NULL,
+ G_UDEV_TYPE_DEVICE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME);
+
+ pcidev_props[PROP_CLASS] =
+ g_param_spec_boxed("class",
+ NULL, NULL,
+ GBB_TYPE_PCI_CLASS,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ pcidev_props[PROP_VENDOR_ID] =
+ g_param_spec_uint("vendor",
+ NULL, NULL,
+ 0, G_MAXUINT16, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ pcidev_props[PROP_VENDOR_NAME] =
+ g_param_spec_string("vendor-name",
+ NULL, NULL,
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ pcidev_props[PROP_DEVICE_ID] =
+ g_param_spec_uint("device",
+ NULL, NULL,
+ 0, G_MAXUINT16, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ pcidev_props[PROP_DEVICE_NAME] =
+ g_param_spec_string("device-name",
+ NULL, NULL,
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ pcidev_props[PROP_ENABLED] =
+ g_param_spec_boolean("enabled",
+ NULL, NULL,
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ g_object_class_install_properties(gobject_class,
+ PROP_PCI_DEVICE_LAST,
+ pcidev_props);
+}
+
+static gboolean
+pci_class_from_udev_device(GUdevDevice *device, GbbPciClass *class_id)
+{
+ guint64 cls = 0;
+ gboolean ok;
+
+ ok = sysfs_read_guint64(device, "class", &cls);
+
+ class_id->code = cls >> (2*8) & 0xFF;
+ class_id->sub = cls >> 8 & 0xFF;
+ class_id->progif = cls & 0xFF;
+
+ return ok;
+}
+
+static void
+gbb_pci_device_constructed(GObject *obj)
+{
+ GbbPciDevice *dev = GBB_PCI_DEVICE(obj);
+ GbbPciDevicePrivate *priv = PCIDEV_GET_PRIV(dev);
+ GUdevDevice *udevice = priv->udevice;
+ guint64 val;
+ gboolean ok;
+
+ pci_class_from_udev_device(priv->udevice, &priv->class_id);
+
+ ok = sysfs_read_guint64(udevice, "vendor", &val);
+ if (ok) {
+ priv->vendor_id = (guint16) val;
+ }
+
+ ok = sysfs_read_guint64(udevice, "device", &val);
+ if (ok) {
+ priv->device_id = (guint16) val;
+ }
+
+ ok = sysfs_read_guint64(udevice, "enable", &val);
+ if (ok) {
+ priv->enabled = val != 0;
+ }
+}
+
+static void
+gbb_pci_device_init(GbbPciDevice *dev)
+{
+
+}
+
+static GPtrArray *
+gbb_pci_device_discover(GUdevClient *client, int code, int sub, int progif)
+{
+ GPtrArray *devices = NULL;
+ GList *udevices;
+
+ if (client == NULL) {
+ client = g_udev_client_new(NULL);
+ } else {
+ client = g_object_ref(client);
+ }
+
+ udevices = g_udev_client_query_by_subsystem (client, "pci");
+
+ devices = g_ptr_array_new_with_free_func(g_object_unref);
+
+ for (GList *l = udevices; l; l = l->next) {
+ GUdevDevice *udev_device = l->data;
+ GbbPciDevice *dev;
+ GbbPciClass cid;
+ gboolean ok;
+
+ ok = pci_class_from_udev_device(udev_device, &cid);
+
+ if (!ok || ((code >= 0 && code != cid.code) ||
+ (sub >= 0 && sub != cid.sub) ||
+ (progif >= 0 && progif != cid.progif))) {
+ continue;
+ }
+
+ dev = g_object_new(GBB_TYPE_PCI_DEVICE,
+ "udev-device", udev_device,
+ NULL);
+
+ g_ptr_array_add(devices, dev);
+ }
+
+ g_list_free_full(udevices, (GDestroyNotify) g_object_unref);
+ g_object_unref(client);
+
+ return devices;
+}
+
struct _GbbSystemInfo {
GObject parent;
@@ -41,6 +331,9 @@ struct _GbbSystemInfo {
/* Batteries */
GPtrArray *batteries;
+ /* GPUs */
+ GPtrArray *gpus;
+
/* GPU/Renderer */
char *renderer;
@@ -87,6 +380,8 @@ enum {
PROP_BATTERIES,
+ PROP_GPUS,
+
PROP_MONITOR_X,
PROP_MONITOR_Y,
PROP_MONITOR_WIDTH,
@@ -136,6 +431,8 @@ gbb_system_info_finalize(GbbSystemInfo *info)
g_ptr_array_unref(info->batteries);
+ g_ptr_array_unref(info->gpus);
+
g_free(info->os_type);
g_free(info->os_kernel);
@@ -209,6 +506,10 @@ gbb_system_info_get_property (GObject *object, guint prop_id, GValue *value, GPa
g_value_set_boxed(value, info->batteries);
break;
+ case PROP_GPUS:
+ g_value_set_boxed(value, info->gpus);
+ break;
+
case PROP_MONITOR_X:
g_value_set_int(value, info->monitor_x);
break;
@@ -334,6 +635,12 @@ gbb_system_info_class_init (GbbSystemInfoClass *klass)
G_TYPE_PTR_ARRAY,
G_PARAM_READABLE);
+ props[PROP_GPUS] =
+ g_param_spec_boxed("gpus",
+ NULL, NULL,
+ G_TYPE_PTR_ARRAY,
+ G_PARAM_READABLE);
+
props[PROP_RENDERER] =
g_param_spec_string("renderer",
NULL, NULL,
@@ -847,6 +1154,7 @@ static void gbb_system_info_init (GbbSystemInfo *info)
info->cpu_info = read_cpu_info(&info->cpu_number);
info->mem_total = read_mem_info();
info->batteries = get_batteries();
+ info->gpus = gbb_pci_device_discover(NULL, 3, -1, -1);
info->renderer = get_renderer_info();
info->desktop = gbb_strdup_clean(g_getenv("XDG_CURRENT_DESKTOP"));
@@ -1011,6 +1319,39 @@ gbb_system_info_to_json (const GbbSystemInfo *info, JsonBuilder *builder)
json_builder_end_object(builder);
}
+ json_builder_set_member_name(builder, "gpus");
+ {
+ json_builder_begin_array(builder);
+ for (i = 0; i < info->gpus->len; i++) {
+ GbbPciDevice *gpu = g_ptr_array_index(info->gpus, i);
+ g_autofree char *vendor_name = NULL;
+ g_autofree char *device_name = NULL;
+ guint vendor_id;
+ guint device_id;
+ gboolean enabled;
+
+ g_object_get(gpu,
+ "vendor", &vendor_id,
+ "vendor-name", &vendor_name,
+ "device", &device_id,
+ "device-name", &device_name,
+ "enabled", &enabled,
+ NULL);
+
+ json_builder_begin_object(builder);
+ json_builder_set_member_name(builder, "vendor");
+ json_builder_add_int_value(builder, vendor_id);
+ json_builder_set_member_name(builder, "device");
+ json_builder_add_int_value(builder, device_id);
+ jsb_add_kv_string(builder, "vendor-name", vendor_name);
+ jsb_add_kv_string(builder, "device-name", device_name);
+ json_builder_set_member_name(builder, "enabled");
+ json_builder_add_boolean_value(builder, enabled);
+ json_builder_end_object(builder);
+ }
+ json_builder_end_array(builder);
+ }
+
json_builder_end_object(builder);
}
diff --git a/src/system-info.h b/src/system-info.h
index e7515d1..d331641 100644
--- a/src/system-info.h
+++ b/src/system-info.h
@@ -4,6 +4,24 @@
#include <glib-object.h>
#include <json-glib/json-glib.h>
+
+typedef struct GbbPciClass {
+ guint8 code;
+ guint8 sub;
+ guint8 progif;
+} GbbPciClass;
+
+#define GBB_TYPE_PCI_CLASS (gbb_pci_class_get_type())
+
+GType gbb_pci_class_get_type (void);
+GbbPciClass * gbb_pci_class_copy (const GbbPciClass *klass);
+void gbb_pci_class_free (GbbPciClass *klass);
+
+
+#define GBB_TYPE_PCI_DEVICE gbb_pci_device_get_type()
+G_DECLARE_DERIVABLE_TYPE(GbbPciDevice, gbb_pci_device, GBB, PCI_DEVICE, GObject)
+
+
#define GBB_TYPE_SYSTEM_INFO gbb_system_info_get_type()
G_DECLARE_FINAL_TYPE(GbbSystemInfo, gbb_system_info, GBB, SYSTEM_INFO, GObject)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]