Initialize Tizen 2.3
[framework/system/deviced.git] / src / display / hbm.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 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 #include <stdbool.h>
20 #include <fcntl.h>
21 #include <Ecore.h>
22
23 #include "util.h"
24 #include "core.h"
25 #include "display-ops.h"
26 #include "core/common.h"
27 #include "core/device-notifier.h"
28 #include "core/edbus-handler.h"
29
30 #define ON              "on"
31 #define OFF             "off"
32
33 #define SIGNAL_HBM_OFF  "HBMOff"
34
35 #define DEFAULT_BRIGHTNESS_LEVEL        80
36
37 static Ecore_Timer *timer = NULL;
38 static struct timespec offtime;
39 static char *hbm_path;
40
41 static void broadcast_hbm_off(void)
42 {
43         broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
44             SIGNAL_HBM_OFF, NULL, NULL);
45 }
46
47 static void hbm_set_offtime(int timeout)
48 {
49         struct timespec now;
50
51         if (timeout <= 0) {
52                 offtime.tv_sec = 0;
53                 return;
54         }
55
56         clock_gettime(CLOCK_REALTIME, &now);
57         offtime.tv_sec = now.tv_sec + timeout;
58 }
59
60 static Eina_Bool hbm_off_cb(void *data)
61 {
62         int ret;
63
64         timer = NULL;
65
66         if (pm_cur_state != S_NORMAL) {
67                 _D("hbm timeout! but it's not lcd normal");
68                 return EINA_FALSE;
69         }
70         hbm_set_offtime(0);
71
72         ret = sys_set_str(hbm_path, OFF);
73         if (ret < 0)
74                 _E("Failed to off hbm");
75
76         vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
77             DEFAULT_BRIGHTNESS_LEVEL);
78         backlight_ops.set_default_brt(DEFAULT_BRIGHTNESS_LEVEL);
79         backlight_ops.update();
80         broadcast_hbm_off();
81
82         return EINA_FALSE;
83 }
84
85 static void hbm_start_timer(int timeout)
86 {
87         if (timer) {
88                 ecore_timer_del(timer);
89                 timer = NULL;
90         }
91         if (!timer) {
92                 timer = ecore_timer_add(timeout,
93                     hbm_off_cb, NULL);
94         }
95 }
96
97 static void hbm_end_timer(void)
98 {
99         if (timer) {
100                 ecore_timer_del(timer);
101                 timer = NULL;
102         }
103 }
104
105 int hbm_get_state(void)
106 {
107         char state[4];
108         int ret, hbm;
109
110         if (!hbm_path)
111                 return -ENODEV;
112
113         ret = sys_get_str(hbm_path, state);
114         if (ret < 0)
115                 return ret;
116
117         if (!strncmp(state, ON, strlen(ON)))
118                 hbm = true;
119         else if (!strncmp(state, OFF, strlen(OFF)))
120                 hbm = false;
121         else
122                 hbm = -EINVAL;
123
124         return hbm;
125 }
126
127 int hbm_set_state(int hbm)
128 {
129         if (!hbm_path)
130                 return -ENODEV;
131
132         return sys_set_str(hbm_path, (hbm ? ON : OFF));
133 }
134
135 int hbm_set_state_with_timeout(int hbm, int timeout)
136 {
137         int ret;
138
139         if (hbm && (timeout <= 0))
140                 return -EINVAL;
141
142         ret = hbm_set_state(hbm);
143         if (ret < 0)
144                 return ret;
145
146         _D("timeout is %d", timeout);
147
148         if (hbm) {
149                 /*
150                  * hbm is turned off after timeout.
151                  */
152                 hbm_set_offtime(timeout);
153                 hbm_start_timer(timeout);
154         } else {
155                 hbm_set_offtime(0);
156                 hbm_end_timer();
157                 broadcast_hbm_off();
158         }
159
160         return 0;
161 }
162
163 void hbm_check_timeout(void)
164 {
165         struct timespec now;
166         int ret;
167
168         if (timer) {
169                 ecore_timer_del(timer);
170                 timer = NULL;
171         }
172
173         if (offtime.tv_sec == 0) {
174                 if (hbm_get_state() == true) {
175                         _E("It's invalid state. hbm is off");
176                         hbm_set_state(false);
177                 }
178                 return;
179         }
180
181         clock_gettime(CLOCK_REALTIME, &now);
182         _D("now %d, offtime %d", now.tv_sec, offtime.tv_sec);
183
184         /* check it's timeout */
185         if (now.tv_sec >= offtime.tv_sec) {
186                 hbm_set_offtime(0);
187
188                 ret = sys_set_str(hbm_path, OFF);
189                 if (ret < 0)
190                         _E("Failed to off hbm");
191                 vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
192                     DEFAULT_BRIGHTNESS_LEVEL);
193                 backlight_ops.set_default_brt(DEFAULT_BRIGHTNESS_LEVEL);
194                 backlight_ops.update();
195                 broadcast_hbm_off();
196         } else {
197                 _D("hbm state is restored!");
198                 hbm_set_state(true);
199                 hbm_start_timer(offtime.tv_sec - now.tv_sec);
200         }
201 }
202
203 static int lcd_state_changed(void *data)
204 {
205         int state = (int)data;
206         int ret;
207
208         switch (state) {
209         case S_NORMAL:
210                 /* restore hbm when old state is dim */
211                 if (pm_old_state == S_LCDDIM)
212                         hbm_check_timeout();
213                 break;
214         case S_LCDDIM:
215                 if (hbm_get_state() == true) {
216                         ret = hbm_set_state(false);
217                         if (ret < 0)
218                                 _E("Failed to off hbm!");
219                 }
220                 /* fall through */
221         case S_LCDOFF:
222         case S_SLEEP:
223                 hbm_end_timer();
224                 break;
225         }
226
227         return 0;
228 }
229
230 static void hbm_init(void *data)
231 {
232         int fd, ret;
233
234         hbm_path = getenv("HBM_NODE");
235
236         /* Check HBM node is valid */
237         fd = open(hbm_path, O_RDONLY);
238         if (fd < 0) {
239                 hbm_path = NULL;
240                 return;
241         }
242         close(fd);
243
244         /* register notifier */
245         register_notifier(DEVICE_NOTIFIER_LCD, lcd_state_changed);
246 }
247
248 static void hbm_exit(void *data)
249 {
250         /* unregister notifier */
251         unregister_notifier(DEVICE_NOTIFIER_LCD, lcd_state_changed);
252 }
253
254 static const struct display_ops display_hbm_ops = {
255         .name     = "hbm",
256         .init     = hbm_init,
257         .exit     = hbm_exit,
258 };
259
260 DISPLAY_OPS_REGISTER(&display_hbm_ops)
261