thermal: fix to read and parse the contents of the sysfs
[platform/hal/backend/tm1/device-tm1.git] / hw / thermal / thermal.c
1 /*
2  * device-node
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <glib.h>
25
26 #include <hw/thermal.h>
27 #include "../shared.h"
28
29 #define THERMAL_PATH "/sys/class/sec/temperature/ap_therm"
30
31 static struct event_data {
32         ThermalUpdated updated_cb;
33         void *data;
34 } edata = { 0, };
35
36 static guint timer;
37
38 static int thermal_get_state(struct thermal_info *info)
39 {
40         int ret, value;
41         FILE *fp;
42         char buf[32];
43         size_t len;
44
45         if (!info)
46                 return -EINVAL;
47
48         fp = fopen(THERMAL_PATH, "r");
49         if (!fp) {
50                 _E("Failed to open %s(%d)", THERMAL_PATH, errno);
51                 return -errno;
52         }
53
54         len = fread(buf, 1, sizeof(buf) - 1, fp);
55         fclose(fp);
56         if (len == 0) {
57                 _E("Failed to read %s(%d)", THERMAL_PATH, errno);
58                 return -errno;
59         }
60         buf[len] = '\0';
61
62         if (!strstr(buf, "temp:")) {
63                 _E("Invalid temparature value (%s)", buf);
64                 return -EINVAL;
65         }
66
67         value = atoi(buf + 5); /* 5 == strlen("temp:") */
68
69         _I("AP temparature(%d)", value);
70
71         if (value < 30) {
72                 info->state = THERMAL_STATE_LOW;
73                 info->level = THERMAL_LEVEL_NORMAL;
74                 return 0;
75         }
76
77         if (value < 40) {
78                 info->state = THERMAL_STATE_NORMAL;
79                 info->level = THERMAL_LEVEL_NORMAL;
80                 return 0;
81         }
82
83         info->state = THERMAL_STATE_HIGH;
84
85         if (value < 42)
86                 info->level = THERMAL_LEVEL_WARNING;
87         else if (value < 43)
88                 info->level = THERMAL_LEVEL_CRITICAL;
89         else
90                 info->level = THERMAL_LEVEL_POWEROFF;
91
92         return 0;
93 }
94
95 static gboolean thermal_timeout(gpointer data)
96 {
97         struct thermal_info info;
98         int ret;
99
100         ret = thermal_get_state(&info);
101         if (ret < 0) {
102                 _E("Failed to read thermal state (%d)", ret);
103                 return G_SOURCE_CONTINUE;
104         }
105
106         if (edata.updated_cb)
107                 edata.updated_cb(&info, edata.data);
108
109         return G_SOURCE_CONTINUE;
110 }
111
112 static int thermal_register_changed_event(ThermalUpdated updated_cb, void *data)
113 {
114         if (timer)
115                 g_source_remove(timer);
116
117         timer = g_timeout_add(10000, thermal_timeout, NULL);
118         if (timer == 0) {
119                 _E("Failed to add timer for thermal");
120                 return -ENOENT;
121         }
122
123         edata.updated_cb = updated_cb;
124         edata.data = data;
125
126         return 0;
127 }
128
129 static int thermal_unregister_changed_event(ThermalUpdated updated_cb)
130 {
131         if (timer) {
132                 g_source_remove(timer);
133                 timer = 0;
134         }
135
136         edata.updated_cb = NULL;
137         edata.data = NULL;
138
139         return 0;
140 }
141
142 static int thermal_open(struct hw_info *info,
143                 const char *id, struct hw_common **common)
144 {
145         struct thermal_device *thermal_dev;
146
147         if (!info || !common)
148                 return -EINVAL;
149
150         thermal_dev = calloc(1, sizeof(struct thermal_device));
151         if (!thermal_dev)
152                 return -ENOMEM;
153
154         thermal_dev->common.info = info;
155         thermal_dev->register_changed_event
156                 = thermal_register_changed_event;
157         thermal_dev->unregister_changed_event
158                 = thermal_unregister_changed_event;
159         thermal_dev->get_state
160                 = thermal_get_state;
161
162         *common = (struct hw_common *)thermal_dev;
163         return 0;
164 }
165
166 static int thermal_close(struct hw_common *common)
167 {
168         if (!common)
169                 return -EINVAL;
170
171         free(common);
172         return 0;
173 }
174
175 HARDWARE_MODULE_STRUCTURE = {
176         .magic = HARDWARE_INFO_TAG,
177         .hal_version = HARDWARE_INFO_VERSION,
178         .device_version = THERMAL_HARDWARE_DEVICE_VERSION,
179         .id = THERMAL_HARDWARE_DEVICE_ID,
180         .name = "thermal",
181         .open = thermal_open,
182         .close = thermal_close,
183 };