2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <sys/types.h>
28 #include "include/ss_data.h"
33 #include <sys/ioctl.h>
34 #include <linux/rtc.h>
36 #include <sys/timerfd.h>
38 #ifndef TFD_TIMER_CANCELON_SET
39 #define TFD_TIMER_CANCELON_SET (1<<1)
42 #define O_CLOEXEC 0x2000000
46 #define O_NONBLOCK 0x4000
50 #define TFD_CLOEXEC O_CLOEXEC
54 #define TFD_NONBLOCK O_NONBLOCK
56 static const char default_rtc0[] = "/dev/rtc0";
57 static const char default_rtc1[] = "/dev/rtc1";
58 static const char default_localtime[] = "/opt/etc/localtime";
60 static const time_t default_time = 2147483645; // max(32bit) -3sec
61 static Ecore_Fd_Handler *tfdh = NULL; // tfd change noti
63 static int tfd_cb(void *data, Ecore_Fd_Handler * fd_handler);
64 static int timerfd_check_stop(int fd);
65 static int timerfd_check_start(void);
67 char *substring(const char *str, size_t begin, size_t len)
69 if (str == 0 || strlen(str) == 0 || strlen(str) < begin
70 || strlen(str) < (begin + len))
73 return strndup(str + begin, len);
76 int handle_timezone(char *str)
80 const char *sympath = default_localtime;
84 const char *tzpath = str;
86 PRT_TRACE("TZPATH = %s\n", tzpath);
88 /* unlink current link
89 * eg. rm /opt/etc/localtime */
90 if (stat(sympath, &sts) == -1 && errno == ENOENT) {
93 ret = unlink(sympath);
95 PRT_TRACE("unlink error : [%d]%s\n", ret,
99 PRT_TRACE("unlink success\n");
104 * eg. ln -s /usr/share/zoneinfo/Asia/Seoul /opt/etc/localtime */
105 ret = symlink(tzpath, sympath);
107 PRT_TRACE("symlink error : [%d]%s\n", ret, strerror(errno));
110 PRT_TRACE("symlink success\n");
117 * TODO : error handling code should be added here.
119 int handle_date(char *str)
128 tmp = (long int)atoi(str);
129 timet = (time_t) tmp;
131 PRT_TRACE("ctime = %s", ctime(&timet));
132 vconf_set_int(VCONFKEY_SYSTEM_TIMECHANGE, timet);
137 int set_datetime_action(int argc, char **argv)
140 unsigned int pm_state;
143 if (vconf_get_int(VCONFKEY_PM_STATE, &ret) != 0)
144 PRT_TRACE("Fail to get vconf value for pm state\n");
152 pm_lock_state(pm_state, STAY_CUR_STATE, 0);
153 ret = handle_date(argv[0]);
154 pm_unlock_state(pm_state, STAY_CUR_STATE);
158 int set_timezone_action(int argc, char **argv)
161 unsigned int pm_state;
164 if (vconf_get_int(VCONFKEY_PM_STATE, &ret) != 0)
165 PRT_TRACE("Fail to get vconf value for pm state\n");
173 pm_lock_state(pm_state, STAY_CUR_STATE, 0);
174 ret = handle_timezone(argv[0]);
175 pm_unlock_state(pm_state, STAY_CUR_STATE);
179 static int timerfd_check_start(void)
182 struct itimerspec tmr;
184 if ((tfd = timerfd_create(CLOCK_REALTIME,TFD_NONBLOCK|TFD_CLOEXEC)) == -1) {
185 PRT_TRACE_ERR("error timerfd_create() %d",errno);
190 tfdh = ecore_main_fd_handler_add(tfd,ECORE_FD_READ,tfd_cb,NULL,NULL,NULL);
192 PRT_TRACE_ERR("error ecore_main_fd_handler_add");
195 memset(&tmr, 0, sizeof(tmr));
196 tmr.it_value.tv_sec = default_time;
198 if (timerfd_settime(tfd,TFD_TIMER_ABSTIME|TFD_TIMER_CANCELON_SET,&tmr,NULL) < 0) {
199 PRT_TRACE_ERR("error timerfd_settime() %d",errno);
205 static int timerfd_check_stop(int tfd)
208 ecore_main_fd_handler_del(tfdh);
218 static int tfd_cb(void *data, Ecore_Fd_Handler * fd_handler)
224 if (!ecore_main_fd_handler_active_get(fd_handler,ECORE_FD_READ)) {
225 PRT_TRACE_ERR("error ecore_main_fd_handler_get()");
229 if((tfd = ecore_main_fd_handler_fd_get(fd_handler)) == -1) {
230 PRT_TRACE_ERR("error ecore_main_fd_handler_fd_get()");
234 ret = read(tfd,&ticks,sizeof(ticks));
236 if (ret < 0 && errno == ECANCELED) {
237 vconf_set_int(VCONFKEY_SYSMAN_STIME, VCONFKEY_SYSMAN_STIME_CHANGED);
238 timerfd_check_stop(tfd);
239 PRT_TRACE("NOTIFICATION here");
240 timerfd_check_start();
242 PRT_TRACE("unexpected read (err:%d)",errno);
247 int ss_time_manager_init(void)
249 ss_action_entry_add_internal(PREDEF_SET_DATETIME, set_datetime_action,
251 ss_action_entry_add_internal(PREDEF_SET_TIMEZONE, set_timezone_action,
253 if (timerfd_check_start() == -1) {
254 PRT_TRACE_ERR("fail system time change detector init");