device: Merge public api on Tizen 2.3 into tizen branch
[platform/core/api/device.git] / src / callback.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
24 #include "callback.h"
25 #include "battery.h"
26 #include "display.h"
27 #include "common.h"
28 #include "dbus.h"
29 #include "list.h"
30
31 struct device_cb_info {
32         device_changed_cb cb;
33         void *data;
34 };
35
36 static dd_list *device_cb_list[DEVICE_CALLBACK_MAX];
37
38 static void battery_capacity_cb(keynode_t *key, void *data)
39 {
40         static device_callback_e type = DEVICE_CALLBACK_BATTERY_CAPACITY;
41         struct device_cb_info *cb_info;
42         dd_list *elem;
43         int val;
44
45         val = vconf_keynode_get_int(key);
46
47         /* invoke the each callback with value */
48         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
49                 cb_info->cb(type, (void*)val, cb_info->data);
50 }
51
52 static void battery_charging_cb(keynode_t *key, void *data)
53 {
54         static device_callback_e type = DEVICE_CALLBACK_BATTERY_CHARGING;
55         struct device_cb_info *cb_info;
56         dd_list *elem;
57         int val;
58
59         val = vconf_keynode_get_int(key);
60
61         /* invoke the each callback with value */
62         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
63                 cb_info->cb(type, (void*)val, cb_info->data);
64 }
65
66 static void battery_level_cb(keynode_t *key, void *data)
67 {
68         static device_callback_e type = DEVICE_CALLBACK_BATTERY_LEVEL;
69         struct device_cb_info *cb_info;
70         dd_list *elem;
71         int val, status;
72
73         val = vconf_keynode_get_int(key);
74
75         if (val == VCONFKEY_SYSMAN_BAT_LEVEL_EMPTY)
76                 status = DEVICE_BATTERY_LEVEL_EMPTY;
77         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_CRITICAL)
78                 status = DEVICE_BATTERY_LEVEL_CRITICAL;
79         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_LOW)
80                 status = DEVICE_BATTERY_LEVEL_LOW;
81         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_HIGH)
82                 status = DEVICE_BATTERY_LEVEL_HIGH;
83         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_FULL)
84                 status = DEVICE_BATTERY_LEVEL_FULL;
85         else
86                 status = -1;
87
88         /* invoke the each callback with value */
89         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
90                 cb_info->cb(type, (void*)status, cb_info->data);
91 }
92
93 static void display_changed_cb(keynode_t *key, void *data)
94 {
95         static device_callback_e type = DEVICE_CALLBACK_DISPLAY_STATE;
96         struct device_cb_info *cb_info;
97         dd_list *elem;
98         display_state_e state;
99         int val;
100
101         val = vconf_keynode_get_int(key);
102
103         switch(val) {
104         case 1: state = DISPLAY_STATE_NORMAL;
105                         break;
106         case 2: state = DISPLAY_STATE_SCREEN_DIM;
107                         break;
108         case 3: state = DISPLAY_STATE_SCREEN_OFF;
109                         break;
110         default: state = -1;
111                         break;
112         }
113
114         /* invoke the each callback with value */
115         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
116                 cb_info->cb(type, (void*)state, cb_info->data);
117 }
118
119 static int register_request(device_callback_e type)
120 {
121         switch (type) {
122         case DEVICE_CALLBACK_BATTERY_CAPACITY:
123                 return vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
124                                 battery_capacity_cb, NULL);
125         case DEVICE_CALLBACK_BATTERY_LEVEL:
126                 return vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS,
127                                 battery_level_cb, NULL);
128         case DEVICE_CALLBACK_BATTERY_CHARGING:
129                 return vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
130                                 battery_charging_cb, NULL);
131         case DEVICE_CALLBACK_DISPLAY_STATE:
132                 return vconf_notify_key_changed(VCONFKEY_PM_STATE,
133                                 display_changed_cb, NULL);
134         default:
135                 break;
136         }
137
138         return -EINVAL;
139 }
140
141 static int release_request(device_callback_e type)
142 {
143         switch (type) {
144         case DEVICE_CALLBACK_BATTERY_CAPACITY:
145                 return vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
146                                 battery_capacity_cb);
147         case DEVICE_CALLBACK_BATTERY_LEVEL:
148                 return vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS,
149                                 battery_level_cb);
150         case DEVICE_CALLBACK_BATTERY_CHARGING:
151                 return vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
152                                 battery_charging_cb);
153         case DEVICE_CALLBACK_DISPLAY_STATE:
154                 return vconf_ignore_key_changed(VCONFKEY_PM_STATE,
155                                 display_changed_cb);
156         default:
157                 break;
158         }
159
160         return -EINVAL;
161 }
162
163 int device_add_callback(device_callback_e type, device_changed_cb cb, void *data)
164 {
165         struct device_cb_info *cb_info;
166         dd_list *elem;
167         int ret, n;
168
169         if (type < 0 || type >= DEVICE_CALLBACK_MAX)
170                 return DEVICE_ERROR_INVALID_PARAMETER;
171
172         if (!cb)
173                 return DEVICE_ERROR_INVALID_PARAMETER;
174
175         /* check if it is the first request */
176         n = DD_LIST_LENGTH(device_cb_list[type]);
177         if (n == 0) {
178                 ret = register_request(type);
179                 if (ret < 0)
180                         return DEVICE_ERROR_OPERATION_FAILED;
181         }
182
183         /* check for the same request */
184         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info) {
185                 if (cb_info->cb == cb)
186                         return DEVICE_ERROR_ALREADY_IN_PROGRESS;
187         }
188
189         /* add device changed callback to list (local) */
190         cb_info = malloc(sizeof(struct device_cb_info));
191         if (!cb_info)
192                 return DEVICE_ERROR_OPERATION_FAILED;
193
194         cb_info->cb = cb;
195         cb_info->data = data;
196
197         DD_LIST_APPEND(device_cb_list[type], cb_info);
198
199         return DEVICE_ERROR_NONE;
200 }
201
202 int device_remove_callback(device_callback_e type, device_changed_cb cb)
203 {
204         struct device_cb_info *cb_info;
205         dd_list *elem;
206         int ret, n;
207
208         if (type < 0 || type >= DEVICE_CALLBACK_MAX)
209                 return DEVICE_ERROR_INVALID_PARAMETER;
210
211         if (!cb)
212                 return DEVICE_ERROR_INVALID_PARAMETER;
213
214         /* search for the same element with callback */
215         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info) {
216                 if (cb_info->cb == cb)
217                         break;
218         }
219
220         if (!cb_info)
221                 return DEVICE_ERROR_INVALID_PARAMETER;
222
223         /* remove device callback from list (local) */
224         DD_LIST_REMOVE(device_cb_list[type], cb_info);
225         free(cb_info);
226
227         /* check if this callback is last element */
228         n = DD_LIST_LENGTH(device_cb_list[type]);
229         if (n == 0) {
230                 ret = release_request(type);
231                 if (ret < 0)
232                         return DEVICE_ERROR_OPERATION_FAILED;
233         }
234
235         return DEVICE_ERROR_NONE;
236 }