switched from wpitchoune@gmail.com to jeanfi@gmail.com (my usual email)
[psensor.git] / src / lib / nvidia.c
1 /*
2     Copyright (C) 2010-2011 jeanfi@gmail.com
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17     02110-1301 USA
18 */
19
20 #include <locale.h>
21 #include <libintl.h>
22 #define _(str) gettext(str)
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <X11/Xlib.h>
29
30 #include <NVCtrl/NVCtrl.h>
31 #include <NVCtrl/NVCtrlLib.h>
32
33
34 #include "psensor.h"
35
36 Display *nvidia_sensors_dpy;
37
38 int nvidia_get_sensor_temp(struct psensor *sensor)
39 {
40         int temp;
41         Bool res;
42
43         res = XNVCTRLQueryTargetAttribute(nvidia_sensors_dpy,
44                                           NV_CTRL_TARGET_TYPE_GPU,
45                                           sensor->nvidia_id,
46                                           0,
47                                           NV_CTRL_GPU_CORE_TEMPERATURE, &temp);
48
49         if (res == True) {
50                 return temp;
51         } else {
52                 fprintf(stderr,
53                         _("ERROR: failed to retrieve nvidia temperature\n"));
54                 return 0;
55         }
56 }
57
58 struct psensor *nvidia_create_sensor(int id, int values_max_length)
59 {
60         char name[200];
61         char *sid;
62         struct psensor *s;
63
64         sprintf(name, "GPU%d", id);
65
66         sid = malloc(strlen("nvidia") + 1 + strlen(name) + 1);
67         sprintf(sid, "nvidia %s", name);
68
69         s = psensor_create(sid, strdup(name),
70                            SENSOR_TYPE_NVIDIA, values_max_length);
71
72         s->nvidia_id = id;
73
74         return s;
75 }
76
77 int nvidia_init()
78 {
79         int event_base, error_base;
80         int num_gpus;
81
82         nvidia_sensors_dpy = XOpenDisplay(NULL);
83
84         if (!nvidia_sensors_dpy) {
85                 fprintf(stderr, _("ERROR: nvidia initialization failure\n"));
86                 return 0;
87         }
88
89         if (XNVCTRLQueryExtension(nvidia_sensors_dpy, &event_base,
90                                   &error_base)) {
91                 if (XNVCTRLQueryTargetCount(nvidia_sensors_dpy,
92                                             NV_CTRL_TARGET_TYPE_GPU,
93                                             &num_gpus)) {
94                         return num_gpus;
95                 }
96
97         }
98
99         fprintf(stderr, _("ERROR: nvidia initialization failure: %d\n"),
100                 error_base);
101
102         return 0;
103 }
104
105 void nvidia_psensor_list_update(struct psensor **sensors)
106 {
107         struct psensor **s_ptr = sensors;
108
109         while (*s_ptr) {
110                 struct psensor *sensor = *s_ptr;
111
112                 if (sensor->type == SENSOR_TYPE_NVIDIA) {
113                         int val = nvidia_get_sensor_temp(sensor);
114
115                         psensor_set_current_value(sensor, (double)val);
116                 }
117
118                 s_ptr++;
119         }
120 }
121
122 struct psensor **nvidia_psensor_list_add(struct psensor **sensors,
123                                          int values_max_length)
124 {
125         int i;
126         int nvidia_gpus_count = nvidia_init();
127         struct psensor **res = sensors;
128
129
130         if (!nvidia_gpus_count) {
131                 fprintf(stderr,
132                         _("ERROR: "
133                           "no nvidia chips or initialization failure\n"));
134         }
135
136         for (i = 0; i < nvidia_gpus_count; i++) {
137                 struct psensor *sensor
138                         = nvidia_create_sensor(i, values_max_length);
139
140                 struct psensor **tmp_psensors = psensor_list_add(res,
141                                                                  sensor);
142
143                 if (res != sensors)
144                         free(res);
145
146                 res = tmp_psensors;
147         }
148
149         return res;
150 }