tizen 2.3 release
[framework/system/deviced.git] / src / core / device-notifier.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
20 #include "log.h"
21 #include "devices.h"
22 #include "device-notifier.h"
23 #include "list.h"
24 #include "common.h"
25 #include <journal/system.h>
26
27 #define LATE_INIT_WAIT_TIME     12
28 #define DEFAULT_LATE_INIT_VALUE ((Ecore_Timer *)0x0DEF0DEF)
29
30 struct device_notifier {
31         enum device_notifier_type status;
32         int (*func)(void *data);
33 };
34
35 static dd_list *device_notifier_list;
36 static Ecore_Timer *late_init_timer = DEFAULT_LATE_INIT_VALUE;
37
38 #define FIND_NOTIFIER(a, b, d, e, f) \
39         DD_LIST_FOREACH(a, b, d) \
40                 if (e == d->e && f == (d->f))
41
42 int register_notifier(enum device_notifier_type status, int (*func)(void *data))
43 {
44         dd_list *n;
45         struct device_notifier *data, *notifier;
46
47         _I("%d, %x", status, func);
48
49         if (!func) {
50                 _E("invalid func address!");
51                 return -EINVAL;
52         }
53
54         FIND_NOTIFIER(device_notifier_list, n, notifier, status, func) {
55                 _E("function is already registered! [%d, %x]",
56                     status, func);
57                 return -EINVAL;
58         }
59
60         notifier = malloc(sizeof(struct device_notifier));
61         if (!notifier) {
62                 _E("Fail to malloc for notifier!");
63                 return -ENOMEM;
64         }
65
66         notifier->status = status;
67         notifier->func = func;
68
69         DD_LIST_APPEND(device_notifier_list, notifier);
70
71         return 0;
72 }
73
74 int unregister_notifier(enum device_notifier_type status, int (*func)(void *data))
75 {
76         dd_list *n;
77         struct device_notifier *notifier;
78
79         if (!func) {
80                 _E("invalid func address!");
81                 return -EINVAL;
82         }
83
84         FIND_NOTIFIER(device_notifier_list, n, notifier, status, func) {
85                 _I("[%d, %x]", status, func);
86                 DD_LIST_REMOVE(device_notifier_list, notifier);
87                 free(notifier);
88         }
89
90         return 0;
91 }
92
93 void device_notify(enum device_notifier_type status, void *data)
94 {
95         dd_list *n, *next;
96         struct device_notifier *notifier;
97         int cnt = 0;
98
99         DD_LIST_FOREACH_SAFE(device_notifier_list, n, next, notifier) {
100                 if (status == notifier->status) {
101                         if (notifier->func) {
102                                 notifier->func(data);
103                                 cnt++;
104                         }
105                 }
106         }
107 }
108
109 static void late_init_stop(void)
110 {
111         if (late_init_timer == NULL ||
112             late_init_timer == DEFAULT_LATE_INIT_VALUE)
113                 return;
114         ecore_timer_del(late_init_timer);
115         late_init_timer = NULL;
116 }
117
118 static int booting_done(void *data)
119 {
120         static int done = 0;
121
122         if (data == NULL)
123                 goto out;
124
125         journal_system_booting_done();
126         done = (int)data;
127         if (late_init_timer == NULL)
128                 return done;
129         late_init_stop();
130 out:
131         return done;
132 }
133
134 static Eina_Bool late_init_timer_cb(void *data)
135 {
136         int done;
137
138         late_init_stop();
139         done = booting_done(NULL);
140         if (done)
141                 return EINA_FALSE;
142         _I("late booting done");
143         device_notify(DEVICE_NOTIFIER_BOOTING_DONE, (void *)TRUE);
144         return EINA_FALSE;
145 }
146
147 static void device_notifier_init(void *data)
148 {
149         int ret;
150
151         ret = check_systemd_active();
152         if (ret == TRUE) {
153                 _I("restart booting done");
154                 return;
155         }
156         register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
157         late_init_timer = ecore_timer_add(LATE_INIT_WAIT_TIME,
158                                                 late_init_timer_cb, NULL);
159         if (!late_init_timer)
160                 late_init_timer = DEFAULT_LATE_INIT_VALUE;
161 }
162
163 static void device_notifier_exit(void *data)
164 {
165         dd_list *n;
166         struct device_notifier *notifier;
167
168         DD_LIST_FOREACH(device_notifier_list, n, notifier)
169                 DD_LIST_REMOVE(device_notifier_list, notifier);
170                 free(notifier);
171 }
172
173 static const struct device_ops notifier_device_ops = {
174         .priority = DEVICE_PRIORITY_NORMAL,
175         .name     = "notifier",
176         .init     = device_notifier_init,
177         .exit     = device_notifier_exit,
178 };
179
180 DEVICE_OPS_REGISTER(&notifier_device_ops)