X-Git-Url: https://git.wpitchoune.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fnvidia.c;h=797bbf4756c918d39c28d11c466d64fcc670032c;hb=2291a5e288aab0c29e2886ae2e60aa254d698e0e;hp=d50774ca8bb9112aa902674fc0feb98b5b6d7926;hpb=e19b7aae2f107f501cdec4f942223152a96054c5;p=psensor.git diff --git a/src/lib/nvidia.c b/src/lib/nvidia.c index d50774c..797bbf4 100644 --- a/src/lib/nvidia.c +++ b/src/lib/nvidia.c @@ -20,6 +20,8 @@ #include #define _(str) gettext(str) +#include +#include #include #include #include @@ -33,11 +35,16 @@ Display *display; -static char *get_product_name(int id) +static const char *PROVIDER_NAME = "nvctrl"; + +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, @@ -45,13 +52,11 @@ static char *get_product_name(int id) NV_CTRL_STRING_PRODUCT_NAME, &name); if (res == True) { - if (strcmp(name, "Unknown")) { + if (strcmp(name, "Unknown")) return name; - } else { - log_err(_("Unknown NVIDIA product name for GPU %d"), - id); - free(name); - } + + log_err(_("Unknown NVIDIA product name for GPU %d"), id); + free(name); } else { log_err(_("Failed to retrieve NVIDIA product name for GPU %d"), id); @@ -60,51 +65,20 @@ static char *get_product_name(int id) return strdup("NVIDIA"); } -static double nv_get_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_GPU_CORE_TEMPERATURE, - &temp); + res = XNVCTRLQueryTargetAttribute(display, target, id, 0, att, &temp); if (res == True) return temp; - else - return UNKNOWN_DBL_VALUE; -} - -static double get_ambient_temp(int id) -{ - Bool res; - int temp; - res = XNVCTRLQueryTargetAttribute(display, - NV_CTRL_TARGET_TYPE_GPU, - id, - 0, - NV_CTRL_AMBIENT_TEMPERATURE, - &temp); - - if (res == True) - return temp; - else - return UNKNOWN_DBL_VALUE; + return UNKNOWN_DBL_VALUE; } -static double get_temp(int id, int type) -{ - if (type & SENSOR_TYPE_AMBIENT) - return get_ambient_temp(id); - else - return nv_get_temp(id); -} - -static double get_usage_att(char *atts, char *att) +static double get_usage_att(char *atts, const char *att) { char *c, *key, *strv, *s; size_t n; @@ -154,21 +128,46 @@ static double get_usage_att(char *atts, char *att) return v; } +static const char *get_nvidia_type_str(int type) +{ + if (type & SENSOR_TYPE_GRAPHICS) + return "graphics"; + + if (type & SENSOR_TYPE_VIDEO) + return "video"; + + if (type & SENSOR_TYPE_MEMORY) + return "memory"; + + if (type & SENSOR_TYPE_PCIE) + return "PCIe"; + + if (type & SENSOR_TYPE_AMBIENT) + return "ambient"; + + if (type & SENSOR_TYPE_TEMP) + return "temp"; + + if (type & SENSOR_TYPE_FAN) { + if (type & SENSOR_TYPE_RPM) + return "fan rpm"; + + return "fan level"; + } + + return "unknown"; +} + static double get_usage(int id, int type) { - char *stype, *atts; + const char *stype; + char *atts; double v; Bool res; - if (type & SENSOR_TYPE_GRAPHICS) - stype = "graphics"; - else if (type & SENSOR_TYPE_VIDEO) - stype = "video"; - else if (type & SENSOR_TYPE_MEMORY) - stype = "memory"; - else if (type & SENSOR_TYPE_PCIE) - stype = "PCIe"; - else + stype = get_nvidia_type_str(type); + + if (!stype) return UNKNOWN_DBL_VALUE; res = XNVCTRLQueryTargetStringAttribute(display, @@ -188,15 +187,36 @@ static double get_usage(int id, int type) return v; } +static double get_value(int id, int type) +{ + int att; + + if (type & SENSOR_TYPE_TEMP) { + if (type & SENSOR_TYPE_AMBIENT) + att = NV_CTRL_AMBIENT_TEMPERATURE; + else + 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); + } +} + static void update(struct psensor *sensor) { double v; - if (sensor->type & SENSOR_TYPE_TEMP) { - v = get_temp(sensor->nvidia_id, sensor->type); - } else { /* SENSOR_TYPE_USAGE */ - v = get_usage(sensor->nvidia_id, sensor->type); - } + v = get_value(sensor->nvidia_id, sensor->type); if (v == UNKNOWN_DBL_VALUE) log_err(_("Failed to retrieve measure of type %x " @@ -206,81 +226,61 @@ static void update(struct psensor *sensor) psensor_set_current_value(sensor, v); } -static struct psensor *create_temp_sensor(int id, int subtype, int values_len) +static int check_sensor(int id, int type) { - char name[200]; - char *sid, *pname; - struct psensor *s; - int t; - - pname = get_product_name(id); - - if (subtype & SENSOR_TYPE_AMBIENT) - sprintf(name, "%s %d ambient", pname, id); - else - sprintf(name, "%s %d", pname, id); - free(pname); - - sid = malloc(strlen("NVIDIA") + 1 + strlen(name) + 1); - sprintf(sid, "NVIDIA %s", name); + return get_value(id, type) != UNKNOWN_DBL_VALUE; +} - t = SENSOR_TYPE_NVCTRL | SENSOR_TYPE_GPU | SENSOR_TYPE_TEMP | subtype; +static char *i2str(int i) +{ + char *str; + size_t n; - s = psensor_create(sid, - strdup(name), - strdup(_("NVIDIA GPU")), - t, - values_len); + /* second +1 to avoid issue about the conversion of a double + * to a lower int */ + n = 1 + (ceil(log10(INT_MAX)) + 1) + 1; - s->nvidia_id = id; + str = malloc(n); + snprintf(str, n, "%d", i); - return s; + return str; } -static struct psensor *create_usage_sensor(int id, - int subtype, - int values_len) +static struct psensor *create_nvidia_sensor(int id, int subtype, int value_len) { - char name[200]; - char *sid; + char *pname, *name, *strnid, *sid; + const char *stype; + int type; + size_t n; struct psensor *s; - int t; - if (subtype & SENSOR_TYPE_GRAPHICS) - sprintf(name, "GPU%d graphics", id); - else if (subtype & SENSOR_TYPE_MEMORY) - sprintf(name, "GPU%d memory", id); - else if (subtype & SENSOR_TYPE_VIDEO) - sprintf(name, "GPU%d video", id); - else /* if (subtype & SENSOR_TYPE_PCIE) */ - sprintf(name, "GPU%d PCIe", id); + type = SENSOR_TYPE_NVCTRL | subtype; + if (!check_sensor(id, type)) + return NULL; - sid = malloc(strlen("NVIDIA") + 1 + strlen(name) + 1); - sprintf(sid, "NVIDIA %s", name); + pname = get_product_name(id, type); + strnid = i2str(id); + stype = get_nvidia_type_str(type); - t = SENSOR_TYPE_NVCTRL | SENSOR_TYPE_GPU | SENSOR_TYPE_USAGE | subtype; + n = strlen(pname) + 1 + strlen(strnid) + 1 + strlen(stype) + 1; + name = malloc(n); + sprintf(name, "%s %s %s", pname, strnid, stype); - s = psensor_create(sid, - strdup(name), - strdup(_("NVIDIA GPU")), - t, - values_len); + sid = malloc(strlen(PROVIDER_NAME) + 1 + strlen(name) + 1); + sprintf(sid, "%s %s", PROVIDER_NAME, name); + s = psensor_create(sid, name, pname, type, value_len); s->nvidia_id = id; + free(strnid); + 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); @@ -289,9 +289,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.")); @@ -306,62 +305,64 @@ void nvidia_psensor_list_update(struct psensor **sensors) while (*ss) { s = *ss; - if (s->type & SENSOR_TYPE_NVCTRL) + if (!(s->type & SENSOR_TYPE_REMOTE) + && s->type & SENSOR_TYPE_NVCTRL) update(s); ss++; } } -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_temp_sensor(i, 0, values_len); - tmp = psensor_list_add(ss, s); - if (ss != tmp) - free(ss); - - ss = tmp; - s = create_temp_sensor(i, SENSOR_TYPE_AMBIENT, values_len); - tmp = psensor_list_add(ss, s); - if (ss != tmp) - free(ss); - - ss = tmp; - s = create_usage_sensor(i, SENSOR_TYPE_GRAPHICS, values_len); - tmp = psensor_list_add(ss, s); - if (ss != tmp) - free(ss); - - ss = tmp; - s = create_usage_sensor(i, SENSOR_TYPE_VIDEO, values_len); - tmp = psensor_list_add(ss, s); - if (ss != tmp) - free(ss); - - ss = tmp; - s = create_usage_sensor(i, SENSOR_TYPE_MEMORY, values_len); - tmp = psensor_list_add(ss, s); - if (ss != tmp) - free(ss); - - ss = tmp; - s = create_usage_sensor(i, 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); +} + +void nvidia_psensor_list_append(struct psensor ***ss, int values_len) +{ + int i, n, utype; + Bool ret; + + if (!init()) + return; + + 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); + } } - return ss; + 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.")); + } } void nvidia_cleanup()