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