capi-system-device: Add flash brightness callback function
[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 #include <gio/gio.h>
24
25 #include "callback.h"
26 #include "battery.h"
27 #include "display.h"
28 #include "common.h"
29 #include "dbus.h"
30 #include "list.h"
31
32 #define SIGNAL_FLASH_STATE  "ChangeFlashState"
33
34 struct device_cb_info {
35         device_changed_cb cb;
36         void *data;
37 };
38
39 static dd_list *device_cb_list[DEVICE_CALLBACK_MAX];
40 static int flash_sigid;
41
42 static void battery_capacity_cb(keynode_t *key, void *data)
43 {
44         static device_callback_e type = DEVICE_CALLBACK_BATTERY_CAPACITY;
45         struct device_cb_info *cb_info;
46         dd_list *elem;
47         int val;
48
49         val = vconf_keynode_get_int(key);
50
51         /* invoke the each callback with value */
52         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
53                 cb_info->cb(type, (void*)val, cb_info->data);
54 }
55
56 static void battery_charging_cb(keynode_t *key, void *data)
57 {
58         static device_callback_e type = DEVICE_CALLBACK_BATTERY_CHARGING;
59         struct device_cb_info *cb_info;
60         dd_list *elem;
61         int val;
62
63         val = vconf_keynode_get_int(key);
64
65         /* invoke the each callback with value */
66         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
67                 cb_info->cb(type, (void*)val, cb_info->data);
68 }
69
70 static void battery_level_cb(keynode_t *key, void *data)
71 {
72         static device_callback_e type = DEVICE_CALLBACK_BATTERY_LEVEL;
73         struct device_cb_info *cb_info;
74         dd_list *elem;
75         int val, status;
76
77         val = vconf_keynode_get_int(key);
78
79         if (val == VCONFKEY_SYSMAN_BAT_LEVEL_EMPTY)
80                 status = DEVICE_BATTERY_LEVEL_EMPTY;
81         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_CRITICAL)
82                 status = DEVICE_BATTERY_LEVEL_CRITICAL;
83         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_LOW)
84                 status = DEVICE_BATTERY_LEVEL_LOW;
85         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_HIGH)
86                 status = DEVICE_BATTERY_LEVEL_HIGH;
87         else if (val == VCONFKEY_SYSMAN_BAT_LEVEL_FULL)
88                 status = DEVICE_BATTERY_LEVEL_FULL;
89         else
90                 status = -1;
91
92         /* invoke the each callback with value */
93         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
94                 cb_info->cb(type, (void*)status, cb_info->data);
95 }
96
97 static void display_changed_cb(keynode_t *key, void *data)
98 {
99         static device_callback_e type = DEVICE_CALLBACK_DISPLAY_STATE;
100         struct device_cb_info *cb_info;
101         dd_list *elem;
102         display_state_e state;
103         int val;
104
105         val = vconf_keynode_get_int(key);
106
107         switch(val) {
108         case 1: state = DISPLAY_STATE_NORMAL;
109                         break;
110         case 2: state = DISPLAY_STATE_SCREEN_DIM;
111                         break;
112         case 3: state = DISPLAY_STATE_SCREEN_OFF;
113                         break;
114         default: state = -1;
115                         break;
116         }
117
118         /* invoke the each callback with value */
119         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
120                 cb_info->cb(type, (void*)state, cb_info->data);
121 }
122
123 static void flash_state_cb(GDBusConnection *conn,
124                 const gchar *sender,
125                 const gchar *object,
126                 const gchar *interface,
127                 const gchar *signal,
128                 GVariant *parameters,
129                 gpointer user_data)
130 {
131         static int type = DEVICE_CALLBACK_FLASH_BRIGHTNESS;
132         struct device_cb_info *cb_info;
133         dd_list *elem;
134         int val;
135
136         if (strncmp(signal, SIGNAL_FLASH_STATE,
137                                 sizeof(SIGNAL_FLASH_STATE)) != 0) {
138                 _E("wrong parameter : signal(%s)", signal);
139                 return;
140         }
141
142         /* get camera value */
143         g_variant_get(parameters, "(i)", &val);
144         _D("%s - %d", signal, val);
145
146         /* invoke the each callback with value */
147         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info)
148                 cb_info->cb(type, (void*)val, cb_info->data);
149 }
150
151 static int register_signal(const char *bus_name,
152                 const char *object_path,
153                 const char *interface_name,
154                 const char *signal,
155                 GDBusSignalCallback callback,
156                 int *sig_id)
157 {
158         GError *err = NULL;
159         GDBusConnection *conn;
160         int id;
161
162 #if !GLIB_CHECK_VERSION(2,35,0)
163         g_type_init();
164 #endif
165
166         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
167         if (!conn) {
168                 _E("fail to get dbus connection : %s", err->message);
169                 g_clear_error(&err);
170                 return -EPERM;
171         }
172
173         /* subscribe signal */
174         id = g_dbus_connection_signal_subscribe(conn,
175                         bus_name,
176                         interface_name,
177                         signal,         /* null to match on all signals */
178                         object_path,
179                         NULL,           /* null to match on all kinds of arguments */
180                         G_DBUS_SIGNAL_FLAGS_NONE,
181                         callback,
182                         NULL,
183                         NULL);
184         if (id == 0) {
185                 _E("fail to connect %s signal", signal);
186                 return -EPERM;
187         }
188
189         if (sig_id)
190                 *sig_id = id;
191
192         return 0;
193 }
194
195 static int unregister_signal(int *sig_id)
196 {
197         GError *err = NULL;
198         GDBusConnection *conn;
199
200         if (!sig_id)
201                 return -EINVAL;
202
203         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
204         if (!conn) {
205                 _E("fail to get dbus connection : %s", err->message);
206                 g_clear_error(&err);
207                 return -EPERM;
208         }
209
210         /* unsubscribe signal */
211         g_dbus_connection_signal_unsubscribe(conn, *sig_id);
212         *sig_id = 0;
213
214         return 0;
215 }
216
217 static int register_request(device_callback_e type)
218 {
219         switch (type) {
220         case DEVICE_CALLBACK_BATTERY_CAPACITY:
221                 return vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
222                                 battery_capacity_cb, NULL);
223         case DEVICE_CALLBACK_BATTERY_LEVEL:
224                 return vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS,
225                                 battery_level_cb, NULL);
226         case DEVICE_CALLBACK_BATTERY_CHARGING:
227                 return vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
228                                 battery_charging_cb, NULL);
229         case DEVICE_CALLBACK_DISPLAY_STATE:
230                 return vconf_notify_key_changed(VCONFKEY_PM_STATE,
231                                 display_changed_cb, NULL);
232         case DEVICE_CALLBACK_FLASH_BRIGHTNESS:
233                 /* sig_id begins with 1. */
234                 if (flash_sigid)
235                         return -EEXIST;
236                 return register_signal(DEVICED_BUS_NAME,
237                                 DEVICED_PATH_LED,
238                                 DEVICED_INTERFACE_LED,
239                                 SIGNAL_FLASH_STATE, flash_state_cb, &flash_sigid);
240         default:
241                 break;
242         }
243
244         return -EINVAL;
245 }
246
247 static int release_request(device_callback_e type)
248 {
249         switch (type) {
250         case DEVICE_CALLBACK_BATTERY_CAPACITY:
251                 return vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
252                                 battery_capacity_cb);
253         case DEVICE_CALLBACK_BATTERY_LEVEL:
254                 return vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS,
255                                 battery_level_cb);
256         case DEVICE_CALLBACK_BATTERY_CHARGING:
257                 return vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
258                                 battery_charging_cb);
259         case DEVICE_CALLBACK_DISPLAY_STATE:
260                 return vconf_ignore_key_changed(VCONFKEY_PM_STATE,
261                                 display_changed_cb);
262         case DEVICE_CALLBACK_FLASH_BRIGHTNESS:
263                 if (!flash_sigid)
264                         return -ENOENT;
265                 return unregister_signal(&flash_sigid);
266         default:
267                 break;
268         }
269
270         return -EINVAL;
271 }
272
273 int device_add_callback(device_callback_e type, device_changed_cb cb, void *data)
274 {
275         struct device_cb_info *cb_info;
276         dd_list *elem;
277         int ret, n;
278
279         if (type < 0 || type >= DEVICE_CALLBACK_MAX)
280                 return DEVICE_ERROR_INVALID_PARAMETER;
281
282         if (!cb)
283                 return DEVICE_ERROR_INVALID_PARAMETER;
284
285         /* check if it is the first request */
286         n = DD_LIST_LENGTH(device_cb_list[type]);
287         if (n == 0) {
288                 ret = register_request(type);
289                 if (ret < 0)
290                         return DEVICE_ERROR_OPERATION_FAILED;
291         }
292
293         /* check for the same request */
294         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info) {
295                 if (cb_info->cb == cb)
296                         return DEVICE_ERROR_ALREADY_IN_PROGRESS;
297         }
298
299         /* add device changed callback to list (local) */
300         cb_info = malloc(sizeof(struct device_cb_info));
301         if (!cb_info)
302                 return DEVICE_ERROR_OPERATION_FAILED;
303
304         cb_info->cb = cb;
305         cb_info->data = data;
306
307         DD_LIST_APPEND(device_cb_list[type], cb_info);
308
309         return DEVICE_ERROR_NONE;
310 }
311
312 int device_remove_callback(device_callback_e type, device_changed_cb cb)
313 {
314         struct device_cb_info *cb_info;
315         dd_list *elem;
316         int ret, n;
317
318         if (type < 0 || type >= DEVICE_CALLBACK_MAX)
319                 return DEVICE_ERROR_INVALID_PARAMETER;
320
321         if (!cb)
322                 return DEVICE_ERROR_INVALID_PARAMETER;
323
324         /* search for the same element with callback */
325         DD_LIST_FOREACH(device_cb_list[type], elem, cb_info) {
326                 if (cb_info->cb == cb)
327                         break;
328         }
329
330         if (!cb_info)
331                 return DEVICE_ERROR_INVALID_PARAMETER;
332
333         /* remove device callback from list (local) */
334         DD_LIST_REMOVE(device_cb_list[type], cb_info);
335         free(cb_info);
336
337         /* check if this callback is last element */
338         n = DD_LIST_LENGTH(device_cb_list[type]);
339         if (n == 0) {
340                 ret = release_request(type);
341                 if (ret < 0)
342                         return DEVICE_ERROR_OPERATION_FAILED;
343         }
344
345         return DEVICE_ERROR_NONE;
346 }