32ec0e9a5770d0998396308f52f6051915cb12da
[framework/appfw/app-core.git] / src / appcore-rotation.c
1 /*
2  *  app-core
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #include <sensor.h>
28 #include <vconf.h>
29
30 #include "appcore-internal.h"
31
32 #define LCD_TYPE_KEY "memory/sensor/lcd_type"
33
34 struct rot_s {
35         int handle;
36         int (*callback) (enum appcore_rm, void *);
37         enum appcore_rm mode;
38         int lock;
39         void *cbdata;
40         int cb_set;
41         int sf_started;
42 };
43 static struct rot_s rot;
44
45 struct rot_evt {
46         enum accelerometer_rotate_state re;
47         enum appcore_rm rm;
48 };
49
50 static struct rot_evt re_to_rm[] = {
51         {
52          ROTATION_EVENT_0,
53           APPCORE_RM_PORTRAIT_NORMAL,
54         },
55         {
56          ROTATION_EVENT_90,
57          APPCORE_RM_LANDSCAPE_NORMAL,
58         },
59         {
60          ROTATION_EVENT_180,
61          APPCORE_RM_PORTRAIT_REVERSE,
62         },
63         {
64          ROTATION_EVENT_270,
65          APPCORE_RM_LANDSCAPE_REVERSE,
66         },
67 };
68
69 static enum appcore_rm __get_mode(int event_data)
70 {
71         int i;
72         enum appcore_rm m;
73
74         m = APPCORE_RM_UNKNOWN;
75
76         for (i = 0; i < sizeof(re_to_rm) / sizeof(re_to_rm[0]); i++) {
77                 if (re_to_rm[i].re == event_data) {
78                         m = re_to_rm[i].rm;
79                         break;
80                 }
81         }
82
83         return m;
84 }
85
86 static void __changed_cb(unsigned int event_type, sensor_event_data_t *event,
87                        void *data)
88 {
89         int *cb_event_data;
90         enum appcore_rm m;
91
92         if (rot.lock)
93                 return;
94
95         if (event_type != ACCELEROMETER_EVENT_ROTATION_CHECK) {
96                 errno = EINVAL;
97                 return;
98         }
99
100         cb_event_data = (int *)(event->event_data);
101
102         m = __get_mode(*cb_event_data);
103
104         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
105
106         if (rot.callback) {
107                 if (rot.cb_set && rot.mode != m) {
108                         rot.callback(m, data);
109                         rot.mode = m;
110                 }
111         }
112 }
113
114 static void __lock_cb(keynode_t *node, void *data)
115 {
116         int r;
117         enum appcore_rm m;
118
119         rot.lock = vconf_keynode_get_bool(node);
120
121         if (rot.lock) {
122                 _DBG("[APP %d] Rotation locked", getpid());
123                 return;
124         }
125
126         _DBG("[APP %d] Rotation unlocked", getpid());
127         if (rot.callback) {
128                 if (rot.cb_set) {
129                         r = appcore_get_rotation_state(&m);
130                         _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(),
131                              rot.mode, m);
132                         if (!r && rot.mode != m) {
133                                 rot.callback(m, data);
134                                 rot.mode = m;
135                         }
136                 }
137         }
138 }
139
140 static void __add_rotlock(void *data)
141 {
142         int r;
143         int lock;
144
145         lock = 0;
146         r = vconf_get_bool(VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL, &lock);
147         if (r) {
148                 _DBG("[APP %d] Rotation vconf get bool failed", getpid());
149         }
150
151         rot.lock = lock;
152
153         vconf_notify_key_changed(VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL, __lock_cb,
154                                  data);
155 }
156
157 static void __del_rotlock(void)
158 {
159         vconf_ignore_key_changed(VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL, __lock_cb);
160         rot.lock = 0;
161 }
162
163 EXPORT_API int appcore_set_rotation_cb(int (*cb) (enum appcore_rm, void *),
164                                        void *data)
165 {
166         int r;
167         int handle;
168
169         if (cb == NULL) {
170                 errno = EINVAL;
171                 return -1;
172         }
173
174         if (rot.callback != NULL) {
175                 errno = EALREADY;
176                 return -1;
177         }
178
179         handle = sf_connect(ACCELEROMETER_SENSOR);
180         if (handle < 0) {
181                 _ERR("sf_connect failed: %d", handle);
182                 return -1;
183         }
184
185         r = sf_register_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK,
186                               NULL, __changed_cb, data);
187         if (r < 0) {
188                 _ERR("sf_register_event failed: %d", r);
189                 sf_disconnect(handle);
190                 return -1;
191         }
192
193         rot.cb_set = 1;
194         rot.callback = cb;
195         rot.cbdata = data;
196
197         r = sf_start(handle, 0);
198         if (r < 0) {
199                 _ERR("sf_start failed: %d", r);
200                 sf_unregister_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK);
201                 rot.callback = NULL;
202                 rot.cbdata = NULL;
203                 rot.cb_set = 0;
204                 rot.sf_started = 0;
205                 sf_disconnect(handle);
206                 return -1;
207         }
208         rot.sf_started = 1;
209
210         rot.handle = handle;
211         __add_rotlock(data);
212
213         return 0;
214 }
215
216 EXPORT_API int appcore_unset_rotation_cb(void)
217 {
218         int r;
219
220         _retv_if(rot.callback == NULL, 0);
221
222         __del_rotlock();
223
224         if (rot.cb_set) {
225                 r = sf_unregister_event(rot.handle,
226                                         ACCELEROMETER_EVENT_ROTATION_CHECK);
227                 if (r < 0) {
228                         _ERR("sf_unregister_event failed: %d", r);
229                         return -1;
230                 }
231                 rot.cb_set = 0;
232         }
233         rot.callback = NULL;
234         rot.cbdata = NULL;
235
236         if (rot.sf_started == 1) {
237                 r = sf_stop(rot.handle);
238                 if (r < 0) {
239                         _ERR("sf_stop failed: %d", r);
240                         return -1;
241                 }
242                 rot.sf_started = 0;
243         }
244
245         r = sf_disconnect(rot.handle);
246         if (r < 0) {
247                 _ERR("sf_disconnect failed: %d", r);
248                 return -1;
249         }
250         rot.handle = -1;
251
252         return 0;
253 }
254
255 EXPORT_API int appcore_get_rotation_state(enum appcore_rm *curr)
256 {
257         int r;
258         unsigned long event;
259
260         if (curr == NULL) {
261                 errno = EINVAL;
262                 return -1;
263         }
264
265         r = sf_check_rotation(&event);
266         if (r < 0) {
267                 _ERR("sf_check_rotation failed: %d", r);
268                 *curr = APPCORE_RM_UNKNOWN;
269                 return -1;
270         }
271
272         *curr = __get_mode(event);
273
274         return 0;
275 }
276
277 EXPORT_API int appcore_pause_rotation_cb(void)
278 {
279         int r;
280
281         _retv_if(rot.callback == NULL, 0);
282         _DBG("[APP %d] appcore_pause_rotation_cb is called", getpid());
283
284         __del_rotlock();
285
286         if (rot.cb_set) {
287                 r = sf_unregister_event(rot.handle,
288                                         ACCELEROMETER_EVENT_ROTATION_CHECK);
289                 if (r < 0) {
290                         _ERR("sf_unregister_event in appcore_internal_sf_stop failed: %d", r);
291                         return -1;
292                 }
293                 rot.cb_set = 0;
294         }
295
296         if (rot.sf_started == 1) {
297                 r = sf_stop(rot.handle);
298                 if (r < 0) {
299                         _ERR("sf_stop in appcore_internal_sf_stop failed: %d",
300                              r);
301                         return -1;
302                 }
303                 rot.sf_started = 0;
304         }
305
306         return 0;
307 }
308
309 EXPORT_API int appcore_resume_rotation_cb(void)
310 {
311         int r;
312         enum appcore_rm m;
313
314         _retv_if(rot.callback == NULL, 0);
315         _DBG("[APP %d] appcore_resume_rotation_cb is called", getpid());
316
317         if (rot.cb_set == 0) {
318                 r = sf_register_event(rot.handle,
319                                       ACCELEROMETER_EVENT_ROTATION_CHECK, NULL,
320                                       __changed_cb, rot.cbdata);
321                 if (r < 0) {
322                         _ERR("sf_register_event in appcore_internal_sf_start failed: %d", r);
323                         return -1;
324                 }
325                 rot.cb_set = 1;
326         }
327
328         if (rot.sf_started == 0) {
329                 r = sf_start(rot.handle, 0);
330                 if (r < 0) {
331                         _ERR("sf_start in appcore_internal_sf_start failed: %d",
332                              r);
333                         sf_unregister_event(rot.handle,
334                                             ACCELEROMETER_EVENT_ROTATION_CHECK);
335                         rot.cb_set = 0;
336                         return -1;
337                 }
338                 rot.sf_started = 1;
339         }
340
341         __add_rotlock(rot.cbdata);
342
343         r = appcore_get_rotation_state(&m);
344         _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(), rot.mode, m);
345         if (!r && rot.mode != m && rot.lock == 0) {
346                 rot.callback(m, rot.cbdata);
347                 rot.mode = m;
348         }
349
350         return 0;
351 }