Remove internal header files
[platform/hal/api/device.git] / src / battery.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <vconf.h>
23 #define _GNU_SOURCE
24 #include <dlfcn.h>
25 #include <libsyscommon/dbus-system.h>
26
27 #include "hal-battery.h"
28 #include "common.h"
29 #include <system_info.h>
30
31 #define METHOD_GET_PERCENT              "GetPercent"
32 #define METHOD_GET_INFO         "GetBatteryInfo"
33
34 #define BATTERY_FEATURE              "http://tizen.org/feature/battery"
35
36 #ifndef LIBPATH
37 #error LIBPATH is not defined.
38 #endif
39
40 #define BATTERY_PLUGIN          LIBPATH"/libbattery-plugin.so"
41 #define GET_INFO_FUNC           "battery_get_info_direct"
42
43 static void *handle;
44 static int (*plugin_battery_get_info)(void *);
45
46 static int is_battery_supported(void)
47 {
48         int ret;
49         bool battery_avail;
50
51         ret = system_info_get_platform_bool(BATTERY_FEATURE, &battery_avail);
52         if (ret < 0) {
53 //LCOV_EXCL_START System Error
54                 _E("Failed to get value of battery feature");
55                 return false;
56 //LCOV_EXCL_STOP
57         } else if (ret == 0 && !battery_avail) {
58 //LCOV_EXCL_START System Error
59                 _D("Battery is not supported");
60                 return false;
61 //LCOV_EXCL_STOP
62         } else
63                 return true;
64 }
65
66
67 int device_battery_get_percent(int *percent)
68 {
69         int ret;
70
71         if (!percent)
72                 return DEVICE_ERROR_INVALID_PARAMETER;
73
74         ret = is_battery_supported();
75         if (!ret)
76                 return DEVICE_ERROR_NOT_SUPPORTED;
77
78         ret = dbus_handle_method_sync_var(DEVICED_BUS_NAME,
79                         DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY,
80                         METHOD_GET_PERCENT, NULL);
81         /* regard not suppoted as disconnected */
82         if (ret == -ENOTSUP)
83                 ret = 0;
84         else if (ret < 0)
85                 return errno_to_device_error(ret); //LCOV_EXCL_LINE System Error
86
87         *percent = ret;
88         return DEVICE_ERROR_NONE;
89 }
90
91 int device_battery_is_charging(bool *charging)
92 {
93         int ret, val;
94
95         if (!charging)
96                 return DEVICE_ERROR_INVALID_PARAMETER;
97
98         ret = is_battery_supported();
99         if (!ret)
100                 return DEVICE_ERROR_NOT_SUPPORTED;
101
102         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, &val);
103         /* regard not supported as disconnected */
104         if (val == -ENOTSUP)
105                 val = 0; //LCOV_EXCL_LINE System Error
106         else if (ret < 0 || val < 0 || val > 1)
107                 return DEVICE_ERROR_OPERATION_FAILED;
108
109         *charging = val;
110         return DEVICE_ERROR_NONE;
111 }
112
113 int device_battery_get_level_status(device_battery_level_e *status)
114 {
115         int val, ret;
116
117         if (!status)
118                 return DEVICE_ERROR_INVALID_PARAMETER;
119
120         ret = is_battery_supported();
121         if (!ret)
122                 return DEVICE_ERROR_NOT_SUPPORTED;
123
124         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, &val);
125         if (ret < 0)
126                 return DEVICE_ERROR_OPERATION_FAILED;
127
128         if (val == VCONFKEY_SYSMAN_BAT_LEVEL_EMPTY)
129                 *status = DEVICE_BATTERY_LEVEL_EMPTY;
130         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_CRITICAL)
131                 *status = DEVICE_BATTERY_LEVEL_CRITICAL;
132         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_LOW)
133                 *status = DEVICE_BATTERY_LEVEL_LOW;
134         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_HIGH)
135                 *status = DEVICE_BATTERY_LEVEL_HIGH;
136         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_FULL)
137                 *status = DEVICE_BATTERY_LEVEL_FULL;
138 //LCOV_EXCL_START System Error
139         /* regard not supported as disconnected */
140         else if (val == -ENOTSUP)
141                 *status = DEVICE_BATTERY_LEVEL_EMPTY;
142 //LCOV_EXCL_STOP
143         else
144                 return DEVICE_ERROR_OPERATION_FAILED;
145
146         return DEVICE_ERROR_NONE;
147 }
148
149 static int load_battery_plugin()
150 {
151         if (plugin_battery_get_info)
152                 return 0;
153
154         if (!handle) {
155                 handle = dlopen(BATTERY_PLUGIN, RTLD_NOW);
156                 if (!handle) {
157 //LCOV_EXCL_START System Error
158                         _E("Failed to open '%s' : %s", BATTERY_PLUGIN, dlerror());
159                         return -1;
160 //LCOV_EXCL_STOP
161                 }
162         }
163
164         plugin_battery_get_info = (int (*)(void *))dlsym(handle, GET_INFO_FUNC);
165         if (!plugin_battery_get_info) {
166 //LCOV_EXCL_START System Error
167                 _E("Failed to get symbol '%s' : %s", GET_INFO_FUNC, dlerror());
168                 return -1;
169 //LCOV_EXCL_STOP
170         }
171
172         return 0;
173 }
174
175 int device_battery_get_info_direct(struct device_battery_info *info)
176 {
177         int ret;
178
179         if (!info)
180                 return DEVICE_ERROR_INVALID_PARAMETER;
181
182         ret = is_battery_supported();
183         if (!ret)
184                 return DEVICE_ERROR_NOT_SUPPORTED;
185
186         if (load_battery_plugin() < 0)
187                 return DEVICE_ERROR_OPERATION_FAILED;
188
189         ret = plugin_battery_get_info(info);
190         if (ret < 0) {
191 //LCOV_EXCL_START System Error
192                 _E("Failed to get battery info: %d", ret);
193                 return DEVICE_ERROR_OPERATION_FAILED;
194 //LCOV_EXCL_STOP
195         }
196
197         return DEVICE_ERROR_NONE;
198 }
199
200 int device_battery_get_info(struct device_battery_info *info)
201 {
202         int ret;
203         GVariant *output = NULL;
204         char *status = NULL;
205         char *health = NULL;
206         char *power_source = NULL;
207         int online;
208         int present;
209         int capacity;
210         int current_now;
211         int current_average;
212         int voltage_now;
213         int voltage_average;
214         int temperature;
215
216         if (!info)
217                 return DEVICE_ERROR_INVALID_PARAMETER;
218
219         ret = is_battery_supported();
220         if (!ret)
221                 return DEVICE_ERROR_NOT_SUPPORTED;
222
223         output = dbus_handle_method_sync_with_reply_var(DEVICED_BUS_NAME,
224                         DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY,
225                         METHOD_GET_INFO, NULL);
226
227         if (!output)
228                 return DEVICE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE System Error
229
230         g_variant_get(output, "(isssiiiiiiii)", &ret,
231                         &status, &health, &power_source,
232                         &online, &present, &capacity,
233                         &current_now, &current_average, &voltage_now,
234                         &voltage_average, &temperature);
235
236         if (ret < 0) {
237                 //LCOV_EXCL_START System Error
238                 ret = errno_to_device_error(ret);
239                 goto out;
240                 //LCOV_EXCL_STOP
241         }
242
243         snprintf(info->status, sizeof(info->status), "%s", status);
244         snprintf(info->health, sizeof(info->health), "%s", health);
245         snprintf(info->power_source, sizeof(info->power_source), "%s", power_source);
246         info->online = online;
247         info->present = present;
248         info->capacity = capacity;
249         info->current_now = current_now;
250         info->current_average = current_average;
251         info->voltage_now = voltage_now;
252         info->voltage_average = voltage_average;
253         info->temperature = temperature;
254
255         ret = DEVICE_ERROR_NONE;
256
257 out:
258         g_free(status);
259         g_free(health);
260         g_free(power_source);
261         g_variant_unref(output);
262
263         return ret;
264 }
265
266 int device_battery_get_health(device_battery_health_e *health)
267 {
268         struct device_battery_info info;
269         int ret;
270         size_t len;
271
272         if (!health)
273                 return DEVICE_ERROR_INVALID_PARAMETER;
274
275         ret = is_battery_supported();
276         if (!ret)
277                 return DEVICE_ERROR_NOT_SUPPORTED;
278
279         ret = device_battery_get_info(&info);
280         if (ret != DEVICE_ERROR_NONE) {
281 //LCOV_EXCL_START System Error
282                 _E("Failed to get battery info (%d)", ret);
283                 return ret;
284 //LCOV_EXCL_STOP
285         }
286
287         len = strlen(info.health);
288         if (!strncmp(info.health, "Good", len))
289                 *health = DEVICE_BATTERY_HEALTH_GOOD;
290         else if (!strncmp(info.health, "Cold", len))
291                 *health = DEVICE_BATTERY_HEALTH_COLD;
292         else if (!strncmp(info.health, "Dead", len))
293                 *health = DEVICE_BATTERY_HEALTH_DEAD;
294         else if (!strncmp(info.health, "Overheat", len))
295                 *health = DEVICE_BATTERY_HEALTH_OVER_HEAT;
296         else if (!strncmp(info.health, "Over voltage", len))
297                 *health = DEVICE_BATTERY_HEALTH_OVER_VOLTAGE;
298         else
299                 return DEVICE_ERROR_OPERATION_FAILED;
300
301         return DEVICE_ERROR_NONE;
302 }
303
304 int device_battery_get_power_source(device_battery_power_source_e *source)
305 {
306         struct device_battery_info info;
307         int ret;
308         size_t len;
309
310         if (!source)
311                 return DEVICE_ERROR_INVALID_PARAMETER;
312
313         ret = is_battery_supported();
314         if (!ret)
315                 return DEVICE_ERROR_NOT_SUPPORTED;
316
317         ret = device_battery_get_info(&info);
318         if (ret != DEVICE_ERROR_NONE) {
319 //LCOV_EXCL_START System Error
320                 _E("Failed to get battery info (%d)", ret);
321                 return ret;
322 //LCOV_EXCL_STOP
323         }
324
325         len = strlen(info.power_source);
326         if (!strncmp(info.power_source, "ac", len))
327                 *source = DEVICE_BATTERY_POWER_SOURCE_AC;
328         else if (!strncmp(info.power_source, "usb", len))
329                 *source = DEVICE_BATTERY_POWER_SOURCE_USB;
330         else if (!strncmp(info.power_source, "wireless", len))
331                 *source = DEVICE_BATTERY_POWER_SOURCE_WIRELESS;
332         else
333                 *source = DEVICE_BATTERY_POWER_SOURCE_NONE;
334
335         return DEVICE_ERROR_NONE;
336 }
337
338 int device_battery_get_property(device_battery_property_e property, int *val)
339 {
340         struct device_battery_info info = {0, };
341         int ret;
342
343         if (!val)
344                 return DEVICE_ERROR_INVALID_PARAMETER;
345
346         ret = is_battery_supported();
347         if (!ret)
348                 return DEVICE_ERROR_NOT_SUPPORTED;
349
350         ret = device_battery_get_info(&info);
351         if (ret != DEVICE_ERROR_NONE) {
352 //LCOV_EXCL_START System Error
353                 _E("Failed to get battery info (%d)", ret);
354                 return ret;
355 //LCOV_EXCL_STOP
356         }
357
358         switch (property) {
359         case DEVICE_BATTERY_PROPERTY_CAPACITY:
360                 *val = info.capacity;
361                 break;
362         case DEVICE_BATTERY_PROPERTY_CURRENT_NOW:
363                 *val = info.current_now;
364                 break;
365         case DEVICE_BATTERY_PROPERTY_CURRENT_AVERAGE:
366                 *val = info.current_average;
367                 break;
368         case DEVICE_BATTERY_PROPERTY_VOLTAGE_NOW:
369                 *val = info.voltage_now;
370                 break;
371         case DEVICE_BATTERY_PROPERTY_VOLTAGE_AVERAGE:
372                 *val = info.voltage_average;
373                 break;
374         case DEVICE_BATTERY_PROPERTY_TEMPERATURE:
375                 *val = info.temperature;
376                 break;
377
378         default:
379                 return DEVICE_ERROR_INVALID_PARAMETER;
380         }
381
382         return DEVICE_ERROR_NONE;
383 }
384
385 int device_battery_get_status(device_battery_status_e *status)
386 {
387         struct device_battery_info info;
388         int ret;
389         size_t len;
390
391         if (!status)
392                 return DEVICE_ERROR_INVALID_PARAMETER;
393
394         ret = is_battery_supported();
395         if (!ret)
396                 return DEVICE_ERROR_NOT_SUPPORTED;
397
398         ret = device_battery_get_info(&info);
399         if (ret != DEVICE_ERROR_NONE) {
400 //LCOV_EXCL_START System Error
401                 _E("Failed to get battery info (%d)", ret);
402                 return ret;
403 //LCOV_EXCL_STOP
404         }
405
406         len = strlen(info.status);
407         if (!strncmp(info.status, "Charging", len))
408                 *status = DEVICE_BATTERY_STATUS_CHARGING;
409         else if (!strncmp(info.status, "Discharging", len))
410                 *status = DEVICE_BATTERY_STATUS_DISCHARGING;
411         else if (!strncmp(info.status, "Full", len))
412                 *status = DEVICE_BATTERY_STATUS_FULL;
413         else if (!strncmp(info.status, "Not charging", len))
414                 *status = DEVICE_BATTERY_STATUS_NOT_CHARGING;
415         else
416                 return DEVICE_ERROR_OPERATION_FAILED;
417
418         return DEVICE_ERROR_NONE;
419 }
420
421 void __attribute__ ((destructor)) battery_finalize(void)
422 {
423         if (handle) {
424                 dlclose(handle);
425                 handle = NULL;
426         }
427 }