diff --git a/configure.in.in b/configure.in.in index 8cf0caf..6b48b41 100644 --- a/configure.in.in +++ b/configure.in.in @@ -217,8 +217,31 @@ if test x"$enable_sysfsacpi" = x"yes"; then enable_procacpi=yes fi +dnl Check for nvidia blahblah to be used +AC_ARG_ENABLE([xnvctrl], + AC_HELP_STRING([--enable-xnvctrl=yes|no], + [Blah-blah]), + [], +[ + enable_xnvctrl=yes +]) + +if test x"$enable_xnvctrl" = x"yes"; then + AC_DEFINE([HAVE_NVIDIA], [1], [Define to 1 if media-video/nvidia-drivers installed]) + NVIDIA_CFLAGS="-I/usr/include/NVCtrl" + NVIDIA_LIBS="-lX11 -lXext -lXNVCtrl" + enable_xnvctrl=yes +AC_SUBST([NVIDIA_CFLAGS]) +AC_SUBST([NVIDIA_LDFLAGS]) +fi + + + + + AM_CONDITIONAL([HAVE_ACPI], [test x$enable_procacpi = x"yes"]) AM_CONDITIONAL([HAVE_SYSFS_ACPI], [test x$enable_sysfsacpi = x"yes"]) +AM_CONDITIONAL([HAVE_NVIDIA], [test x$enable_xnvctrl = x"yes"]) dnl Check for full debugging diff --git a/include/Makefile.am b/include/Makefile.am index 0662562..058bd4c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -10,6 +10,7 @@ EXTRA_DIST = \ configuration.h \ lmsensors.h \ middlelayer.h \ - sensors-interface.h + sensors-interface.h \ + nvidia.h # vi:set ts=4 sw=4 noet ai nocindent syntax=automake: diff --git a/include/nvidia.h b/include/nvidia.h new file mode 100644 index 0000000..4452a9d --- /dev/null +++ b/include/nvidia.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2011 Amir Aupov + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef XFCE4_SENSORS_NVIDIA_H +#define XFCE4_SENSORS_NVIDIA_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Gtk/Glib includes */ +#include +#include +/* + * Initialize nvidia sensor + */ +int initialize_nvidia (GPtrArray *chips); + +/* + * Refresh an nvidia chip's feature + */ +void refresh_nvidia (gpointer chip_feature, gpointer data); + + +double get_nvidia_value (int gpu); + +#endif /* XFCE4_SENSORS_NVIDIA_H */ diff --git a/include/types.h b/include/types.h index f700901..e1859a2 100644 --- a/include/types.h +++ b/include/types.h @@ -60,7 +60,8 @@ typedef enum { typedef enum { LMSENSOR, HDD, - ACPI + ACPI, + GPU } t_chiptype; /* diff --git a/lib/Makefile.am b/lib/Makefile.am index 7daad8a..7f20e1e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -22,6 +22,11 @@ ACPI_SOURCES = acpi.c #acpi.h endif +if HAVE_NVIDIA +NVIDIA_SOURCES = nvidia.c +#nvidia.c +endif + libxfce4sensors_la_SOURCES = \ middlelayer.c \ configuration.c \ @@ -30,7 +35,8 @@ libxfce4sensors_la_SOURCES = \ cpu.c \ $(SENSORS_SOURCES) \ $(HDDTEMP_SOURCES) \ - $(ACPI_SOURCES) + $(ACPI_SOURCES) \ + $(NVIDIA_SOURCES) # configuration.h \ # sensors-plugin.h \ @@ -44,8 +50,9 @@ libxfce4sensors_la_CFLAGS = \ @GLIB_CFLAGS@ \ @LIBXFCEGUI4_CFLAGS@ \ @LIBXFCE4UTIL_CFLAGS@ \ - @LIBXFCE4PANEL_CFLAGS@ \ - @LIBSENSORS_CFLAGS@ + @LIBXFCE4PANEL_CFLAGS@ \ + @LIBSENSORS_CFLAGS@ \ + @NVIDIA_CFLAGS@ if HAVE_LIBNOTIFY libxfce4sensors_la_CFLAGS += @LIBNOTIFY_CFLAGS@ @@ -74,7 +81,8 @@ libxfce4sensors_la_LIBADD = \ @LIBXFCEGUI4_LIBS@ \ @LIBXFCE4PANEL_LIBS@ \ @LIBSENSORS_LDFLAGS@ \ - @LIBM@ + @LIBM@ \ + @NVIDIA_LIBS@ if HAVE_LIBNOTIFY libxfce4sensors_la_LIBADD += @LIBNOTIFY_LIBS@ diff --git a/lib/middlelayer.c b/lib/middlelayer.c index 6595515..baab393 100644 --- a/lib/middlelayer.c +++ b/lib/middlelayer.c @@ -51,6 +51,9 @@ #ifdef HAVE_ACPI #include #endif +#ifdef HAVE_NVIDIA + #include +#endif int initialize_all (GPtrArray **chips, gboolean *suppressmessage) @@ -73,6 +76,10 @@ initialize_all (GPtrArray **chips, gboolean *suppressmessage) res += initialize_ACPI (*chips); #endif + #ifdef HAVE_NVIDIA + res += initialize_nvidia (*chips); + #endif + TRACE ("leaves initialize_all, chips->len=%d", (*chips)->len); return res; @@ -111,6 +118,13 @@ refresh_chip (gpointer chip, gpointer data) } #endif + #ifdef HAVE_NVIDIA + if (c->type==GPU) { + g_ptr_array_foreach (c->chip_features, refresh_nvidia, NULL); + return; + } + #endif + TRACE ("leaves refresh_chip"); } @@ -205,6 +219,19 @@ sensor_get_value (t_chip *chip, int number, double *value, gboolean *suppressmes return -1; #endif } + if (chip->type==GPU ) { + #ifdef HAVE_NVIDIA + g_assert (numbernum_features); + feature = (t_chipfeature *) g_ptr_array_index (chip->chip_features, number); + g_assert (feature!=NULL); + refresh_nvidia ((gpointer) feature, NULL); + //*value = get_nvidia_value(feature->address); + *value = feature->raw_value; + return 0; + #else + return -1; + #endif + } else { feature = NULL; return -1; diff --git a/lib/nvidia.c b/lib/nvidia.c new file mode 100644 index 0000000..13d3b3e --- /dev/null +++ b/lib/nvidia.c @@ -0,0 +1,182 @@ +/* Copyright (c) 2011 Amir Aupov + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* Package includes */ +#include +#include +#include +#include +#include +#include +#include + +/* Gtk/Glib includes */ +#include + +/* Global includes */ +#include +#include +#include + +/* Global variables */ +Display *nvidia_sensors_display; + +/* Local functions */ +int read_gpus (t_chip *chip); + +/* Defines */ +#define ZERO_KELVIN -273 + +int initialize_nvidia (GPtrArray *chips) { + int retval; + int num_gpus; + t_chip *chip; + t_chipfeature *chipfeature; + + TRACE ("enters initialize_nvidia"); + + chip = g_new0 (t_chip, 1); + //chip -> chip_name = g_strdup(_("nvidia")); + chip -> chip_features = g_ptr_array_new (); + chip -> num_features = 0; + chip -> description = g_strdup(_("NVidia GPU core temperature")); + chip -> name = g_strdup(_("nvidia")); + chip -> sensorId = g_strdup("nvidia"); + chip -> type = GPU; + + num_gpus = read_gpus (chip); + if (chip -> num_features > 0) { + int i; + for (i = 0; i < num_gpus; i++) { + chipfeature = g_ptr_array_index (chip -> chip_features, i); + g_assert (chipfeature != NULL); + chipfeature -> address = i; + chipfeature -> name = g_strdup(chipfeature -> devicename); + chipfeature -> color = g_strdup ("#000000"); + chipfeature -> valid = TRUE; + chipfeature -> formatted_value = g_strdup ("0.0"); + chipfeature -> raw_value = 0.0; + chipfeature -> class = TEMPERATURE; + chipfeature -> min_value = 10.0; + chipfeature -> max_value = 50.0; + chipfeature -> show = FALSE; + } + g_ptr_array_add (chips, chip); + retval = 2; + } else retval = 0; + + TRACE ("leaves initialize_nvidia"); + + return retval; +} + +double get_nvidia_value (int gpu) { + int temp; + + TRACE ("enters get_nvidia_value for %d gpu", gpu); + + if (!(XNVCTRLQueryTargetAttribute (nvidia_sensors_display, + NV_CTRL_TARGET_TYPE_GPU, + gpu, + 0, + NV_CTRL_GPU_CORE_TEMPERATURE, + &temp))) { + TRACE ("NVCtrl doesn't work properly"); + return ZERO_KELVIN; + } + + TRACE ("leaves get_nvidia_value for %d gpu", gpu); + + return 1.d * temp; +} + +void refresh_nvidia (gpointer chip_feature, gpointer data) { + t_chipfeature *cf; + double value; + t_sensors *sensors; + + g_assert (chip_feature != NULL); + + TRACE ("enters refresh_nvidia"); + + if (data) sensors = (t_sensors *) data; + cf = (t_chipfeature *) chip_feature; + value = get_nvidia_value (cf -> address); + if (value == ZERO_KELVIN) return; + + g_free (cf -> formatted_value); + cf -> formatted_value = g_strdup_printf(_("%ld °C"), value); + cf -> raw_value = value; + + TRACE ("leaves refresh_nvidia"); + +} + +int read_gpus (t_chip *chip) { + t_chipfeature *chipfeature; + int num_gpus; + int event, error; + int i; + + TRACE ("enters read_gpus"); + + /* create the connection to the X server */ + if (!(nvidia_sensors_display = XOpenDisplay (NULL))) { + TRACE ("failed to connect to X server"); + return 0; + } + + /* check if the NVCtrl is available on this X server + * if so - add sensors*/ + if (!(XNVCTRLQueryExtension (nvidia_sensors_display, + &event, &error))) { + TRACE ("NVCtrl is not available"); + return 0; + } + + if (!(XNVCTRLQueryTargetCount (nvidia_sensors_display, + NV_CTRL_TARGET_TYPE_GPU, + &num_gpus))) { + TRACE ("No NVidia devices found"); + return 0; + } + + for (i = 0; i < num_gpus; i++){ + gchar *device_name = (gchar*) malloc (100 * sizeof(gchar)); + if (XNVCTRLQueryTargetStringAttribute ( + nvidia_sensors_display, + NV_CTRL_TARGET_TYPE_GPU, + i, + 0, + NV_CTRL_STRING_PRODUCT_NAME, + &device_name)) + TRACE ("GPU%d:%s", i, device_name); + chipfeature = g_new0 (t_chipfeature, 1); + chipfeature -> devicename = g_strdup (device_name); + chipfeature -> name = g_strdup (device_name); + g_ptr_array_add (chip -> chip_features, chipfeature); + chip -> num_features++; + } + + TRACE ("leaves read_gpus"); + return num_gpus; +} +