meta-tizen: neard: move recipe and patches to the proper dir
[scm/bb/tizen-distro.git] / meta-tizen / meta-tizen-adaptation / meta-oe / recipes-connectivity / connman / connman / 0012-Tizen-Integrate-telephony-plugin.patch
1 From f5af9712213cb0da9e5066e0a2fcf8fbedccc075 Mon Sep 17 00:00:00 2001
2 From: Arron Wang <arron.wang@intel.com>
3 Date: Wed, 10 Oct 2012 09:56:13 +0800
4 Subject: [PATCH 12/32] Tizen: Integrate telephony plugin
5
6 Change-Id: Ia178f5de981501296573bf3f48e329d5a1355af6
7 ---
8  Makefile.plugins       |   12 +
9  configure.ac           |    6 +
10  packaging/connman.spec |    2 +
11  plugins/telephony.c    | 1757 ++++++++++++++++++++++++++++++++++++++++++++++++
12  4 files changed, 1777 insertions(+)
13  create mode 100644 plugins/telephony.c
14
15 diff --git a/Makefile.plugins b/Makefile.plugins
16 index e90ad19..83ad8fb 100644
17 --- a/Makefile.plugins
18 +++ b/Makefile.plugins
19 @@ -55,6 +55,18 @@ builtin_modules += dundee
20  builtin_sources += plugins/dundee.c
21  endif
22  
23 +if TELEPHONY
24 +if TELEPHONY_BUILTIN
25 +builtin_modules += telephony
26 +builtin_sources += plugins/telephony.c
27 +else
28 +plugin_LTLIBRARIES += plugins/telephony.la
29 +plugin_objects += $(plugins_telephony_la_OBJECTS)
30 +plugins_telephony_la_CFLAGS = $(plugin_cflags)
31 +plugins_telephony_la_LDFLAGS = $(plugin_ldflags)
32 +endif
33 +endif
34 +
35  if VPN
36  builtin_modules += vpn
37  builtin_sources += plugins/vpn.c
38 diff --git a/configure.ac b/configure.ac
39 index 6f35c78..dee2dcb 100644
40 --- a/configure.ac
41 +++ b/configure.ac
42 @@ -61,6 +61,12 @@ AC_ARG_ENABLE(hh2serial-gps,
43  AM_CONDITIONAL(HH2SERIAL_GPS, test "${enable_hh2serial_gps}" != "no")
44  AM_CONDITIONAL(HH2SERIAL_GPS_BUILTIN, test "${enable_hh2serial_gps}" = "builtin")
45  
46 +AC_ARG_ENABLE(telephony,
47 +       AC_HELP_STRING([--enable-telephony], [enable Telephony support]),
48 +                       [enable_telephony=${enableval}], [enable_telephony="yes"])
49 +AM_CONDITIONAL(TELEPHONY, test "${enable_telephony}" != "no")
50 +AM_CONDITIONAL(TELEPHONY_BUILTIN, test "${enable_telephony}" = "builtin")
51 +
52  AC_ARG_WITH(openconnect, AC_HELP_STRING([--with-openconnect=PROGRAM],
53          [specify location of openconnect binary]), [path_openconnect=${withval}])
54  
55 diff --git a/packaging/connman.spec b/packaging/connman.spec
56 index edc1d53..f4faf92 100644
57 --- a/packaging/connman.spec
58 +++ b/packaging/connman.spec
59 @@ -152,6 +152,8 @@ systemctl daemon-reload
60  %manifest %{name}.manifest
61  %license COPYING
62  %{_sbindir}/*
63 +%{_libdir}/connman/plugins/*.so
64 +%{_datadir}/man/*
65  %config %{_sysconfdir}/connman/main.conf
66  %config %{_sysconfdir}/dbus-1/system.d/*
67  %{_unitdir}/connman.service
68 diff --git a/plugins/telephony.c b/plugins/telephony.c
69 new file mode 100644
70 index 0000000..63e7f6e
71 --- /dev/null
72 +++ b/plugins/telephony.c
73 @@ -0,0 +1,1757 @@
74 +/*
75 + *
76 + *  Connection Manager
77 + *
78 + *  Copyright (C) 2011-2013  Samsung Electronics Co., Ltd. All rights reserved.
79 + *
80 + *  This program is free software; you can redistribute it and/or modify
81 + *  it under the terms of the GNU General Public License version 2 as
82 + *  published by the Free Software Foundation.
83 + *
84 + *  This program is distributed in the hope that it will be useful,
85 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
86 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
87 + *  GNU General Public License for more details.
88 + *
89 + *  You should have received a copy of the GNU General Public License
90 + *  along with this program; if not, write to the Free Software
91 + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
92 + *
93 + */
94 +
95 +
96 +#ifdef HAVE_CONFIG_H
97 +#include <config.h>
98 +#endif
99 +
100 +#include <errno.h>
101 +#include <stdlib.h>
102 +
103 +#include <gdbus.h>
104 +#include <string.h>
105 +
106 +#define CONNMAN_API_SUBJECT_TO_CHANGE
107 +#include <connman/plugin.h>
108 +#include <connman/device.h>
109 +#include <connman/network.h>
110 +#include <connman/ipconfig.h>
111 +#include <connman/dbus.h>
112 +#include <connman/inet.h>
113 +#include <connman/technology.h>
114 +#include <connman/log.h>
115 +
116 +#define PS_DBUS_SERVICE                                "com.tcore.ps"
117 +
118 +#define PS_MASTER_INTERFACE            PS_DBUS_SERVICE ".master"
119 +#define PS_MODEM_INTERFACE             PS_DBUS_SERVICE ".modem"
120 +#define PS_SERVICE_INTERFACE           PS_DBUS_SERVICE ".service"
121 +#define PS_CONTEXT_INTERFACE           PS_DBUS_SERVICE ".context"
122 +
123 +/* methods */
124 +#define GET_MODEMS                     "GetModems"
125 +#define GET_SERVICES                   "GetServices"
126 +#define GET_CONTEXTS                   "GetContexts"
127 +#define ACTIVATE_CONTEXT               "Activate"
128 +#define DEACTIVATE_CONTEXT             "Deactivate"
129 +#define GET_PROPERTIES                 "GetProperties"
130 +#define SET_PROPERTY                   "SetProperties"
131 +
132 +/* signals */
133 +#define MODEM_ADDED                    "ModemAdded"
134 +#define MODEM_REMOVED                  "ModemRemoved"
135 +#define SERVICE_ADDED                  "ServiceAdded"
136 +#define SERVICE_REMOVED                        "ServiceRemoved"
137 +#define CONTEXT_ADDED                  "ContextAdded"
138 +#define CONTEXT_REMOVED                        "ContextRemoved"
139 +#define PROPERTY_CHANGED               "PropertyChanged"
140 +
141 +#define TIMEOUT 40000
142 +
143 +#define STRING2BOOL(a) ((g_str_equal(a, "TRUE")) ?  (TRUE):(FALSE))
144 +
145 +static DBusConnection *connection;
146 +static GHashTable      *modem_hash;
147 +static GHashTable      *service_hash;
148 +static GHashTable      *network_hash;
149 +
150 +struct telephony_service {
151 +       char *path;
152 +
153 +       gpointer p_modem;
154 +       char *act;
155 +       gboolean roaming; /* global roaming state */
156 +       gboolean ps_attached; /* packet service is available */
157 +};
158 +
159 +struct telephony_modem {
160 +       char *path;
161 +
162 +       char *operator;
163 +       gboolean powered;
164 +       gboolean sim_init;
165 +       gboolean flight_mode;
166 +       gboolean data_allowed;
167 +       gboolean roaming_allowed;
168 +
169 +       struct connman_device *device;
170 +       struct telephony_service *s_service;
171 +};
172 +
173 +struct telephony_network {
174 +       char *path;
175 +       struct connman_network *network;
176 +
177 +       enum connman_ipconfig_method ipv4_method;
178 +       struct connman_ipaddress *ipv4_address;
179 +
180 +       enum connman_ipconfig_method ipv6_method;
181 +       struct connman_ipaddress *ipv6_address;
182 +};
183 +
184 +/* function prototype */
185 +static void telephony_connect(DBusConnection *connection, void *user_data);
186 +static void telephony_disconnect(DBusConnection *connection, void *user_data);
187 +static void __remove_modem(gpointer data);
188 +static void __remove_service(gpointer data);
189 +static void __remove_network(gpointer data);
190 +
191 +static int __modem_probe(struct connman_device *device);
192 +static void __modem_remove(struct connman_device *device);
193 +static int __modem_enable(struct connman_device *device);
194 +static int __modem_disable(struct connman_device *device);
195 +
196 +static int __network_probe(struct connman_network *network);
197 +static void __network_remove(struct connman_network *network);
198 +static int __network_connect(struct connman_network *network);
199 +static int __network_disconnect(struct connman_network *network);
200 +
201 +
202 +/* dbus request and reply */
203 +static int __dbus_request(const char *path, const char *interface,
204 +                       const char *method,
205 +                       DBusPendingCallNotifyFunction notify, void *user_data,
206 +                       DBusFreeFunction free_function, int type, ...);
207 +
208 +static int __request_get_modems(void);
209 +static void __response_get_modems(DBusPendingCall *call, void *user_data);
210 +static int __request_get_services(const char *path);
211 +static void __response_get_services(DBusPendingCall *call, void *user_data);
212 +static int __request_get_contexts(struct telephony_modem *modem);
213 +static void __response_get_contexts(DBusPendingCall *call, void *user_data);
214 +static int __request_network_activate(struct connman_network *network);
215 +static void __response_network_activate(DBusPendingCall *call, void *user_data);
216 +static int __request_network_deactivate(struct connman_network *network);
217 +
218 +/* telephony internal function */
219 +static void __add_modem(const char *path, DBusMessageIter *prop);
220 +static void __add_service(struct telephony_modem *modem,
221 +                       const char *service_path, DBusMessageIter *prop);
222 +static void __add_connman_device(const char *modem_path, const char *operator);
223 +static void __remove_connman_device(struct telephony_modem *modem);
224 +static void __remove_connman_networks(struct connman_device *device);
225 +static void __set_device_powered(struct telephony_modem *modem,
226 +                                       gboolean powered);
227 +static int __check_device_powered(const char *path, gboolean online);
228 +static gboolean __check_network_available(struct connman_network *network);
229 +static void __create_service(struct connman_network *network);
230 +static int __add_context(struct connman_device *device, const char *path,
231 +                                                       DBusMessageIter *prop);
232 +static gboolean __set_network_ipconfig(struct telephony_network *network,
233 +                                                       DBusMessageIter *dict);
234 +static void __set_network_connected(struct telephony_network *network,
235 +                                                       gboolean connected);
236 +static char *__get_ident(const char *path);
237 +
238 +/* signal handler */
239 +static gboolean __changed_modem(DBusConnection *connection,
240 +                               DBusMessage *message, void *user_data);
241 +static gboolean __added_modem(DBusConnection *connection,
242 +                               DBusMessage *message, void *user_data);
243 +static gboolean __removed_modem(DBusConnection *connection,
244 +                               DBusMessage *message, void *user_data);
245 +static gboolean __changed_service(DBusConnection *connection,
246 +                               DBusMessage *message, void *user_data);
247 +static gboolean __added_service(DBusConnection *connection,
248 +                               DBusMessage *message, void *user_data);
249 +static gboolean __removed_service(DBusConnection *connection,
250 +                               DBusMessage *message, void *user_data);
251 +static gboolean __changed_context(DBusConnection *connection,
252 +                               DBusMessage *message, void *user_data);
253 +static gboolean __added_context(DBusConnection *connection,
254 +                               DBusMessage *message, void *user_data);
255 +static gboolean __removed_context(DBusConnection *connection,
256 +                               DBusMessage *message, void *user_data);
257 +
258 +/* device driver */
259 +static struct connman_device_driver modem_driver = {
260 +       .name           = "device",
261 +       .type           = CONNMAN_DEVICE_TYPE_CELLULAR,
262 +       .probe          = __modem_probe,
263 +       .remove         = __modem_remove,
264 +       .enable         = __modem_enable,
265 +       .disable        = __modem_disable,
266 +};
267 +
268 +/* network driver */
269 +static struct connman_network_driver network_driver = {
270 +       .name           = "network",
271 +       .type           = CONNMAN_NETWORK_TYPE_CELLULAR,
272 +       .probe          = __network_probe,
273 +       .remove         = __network_remove,
274 +       .connect        = __network_connect,
275 +       .disconnect     = __network_disconnect,
276 +};
277 +
278 +static int tech_probe(struct connman_technology *technology)
279 +{
280 +       return 0;
281 +}
282 +
283 +static void tech_remove(struct connman_technology *technology)
284 +{
285 +}
286 +
287 +static struct connman_technology_driver tech_driver = {
288 +       .name           = "cellular",
289 +       .type           = CONNMAN_SERVICE_TYPE_CELLULAR,
290 +       .probe          = tech_probe,
291 +       .remove         = tech_remove,
292 +};
293 +
294 +/* local function */
295 +static void telephony_connect(DBusConnection *connection, void *user_data)
296 +{
297 +       DBG("connection %p", connection);
298 +       modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
299 +                                               g_free, __remove_modem);
300 +       service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
301 +                                               g_free, __remove_service);
302 +       network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
303 +                                               g_free, __remove_network);
304 +       __request_get_modems();
305 +       return;
306 +}
307 +
308 +static void telephony_disconnect(DBusConnection *connection, void *user_data)
309 +{
310 +       DBG("connection %p", connection);
311 +
312 +       if (modem_hash != NULL) {
313 +               g_hash_table_destroy(modem_hash);
314 +               modem_hash = NULL;
315 +       }
316 +
317 +       if (network_hash != NULL) {
318 +               g_hash_table_destroy(network_hash);
319 +               network_hash = NULL;
320 +       }
321 +
322 +       return;
323 +}
324 +
325 +static void __remove_modem(gpointer data)
326 +{
327 +       struct telephony_modem *modem = data;
328 +
329 +       __remove_connman_device(modem);
330 +
331 +       g_free(modem->path);
332 +       g_free(modem->operator);
333 +       g_free(modem);
334 +}
335 +
336 +static void __remove_service(gpointer data)
337 +{
338 +       struct telephony_service *service = data;
339 +
340 +       g_free(service->path);
341 +       g_free(service->act);
342 +       g_free(service);
343 +}
344 +
345 +static void __remove_network(gpointer data)
346 +{
347 +       struct telephony_network *info = data;
348 +       struct connman_device *device;
349 +
350 +       device = connman_network_get_device(info->network);
351 +       if (device != NULL)
352 +               connman_device_remove_network(device, info->network);
353 +
354 +       connman_network_unref(info->network);
355 +
356 +       g_free(info->path);
357 +       connman_ipaddress_free(info->ipv4_address);
358 +       connman_ipaddress_free(info->ipv6_address);
359 +       g_free(info);
360 +}
361 +
362 +static int __modem_probe(struct connman_device *device)
363 +{
364 +       DBG("device %p", device);
365 +       return 0;
366 +}
367 +
368 +static void __modem_remove(struct connman_device *device)
369 +{
370 +       DBG("device %p", device);
371 +}
372 +
373 +static int __modem_enable(struct connman_device *device)
374 +{
375 +       const char *path = connman_device_get_string(device, "Path");
376 +       DBG("device %p, path, %s", device, path);
377 +
378 +       return __check_device_powered(path, TRUE);
379 +}
380 +
381 +static int __modem_disable(struct connman_device *device)
382 +{
383 +       const char *path = connman_device_get_string(device, "Path");
384 +       DBG("device %p, path, %s", device, path);
385 +
386 +       return __check_device_powered(path, FALSE);
387 +}
388 +
389 +static int __network_probe(struct connman_network *network)
390 +{
391 +       DBG("network_prove network(%p)", network);
392 +       return 0;
393 +}
394 +
395 +static int __network_connect(struct connman_network *network)
396 +{
397 +       struct connman_device *device;
398 +       struct telephony_modem *modem;
399 +
400 +       DBG("network %p", network);
401 +
402 +       device = connman_network_get_device(network);
403 +       if (device == NULL)
404 +               return -ENODEV;
405 +
406 +       modem = connman_device_get_data(device);
407 +       if (modem == NULL)
408 +               return -ENODEV;
409 +
410 +       if (modem->powered == FALSE)
411 +               return -ENOLINK;
412 +
413 +       return __request_network_activate(network);
414 +}
415 +
416 +static int __network_disconnect(struct connman_network *network)
417 +{
418 +       DBG("network %p", network);
419 +
420 +       if (connman_network_get_index(network) < 0)
421 +               return -ENOTCONN;
422 +
423 +       connman_network_set_associating(network, FALSE);
424 +
425 +       return __request_network_deactivate(network);
426 +}
427 +
428 +static void __network_remove(struct connman_network *network)
429 +{
430 +       char const *path = connman_network_get_string(network, "Path");
431 +       DBG("network %p path %s", network, path);
432 +
433 +       g_hash_table_remove(network_hash, path);
434 +       return;
435 +}
436 +
437 +static int __dbus_request(const char *path, const char *interface,
438 +                       const char *method,
439 +                       DBusPendingCallNotifyFunction notify, void *user_data,
440 +                       DBusFreeFunction free_function, int type, ...)
441 +{
442 +       DBusMessage *message;
443 +       DBusPendingCall *call;
444 +       dbus_bool_t ok;
445 +       va_list va;
446 +
447 +       DBG("Telephony request path %s %s.%s", path, interface, method);
448 +
449 +       if (path == NULL)
450 +               return -EINVAL;
451 +
452 +       message = dbus_message_new_method_call(PS_DBUS_SERVICE, path,
453 +                                               interface, method);
454 +       if (message == NULL)
455 +               return -ENOMEM;
456 +
457 +       dbus_message_set_auto_start(message, FALSE);
458 +
459 +       va_start(va, type);
460 +       ok = dbus_message_append_args_valist(message, type, va);
461 +       va_end(va);
462 +
463 +       if (!ok)
464 +               return -ENOMEM;
465 +
466 +       if (dbus_connection_send_with_reply(connection, message,
467 +                                               &call, TIMEOUT) == FALSE) {
468 +               connman_error("Failed to call %s.%s", interface, method);
469 +               dbus_message_unref(message);
470 +               return -EINVAL;
471 +       }
472 +
473 +       if (call == NULL) {
474 +               connman_error("D-Bus connection not available");
475 +               dbus_message_unref(message);
476 +               return -EINVAL;
477 +       }
478 +
479 +       dbus_pending_call_set_notify(call, notify, user_data, free_function);
480 +
481 +       dbus_message_unref(message);
482 +
483 +       return -EINPROGRESS;
484 +}
485 +
486 +static int __request_get_modems(void)
487 +{
488 +       DBG("request get modem");
489 +       /* call connect master */
490 +       return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS,
491 +                       __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
492 +}
493 +
494 +static void __response_get_modems(DBusPendingCall *call, void *user_data)
495 +{
496 +       DBusMessage *reply;
497 +       DBusError error;
498 +       DBusMessageIter args, dict;
499 +
500 +       DBG("");
501 +
502 +       reply = dbus_pending_call_steal_reply(call);
503 +
504 +       dbus_error_init(&error);
505 +
506 +       if (dbus_set_error_from_message(&error, reply)) {
507 +               connman_error("GetModems() %s %s", error.name, error.message);
508 +               dbus_error_free(&error);
509 +               goto done;
510 +       }
511 +
512 +       DBG("message signature (%s)", dbus_message_get_signature(reply));
513 +
514 +       if (dbus_message_iter_init(reply, &args) == FALSE)
515 +               goto done;
516 +
517 +       dbus_message_iter_recurse(&args, &dict);
518 +
519 +       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
520 +               DBusMessageIter entry, property;
521 +               const char *modem_path;
522 +
523 +               dbus_message_iter_recurse(&dict, &entry);
524 +               dbus_message_iter_get_basic(&entry, &modem_path);
525 +               DBG("modem path (%s)", modem_path);
526 +
527 +               dbus_message_iter_next(&entry);
528 +               dbus_message_iter_recurse(&entry, &property);
529 +
530 +               __add_modem(modem_path, &property);
531 +
532 +               dbus_message_iter_next(&dict);
533 +       }
534 +
535 +done:
536 +       dbus_message_unref(reply);
537 +       dbus_pending_call_unref(call);
538 +       return;
539 +}
540 +
541 +static int __request_get_services(const char *path)
542 +{
543 +       DBG("request get service");
544 +       return __dbus_request(path, PS_MODEM_INTERFACE, GET_SERVICES,
545 +                               __response_get_services, g_strdup(path),
546 +                               g_free, DBUS_TYPE_INVALID);
547 +}
548 +
549 +static void __response_get_services(DBusPendingCall *call, void *user_data)
550 +{
551 +       DBusMessage *reply;
552 +       DBusError error;
553 +       DBusMessageIter args, dict;
554 +
555 +       const char *path = user_data;
556 +       struct telephony_modem *modem;
557 +
558 +       modem = g_hash_table_lookup(modem_hash, path);
559 +       if (modem == NULL)
560 +               return;
561 +       if (modem->device == NULL)
562 +               return;
563 +
564 +       DBG("");
565 +
566 +       reply = dbus_pending_call_steal_reply(call);
567 +
568 +       dbus_error_init(&error);
569 +
570 +       if (dbus_set_error_from_message(&error, reply)) {
571 +               connman_error("GetServices() %s %s", error.name, error.message);
572 +               dbus_error_free(&error);
573 +               goto done;
574 +       }
575 +
576 +       DBG("message signature (%s)", dbus_message_get_signature(reply));
577 +
578 +       if (dbus_message_iter_init(reply, &args) == FALSE)
579 +               goto done;
580 +
581 +       dbus_message_iter_recurse(&args, &dict);
582 +
583 +       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
584 +               DBusMessageIter entry, property;
585 +               const char *service_path;
586 +
587 +               dbus_message_iter_recurse(&dict, &entry);
588 +               dbus_message_iter_get_basic(&entry, &service_path);
589 +               DBG("service path (%s)", service_path);
590 +
591 +               dbus_message_iter_next(&entry);
592 +               dbus_message_iter_recurse(&entry, &property);
593 +
594 +               __add_service(modem, service_path, &property);
595 +
596 +               dbus_message_iter_next(&dict);
597 +       }
598 +
599 +done:
600 +       dbus_message_unref(reply);
601 +       dbus_pending_call_unref(call);
602 +       return;
603 +}
604 +
605 +static int __request_get_contexts(struct telephony_modem *modem)
606 +{
607 +       DBG("request get contexts");
608 +       return __dbus_request(modem->s_service->path,
609 +                               PS_SERVICE_INTERFACE, GET_CONTEXTS,
610 +                               __response_get_contexts, g_strdup(modem->path),
611 +                               g_free, DBUS_TYPE_INVALID);
612 +}
613 +
614 +static void __response_get_contexts(DBusPendingCall *call, void *user_data)
615 +{
616 +       DBusError error;
617 +       DBusMessage *reply;
618 +       DBusMessageIter args, dict;
619 +
620 +       const char *path = user_data;
621 +       struct telephony_modem *modem;
622 +
623 +       DBG("");
624 +
625 +       modem = g_hash_table_lookup(modem_hash, path);
626 +       if (modem == NULL)
627 +               return;
628 +       if (modem->s_service == NULL)
629 +                       return;
630 +       if (modem->device == NULL)
631 +               return;
632 +
633 +       reply = dbus_pending_call_steal_reply(call);
634 +
635 +       dbus_error_init(&error);
636 +
637 +       if (dbus_set_error_from_message(&error, reply)) {
638 +               connman_error("GetContexts() %s %s", error.name, error.message);
639 +               dbus_error_free(&error);
640 +               goto done;
641 +       }
642 +
643 +       DBG("message signature (%s)", dbus_message_get_signature(reply));
644 +
645 +       if (dbus_message_iter_init(reply, &args) == FALSE)
646 +               goto done;
647 +
648 +       dbus_message_iter_recurse(&args, &dict);
649 +
650 +       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
651 +               DBusMessageIter entry, property;
652 +               const char *context_path;
653 +
654 +               dbus_message_iter_recurse(&dict, &entry);
655 +               dbus_message_iter_get_basic(&entry, &context_path);
656 +               DBG("context path (%s)", context_path);
657 +
658 +               dbus_message_iter_next(&entry);
659 +               dbus_message_iter_recurse(&entry, &property);
660 +
661 +               __add_context(modem->device, context_path, &property);
662 +
663 +               dbus_message_iter_next(&dict);
664 +       }
665 +
666 +done:
667 +       dbus_message_unref(reply);
668 +       dbus_pending_call_unref(call);
669 +       return;
670 +}
671 +
672 +static int __request_network_activate(struct connman_network *network)
673 +{
674 +       DBG("request network activate");
675 +
676 +       const char *path = connman_network_get_string(network, "Path");
677 +       DBG("network %p, path %s", network, path);
678 +
679 +       return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
680 +                       __response_network_activate,
681 +                       g_strdup(path), NULL, DBUS_TYPE_INVALID);
682 +}
683 +
684 +static void __response_network_activate(DBusPendingCall *call, void *user_data)
685 +{
686 +       DBG("network activation response");
687 +
688 +       DBusError error;
689 +       DBusMessage *reply;
690 +
691 +       struct telephony_network *info;
692 +       const char *path = user_data;
693 +
694 +       info = g_hash_table_lookup(network_hash, path);
695 +       reply = dbus_pending_call_steal_reply(call);
696 +
697 +       if (info == NULL)
698 +               goto done;
699 +
700 +       if (!__check_network_available(info->network)) {
701 +               g_hash_table_remove(network_hash, path);
702 +               goto done;
703 +       }
704 +
705 +       dbus_error_init(&error);
706 +       if (dbus_set_error_from_message(&error, reply)) {
707 +               connman_error("connection activate() %s %s",
708 +                                       error.name, error.message);
709 +
710 +               if (connman_network_get_index(info->network) < 0)
711 +                       connman_network_set_error(info->network,
712 +                                       CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
713 +
714 +               dbus_error_free(&error);
715 +               goto done;
716 +       }
717 +
718 +done:
719 +       dbus_message_unref(reply);
720 +       dbus_pending_call_unref(call);
721 +       return;
722 +}
723 +
724 +static int __request_network_deactivate(struct connman_network *network)
725 +{
726 +       DBG("request network deactivate");
727 +
728 +       const char *path = connman_network_get_string(network, "Path");
729 +       DBG("network %p, path %s", network, path);
730 +
731 +       return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
732 +               NULL, NULL, NULL, DBUS_TYPE_INVALID);
733 +}
734 +
735 +static void __add_modem(const char *path, DBusMessageIter *prop)
736 +{
737 +       struct telephony_modem *modem;
738 +
739 +       modem = g_hash_table_lookup(modem_hash, path);
740 +       if (modem != NULL)
741 +               return;
742 +
743 +       modem = (struct telephony_modem *)malloc(
744 +                                       sizeof(struct telephony_modem));
745 +       memset(modem, 0, sizeof(struct telephony_modem));
746 +
747 +       modem->path = g_strdup(path);
748 +       modem->device = NULL;
749 +       modem->s_service = NULL;
750 +
751 +       g_hash_table_insert(modem_hash, g_strdup(path), modem);
752 +
753 +       while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
754 +               DBusMessageIter entry;
755 +               const char *key, *tmp;
756 +
757 +               dbus_message_iter_recurse(prop, &entry);
758 +               dbus_message_iter_get_basic(&entry, &key);
759 +
760 +               dbus_message_iter_next(&entry);
761 +               dbus_message_iter_get_basic(&entry, &tmp);
762 +
763 +               DBG("key (%s) value(%s)", key, tmp);
764 +
765 +               if (g_str_equal(key, "powered") == TRUE) {
766 +                       modem->powered = STRING2BOOL(tmp);
767 +               } else if (g_str_equal(key, "operator") == TRUE) {
768 +                       modem->operator = g_strdup(tmp);
769 +               } else if (g_str_equal(key, "sim_init") == TRUE) {
770 +                       modem->sim_init = STRING2BOOL(tmp);
771 +               } else if (g_str_equal(key, "flight_mode") == TRUE) {
772 +                       modem->flight_mode = STRING2BOOL(tmp);
773 +               } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
774 +                       modem->roaming_allowed = STRING2BOOL(tmp);
775 +               } else if (g_str_equal(key, "data_allowed") == TRUE) {
776 +                       modem->data_allowed = STRING2BOOL(tmp);
777 +               }
778 +               dbus_message_iter_next(prop);
779 +       }
780 +
781 +       __add_connman_device(path, modem->operator);
782 +       __set_device_powered(modem, modem->powered);
783 +
784 +       if (modem->powered != TRUE) {
785 +               DBG("modem is not powered");
786 +               return;
787 +       }
788 +
789 +       __request_get_services(modem->path);
790 +
791 +       return;
792 +}
793 +
794 +static void __add_service(struct telephony_modem *modem,
795 +                               const char *service_path, DBusMessageIter *prop)
796 +{
797 +       struct telephony_service *service;
798 +
799 +       if (modem->s_service != NULL)
800 +               return;
801 +
802 +       service = (struct telephony_service *)g_try_malloc(
803 +                                       sizeof(struct telephony_service));
804 +       if (service == NULL)
805 +               return;
806 +
807 +       memset(service, 0, sizeof(struct telephony_service));
808 +
809 +       service->path = g_strdup(service_path);
810 +       service->p_modem = modem;
811 +       g_hash_table_insert(service_hash, g_strdup(service_path), service);
812 +
813 +       while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
814 +               DBusMessageIter entry;
815 +               const char *key, *tmp;
816 +
817 +               dbus_message_iter_recurse(prop, &entry);
818 +               dbus_message_iter_get_basic(&entry, &key);
819 +
820 +               dbus_message_iter_next(&entry);
821 +               dbus_message_iter_get_basic(&entry, &tmp);
822 +
823 +               DBG("key (%s) value(%s)", key, tmp);
824 +
825 +               if (g_str_equal(key, "roaming") == TRUE) {
826 +                       service->roaming = STRING2BOOL(tmp);
827 +               } else if (g_str_equal(key, "act") == TRUE) {
828 +                       service->act = g_strdup(tmp);
829 +               } else if (g_str_equal(key, "ps_attached") == TRUE) {
830 +                       service->ps_attached = STRING2BOOL(tmp);
831 +               }
832 +
833 +               dbus_message_iter_next(prop);
834 +       }
835 +
836 +       modem->s_service = service;
837 +       __request_get_contexts(modem);
838 +
839 +       return;
840 +}
841 +
842 +static void __add_connman_device(const char *modem_path, const char *operator)
843 +{
844 +       struct telephony_modem *modem;
845 +       struct connman_device *device;
846 +
847 +       DBG("path %s operator %s", modem_path, operator);
848 +
849 +       if (modem_path == NULL)
850 +               return;
851 +
852 +       if (operator == NULL)
853 +               return;
854 +
855 +       modem = g_hash_table_lookup(modem_hash, modem_path);
856 +       if (modem == NULL)
857 +               return;
858 +
859 +       if (modem->device) {
860 +               if (!g_strcmp0(operator,
861 +                               connman_device_get_ident(modem->device)))
862 +                       return;
863 +
864 +               __remove_connman_device(modem);
865 +       }
866 +
867 +       if (strlen(operator) == 0)
868 +               return;
869 +
870 +       device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR);
871 +       if (device == NULL)
872 +               return;
873 +
874 +       connman_device_set_ident(device, operator);
875 +       connman_device_set_string(device, "Path", modem_path);
876 +       connman_device_set_data(device, modem);
877 +
878 +       if (connman_device_register(device) < 0) {
879 +               connman_error("Failed to register cellular device");
880 +               connman_device_unref(device);
881 +               return;
882 +       }
883 +
884 +       modem->device = device;
885 +
886 +       return;
887 +}
888 +
889 +static void __remove_connman_device(struct telephony_modem *modem)
890 +{
891 +       DBG("modem %p path %s device %p", modem, modem->path, modem->device);
892 +
893 +       if (modem->device == NULL)
894 +               return;
895 +
896 +       __remove_connman_networks(modem->device);
897 +
898 +       connman_device_unregister(modem->device);
899 +       connman_device_unref(modem->device);
900 +
901 +       modem->device = NULL;
902 +
903 +       return;
904 +}
905 +
906 +static void __remove_connman_networks(struct connman_device *device)
907 +{
908 +       GHashTableIter iter;
909 +       gpointer key, value;
910 +       GSList *info_list = NULL;
911 +       GSList *list;
912 +
913 +       if (network_hash == NULL)
914 +               return;
915 +
916 +       g_hash_table_iter_init(&iter, network_hash);
917 +
918 +       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
919 +               struct telephony_network *info = value;
920 +
921 +               if (connman_network_get_device(info->network) != device)
922 +                       continue;
923 +
924 +               info_list = g_slist_append(info_list, info);
925 +       }
926 +
927 +       for (list = info_list; list != NULL; list = list->next) {
928 +               struct telephony_network *info = list->data;
929 +               connman_device_remove_network(device, info->network);
930 +       }
931 +
932 +       g_slist_free(info_list);
933 +}
934 +
935 +static void __set_device_powered(struct telephony_modem *modem,
936 +                                       gboolean powered)
937 +{
938 +       DBG("set modem(%s) powered(%d)", modem->path, powered);
939 +
940 +       if (modem->device)
941 +               connman_device_set_powered(modem->device, powered);
942 +
943 +       return;
944 +}
945 +
946 +static int __check_device_powered(const char *path, gboolean powered)
947 +{
948 +       struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
949 +
950 +       if (modem == NULL)
951 +               return -ENODEV;
952 +
953 +       DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
954 +
955 +       if (modem->powered == powered)
956 +               return -EALREADY;
957 +
958 +       return 0;
959 +}
960 +
961 +static gboolean __check_network_available(struct connman_network *network)
962 +{
963 +       if (network == NULL || connman_network_get_device(network) == NULL) {
964 +               DBG("Modem or network was removed");
965 +               return FALSE;
966 +       }
967 +
968 +       return TRUE;
969 +}
970 +
971 +static int __add_context(struct connman_device *device, const char *path,
972 +                               DBusMessageIter *prop)
973 +{
974 +       char *ident;
975 +       gboolean active = FALSE;
976 +
977 +       struct telephony_modem *modem = connman_device_get_data(device);
978 +       struct connman_network *network;
979 +       struct telephony_network *info;
980 +
981 +       DBG("modem %p device %p path %s", modem, device, path);
982 +
983 +       ident = __get_ident(path);
984 +
985 +       network = connman_device_get_network(device, ident);
986 +       if (network != NULL)
987 +               return -EALREADY;
988 +
989 +       info = g_hash_table_lookup(network_hash, path);
990 +       if (info != NULL) {
991 +               DBG("path %p already exists with device %p", path,
992 +                       connman_network_get_device(info->network));
993 +
994 +               if (connman_network_get_device(info->network))
995 +                       return -EALREADY;
996 +
997 +               g_hash_table_remove(network_hash, path);
998 +       }
999 +
1000 +       network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
1001 +       if (network == NULL)
1002 +               return -ENOMEM;
1003 +
1004 +       info = (struct telephony_network *)g_try_malloc(
1005 +                                       sizeof(struct telephony_network));
1006 +       if (info == NULL) {
1007 +               connman_network_unref(network);
1008 +               return -ENOMEM;
1009 +       }
1010 +
1011 +       memset(info, 0, sizeof(struct telephony_network));
1012 +
1013 +       info->path = g_strdup(path);
1014 +
1015 +       connman_ipaddress_clear(info->ipv4_address);
1016 +       connman_ipaddress_clear(info->ipv6_address);
1017 +       info->network = network;
1018 +
1019 +       connman_network_set_string(network, "Path", path);
1020 +       connman_network_set_name(network, path);
1021 +
1022 +       __create_service(network);
1023 +
1024 +       g_hash_table_insert(network_hash, g_strdup(path), info);
1025 +
1026 +       connman_network_set_available(network, TRUE);
1027 +       connman_network_set_index(network, -1);
1028 +       connman_network_set_bool(network, "Roaming", modem->s_service->roaming);
1029 +
1030 +       if (connman_device_add_network(device, network) != 0) {
1031 +               g_hash_table_remove(network_hash, path);
1032 +               return -EIO;
1033 +       }
1034 +
1035 +       active = __set_network_ipconfig(info, prop);
1036 +
1037 +       if (active && (connman_network_get_connecting(network) ||
1038 +                               connman_network_get_associating(network)))
1039 +               __set_network_connected(info, active);
1040 +
1041 +       return 0;
1042 +}
1043 +
1044 +static void __create_service(struct connman_network *network)
1045 +{
1046 +       const char *path;
1047 +       char *group;
1048 +
1049 +       DBG("");
1050 +
1051 +       path = connman_network_get_string(network, "Path");
1052 +
1053 +       group = __get_ident(path);
1054 +
1055 +       connman_network_set_group(network, group);
1056 +}
1057 +
1058 +static gboolean __set_network_ipconfig(struct telephony_network *network,
1059 +                                       DBusMessageIter *dict)
1060 +{
1061 +       DBG("set network info");
1062 +
1063 +       gboolean active = FALSE;
1064 +       char *dev_name = NULL, *proxy_addr = NULL;
1065 +       char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
1066 +                                       *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
1067 +       char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
1068 +                                       *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
1069 +       int index;
1070 +       int dns_flag = 0;
1071 +
1072 +       while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
1073 +               DBusMessageIter entry;
1074 +               const char *key, *tmp;
1075 +
1076 +               dbus_message_iter_recurse(dict, &entry);
1077 +               dbus_message_iter_get_basic(&entry, &key);
1078 +
1079 +               dbus_message_iter_next(&entry);
1080 +
1081 +               DBG("key (%s)", key);
1082 +
1083 +               if (g_str_equal(key, "dev_name") == TRUE) {
1084 +                       dbus_message_iter_get_basic(&entry, &dev_name);
1085 +                       DBG("dev_name (%s)", dev_name);
1086 +               } else if (g_str_equal(key, "proxy") == TRUE) {
1087 +                       dbus_message_iter_get_basic(&entry, &proxy_addr);
1088 +               } else if (g_str_equal(key, "ipv4_address") == TRUE) {
1089 +                       dbus_message_iter_get_basic(&entry, &ipv4_addr);
1090 +                       DBG("ipv4 address (%s)", ipv4_addr);
1091 +               } else if (g_str_equal(key, "ipv4_gateway") == TRUE) {
1092 +                       dbus_message_iter_get_basic(&entry, &ipv4_gw);
1093 +               } else if (g_str_equal(key, "ipv4_netmask") == TRUE) {
1094 +                       dbus_message_iter_get_basic(&entry, &ipv4_netmask);
1095 +               } else if (g_str_equal(key, "ipv4_dns1") == TRUE) {
1096 +                       dbus_message_iter_get_basic(&entry, &ipv4_dns1);
1097 +               } else if (g_str_equal(key, "ipv4_dns2") == TRUE) {
1098 +                       dbus_message_iter_get_basic(&entry, &ipv4_dns2);
1099 +               } else if (g_str_equal(key, "ipv6_address") == TRUE) {
1100 +                       dbus_message_iter_get_basic(&entry, &ipv6_addr);
1101 +                       DBG("ipv6 address (%s)", ipv6_addr);
1102 +               } else if (g_str_equal(key, "ipv6_gateway") == TRUE) {
1103 +                       dbus_message_iter_get_basic(&entry, &ipv6_gw);
1104 +               } else if (g_str_equal(key, "ipv6_netmask") == TRUE) {
1105 +                       dbus_message_iter_get_basic(&entry, &ipv6_netmask);
1106 +               } else if (g_str_equal(key, "ipv6_dns1") == TRUE) {
1107 +                       dbus_message_iter_get_basic(&entry, &ipv6_dns1);
1108 +               } else if (g_str_equal(key, "ipv6_dns2") == TRUE) {
1109 +                       dbus_message_iter_get_basic(&entry, &ipv6_dns2);
1110 +               } else if (g_str_equal(key, "active") == TRUE) {
1111 +                       dbus_message_iter_get_basic(&entry, &tmp);
1112 +                       DBG("active (%s)", tmp);
1113 +                       active = STRING2BOOL(tmp);
1114 +               }
1115 +
1116 +               dbus_message_iter_next(dict);
1117 +       }
1118 +
1119 +       /* interface index set */
1120 +       if (dev_name == NULL)
1121 +               dev_name = "";
1122 +
1123 +       if (!g_str_equal(dev_name, "")) {
1124 +               index = connman_inet_ifindex(dev_name);
1125 +               DBG("interface %s, index %d", dev_name, index);
1126 +               connman_network_set_index(network->network, index);
1127 +       }
1128 +
1129 +       /* proxy set */
1130 +       if (proxy_addr == NULL)
1131 +               proxy_addr = "";
1132 +
1133 +       DBG("proxy (%s) is set", proxy_addr);
1134 +       connman_network_set_proxy(network->network, proxy_addr);
1135 +
1136 +       /* ipv4 set */
1137 +       if (ipv4_addr == NULL)
1138 +               ipv4_addr = "0.0.0.0";
1139 +
1140 +       if (g_str_equal(ipv4_addr, "0.0.0.0")) {
1141 +               network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
1142 +       } else {
1143 +               network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1144 +               network->ipv4_address =
1145 +                       connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
1146 +               if (network->ipv4_address == NULL)
1147 +                       return FALSE;
1148 +
1149 +               connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
1150 +                                               ipv4_netmask, ipv4_gw);
1151 +
1152 +               if (ipv4_dns1 == NULL)
1153 +                       ipv4_dns1 = "0.0.0.0";
1154 +               if (ipv4_dns2 == NULL)
1155 +                       ipv4_dns2 = "0.0.0.0";
1156 +
1157 +               if (g_str_equal(ipv4_dns1, "0.0.0.0"))
1158 +                       dns_flag += 1;
1159 +
1160 +               if (g_str_equal(ipv4_dns2, "0.0.0.0"))
1161 +                       dns_flag += 2;
1162 +
1163 +               gchar *nameservers = NULL;
1164 +
1165 +               switch (dns_flag) {
1166 +               case 0:
1167 +                       nameservers = g_strdup_printf("%s %s", ipv4_dns1,
1168 +                                                               ipv4_dns2);
1169 +                       break;
1170 +               case 1:
1171 +                       nameservers = g_strdup_printf("%s", ipv4_dns2);
1172 +                       break;
1173 +               case 2:
1174 +                       nameservers = g_strdup_printf("%s", ipv4_dns1);
1175 +               }
1176 +
1177 +               connman_network_set_nameservers(network->network, nameservers);
1178 +               g_free(nameservers);
1179 +       }
1180 +
1181 +       /* ipv6 set */
1182 +       if (ipv6_addr == NULL)
1183 +               ipv6_addr = "::";
1184 +
1185 +       if (g_str_equal(ipv6_addr, "::")) {
1186 +               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
1187 +       } else {
1188 +               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1189 +               unsigned char prefix_length = 64;
1190 +               network->ipv6_address =
1191 +                       connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
1192 +               if (network->ipv6_address == NULL)
1193 +                       return FALSE;
1194 +
1195 +               connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
1196 +                                               prefix_length, ipv6_gw);
1197 +
1198 +               dns_flag = 0;
1199 +
1200 +               if (ipv6_dns1 == NULL)
1201 +                       ipv6_dns1 = "::";
1202 +               if (ipv6_dns2 == NULL)
1203 +                       ipv6_dns2 = "::";
1204 +
1205 +               if (g_str_equal(ipv6_dns1, "::"))
1206 +                       dns_flag += 1;
1207 +
1208 +               if (g_str_equal(ipv6_dns2, "::"))
1209 +                       dns_flag += 2;
1210 +
1211 +               gchar *nameservers = NULL;
1212 +
1213 +               switch (dns_flag) {
1214 +               case 0:
1215 +                       nameservers = g_strdup_printf("%s %s", ipv6_dns1,
1216 +                                                               ipv6_dns2);
1217 +                       break;
1218 +               case 1:
1219 +                       nameservers = g_strdup_printf("%s", ipv6_dns2);
1220 +                       break;
1221 +               case 2:
1222 +                       nameservers = g_strdup_printf("%s", ipv6_dns1);
1223 +               }
1224 +
1225 +               connman_network_set_nameservers(network->network, nameservers);
1226 +               g_free(nameservers);
1227 +       }
1228 +
1229 +       if (active)
1230 +               connman_network_set_associating(network->network, TRUE);
1231 +
1232 +       return active;
1233 +}
1234 +
1235 +static void __set_network_connected(struct telephony_network *network,
1236 +                                       gboolean connected)
1237 +{
1238 +       gboolean setip = FALSE;
1239 +
1240 +       DBG("network %p connected %d", network, connected);
1241 +
1242 +       switch (network->ipv4_method) {
1243 +       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1244 +       case CONNMAN_IPCONFIG_METHOD_OFF:
1245 +       case CONNMAN_IPCONFIG_METHOD_MANUAL:
1246 +       case CONNMAN_IPCONFIG_METHOD_AUTO:
1247 +               setip = TRUE;
1248 +               break;
1249 +
1250 +       case CONNMAN_IPCONFIG_METHOD_FIXED:
1251 +               connman_network_set_ipv4_method(network->network,
1252 +                                                       network->ipv4_method);
1253 +               connman_network_set_ipaddress(network->network,
1254 +                                                       network->ipv4_address);
1255 +               setip = TRUE;
1256 +               break;
1257 +
1258 +       case CONNMAN_IPCONFIG_METHOD_DHCP:
1259 +               connman_network_set_ipv4_method(network->network,
1260 +                                                       network->ipv4_method);
1261 +               setip = TRUE;
1262 +               break;
1263 +       }
1264 +
1265 +       switch (network->ipv6_method) {
1266 +       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1267 +       case CONNMAN_IPCONFIG_METHOD_OFF:
1268 +       case CONNMAN_IPCONFIG_METHOD_MANUAL:
1269 +       case CONNMAN_IPCONFIG_METHOD_DHCP:
1270 +       case CONNMAN_IPCONFIG_METHOD_AUTO:
1271 +               DBG("ipv6 not supported");
1272 +               break;
1273 +
1274 +       case CONNMAN_IPCONFIG_METHOD_FIXED:
1275 +               connman_network_set_ipv6_method(network->network,
1276 +                                                       network->ipv6_method);
1277 +               connman_network_set_ipaddress(network->network,
1278 +                                                       network->ipv6_address);
1279 +               setip = TRUE;
1280 +               break;
1281 +       }
1282 +
1283 +       if (setip == TRUE)
1284 +               connman_network_set_connected(network->network, connected);
1285 +
1286 +       return;
1287 +}
1288 +
1289 +static char *__get_ident(const char *path)
1290 +{
1291 +       char *pos;
1292 +
1293 +       if (*path != '/')
1294 +               return NULL;
1295 +
1296 +       pos = strrchr(path, '/');
1297 +       if (pos == NULL)
1298 +               return NULL;
1299 +
1300 +       return pos + 1;
1301 +}
1302 +
1303 +static gboolean __changed_modem(DBusConnection *connection,
1304 +                               DBusMessage *message, void *user_data)
1305 +{
1306 +       DBG("modem changed signal");
1307 +
1308 +       DBusMessageIter args, dict;
1309 +       const char *path = dbus_message_get_path(message);
1310 +       struct telephony_modem *modem;
1311 +
1312 +       DBG("modem path %s", path);
1313 +
1314 +       modem = g_hash_table_lookup(modem_hash, path);
1315 +       if (modem == NULL) {
1316 +               DBG("modem object does not exists");
1317 +               return TRUE;
1318 +       }
1319 +
1320 +       DBG("message signature (%s)", dbus_message_get_signature(message));
1321 +
1322 +       if (dbus_message_iter_init(message, &args) == FALSE) {
1323 +               DBG("error to read message");
1324 +               return TRUE;
1325 +       }
1326 +
1327 +       dbus_message_iter_recurse(&args, &dict);
1328 +
1329 +       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1330 +               DBusMessageIter entry;
1331 +               const char *key, *tmp;
1332 +
1333 +               dbus_message_iter_recurse(&dict, &entry);
1334 +               dbus_message_iter_get_basic(&entry, &key);
1335 +
1336 +               dbus_message_iter_next(&entry);
1337 +               dbus_message_iter_get_basic(&entry, &tmp);
1338 +
1339 +               DBG("key(%s), value(%s)", key, tmp);
1340 +
1341 +               if (g_str_equal(key, "powered") == TRUE) {
1342 +                       modem->powered = STRING2BOOL(tmp);
1343 +               } else if (g_str_equal(key, "operator") == TRUE) {
1344 +                       modem->operator = g_strdup(tmp);
1345 +               } else if (g_str_equal(key, "sim_init") == TRUE) {
1346 +                       modem->sim_init = STRING2BOOL(tmp);
1347 +               } else if (g_str_equal(key, "flight_mode") == TRUE) {
1348 +                       modem->flight_mode = STRING2BOOL(tmp);
1349 +               } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
1350 +                       modem->roaming_allowed = STRING2BOOL(tmp);
1351 +               } else if (g_str_equal(key, "data_allowed") == TRUE) {
1352 +                       modem->data_allowed = STRING2BOOL(tmp);
1353 +               }
1354 +
1355 +               dbus_message_iter_next(&dict);
1356 +       }
1357 +
1358 +       if (modem->device == NULL)
1359 +               __add_connman_device(path, modem->operator);
1360 +
1361 +       __set_device_powered(modem, modem->powered);
1362 +
1363 +       if (modem->powered != TRUE) {
1364 +               DBG("modem is not powered");
1365 +               return TRUE;
1366 +       }
1367 +
1368 +       if (!modem->s_service) {
1369 +               __request_get_services(modem->path);
1370 +               return TRUE;
1371 +       }
1372 +
1373 +       if (modem->flight_mode || !modem->data_allowed) {
1374 +               DBG("modem(%s) flight mode(%d) data allowed(%d)",
1375 +                       modem->path, modem->flight_mode, modem->data_allowed);
1376 +               return TRUE;
1377 +       }
1378 +
1379 +       return TRUE;
1380 +}
1381 +
1382 +static gboolean __added_modem(DBusConnection *connection,
1383 +                               DBusMessage *message, void *user_data)
1384 +{
1385 +       DBG("modem added signal");
1386 +
1387 +       const char *modem_path = NULL;
1388 +       DBusMessageIter args, dict, tmp;
1389 +
1390 +       DBG("message signature (%s)", dbus_message_get_signature(message));
1391 +       if (dbus_message_iter_init(message, &args) == FALSE) {
1392 +               DBG("error to read message");
1393 +               return TRUE;
1394 +       }
1395 +
1396 +       dbus_message_iter_recurse(&args, &dict);
1397 +       memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1398 +
1399 +       while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1400 +               DBusMessageIter entry;
1401 +               const char *key, *value;
1402 +
1403 +               dbus_message_iter_recurse(&tmp, &entry);
1404 +               dbus_message_iter_get_basic(&entry, &key);
1405 +
1406 +               dbus_message_iter_next(&entry);
1407 +               dbus_message_iter_get_basic(&entry, &value);
1408 +
1409 +               DBG("key (%s) value(%s)", key, value);
1410 +
1411 +               if (g_str_equal(key, "path") == TRUE)
1412 +                       modem_path = g_strdup(value);
1413 +
1414 +               dbus_message_iter_next(&tmp);
1415 +       }
1416 +
1417 +       if (modem_path != NULL)
1418 +               __add_modem(modem_path, &dict);
1419 +
1420 +       return TRUE;
1421 +}
1422 +
1423 +static gboolean __removed_modem(DBusConnection *connection,
1424 +                                       DBusMessage *message, void *user_data)
1425 +{
1426 +       DBG("modem removed signal");
1427 +
1428 +       DBusMessageIter iter;
1429 +       const char *modem_path;
1430 +
1431 +       if (dbus_message_iter_init(message, &iter) == FALSE) {
1432 +               DBG("error to read message");
1433 +               return TRUE;
1434 +       }
1435 +
1436 +       dbus_message_iter_get_basic(&iter, &modem_path);
1437 +       g_hash_table_remove(modem_hash, modem_path);
1438 +
1439 +       return TRUE;
1440 +}
1441 +
1442 +static gboolean __changed_service(DBusConnection *connection,
1443 +                                       DBusMessage *message, void *user_data)
1444 +{
1445 +       DBG("service changed signal");
1446 +
1447 +       DBusMessageIter args, dict;
1448 +       const char *service_path = dbus_message_get_path(message);
1449 +       struct telephony_modem *modem;
1450 +       struct telephony_service *s_service;
1451 +       gboolean roaming_option = TRUE;
1452 +
1453 +       DBG("service path %s", service_path);
1454 +
1455 +       s_service = g_hash_table_lookup(service_hash, service_path);
1456 +       if (s_service == NULL) {
1457 +               DBG("service object does not exists");
1458 +               return TRUE;
1459 +       }
1460 +
1461 +       modem = s_service->p_modem;
1462 +       if (modem == NULL) {
1463 +               DBG("modem object does not exists");
1464 +               return TRUE;
1465 +       }
1466 +
1467 +       DBG("message signature (%s)", dbus_message_get_signature(message));
1468 +
1469 +       if (dbus_message_iter_init(message, &args) == FALSE) {
1470 +               DBG("error to read message");
1471 +               return TRUE;
1472 +       }
1473 +
1474 +       dbus_message_iter_recurse(&args, &dict);
1475 +
1476 +       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1477 +               DBusMessageIter entry;
1478 +               const char *key, *tmp;
1479 +
1480 +               dbus_message_iter_recurse(&dict, &entry);
1481 +               dbus_message_iter_get_basic(&entry, &key);
1482 +
1483 +               dbus_message_iter_next(&entry);
1484 +               dbus_message_iter_get_basic(&entry, &tmp);
1485 +
1486 +               DBG("key(%s), value(%s)", key, tmp);
1487 +
1488 +               if (g_str_equal(key, "roaming") == TRUE) {
1489 +                       s_service->roaming = STRING2BOOL(tmp);
1490 +               } else if (g_str_equal(key, "act") == TRUE) {
1491 +                       s_service->act = g_strdup(tmp);
1492 +               } else if (g_str_equal(key, "ps_attached") == TRUE) {
1493 +                       s_service->ps_attached = STRING2BOOL(tmp);
1494 +               }
1495 +
1496 +               dbus_message_iter_next(&dict);
1497 +       }
1498 +
1499 +       roaming_option &= (!s_service->roaming && !modem->roaming_allowed)
1500 +                               || modem->roaming_allowed;
1501 +
1502 +       return TRUE;
1503 +}
1504 +
1505 +
1506 +static gboolean __added_service(DBusConnection *connection,
1507 +                               DBusMessage *message, void *user_data)
1508 +{
1509 +       DBG("service added signal");
1510 +
1511 +       const char *path = dbus_message_get_path(message);
1512 +       const char *service_path = NULL;
1513 +       DBusMessageIter args, dict, tmp;
1514 +       struct telephony_modem *modem;
1515 +
1516 +       modem = g_hash_table_lookup(modem_hash, path);
1517 +       if (modem == NULL || modem->device == NULL)
1518 +               return TRUE;
1519 +
1520 +       DBG("message signature (%s)", dbus_message_get_signature(message));
1521 +       if (dbus_message_iter_init(message, &args) == FALSE) {
1522 +               DBG("error to read message");
1523 +               return TRUE;
1524 +       }
1525 +
1526 +       dbus_message_iter_recurse(&args, &dict);
1527 +       memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1528 +
1529 +       while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1530 +               DBusMessageIter entry;
1531 +               const char *key, *value;
1532 +
1533 +               dbus_message_iter_recurse(&tmp, &entry);
1534 +               dbus_message_iter_get_basic(&entry, &key);
1535 +
1536 +               dbus_message_iter_next(&entry);
1537 +               dbus_message_iter_get_basic(&entry, &value);
1538 +
1539 +               DBG("key (%s) value(%s)", key, value);
1540 +
1541 +               if (g_str_equal(key, "path") == TRUE) {
1542 +                       service_path = g_strdup(value);
1543 +               }
1544 +
1545 +               dbus_message_iter_next(&tmp);
1546 +       }
1547 +
1548 +       if (service_path != NULL)
1549 +               __add_service(modem, service_path, &dict);
1550 +
1551 +       return TRUE;
1552 +}
1553 +
1554 +static gboolean __removed_service(DBusConnection *connection,
1555 +                                       DBusMessage *message, void *user_data)
1556 +{
1557 +       DBG("service removed signal");
1558 +
1559 +       DBusMessageIter iter;
1560 +       const char *service_path;
1561 +
1562 +       if (dbus_message_iter_init(message, &iter) == FALSE) {
1563 +               DBG("error to read message");
1564 +               return TRUE;
1565 +       }
1566 +
1567 +       dbus_message_iter_get_basic(&iter, &service_path);
1568 +       g_hash_table_remove(service_hash, service_path);
1569 +
1570 +       return TRUE;
1571 +}
1572 +
1573 +static gboolean __changed_context(DBusConnection *connection,
1574 +                                       DBusMessage *message, void *user_data)
1575 +{
1576 +       DBG("network changed signal");
1577 +
1578 +       gboolean active = FALSE;
1579 +       const char *path = dbus_message_get_path(message);
1580 +       struct telephony_network *info;
1581 +       DBusMessageIter args, dict;
1582 +
1583 +       DBG("path %s", path);
1584 +       info = g_hash_table_lookup(network_hash, path);
1585 +       if (info == NULL)
1586 +               return TRUE;
1587 +
1588 +       if (!__check_network_available(info->network)) {
1589 +               g_hash_table_remove(network_hash, path);
1590 +               return TRUE;
1591 +       }
1592 +
1593 +       if (dbus_message_iter_init(message, &args) == FALSE) {
1594 +               DBG("error to read message");
1595 +               return TRUE;
1596 +       }
1597 +
1598 +       dbus_message_iter_recurse(&args, &dict);
1599 +
1600 +       active = __set_network_ipconfig(info, &dict);
1601 +
1602 +       if (active == FALSE)
1603 +               __set_network_connected(info, active);
1604 +       else if ((connman_network_get_connecting(info->network) ||
1605 +                       connman_network_get_associating(info->network)))
1606 +               __set_network_connected(info, active);
1607 +
1608 +       return TRUE;
1609 +}
1610 +
1611 +static gboolean __added_context(DBusConnection *connection,
1612 +                                       DBusMessage *message, void *user_data)
1613 +{
1614 +       DBG("network added signal");
1615 +
1616 +       DBusMessageIter args, dict, tmp;
1617 +       const char *path = dbus_message_get_path(message);
1618 +       const char *network_path = NULL;
1619 +       struct telephony_service *service = NULL;
1620 +       struct telephony_modem *modem = NULL;
1621 +
1622 +       service = g_hash_table_lookup(service_hash, path);
1623 +       if (service == NULL || service->p_modem == NULL)
1624 +               return TRUE;
1625 +
1626 +       modem = service->p_modem;
1627 +       if (modem == NULL || modem->device == NULL)
1628 +               return TRUE;
1629 +
1630 +       DBG("message signature (%s)", dbus_message_get_signature(message));
1631 +       if (dbus_message_iter_init(message, &args) == FALSE) {
1632 +               DBG("error to read message");
1633 +               return TRUE;
1634 +       }
1635 +
1636 +       dbus_message_iter_recurse(&args, &dict);
1637 +       memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1638 +
1639 +       while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1640 +               DBusMessageIter entry;
1641 +               const char *key, *value;
1642 +
1643 +               dbus_message_iter_recurse(&tmp, &entry);
1644 +               dbus_message_iter_get_basic(&entry, &key);
1645 +
1646 +               dbus_message_iter_next(&entry);
1647 +               dbus_message_iter_get_basic(&entry, &value);
1648 +
1649 +               DBG("key (%s) value(%s)", key, value);
1650 +
1651 +               if (g_str_equal(key, "path") == TRUE)
1652 +                       network_path = g_strdup(value);
1653 +
1654 +               dbus_message_iter_next(&tmp);
1655 +       }
1656 +
1657 +       if (network_path != NULL)
1658 +               __add_context(modem->device, network_path, &dict);
1659 +
1660 +       return TRUE;
1661 +}
1662 +
1663 +static gboolean __removed_context(DBusConnection *connection,
1664 +                                       DBusMessage *message, void *user_data)
1665 +{
1666 +       DBG("network removed signal");
1667 +
1668 +       DBusMessageIter iter;
1669 +       const char *path = dbus_message_get_path(message);
1670 +       const char *network_path = NULL;
1671 +       struct telephony_service *service = NULL;
1672 +
1673 +       service = g_hash_table_lookup(service_hash, path);
1674 +       if (service == NULL || service->p_modem == NULL)
1675 +               return TRUE;
1676 +
1677 +       if (dbus_message_iter_init(message, &iter) == FALSE) {
1678 +               DBG("error to read message");
1679 +               return TRUE;
1680 +       }
1681 +
1682 +       dbus_message_iter_get_basic(&iter, &network_path);
1683 +       g_hash_table_remove(network_hash, network_path);
1684 +
1685 +       return TRUE;
1686 +}
1687 +
1688 +/* telephony initialization */
1689 +static guint watch;
1690 +static guint modem_watch;
1691 +static guint modem_added_watch;
1692 +static guint modem_removed_watch;
1693 +static guint service_watch;
1694 +static guint service_added_watch;
1695 +static guint service_removed_watch;
1696 +static guint context_watch;
1697 +static guint context_added_watch;
1698 +static guint context_removed_watch;
1699 +
1700 +static int telephony_init(void)
1701 +{
1702 +       DBG("telephony plugin");
1703 +       int err;
1704 +
1705 +       connection = connman_dbus_get_connection();
1706 +       if (connection == NULL)
1707 +               return -EIO;
1708 +
1709 +       /* telephony watch */
1710 +       watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE,
1711 +                                       telephony_connect, telephony_disconnect,
1712 +                                       NULL, NULL);
1713 +
1714 +       modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1715 +                                               PS_MODEM_INTERFACE,
1716 +                                               PROPERTY_CHANGED,
1717 +                                               __changed_modem, NULL, NULL);
1718 +
1719 +       modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1720 +                                               PS_MASTER_INTERFACE,
1721 +                                               MODEM_ADDED, __added_modem,
1722 +                                               NULL, NULL);
1723 +
1724 +       modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1725 +                                               PS_MASTER_INTERFACE,
1726 +                                               MODEM_REMOVED, __removed_modem,
1727 +                                               NULL, NULL);
1728 +
1729 +       service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1730 +                                               PS_SERVICE_INTERFACE,
1731 +                                               PROPERTY_CHANGED,
1732 +                                               __changed_service,
1733 +                                               NULL, NULL);
1734 +
1735 +       service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1736 +                                               PS_MODEM_INTERFACE,
1737 +                                               SERVICE_ADDED, __added_service,
1738 +                                               NULL, NULL);
1739 +
1740 +       service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1741 +                                               PS_MODEM_INTERFACE,
1742 +                                               SERVICE_REMOVED,
1743 +                                               __removed_service,
1744 +                                               NULL, NULL);
1745 +
1746 +       context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1747 +                                               PS_CONTEXT_INTERFACE,
1748 +                                               PROPERTY_CHANGED,
1749 +                                               __changed_context,
1750 +                                               NULL, NULL);
1751 +
1752 +       context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1753 +                                               PS_SERVICE_INTERFACE,
1754 +                                               CONTEXT_ADDED, __added_context,
1755 +                                               NULL, NULL);
1756 +
1757 +       context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1758 +                                               PS_SERVICE_INTERFACE,
1759 +                                               CONTEXT_REMOVED,
1760 +                                               __removed_context,
1761 +                                               NULL, NULL);
1762 +
1763 +       if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
1764 +                       || modem_removed_watch == 0 || service_watch == 0
1765 +                       || service_added_watch == 0 || context_watch == 0
1766 +                       || service_removed_watch == 0
1767 +                       || context_added_watch == 0
1768 +                       || context_removed_watch == 0) {
1769 +               err = -EIO;
1770 +               goto remove;
1771 +       }
1772 +
1773 +       err = connman_network_driver_register(&network_driver);
1774 +       if (err < 0)
1775 +               goto remove;
1776 +
1777 +       err = connman_device_driver_register(&modem_driver);
1778 +       if (err < 0) {
1779 +               connman_network_driver_unregister(&network_driver);
1780 +               goto remove;
1781 +       }
1782 +
1783 +       err = connman_technology_driver_register(&tech_driver);
1784 +       if (err < 0) {
1785 +               connman_device_driver_unregister(&modem_driver);
1786 +               connman_network_driver_unregister(&network_driver);
1787 +               goto remove;
1788 +       }
1789 +
1790 +       return 0;
1791 +
1792 +remove:
1793 +       g_dbus_remove_watch(connection, watch);
1794 +       g_dbus_remove_watch(connection, modem_watch);
1795 +       g_dbus_remove_watch(connection, modem_added_watch);
1796 +       g_dbus_remove_watch(connection, modem_removed_watch);
1797 +       g_dbus_remove_watch(connection, service_watch);
1798 +       g_dbus_remove_watch(connection, service_added_watch);
1799 +       g_dbus_remove_watch(connection, service_removed_watch);
1800 +       g_dbus_remove_watch(connection, context_watch);
1801 +       g_dbus_remove_watch(connection, context_added_watch);
1802 +       g_dbus_remove_watch(connection, context_removed_watch);
1803 +
1804 +       dbus_connection_unref(connection);
1805 +       return err;
1806 +}
1807 +
1808 +static void telephony_exit(void)
1809 +{
1810 +       g_dbus_remove_watch(connection, watch);
1811 +       g_dbus_remove_watch(connection, modem_watch);
1812 +       g_dbus_remove_watch(connection, modem_added_watch);
1813 +       g_dbus_remove_watch(connection, modem_removed_watch);
1814 +       g_dbus_remove_watch(connection, service_watch);
1815 +       g_dbus_remove_watch(connection, service_added_watch);
1816 +       g_dbus_remove_watch(connection, service_removed_watch);
1817 +       g_dbus_remove_watch(connection, context_watch);
1818 +       g_dbus_remove_watch(connection, context_added_watch);
1819 +       g_dbus_remove_watch(connection, context_removed_watch);
1820 +
1821 +       telephony_disconnect(connection, NULL);
1822 +
1823 +       connman_device_driver_unregister(&modem_driver);
1824 +       connman_network_driver_unregister(&network_driver);
1825 +
1826 +       dbus_connection_unref(connection);
1827 +}
1828 +
1829 +CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION,
1830 +               CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit)
1831 -- 
1832 1.8.1.4
1833