added support of free memory.
[psensor.git] / src / lib / nvidia.c
index a5b8128..fa5a898 100644 (file)
 
 Display *display;
 
-static char *get_product_name(int id)
+static char *get_product_name(int id, int type)
 {
        char *name;
        Bool res;
 
+       if (type & SENSOR_TYPE_FAN)
+               return strdup("NVIDIA");
+
        res = XNVCTRLQueryTargetStringAttribute(display,
                                                NV_CTRL_TARGET_TYPE_GPU,
                                                id,
@@ -62,35 +65,12 @@ static char *get_product_name(int id)
        return strdup("NVIDIA");
 }
 
-static double get_temp(int id)
-{
-       Bool res;
-       int temp;
-
-       res = XNVCTRLQueryTargetAttribute(display,
-                                         NV_CTRL_TARGET_TYPE_GPU,
-                                         id,
-                                         0,
-                                         NV_CTRL_GPU_CORE_TEMPERATURE,
-                                         &temp);
-
-       if (res == True)
-               return temp;
-       else
-               return UNKNOWN_DBL_VALUE;
-}
-
-static double get_ambient_temp(int id)
+static double get_att(int target, int id, int att)
 {
        Bool res;
        int temp;
 
-       res = XNVCTRLQueryTargetAttribute(display,
-                                         NV_CTRL_TARGET_TYPE_GPU,
-                                         id,
-                                         0,
-                                         NV_CTRL_AMBIENT_TEMPERATURE,
-                                         &temp);
+       res = XNVCTRLQueryTargetAttribute(display, target, id, 0, att, &temp);
 
        if (res == True)
                return temp;
@@ -152,18 +132,30 @@ static const char *get_nvidia_type_str(int type)
 {
        if (type & SENSOR_TYPE_GRAPHICS)
                return "graphics";
-       else if (type & SENSOR_TYPE_VIDEO)
+
+       if (type & SENSOR_TYPE_VIDEO)
                return "video";
-       else if (type & SENSOR_TYPE_MEMORY)
+
+       if (type & SENSOR_TYPE_MEMORY)
                return "memory";
-       else if (type & SENSOR_TYPE_PCIE)
+
+       if (type & SENSOR_TYPE_PCIE)
                return "PCIe";
-       else if (type & SENSOR_TYPE_AMBIENT)
+
+       if (type & SENSOR_TYPE_AMBIENT)
                return "ambient";
-       else if (type & SENSOR_TYPE_TEMP)
+
+       if (type & SENSOR_TYPE_TEMP)
                return "temp";
-       else
-               return "unknown";
+
+       if (type & SENSOR_TYPE_FAN) {
+               if (type & SENSOR_TYPE_RPM)
+                       return "fan rpm";
+               else
+                       return "fan level";
+       }
+
+       return "unknown";
 }
 
 static double get_usage(int id, int type)
@@ -197,12 +189,25 @@ static double get_usage(int id, int type)
 
 static double get_value(int id, int type)
 {
+       int att;
+
        if (type & SENSOR_TYPE_TEMP) {
                if (type & SENSOR_TYPE_AMBIENT)
-                       return get_ambient_temp(id);
+                       att = NV_CTRL_AMBIENT_TEMPERATURE;
                else
-                       return get_temp(id);
-       } else { /* SENSOR_TYPE_USAGE */
+                       att = NV_CTRL_GPU_CORE_TEMPERATURE;
+
+               return get_att(NV_CTRL_TARGET_TYPE_GPU, id, att);
+       } else if (type & SENSOR_TYPE_FAN) {
+               if (type & SENSOR_TYPE_RPM)
+                       return get_att(NV_CTRL_TARGET_TYPE_COOLER,
+                                      id,
+                                      NV_CTRL_THERMAL_COOLER_SPEED);
+               else /* SENSOR_TYPE_PERCENT */
+                       return get_att(NV_CTRL_TARGET_TYPE_COOLER,
+                                      id,
+                                      NV_CTRL_THERMAL_COOLER_LEVEL);
+       } else { /* SENSOR_TYPE_PERCENT */
                return get_usage(id, type);
        }
 }
@@ -249,12 +254,12 @@ static struct psensor *create_nvidia_sensor(int id, int subtype, int value_len)
        size_t n;
        struct psensor *s;
 
-       type = SENSOR_TYPE_NVCTRL | SENSOR_TYPE_GPU | subtype;
+       type = SENSOR_TYPE_NVCTRL | subtype;
 
        if (!check_sensor(id, type))
                return NULL;
 
-       pname = get_product_name(id);
+       pname = get_product_name(id, type);
        strnid = i2str(id);
        stype = get_nvidia_type_str(type);
 
@@ -274,15 +279,9 @@ static struct psensor *create_nvidia_sensor(int id, int subtype, int value_len)
        return s;
 }
 
-/*
-  Opens connection to X server and returns the number
-  of NVIDIA GPUs.
-
-  Return 0 if no NVIDIA gpus or cannot get information.
-*/
 static int init()
 {
-       int evt, err, n;
+       int evt, err;
 
        display = XOpenDisplay(NULL);
 
@@ -291,9 +290,8 @@ static int init()
                return 0;
        }
 
-       if (XNVCTRLQueryExtension(display, &evt, &err) &&
-           XNVCTRLQueryTargetCount(display, NV_CTRL_TARGET_TYPE_GPU, &n))
-               return n;
+       if (XNVCTRLQueryExtension(display, &evt, &err))
+               return 1;
 
        log_err(_("Failed to retrieve NVIDIA information."));
 
@@ -315,72 +313,56 @@ void nvidia_psensor_list_update(struct psensor **sensors)
        }
 }
 
-/* static struct psensor ** */
-/* sensor_add(struct psensor **sensors, int subtype, int values_len) */
-/* { */
-/* } */
-
-struct psensor **nvidia_psensor_list_add(struct psensor **sensors,
-                                        int values_len)
+static void add(struct psensor ***sensors, int id, int type, int values_len)
 {
-       int i, n;
-       struct psensor **tmp, **ss, *s;
+       struct psensor *s;
 
-       n = init();
+       s = create_nvidia_sensor(id, type, values_len);
 
-       ss = sensors;
-       for (i = 0; i < n; i++) {
-               s = create_nvidia_sensor(i, SENSOR_TYPE_TEMP, values_len);
-               tmp = psensor_list_add(ss, s);
-               if (ss != tmp)
-                       free(ss);
-
-               ss = tmp;
-               s = create_nvidia_sensor
-                       (i,
-                        SENSOR_TYPE_USAGE | SENSOR_TYPE_AMBIENT,
-                        values_len);
-               tmp = psensor_list_add(ss, s);
-               if (ss != tmp)
-                       free(ss);
-
-               ss = tmp;
-               s = create_nvidia_sensor
-                       (i,
-                        SENSOR_TYPE_USAGE | SENSOR_TYPE_GRAPHICS,
-                        values_len);
-               tmp = psensor_list_add(ss, s);
-               if (ss != tmp)
-                       free(ss);
-
-               ss = tmp;
-               s = create_nvidia_sensor
-                       (i,
-                        SENSOR_TYPE_USAGE | SENSOR_TYPE_VIDEO,
-                        values_len);
-               tmp = psensor_list_add(ss, s);
-               if (ss != tmp)
-                       free(ss);
-
-               ss = tmp;
-               s = create_nvidia_sensor
-                       (i,
-                        SENSOR_TYPE_USAGE | SENSOR_TYPE_MEMORY,
-                        values_len);
-               tmp = psensor_list_add(ss, s);
-               if (ss != tmp)
-                       free(ss);
-
-               ss = tmp;
-               s = create_nvidia_sensor
-                       (i,
-                        SENSOR_TYPE_USAGE | SENSOR_TYPE_PCIE,
-                        values_len);
-               tmp = psensor_list_add(ss, s);
-               if (ss != tmp)
-                       free(ss);
-
-               ss = tmp;
+       if (s)
+               psensor_list_append(sensors, s);
+}
+
+struct psensor **
+nvidia_psensor_list_add(struct psensor **ss, int values_len)
+{
+       int i, n, utype;
+       Bool ret;
+
+       if (!init())
+               return ss;
+
+       ret = XNVCTRLQueryTargetCount(display, NV_CTRL_TARGET_TYPE_GPU, &n);
+       if (ret == True) {
+               for (i = 0; i < n; i++) {
+                       add(&ss,
+                           i,
+                           SENSOR_TYPE_GPU | SENSOR_TYPE_TEMP,
+                           values_len);
+
+                       utype = SENSOR_TYPE_GPU | SENSOR_TYPE_PERCENT;
+                       add(&ss, i, utype | SENSOR_TYPE_AMBIENT, values_len);
+                       add(&ss, i, utype | SENSOR_TYPE_GRAPHICS, values_len);
+                       add(&ss, i, utype | SENSOR_TYPE_VIDEO, values_len);
+                       add(&ss, i, utype | SENSOR_TYPE_MEMORY, values_len);
+                       add(&ss, i, utype | SENSOR_TYPE_PCIE, values_len);
+               }
+       }
+
+       ret = XNVCTRLQueryTargetCount(display, NV_CTRL_TARGET_TYPE_COOLER, &n);
+       if (ret == True) {
+               log_debug("NVIDIA: number of fans: %d", n);
+               for (i = 0; i < n; i++) {
+                       utype = SENSOR_TYPE_FAN | SENSOR_TYPE_RPM;
+                       if (check_sensor(i, utype))
+                               add(&ss, i, utype, values_len);
+
+                       utype = SENSOR_TYPE_FAN | SENSOR_TYPE_PERCENT;
+                       if (check_sensor(i, utype))
+                               add(&ss, i, utype, values_len);
+               }
+       } else {
+               log_err(_("NVIDIA: failed to retrieve number of fans."));
        }
 
        return ss;