99495a3c39f418b88b3ec01aeee5cbc7aeec941b
[framework/uifw/e17.git] / src / modules / temperature / tempget.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <limits.h>
5
6 #ifdef __FreeBSD__
7 # include <sys/types.h>
8 # include <sys/sysctl.h>
9 #endif
10
11 #include <Ecore.h>
12 #include <Ecore_File.h>
13
14 #include "e_mod_main_private.h"
15
16 static int sensor_type = SENSOR_TYPE_NONE;
17 static char *sensor_name = NULL;
18 static int poll_interval = 32;
19 static int cur_poll_interval = 32;
20
21 static char *sensor_path = NULL;
22 #ifdef __FreeBSD__
23 static int mib[5];
24 #endif
25 static Ecore_Poller *poller = NULL;
26 static int ptemp = 0;
27
28 static void init(void);
29 static int check(void);
30 static Eina_Bool poll_cb(void *data);
31
32 Eina_List *
33 temperature_get_bus_files(const char* bus)
34 {
35    Eina_List *result;
36    Eina_List *therms;
37    char path[PATH_MAX];
38    char busdir[PATH_MAX];
39    char *name;
40
41    result = NULL;
42
43    snprintf(busdir, sizeof(busdir), "/sys/bus/%s/devices", bus);
44    /* Look through all the devices for the given bus. */
45    therms = ecore_file_ls(busdir);
46
47    EINA_LIST_FREE(therms, name)
48      {
49         Eina_List *files;
50         char *file;
51
52         /* Search each device for temp*_input, these should be
53          * temperature devices. */
54         snprintf(path, sizeof(path),"%s/%s", busdir, name);
55         files = ecore_file_ls(path);
56         EINA_LIST_FREE(files, file)
57           {
58              if ((!strncmp("temp", file, 4)) &&
59                  (!strcmp("_input", &file[strlen(file) - 6])))
60                {
61                   char *f;
62
63                   snprintf(path, sizeof(path),
64                            "%s/%s/%s", busdir, name, file);
65                   f = strdup(path);
66                   if (f) result = eina_list_append(result, f);
67                }
68              free(file);
69           }
70         free(name);
71      }
72    return result;
73 }
74
75 static void
76 init(void)
77 {
78    Eina_List *therms;
79    char path[PATH_MAX];
80 #ifdef __FreeBSD__
81    int len;
82 #endif
83
84    if ((!sensor_type) || ((!sensor_name) || (sensor_name[0] == 0)))
85      {
86         if (sensor_name) free(sensor_name);
87         if (sensor_path) free(sensor_path);
88         sensor_path = NULL;
89 #ifdef __FreeBSD__
90         /* TODO: FreeBSD can also have more temperature sensors! */
91         sensor_type = SENSOR_TYPE_FREEBSD;
92         sensor_name = strdup("tz0");
93 #else
94         therms = ecore_file_ls("/proc/acpi/thermal_zone");
95         if (therms)
96           {
97              char *name;
98
99              name = eina_list_data_get(therms);
100              sensor_type = SENSOR_TYPE_LINUX_ACPI;
101              sensor_name = strdup(name);
102
103              eina_list_free(therms);
104           }
105         else
106           {
107              eina_list_free(therms);
108              if (ecore_file_exists("/proc/omnibook/temperature"))
109                {
110                   sensor_type = SENSOR_TYPE_OMNIBOOK;
111                   sensor_name = strdup("dummy");
112                }
113              else if (ecore_file_exists("/sys/devices/temperatures/sensor1_temperature"))
114                {
115                   sensor_type = SENSOR_TYPE_LINUX_PBOOK;
116                   sensor_name = strdup("dummy");
117                }
118              else if (ecore_file_exists("/sys/devices/temperatures/cpu_temperature"))
119                {
120                   sensor_type = SENSOR_TYPE_LINUX_MACMINI;
121                   sensor_name = strdup("dummy");
122                }
123              else if (ecore_file_exists("/sys/devices/platform/coretemp.0/temp1_input"))
124                {
125                   sensor_type = SENSOR_TYPE_LINUX_INTELCORETEMP;
126                   sensor_name = strdup("dummy");
127                }
128              else if (ecore_file_exists("/sys/devices/platform/thinkpad_hwmon/temp1_input"))
129                {
130                   sensor_type = SENSOR_TYPE_LINUX_THINKPAD;
131                   sensor_name = strdup("dummy");
132                }
133              else
134                {
135                   // try the i2c bus
136                   therms = temperature_get_bus_files("i2c");
137                   if (therms)
138                     {
139                        char *name;
140
141                        if ((name = eina_list_data_get(therms)))
142                          {
143                             if (ecore_file_exists(name))
144                               {
145                                  int len;
146
147                                  snprintf(path, sizeof(path),
148                                           "%s", ecore_file_file_get(name));
149                                  len = strlen(path);
150                                  if (len > 6) path[len - 6] = '\0';
151                                  sensor_type = SENSOR_TYPE_LINUX_I2C;
152                                  sensor_path = strdup(name);
153                                  sensor_name = strdup(path);
154                                  printf("sensor type = i2c\n"
155                                         "sensor path = %s\n"
156                                         "sensor name = %s\n",
157                                         sensor_path, sensor_name);
158                               }
159                          }
160                        eina_list_free(therms);
161                     }
162                   if (!sensor_path)
163                     {
164                        // try the pci bus
165                        therms = temperature_get_bus_files("pci");
166                        if (therms)
167                          {
168                             char *name;
169
170                             if ((name = eina_list_data_get(therms)))
171                               {
172                                  if (ecore_file_exists(name))
173                                    {
174                                       int len;
175
176                                       snprintf(path, sizeof(path),
177                                                "%s", ecore_file_file_get(name));
178                                       len = strlen(path);
179                                       if (len > 6) path[len - 6] = '\0';
180                                       sensor_type = SENSOR_TYPE_LINUX_PCI;
181                                       sensor_path = strdup(name);
182                                       sensor_name = strdup(path);
183                                       printf("sensor type = pci\n"
184                                              "sensor path = %s\n"
185                                              "sensor name = %s\n",
186                                              sensor_path, sensor_name);
187                                    }
188                               }
189                             eina_list_free(therms);
190                          }
191                     }
192                }
193           }
194 #endif
195      }
196    if ((sensor_type) && (sensor_name) && (!sensor_path))
197      {
198         char *name;
199
200         switch (sensor_type)
201           {
202            case SENSOR_TYPE_NONE:
203              break;
204            case SENSOR_TYPE_FREEBSD:
205 #ifdef __FreeBSD__
206              snprintf(path, sizeof(path), "hw.acpi.thermal.%s.temperature",
207                       sensor_name);
208              sensor_path = strdup(path);
209              len = 5;
210              sysctlnametomib(sensor_path, mib, &len);
211 #endif
212              break;
213            case SENSOR_TYPE_OMNIBOOK:
214              sensor_path = strdup("/proc/omnibook/temperature");
215              break;
216            case SENSOR_TYPE_LINUX_MACMINI:
217              sensor_path = strdup("/sys/devices/temperatures/cpu_temperature");
218              break;
219            case SENSOR_TYPE_LINUX_PBOOK:
220              sensor_path = strdup("/sys/devices/temperatures/sensor1_temperature");
221              break;
222            case SENSOR_TYPE_LINUX_INTELCORETEMP:
223              sensor_path = strdup("/sys/devices/platform/coretemp.0/temp1_input");
224              break;
225            case SENSOR_TYPE_LINUX_THINKPAD:
226              sensor_path = strdup("/sys/devices/platform/thinkpad_hwmon/temp1_input");
227              break;
228            case SENSOR_TYPE_LINUX_I2C:
229              therms = ecore_file_ls("/sys/bus/i2c/devices");
230
231              EINA_LIST_FREE(therms, name)
232                {
233                   snprintf(path, sizeof(path),
234                            "/sys/bus/i2c/devices/%s/%s_input",
235                            name, sensor_name);
236                   if (ecore_file_exists(path))
237                     {
238                        sensor_path = strdup(path);
239                             /* We really only care about the first
240                              * one for the default. */
241                        break;
242                          }
243                   free(name);
244                }
245              break;
246            case SENSOR_TYPE_LINUX_PCI:
247              therms = ecore_file_ls("/sys/bus/pci/devices");
248
249              EINA_LIST_FREE(therms, name)
250                {
251                   snprintf(path, sizeof(path),
252                            "/sys/bus/pci/devices/%s/%s_input",
253                            name, sensor_name);
254                   if (ecore_file_exists(path))
255                     {
256                        sensor_path = strdup(path);
257                             /* We really only care about the first
258                              * one for the default. */
259                        break;
260                          }
261                   free(name);
262                }
263              break;
264            case SENSOR_TYPE_LINUX_ACPI:
265              snprintf(path, sizeof(path),
266                       "/proc/acpi/thermal_zone/%s/temperature", sensor_name);
267              sensor_path = strdup(path);
268              break;
269           }
270      }
271 }
272
273 static int
274 check(void)
275 {
276    FILE *f;
277    int ret = 0;
278    int temp = 0;
279    char buf[PATH_MAX];
280 #ifdef __FreeBSD__
281    int len;
282    size_t ftemp = 0;
283 #endif
284
285    /* TODO: Make standard parser. Seems to be two types of temperature string:
286     * - Somename: <temp> C
287     * - <temp>
288     */
289    switch (sensor_type)
290      {
291       case SENSOR_TYPE_NONE:
292         /* TODO: Slow down poller? */
293         break;
294       case SENSOR_TYPE_FREEBSD:
295 #ifdef __FreeBSD__
296         len = sizeof(temp);
297         if (sysctl(mib, 5, &ftemp, &len, NULL, 0) != -1)
298           {
299              temp = (ftemp - 2732) / 10;
300              ret = 1;
301           }
302         else
303           goto error;
304 #endif
305         break;
306       case SENSOR_TYPE_OMNIBOOK:
307         f = fopen(sensor_path, "r");
308         if (f)
309           {
310              char dummy[4096];
311
312              fgets(buf, sizeof(buf), f);
313              buf[sizeof(buf) - 1] = 0;
314              if (sscanf(buf, "%s %s %i", dummy, dummy, &temp) == 3)
315                ret = 1;
316              else
317                goto error;
318              fclose(f);
319           }
320         else
321           goto error;
322         break;
323       case SENSOR_TYPE_LINUX_MACMINI:
324       case SENSOR_TYPE_LINUX_PBOOK:
325         f = fopen(sensor_path, "rb");
326         if (f)
327           {
328              fgets(buf, sizeof(buf), f);
329              fclose(f);
330              buf[sizeof(buf) - 1] = 0;
331              if (sscanf(buf, "%i", &temp) == 1)
332                ret = 1;
333              else
334                goto error;
335           }
336         else
337           goto error;
338         break;
339       case SENSOR_TYPE_LINUX_INTELCORETEMP:
340       case SENSOR_TYPE_LINUX_I2C:
341       case SENSOR_TYPE_LINUX_THINKPAD:
342         f = fopen(sensor_path, "r");
343         if (f)
344           {
345              fgets(buf, sizeof(buf), f);
346              buf[sizeof(buf) - 1] = 0;
347
348              /* actually read the temp */
349              if (sscanf(buf, "%i", &temp) == 1)
350                ret = 1;
351              else
352                goto error;
353              /* Hack for temp */
354              temp = temp / 1000;
355              fclose(f);
356           }
357         else
358           goto error;
359         break;
360       case SENSOR_TYPE_LINUX_PCI:
361         f = fopen(sensor_path, "r");
362         if (f)
363           {
364              fgets(buf, sizeof(buf), f);
365              buf[sizeof(buf) - 1] = 0;
366
367              /* actually read the temp */
368              if (sscanf(buf, "%i", &temp) == 1)
369                ret = 1;
370              else
371                goto error;
372              /* Hack for temp */
373              temp = temp / 1000;
374              fclose(f);
375           }
376         else
377           goto error;
378         break;
379       case SENSOR_TYPE_LINUX_ACPI:
380         f = fopen(sensor_path, "r");
381         if (f)
382           {
383              char *p, *q;
384
385              fgets(buf, sizeof(buf), f);
386              buf[sizeof(buf) - 1] = 0;
387              fclose(f);
388              p = strchr(buf, ':');
389              if (p)
390                {
391                   p++;
392                   while (*p == ' ') p++;
393                   q = strchr(p, ' ');
394                   if (q) *q = 0;
395                   temp = atoi(p);
396                   ret = 1;
397                }
398              else
399                goto error;
400           }
401         else
402           goto error;
403         break;
404      }
405
406    if (ret) return temp;
407
408    return -999;
409 error:
410    sensor_type = SENSOR_TYPE_NONE;
411    if (sensor_name) free(sensor_name);
412    sensor_name = NULL;
413    if (sensor_path) free(sensor_path);
414    sensor_path = NULL;
415    return -999;
416 }
417
418 static Eina_Bool
419 poll_cb(void *data)
420 {
421    int t, pp;
422
423    t = check();
424    pp = cur_poll_interval;
425    if (t != ptemp)
426      {
427         cur_poll_interval /= 2;
428         if (cur_poll_interval < 4) cur_poll_interval = 4;
429      }
430    else
431      {
432         cur_poll_interval *= 2;
433         if (cur_poll_interval > 256) cur_poll_interval = 256;
434      }
435    /* adapt polling based on if temp changes - every time it changes,
436     * halve the time between polls, otherwise double it, between 4 and
437     * 256 ticks */
438    if (pp != cur_poll_interval)
439      {
440         if (poller) ecore_poller_del(poller);
441         poller = ecore_poller_add(ECORE_POLLER_CORE, cur_poll_interval,
442                                   poll_cb, NULL);
443      }
444    if (t != ptemp)
445      {
446         if (t == -999) printf("ERROR\n");
447         else printf("%i\n", t);
448         fflush(stdout);
449      }
450    ptemp = t;
451    return ECORE_CALLBACK_RENEW;
452 }
453
454 int
455 main(int argc, char *argv[])
456 {
457    if (argc != 4)
458      {
459         printf("ARGS INCORRECT!\n");
460         return 0;
461      }
462    sensor_type = atoi(argv[1]);
463    sensor_name = strdup(argv[2]);
464    if (!strcmp(sensor_name, "-null-"))
465      {
466         free(sensor_name);
467         sensor_name = NULL;
468      }
469    poll_interval = atoi(argv[3]);
470    cur_poll_interval = poll_interval;
471
472    ecore_init();
473
474    init();
475
476    if (poller) ecore_poller_del(poller);
477    poller = ecore_poller_add(ECORE_POLLER_CORE, cur_poll_interval,
478                              poll_cb, NULL);
479    poll_cb(NULL);
480
481    ecore_main_loop_begin();
482    ecore_shutdown();
483
484    return 0;
485 }