00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <glib/gmain.h>
00023 #include <glib/gtypes.h>
00024 #include <dbus/dbus.h>
00025 #include <time.h>
00026 #include <osso-log.h>
00027 #include <string.h>
00028 #include <glib/gfileutils.h>
00029 #include "rpc-retutime.h"
00030 #include "include/timer-interface.h"
00031 #include "debug.h"
00032
00033 #define RETUTIME_DBUS_SIGNAL_RULE "type='signal',interface='org.kernel.kevent',path='/org/kernel/bus/platform/drivers/retu_rtc/alarm_expired'"
00034
00035 #define RETUTIME_MAX_TIME 86340
00036
00037 static gboolean retu_set_event(TimerPlugin *plugin, time_t wanted_time, TimerCallback cb, TimerCancel cancel, gpointer user_data);
00038 static gboolean retu_remove_event(TimerPlugin *plugin);
00039 static time_t retu_get_time(TimerPlugin *plugin);
00040 static void retu_time_changed(TimerPlugin *plugin);
00041 static void retu_plugin_deinit(TimerPlugin *plugin);
00042 static void _clock_set_alarm(time_t alarm_time);
00043
00044 static gboolean _retu_event_fire(gpointer event);
00045 static gboolean _retu_idle_event_fire(gpointer event);
00046
00047 typedef struct _RetuTimerEvent RetuTimerEvent;
00048 struct _RetuTimerEvent {
00049 guint timer_id;
00050 time_t timer_time;
00051 TimerCallback cb;
00052 TimerCancel cancel;
00053 gpointer cb_data;
00054
00055 TimerPlugin *plugin;
00056 };
00057
00058 typedef struct _RetuIdleEvent RetuIdleEvent;
00059 struct _RetuIdleEvent {
00060 TimerCallback cb;
00061 gpointer cb_data;
00062 gboolean delayed;
00063 };
00064
00065
00066 gboolean plugin_initialize(TimerPlugin *plugin)
00067 {
00068 ENTER_FUNC;
00069
00070 plugin->set_event = retu_set_event;
00071 plugin->remove_event = retu_remove_event;
00072 plugin->get_time = retu_get_time;
00073 plugin->plugin_deinit = retu_plugin_deinit;
00074 plugin->time_changed = retu_time_changed;
00075
00076 if (!g_file_test("/mnt/initfs/usr/bin/retutime", G_FILE_TEST_IS_REGULAR)) {
00077 DEBUG("No retutime found.");
00078 LEAVE_FUNC;
00079 return FALSE;
00080 }
00081
00082 plugin->can_power_up = TRUE;
00083 plugin->priority = 5;
00084 plugin->plugin_data = NULL;
00085
00086 LEAVE_FUNC;
00087 return TRUE;
00088 }
00089
00090 static gboolean _retu_idle_event_fire(gpointer event) {
00091 RetuIdleEvent *ev = event;
00092 ENTER_FUNC;
00093
00094 if (ev->cb) {
00095 ev->cb(ev->cb_data, ev->delayed);
00096 }
00097
00098 g_free(event);
00099
00100 LEAVE_FUNC;
00101 return FALSE;
00102 }
00103
00104 static gboolean _retu_event_fire(gpointer event) {
00105 RetuTimerEvent *ev = (RetuTimerEvent *)event;
00106 ENTER_FUNC;
00107
00108 ev->plugin->plugin_data = NULL;
00109
00110 if (ev->cb) {
00111 ev->cb(ev->cb_data, FALSE);
00112 }
00113
00114 g_free(event);
00115
00116 if (retutime_query_alarm()) {
00117 retutime_ack_alarm();
00118 } else {
00119 retutime_disable_alarm();
00120 }
00121
00122 LEAVE_FUNC;
00123 return FALSE;
00124 }
00125
00126 static gboolean retu_set_event(TimerPlugin *plugin, time_t wanted_time, TimerCallback cb, TimerCancel cancel, gpointer user_data)
00127 {
00128 RetuTimerEvent *event = NULL;
00129 time_t time_now = time(NULL);
00130
00131 ENTER_FUNC;
00132
00133 if (plugin == NULL || cb == NULL) {
00134 DEBUG("plugin == NULL || cb == NULL");
00135 LEAVE_FUNC;
00136 return FALSE;
00137 }
00138
00139 plugin->remove_event(plugin);
00140
00141 if (time_now > wanted_time) {
00142 RetuIdleEvent *ev = g_new0(RetuIdleEvent, 1);
00143 ev->cb = cb;
00144 ev->cb_data = user_data;
00145 ev->delayed = time_now > wanted_time +
00146 (plugin->is_startup ? 120 : 10) ? TRUE : FALSE;
00147 g_idle_add(_retu_idle_event_fire, ev);
00148
00149 LEAVE_FUNC;
00150 return TRUE;
00151 }
00152
00153 event = g_new0(RetuTimerEvent, 1);
00154
00155 event->timer_id = g_timeout_add((wanted_time - time_now) * 1000, _retu_event_fire, event);
00156
00157 if (event->timer_id == 0) {
00158 ULOG_WARN_F("Adding timeout failed.");
00159 g_free(event);
00160
00161 LEAVE_FUNC;
00162 return FALSE;
00163 }
00164
00165 event->timer_time = wanted_time;
00166 event->cb = cb;
00167 event->cb_data = user_data;
00168 event->cancel = cancel;
00169 event->plugin = plugin;
00170
00171 plugin->plugin_data = (gpointer)event;
00172
00173 _clock_set_alarm(wanted_time);
00174
00175 LEAVE_FUNC;
00176 return TRUE;
00177 }
00178
00179 static gboolean retu_remove_event(TimerPlugin *plugin)
00180 {
00181 ENTER_FUNC;
00182
00183 if (plugin && plugin->plugin_data) {
00184 RetuTimerEvent *event = (RetuTimerEvent *)plugin->plugin_data;
00185
00186 g_source_remove(event->timer_id);
00187
00188 if (event->cancel) {
00189 event->cancel(event->cb_data);
00190 }
00191
00192 plugin->plugin_data = NULL;
00193
00194 g_free(event);
00195
00196 retutime_disable_alarm();
00197
00198 LEAVE_FUNC;
00199 return TRUE;
00200 }
00201
00202 LEAVE_FUNC;
00203 return FALSE;
00204 }
00205
00206 static time_t retu_get_time(TimerPlugin *plugin)
00207 {
00208 ENTER_FUNC;
00209 if (plugin && plugin->plugin_data) {
00210 RetuTimerEvent *event = (RetuTimerEvent *)plugin->plugin_data;
00211
00212 LEAVE_FUNC;
00213 return event->timer_time;
00214 }
00215
00216 LEAVE_FUNC;
00217 return 0;
00218 }
00219
00220 static void retu_plugin_deinit(TimerPlugin *plugin)
00221 {
00222 ENTER_FUNC;
00223 if (plugin && plugin->plugin_data) {
00224 RetuTimerEvent *event = (RetuTimerEvent *)plugin->plugin_data;
00225
00226 g_source_remove(event->timer_id);
00227
00228 if (event->cancel) {
00229 event->cancel(event->cb_data);
00230 }
00231
00232 plugin->plugin_data = NULL;
00233
00234 g_free(event);
00235 }
00236 LEAVE_FUNC;
00237 }
00238
00239 static void retu_time_changed(TimerPlugin *plugin)
00240 {
00241 ENTER_FUNC;
00242 if (plugin && plugin->plugin_data) {
00243 RetuTimerEvent *event = (RetuTimerEvent *)plugin->plugin_data;
00244 time_t now = time(NULL);
00245 g_source_remove(event->timer_id);
00246 if (now > event->timer_time) {
00247 plugin->plugin_data = NULL;
00248
00249 if (event->cb) {
00250 event->cb(event->cb_data, TRUE);
00251 }
00252
00253 g_free(event);
00254 } else {
00255 event->timer_id = g_timeout_add((event->timer_time - now) * 1000, _retu_event_fire, event);
00256 }
00257 }
00258 LEAVE_FUNC;
00259 }
00260
00261 static void _clock_set_alarm(time_t alarm_time)
00262 {
00263 time_t now = time(NULL);
00264 ENTER_FUNC;
00265
00266 if (alarm_time - now > RETUTIME_MAX_TIME) {
00267 retutime_set_alarm_time(now + RETUTIME_MAX_TIME);
00268 } else {
00269 if (!retutime_set_alarm_time(alarm_time)) {
00270 retutime_set_alarm_time(alarm_time + 60);
00271 }
00272 }
00273
00274 LEAVE_FUNC;
00275 }