Fix the swapped registered vs enabled technologies signal
[platform/upstream/connman.git] / src / notifier.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <gdbus.h>
27
28 #include "connman.h"
29
30 static DBusConnection *connection = NULL;
31
32 static GSList *notifier_list = NULL;
33
34 static gint compare_priority(gconstpointer a, gconstpointer b)
35 {
36         const struct connman_notifier *notifier1 = a;
37         const struct connman_notifier *notifier2 = b;
38
39         return notifier2->priority - notifier1->priority;
40 }
41
42 /**
43  * connman_notifier_register:
44  * @notifier: notifier module
45  *
46  * Register a new notifier module
47  *
48  * Returns: %0 on success
49  */
50 int connman_notifier_register(struct connman_notifier *notifier)
51 {
52         DBG("notifier %p name %s", notifier, notifier->name);
53
54         notifier_list = g_slist_insert_sorted(notifier_list, notifier,
55                                                         compare_priority);
56
57         return 0;
58 }
59
60 /**
61  * connman_notifier_unregister:
62  * @notifier: notifier module
63  *
64  * Remove a previously registered notifier module
65  */
66 void connman_notifier_unregister(struct connman_notifier *notifier)
67 {
68         DBG("notifier %p name %s", notifier, notifier->name);
69
70         notifier_list = g_slist_remove(notifier_list, notifier);
71 }
72
73 static const char *type2string(enum connman_service_type type)
74 {
75         switch (type) {
76         case CONNMAN_SERVICE_TYPE_UNKNOWN:
77                 break;
78         case CONNMAN_SERVICE_TYPE_ETHERNET:
79                 return "ethernet";
80         case CONNMAN_SERVICE_TYPE_WIFI:
81                 return "wifi";
82         case CONNMAN_SERVICE_TYPE_WIMAX:
83                 return "wimax";
84         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
85                 return "bluetooth";
86         case CONNMAN_SERVICE_TYPE_CELLULAR:
87                 return "cellular";
88         }
89
90         return NULL;
91 }
92
93 #define MAX_TECHNOLOGIES 10
94
95 static volatile gint registered[MAX_TECHNOLOGIES];
96 static volatile gint enabled[MAX_TECHNOLOGIES];
97 static volatile gint connected[MAX_TECHNOLOGIES];
98
99 void __connman_notifier_list_registered(DBusMessageIter *iter)
100 {
101         int i;
102
103         for (i = 0; i < 10; i++) {
104                 const char *type = type2string(i);
105
106                 if (type == NULL)
107                         continue;
108
109                 if (g_atomic_int_get(&registered[i]) > 0)
110                         dbus_message_iter_append_basic(iter,
111                                                 DBUS_TYPE_STRING, &type);
112         }
113 }
114
115 void __connman_notifier_list_enabled(DBusMessageIter *iter)
116 {
117         int i;
118
119         for (i = 0; i < 10; i++) {
120                 const char *type = type2string(i);
121
122                 if (type == NULL)
123                         continue;
124
125                 if (g_atomic_int_get(&enabled[i]) > 0)
126                         dbus_message_iter_append_basic(iter,
127                                                 DBUS_TYPE_STRING, &type);
128         }
129 }
130
131 void __connman_notifier_list_connected(DBusMessageIter *iter)
132 {
133         int i;
134
135         for (i = 0; i < 10; i++) {
136                 const char *type = type2string(i);
137
138                 if (type == NULL)
139                         continue;
140
141                 if (g_atomic_int_get(&connected[i]) > 0)
142                         dbus_message_iter_append_basic(iter,
143                                                 DBUS_TYPE_STRING, &type);
144         }
145 }
146
147 static void technology_registered(enum connman_service_type type,
148                                                 connman_bool_t registered)
149 {
150         DBusMessage *signal;
151         DBusMessageIter entry, value, iter;
152         const char *key = "AvailableTechnologies";
153
154         DBG("type %d registered %d", type, registered);
155
156         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
157                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
158         if (signal == NULL)
159                 return;
160
161         dbus_message_iter_init_append(signal, &entry);
162
163         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
164
165         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
166                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
167                                                                 &value);
168
169         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
170                                         DBUS_TYPE_STRING_AS_STRING, &iter);
171         __connman_notifier_list_registered(&iter);
172         dbus_message_iter_close_container(&value, &iter);
173
174         dbus_message_iter_close_container(&entry, &value);
175
176         g_dbus_send_message(connection, signal);
177 }
178
179 static void technology_enabled(enum connman_device_type type,
180                                                 connman_bool_t enabled)
181 {
182         GSList *list;
183         DBusMessage *signal;
184         DBusMessageIter entry, value, iter;
185         const char *key = "EnabledTechnologies";
186
187         DBG("type %d enabled %d", type, enabled);
188
189         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
190                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
191         if (signal == NULL)
192                 goto done;
193
194         dbus_message_iter_init_append(signal, &entry);
195
196         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
197
198         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
199                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
200                                                                 &value);
201
202         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
203                                         DBUS_TYPE_STRING_AS_STRING, &iter);
204         __connman_notifier_list_enabled(&iter);
205         dbus_message_iter_close_container(&value, &iter);
206
207         dbus_message_iter_close_container(&entry, &value);
208
209         g_dbus_send_message(connection, signal);
210
211 done:
212         for (list = notifier_list; list; list = list->next) {
213                 struct connman_notifier *notifier = list->data;
214
215                 if (notifier->device_enabled)
216                         notifier->device_enabled(type, enabled);
217         }
218 }
219
220 static void technology_connected(enum connman_service_type type,
221                                                 connman_bool_t connected)
222 {
223         DBusMessage *signal;
224         DBusMessageIter entry, value, iter;
225         const char *key = "ConnectedTechnologies";
226
227         DBG("type %d connected %d", type, connected);
228
229         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
230                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
231         if (signal == NULL)
232                 return;
233
234         dbus_message_iter_init_append(signal, &entry);
235
236         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
237
238         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
239                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
240                                                                 &value);
241
242         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
243                                         DBUS_TYPE_STRING_AS_STRING, &iter);
244         __connman_notifier_list_connected(&iter);
245         dbus_message_iter_close_container(&value, &iter);
246
247         dbus_message_iter_close_container(&entry, &value);
248
249         g_dbus_send_message(connection, signal);
250 }
251
252 void __connman_notifier_register(enum connman_service_type type)
253 {
254         DBG("type %d", type);
255
256         switch (type) {
257         case CONNMAN_SERVICE_TYPE_UNKNOWN:
258                 return;
259         case CONNMAN_SERVICE_TYPE_ETHERNET:
260         case CONNMAN_SERVICE_TYPE_WIFI:
261         case CONNMAN_SERVICE_TYPE_WIMAX:
262         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
263         case CONNMAN_SERVICE_TYPE_CELLULAR:
264                 break;
265         }
266
267         if (g_atomic_int_exchange_and_add(&registered[type], 1) == 0)
268                 technology_registered(type, TRUE);
269 }
270
271 void __connman_notifier_unregister(enum connman_service_type type)
272 {
273         DBG("type %d", type);
274
275         switch (type) {
276         case CONNMAN_SERVICE_TYPE_UNKNOWN:
277                 return;
278         case CONNMAN_SERVICE_TYPE_ETHERNET:
279         case CONNMAN_SERVICE_TYPE_WIFI:
280         case CONNMAN_SERVICE_TYPE_WIMAX:
281         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
282         case CONNMAN_SERVICE_TYPE_CELLULAR:
283                 break;
284         }
285
286         if (g_atomic_int_dec_and_test(&registered[type]) == TRUE)
287                 technology_registered(type, FALSE);
288 }
289
290 void __connman_notifier_enable(enum connman_service_type type)
291 {
292         DBG("type %d", type);
293
294         switch (type) {
295         case CONNMAN_SERVICE_TYPE_UNKNOWN:
296                 return;
297         case CONNMAN_SERVICE_TYPE_ETHERNET:
298         case CONNMAN_SERVICE_TYPE_WIFI:
299         case CONNMAN_SERVICE_TYPE_WIMAX:
300         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
301         case CONNMAN_SERVICE_TYPE_CELLULAR:
302                 break;
303         }
304
305         if (g_atomic_int_exchange_and_add(&enabled[type], 1) == 0)
306                 technology_enabled(type, TRUE);
307 }
308
309 void __connman_notifier_disable(enum connman_service_type type)
310 {
311         DBG("type %d", type);
312
313         switch (type) {
314         case CONNMAN_SERVICE_TYPE_UNKNOWN:
315                 return;
316         case CONNMAN_SERVICE_TYPE_ETHERNET:
317         case CONNMAN_SERVICE_TYPE_WIFI:
318         case CONNMAN_SERVICE_TYPE_WIMAX:
319         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
320         case CONNMAN_SERVICE_TYPE_CELLULAR:
321                 break;
322         }
323
324         if (g_atomic_int_dec_and_test(&enabled[type]) == TRUE)
325                 technology_enabled(type, FALSE);
326 }
327
328 void __connman_notifier_connect(enum connman_service_type type)
329 {
330         DBG("type %d", type);
331
332         switch (type) {
333         case CONNMAN_SERVICE_TYPE_UNKNOWN:
334                 return;
335         case CONNMAN_SERVICE_TYPE_ETHERNET:
336         case CONNMAN_SERVICE_TYPE_WIFI:
337         case CONNMAN_SERVICE_TYPE_WIMAX:
338         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
339         case CONNMAN_SERVICE_TYPE_CELLULAR:
340                 break;
341         }
342
343         if (g_atomic_int_exchange_and_add(&connected[type], 1) == 0)
344                 technology_connected(type, TRUE);
345 }
346
347 void __connman_notifier_disconnect(enum connman_service_type type)
348 {
349         DBG("type %d", type);
350
351         switch (type) {
352         case CONNMAN_SERVICE_TYPE_UNKNOWN:
353                 return;
354         case CONNMAN_SERVICE_TYPE_ETHERNET:
355         case CONNMAN_SERVICE_TYPE_WIFI:
356         case CONNMAN_SERVICE_TYPE_WIMAX:
357         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
358         case CONNMAN_SERVICE_TYPE_CELLULAR:
359                 break;
360         }
361
362         if (g_atomic_int_dec_and_test(&connected[type]) == TRUE)
363                 technology_connected(type, FALSE);
364 }
365
366 void __connman_notifier_offline_mode(connman_bool_t enabled)
367 {
368         GSList *list;
369
370         DBG("enabled %d", enabled);
371
372         __connman_profile_changed(FALSE);
373
374         for (list = notifier_list; list; list = list->next) {
375                 struct connman_notifier *notifier = list->data;
376
377                 if (notifier->offline_mode)
378                         notifier->offline_mode(enabled);
379         }
380 }
381
382 int __connman_notifier_init(void)
383 {
384         DBG("");
385
386         connection = connman_dbus_get_connection();
387
388         return 0;
389 }
390
391 void __connman_notifier_cleanup(void)
392 {
393         DBG("");
394
395         dbus_connection_unref(connection);
396 }