Add new features and fixes
[platform/core/telephony/tel-plugin-packetservice.git] / src / ps_master.c
1 /*
2  * tel-plugin-packetservice
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: DongHoo Park <donghoo.park@samsung.com>
7  *          Arun Shukla <arun.shukla@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #include <unistd.h>
24
25 #include "ps_common.h"
26 #include "generated-code.h"
27
28 #include <server.h>
29 #include <plugin.h>
30 #include <storage.h>
31 #include <hal.h>
32 #include <user_request.h>
33 #include <co_context.h>
34
35 #define PS_MASTER_PATH  "/"
36 #define PROP_DEFAULT            FALSE
37 #define PROP_DEFAULT_STR        NULL
38
39 /* [Wearable][sap-stack] SAPInterface.h */
40 #define SAP_CONN_TYPE_ALL       0x00
41 #define SAP_CONN_TYPE_BT        0x01
42 #define SAP_CONN_TYPE_MOBILE    0x10 /* scs */
43
44 static void __ps_master_emit_modem_added_signal(ps_master_t *master, gpointer modem);
45 /*static void __ps_master_emit_modem_removed_signal(ps_master_t *master, gpointer modem);*/
46 static void _ps_master_setup_interface(PacketServiceMaster *master, ps_master_t *master_data);
47
48 static void __ps_master_register_key_callback(gpointer master, enum tcore_storage_key key);
49 static void __ps_master_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data);
50
51 static void __ps_master_handle_ups_mode(gpointer object, gchar *request)
52 {
53         ps_modem_t *modem = object;
54         GSList *contexts = NULL;
55         unsigned int index;
56
57         if (modem == NULL)
58                 return;
59
60         info("send dbus %s requeset", request);
61         contexts = modem->contexts;
62         if (contexts == NULL) {
63                 err("no profiles");
64                 return;
65         }
66
67         for (index = 0; index < g_slist_length(contexts); index++) {
68                 gchar *s_path = NULL;
69                 gpointer value = g_slist_nth_data(contexts, index);
70                 ps_context_t *pscontext = (ps_context_t *)value;
71                 int role = tcore_context_get_role(pscontext->co_context);
72
73                 s_path = _ps_context_ref_path(value);
74                 dbg("value(%p), path(%s)", value, s_path);
75
76                 if (role == CONTEXT_ROLE_INTERNET && pscontext->is_default) {
77                         if (!g_strcmp0(request, "IfaceDown"))
78                                 _ps_context_handle_ifacedown(value);
79                         else if (!g_strcmp0(request, "IfaceUp"))
80                                 _ps_context_handle_ifaceup(value);
81                 } else if (role == CONTEXT_ROLE_UNKNOWN || role == CONTEXT_ROLE_USER_DEFINED) {
82                         warn("Not supported profile type: %d", role);
83                         continue;
84                 } else {
85                         if (CONTEXT_STATE_ACTIVATED != tcore_context_get_state(pscontext->co_context))
86                                 continue;
87
88                         if (!g_strcmp0(request, "InterfaceDown")) {
89                                 warn("disconnect context request.");
90                                 _ps_service_deactivate_context(pscontext->p_service, pscontext);
91                         }
92                 }
93         }
94         return;
95 }
96
97 void __remove_master(gpointer data, gpointer user_data)
98 {
99         ps_master_t *master = data;
100
101         info("Entered");
102
103         /*Deinit alarm*/
104         alarmmgr_fini();
105
106         /* Remove notification hooks */
107         tcore_server_remove_notification_hook(tcore_plugin_ref_server(master->plg), __on_hook_modem_added);
108         tcore_server_remove_notification_hook(tcore_plugin_ref_server(master->plg), __on_hook_modem_removed);
109
110         /*Need to remove the compelete hash table*/
111         g_hash_table_remove_all(master->modems);
112
113         /*Need to UNexport and Unref the master Object */
114         g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(master->if_obj));
115
116         g_object_unref(master->if_obj);
117
118         /*Need to free the memory allocated for the members of the master*/
119         g_free(master->path);
120         g_free(master);
121
122         dbg("Exiting");
123         return;
124 }
125
126 static void __ps_master_emit_modem_added_signal(ps_master_t *master, gpointer modem)
127 {
128         GVariant *gv = NULL;
129         GVariantBuilder properties;
130
131         dbg("get modem properties");
132
133         gv = _ps_modem_get_properties(modem, &properties);
134         packet_service_master_emit_modem_added(master->if_obj, gv);
135
136         dbg("Exiting");
137 }
138
139 #if 0
140 static void __ps_master_emit_modem_removed_signal(ps_master_t *master, gpointer modem)
141 {
142         g_signal_emit(master, signals[SIG_MASTER_MODEM_REMOVED], 0, _ps_modem_ref_path(modem));
143         dbg("master (%p) emit the modem(%p) removed signal", master, modem);
144 }
145 #endif
146
147 static void __ps_master_register_key_callback(gpointer object, enum tcore_storage_key key)
148 {
149         ps_master_t *master = (ps_master_t *) object;
150         Server *s = tcore_plugin_ref_server(master->plg);
151         static Storage *strg;
152
153         strg = tcore_server_find_storage(s, "vconf");
154         tcore_storage_set_key_callback(strg, key, __ps_master_storage_key_callback, object);
155
156         return;
157 }
158
159 static void __ps_master_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data)
160 {
161         GVariant *tmp = NULL;
162         GHashTableIter iter;
163         gpointer h_key, h_value;
164         gboolean type_check = FALSE;
165         ps_master_t *master = (ps_master_t *)user_data;
166
167         dbg("storage key(%d) callback", key);
168         g_return_if_fail(master != NULL);
169
170         tmp = (GVariant *)value;
171         if (!tmp) {
172                 err("value is null");
173                 return;
174         }
175
176         switch (key) {
177         case KEY_3G_ENABLE:
178         case KEY_DATA_ROAMING_SETTING:
179         case KEY_NETWORK_RESTRICT_MODE:
180         case KEY_TELEPHONY_READY:
181                 type_check = g_variant_is_of_type(tmp, G_VARIANT_TYPE_BOOLEAN);
182                 if (!type_check) {
183                         err("wrong variant data type");
184                         g_variant_unref(tmp);
185                         return;
186                 }
187         break;
188
189         case KEY_POWER_SAVING_MODE:
190         case KEY_PM_STATE:
191 #ifdef POWER_SAVING_FEATURE_WEARABLE
192         case KEY_WECONN_ALL_CONNECTED:
193 #endif
194                 type_check = g_variant_is_of_type(tmp, G_VARIANT_TYPE_INT32);
195                 if (!type_check) {
196                         err("wrong variant data type");
197                         g_variant_unref(tmp);
198                         return;
199                 }
200         break;
201
202         default:
203                 warn("unknown key (0x%x)", key);
204                 return;
205         }
206
207         g_hash_table_iter_init(&iter, master->modems);
208         while (g_hash_table_iter_next(&iter, &h_key, &h_value) == TRUE) {
209                 if (key == KEY_3G_ENABLE) {
210                         gboolean data_allowed = g_variant_get_boolean(tmp);
211                         msg("[PSINFO] data_allowed [%d] changed", data_allowed);
212 #if defined(TIZEN_PS_FORCE_ATTACH_DETACH)
213                         if (_ps_master_get_storage_value_int(master, KEY_WECONN_ALL_CONNECTED) > 0) {
214                                 if (data_allowed) {
215                                         int sap_conn_type = SAP_CONN_TYPE_ALL;
216                                         sap_conn_type = _ps_master_get_storage_value_int(master, KEY_SAP_CONNECTION_TYPE);
217                                         if (sap_conn_type == SAP_CONN_TYPE_BT) {
218                                                 warn("[Companion mode] ignore data_allowed.");
219                                                 return;
220                                         }
221                                 }
222                         }
223 #endif
224                         _ps_modem_set_data_allowed(h_value, data_allowed);
225                 } else if (key == KEY_DATA_ROAMING_SETTING) {
226                         gboolean roaming_allowed = g_variant_get_boolean(tmp);
227                         msg("[PSINFO] roaming_allowed [%d] changed.", roaming_allowed);
228                         _ps_modem_set_data_roaming_allowed(h_value, roaming_allowed);
229                 } else if (key == KEY_POWER_SAVING_MODE) {
230                         gint new_ps_mode = g_variant_get_int32(tmp);
231                         gint curr_ps_mode = _ps_modem_get_psmode(h_value);
232
233                         if (curr_ps_mode & POWER_SAVING_MODE_DATA_ALLOWED)
234                                 new_ps_mode |= POWER_SAVING_MODE_DATA_ALLOWED;
235
236                         info("curr_ps_mode [0X%x] new_ps_mode[0X%x]", curr_ps_mode, new_ps_mode);
237                         _ps_modem_set_psmode(h_value, new_ps_mode);
238                 } else if (key == KEY_PM_STATE) {
239                         gint pm_state = g_variant_get_int32(tmp);
240                         gint ps_mode = _ps_modem_get_psmode(h_value);
241
242                         if (ps_mode != POWER_SAVING_MODE_NORMAL)
243                                 dbg("current power saving mode: %d, pm_state: %d", ps_mode, pm_state);
244
245                         if (ps_mode & POWER_SAVING_MODE_DATA_ALLOWED) {
246                                 warn("UPS by FMM: Do not change data network state.");
247                                 return;
248                         }
249                         if (pm_state == 3) {/* LCD Off */
250                                 if (ps_mode > POWER_SAVING_MODE_NORMAL && ps_mode < POWER_SAVING_MODE_WEARABLE) {
251                                         msg("[PSINFO] LCD OFF. Start Deactivate with power saving [%d]", ps_mode);
252                                         /* send dbus request pdp context deactivation. */
253                                         __ps_master_handle_ups_mode(h_value, "IfaceDown");
254                                 }
255                         } else { /* LCD On or dimming */
256                                 if (ps_mode > POWER_SAVING_MODE_NORMAL && ps_mode < POWER_SAVING_MODE_WEARABLE) {
257                                         msg("[PSINFO] pm_state(%d) changed. Start activate with power saving [%d]", pm_state, ps_mode);
258                                         /* send dbus request pdp context activation. */
259                                         __ps_master_handle_ups_mode(h_value, "IfaceUp");
260                                 }
261                         }
262                 } else if (key == KEY_NETWORK_RESTRICT_MODE) {
263                         gboolean b_network_restrict = g_variant_get_boolean(tmp);
264                         if (b_network_restrict) {
265                                 msg("[PSINFO] network restricted mode on");
266                                 _ps_modem_set_data_allowed(h_value, FALSE);
267                         } else {
268                                 gboolean key_3g_enable = FALSE;
269                                 msg("[PSINFO] network restricted mode off");
270                                 key_3g_enable = _ps_master_get_storage_value_bool(master, KEY_3G_ENABLE);
271                                 _ps_modem_set_data_allowed(h_value, key_3g_enable);
272                         }
273 #ifdef STORAGE_KEY_WECONN_ALL_CONNECTED
274                 } else if (key == KEY_WECONN_ALL_CONNECTED) {
275                         int b_wms_connected = g_variant_get_int32(tmp);
276                         if (b_wms_connected) {
277                                 int sap_conn_type = SAP_CONN_TYPE_ALL;
278                                 sap_conn_type = _ps_master_get_storage_value_int(master, KEY_SAP_CONNECTION_TYPE);
279                                 if (sap_conn_type == SAP_CONN_TYPE_BT) {
280                                         msg("[PSINFO][Wearable] Companinon mode. set data allowed FALSE");
281                                         _ps_modem_set_data_allowed(h_value, FALSE);
282                                 }
283                         } else {
284                                 gboolean key_3g_enable = FALSE;
285                                 key_3g_enable = _ps_master_get_storage_value_bool(master, KEY_3G_ENABLE);
286                                 msg("[PSINFO][Wearable] Standalone mode. set data allowed (%d)", key_3g_enable);
287                                 _ps_modem_set_data_allowed(h_value, key_3g_enable);
288                         }
289 #endif
290                 } else if (key == KEY_TELEPHONY_READY) {
291                         gboolean b_telephony_ready = _ps_master_get_storage_value_bool(master, KEY_TELEPHONY_READY);
292                         if (b_telephony_ready)
293                                 __ps_master_emit_modem_added_signal(master, h_value);
294                 }
295         }
296
297         return;
298 }
299
300 gpointer _ps_master_create_master(GDBusConnection *conn, TcorePlugin *p)
301 {
302         PacketServiceMaster *master = NULL;
303         ps_master_t *new_master = NULL;
304         GError *error = NULL;
305
306         dbg("master object create");
307         g_return_val_if_fail(conn != NULL, NULL);
308
309         /*creating the master object for the interface com.tcore.ps.master*/
310         master = packet_service_master_skeleton_new();
311         g_return_val_if_fail(master != NULL, NULL);
312
313         /*Alarm manager init*/
314         dbg("init alarm manager.");
315         if (alarmmgr_init("packetservice") != ALARMMGR_RESULT_SUCCESS) {
316                 err("Failed to init alarm manager");
317                 goto FAILURE;
318         }
319
320         /*Initializing the master list for internal referencing*/
321         new_master = g_try_malloc0(sizeof(ps_master_t));
322         if (NULL == new_master) {
323                 err("Unable to allocate memory for master");
324                 goto FAILURE;
325         }
326
327         new_master->conn = conn;
328         new_master->path = g_strdup(PS_MASTER_PATH);
329         new_master->plg = p;
330         new_master->if_obj = master;
331         new_master->modems = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __remove_modem_handler);
332
333         /*Setting Up the call backs for the interface*/
334         _ps_master_setup_interface(master, new_master);
335
336         /*exporting the interface object to the path mention for master*/
337         g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(master),
338                         conn,
339                         PS_MASTER_PATH,
340                         &error);
341
342         g_assert_no_error(error);
343
344         /*Registering the key callbacks for values in storage settings */
345         __ps_master_register_key_callback(new_master, KEY_TELEPHONY_READY);
346         __ps_master_register_key_callback(new_master, KEY_3G_ENABLE);
347         __ps_master_register_key_callback(new_master, KEY_DATA_ROAMING_SETTING);
348 #if defined(TIZEN_UPS_ENABLED)
349         __ps_master_register_key_callback(new_master, KEY_POWER_SAVING_MODE);
350         __ps_master_register_key_callback(new_master, KEY_PM_STATE);
351 #endif
352         /* __ps_master_register_key_callback(new_master, KEY_PM_STATE); */
353 #if defined(TIZEN_PS_FORCE_ATTACH_DETACH)
354         __ps_master_register_key_callback(new_master, KEY_WECONN_ALL_CONNECTED);
355 #endif
356
357         /*Adding Hook for modem addition laters*/
358         tcore_server_add_notification_hook(tcore_plugin_ref_server(p),
359                 TNOTI_SERVER_ADDED_MODEM_PLUGIN, __on_hook_modem_added, new_master);
360
361         /*Adding Hook for modem removal laters*/
362         tcore_server_add_notification_hook(tcore_plugin_ref_server(p),
363                 TNOTI_SERVER_REMOVED_MODEM_PLUGIN, __on_hook_modem_removed, new_master);
364
365         info("Successfully created the master");
366         return new_master;
367
368 FAILURE:
369         err("Unable to create master");
370         g_object_unref(master);
371         return NULL;
372 }
373
374 gboolean _ps_master_create_modems(gpointer object, TcorePlugin *modem_plg)
375 {
376
377         gpointer modem = NULL, tmp = NULL;
378         ps_master_t *master = NULL;
379         CoreObject *co_modem = NULL;
380         gchar *modem_name = NULL;
381         gchar *cp_name = NULL;
382         gboolean key_telephony_ready;
383
384         g_return_val_if_fail(object != NULL, FALSE);
385         dbg("create modem objects");
386
387         master = (ps_master_t *)object;
388         key_telephony_ready = _ps_master_get_storage_value_bool(master, KEY_TELEPHONY_READY);
389         if (modem_plg) {
390                 cp_name = (gchar *)tcore_server_get_cp_name_by_plugin(modem_plg);
391                 modem_name = g_strdup_printf("/%s", cp_name);
392                 tmp = g_hash_table_lookup(master->modems, modem_name);
393                 if (tmp != NULL) {
394                         dbg("modem (%p) already existed", tmp);
395                         g_free(modem_name);
396                         return FALSE;
397                 }
398
399                 co_modem = tcore_plugin_ref_core_object(modem_plg, CORE_OBJECT_TYPE_MODEM);
400
401                 modem = _ps_modem_create_modem(master->conn, master->plg,
402                         master, modem_name, co_modem, cp_name);
403                 if (modem == NULL) {
404                         err("fail to create modem");
405                         g_free(modem_name);
406                         return FALSE;
407                 }
408
409                 g_hash_table_insert(master->modems, g_strdup(modem_name), modem);
410                 info("modem (%p) created at path %s", modem , modem_name);
411
412                 if (key_telephony_ready) {
413                         __ps_master_emit_modem_added_signal(master, modem);
414                 } else {
415                         warn("Wait for telephony ready");
416                 }
417
418                 g_free(modem_name);
419         } else {
420
421                 /*Need to walk through all modem if any present before packet service intialization*/
422                 Server *s;
423                 TcorePlugin *p = NULL;
424                 GSList *plist_head = NULL;
425                 GSList *plist = NULL;
426                 GSList *modemlist_head = NULL;
427                 GSList *modemlist = NULL;
428
429                 s = tcore_plugin_ref_server(master->plg);
430                 plist_head = tcore_server_get_modem_plugin_list(s);
431
432                 if (!plist_head) {
433                         warn("Modem plugin is not present");
434                         return TRUE;
435                 }
436
437                 plist = plist_head;
438
439                 while (plist) {
440                         p = plist->data;
441                         modemlist_head = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_MODEM);
442                         if (!modemlist_head) {
443                                 warn("Found no modem core-objects");
444                                 plist = plist->next;
445                                 continue;
446                         }
447                         modemlist = modemlist_head;
448                         while (modemlist) {
449                                 co_modem = modemlist->data;
450                                 cp_name = (gchar *)tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(co_modem));
451                                 modem_name = g_strdup_printf("/%s", cp_name);
452                                 tmp = g_hash_table_lookup(master->modems, modem_name);
453                                 if (tmp != NULL) {
454                                         dbg("modem (%p) already existed", tmp);
455                                         modemlist = modemlist->next;
456                                         g_free(modem_name);
457                                         continue;
458                                 }
459
460                                 modem = _ps_modem_create_modem(master->conn, master->plg, master, modem_name, co_modem, cp_name);
461                                 if (!modem) {
462                                         err("Fail to create modem ");
463                                         modemlist = modemlist->next;
464                                         g_free(modem_name);
465                                         continue;
466                                 }
467
468                                 g_hash_table_insert(master->modems, g_strdup(modem_name), modem);
469                                 info("modem (%p) created at path %s", modem , modem_name);
470                                 if (key_telephony_ready) {
471                                         __ps_master_emit_modem_added_signal(master, modem);
472                                 } else {
473                                         warn("Wait for telephony ready");
474                                 }
475                                 g_free(modem_name);
476                                 modemlist = modemlist->next;
477                         }
478                         g_slist_free(modemlist_head);
479                         plist = plist->next;
480                 }
481
482                 g_slist_free(plist_head);
483         }
484         return TRUE;
485 }
486
487 gboolean _ps_master_destroy_modem(gpointer object, TcorePlugin *plugin)
488 {
489         ps_master_t *master = NULL;
490
491         gchar *modem_name;
492         gpointer modem;
493
494         dbg("destroy modem object");
495
496         master = (ps_master_t *)object;
497
498         modem_name = g_strdup_printf("/%s",
499                         tcore_server_get_cp_name_by_plugin(plugin));
500
501         modem = g_hash_table_lookup(master->modems, modem_name);
502         if (modem == NULL) {
503                 warn("modem '%s' doesn't exists", modem_name);
504                 g_free(modem_name);
505                 return FALSE;
506         }
507
508         /*  Destroy Modem */
509         info("Destroying modem object for '%s' modem[%p]", modem_name, modem);
510         _ps_modem_destroy_modem(master->conn, modem);
511
512         if (g_hash_table_remove(master->modems, modem_name) == TRUE)
513                 info("Removed modem '%s'", modem_name);
514
515         g_free(modem_name);
516
517         return TRUE;
518 }
519
520 gboolean _ps_master_get_storage_value_bool(gpointer object, enum tcore_storage_key key)
521 {
522         Server *s = NULL;
523         Storage *strg = NULL;
524         ps_master_t *master = object;
525
526         g_return_val_if_fail(master != NULL, FALSE);
527         s = tcore_plugin_ref_server(master->plg);
528         strg = tcore_server_find_storage(s, "vconf");
529
530         return tcore_storage_get_bool(strg, key);;
531 }
532
533 gint _ps_master_get_storage_value_int(gpointer object, enum tcore_storage_key key)
534 {
535         Server *s = NULL;
536         Storage *strg = NULL;
537         ps_master_t *master = object;
538
539         g_return_val_if_fail(master != NULL, FALSE);
540         s = tcore_plugin_ref_server(master->plg);
541         strg = tcore_server_find_storage(s, "vconf");
542
543         return tcore_storage_get_int(strg, key);;
544 }
545
546 gboolean _ps_master_set_storage_value_bool(gpointer object, enum tcore_storage_key key, gboolean value)
547 {
548         Server *s = NULL;
549         Storage *strg = NULL;
550         ps_master_t *master = object;
551
552         g_return_val_if_fail(master != NULL, FALSE);
553         s = tcore_plugin_ref_server(master->plg);
554         strg = tcore_server_find_storage(s, "vconf");
555
556         return tcore_storage_set_bool(strg, key, value);
557 }
558
559 gboolean _ps_master_set_storage_value_int(gpointer object, enum tcore_storage_key key, gint value)
560 {
561         Server *s = NULL;
562         Storage *strg = NULL;
563         ps_master_t *master = object;
564
565         g_return_val_if_fail(master != NULL, FALSE);
566         s = tcore_plugin_ref_server(master->plg);
567         strg = tcore_server_find_storage(s, "vconf");
568
569         return tcore_storage_set_int(strg, key, value);
570 }
571
572 gboolean _ps_master_set_always_on_control(gpointer user_data, gboolean enable)
573 {
574         ps_master_t *master = user_data;
575         GHashTableIter iter;
576         gpointer key, value;
577
578         g_return_val_if_fail(master != NULL, FALSE);
579         g_return_val_if_fail(master->modems != NULL, FALSE);
580
581         dbg("Entered");
582
583         g_hash_table_iter_init(&iter, master->modems);
584         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
585                 unsigned int i;
586                 ps_modem_t *modem = value;
587
588                 if (modem == NULL)
589                         continue;
590                 if (modem->contexts == NULL)
591                         continue;
592
593                 for (i = 0; i < g_slist_length(modem->contexts); i++) {
594                         ps_context_t *context = (ps_context_t*)g_slist_nth_data(modem->contexts, i);
595                         gchar *path = _ps_context_ref_path(context);
596                         if (path) {
597                                 dbg("context(%s)", path);
598                                 _ps_context_set_alwayson_enable(context, enable);
599                         }
600                 }
601         }
602         return TRUE;
603 }
604
605 static gboolean on_master_get_modems(PacketServiceMaster *obj_master,
606                 GDBusMethodInvocation *invocation,
607                 gpointer user_data)
608 {
609         GVariantBuilder b_modem;
610         GVariant *modems;
611
612         GHashTableIter iter;
613         gpointer key, value;
614         ps_master_t *master = user_data;
615
616         info("Entered");
617
618         if (master->modems == NULL) {
619                 err("No modem Present");
620                 FAIL_RESPONSE(invocation, PS_ERR_INTERNAL);
621                 return TRUE;
622         }
623
624         g_variant_builder_init(&b_modem, G_VARIANT_TYPE("a{sa{ss}}"));
625
626         g_hash_table_iter_init(&iter, master->modems);
627         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
628                 gchar *path = NULL;
629                 path = _ps_modem_ref_path(value);
630                 dbg("modem path [%s]", path);
631
632                 g_variant_builder_open(&b_modem, G_VARIANT_TYPE("{sa{ss}}"));
633                 g_variant_builder_add(&b_modem, "s", path);
634                 if (FALSE == _ps_modem_get_properties_handler(value, &b_modem)) {
635                         err("Unable to get the modem properties");
636                         g_variant_builder_close(&b_modem);
637                         FAIL_RESPONSE(invocation, PS_ERR_INTERNAL);
638                         return TRUE;
639                 }
640                 g_variant_builder_close(&b_modem);
641         }
642         modems = g_variant_builder_end(&b_modem);
643
644         packet_service_master_complete_get_modems(obj_master, invocation, modems);
645         return TRUE;
646 }
647
648 static gboolean on_master_set_alwayson(PacketServiceMaster *obj_master,
649                 GDBusMethodInvocation *invocation,
650                 gboolean enable,
651                 gpointer user_data)
652 {
653         gboolean result = FALSE;
654
655         info("Entered");
656         result = _ps_master_set_always_on_control(user_data, enable);
657         if (result)
658                 packet_service_master_complete_set_alwayson(obj_master, invocation, result);
659         else
660                 FAIL_RESPONSE(invocation, PS_ERR_INTERNAL);
661         return TRUE;
662 }
663
664 static void _ps_master_setup_interface(PacketServiceMaster *master, ps_master_t *master_data)
665 {
666         dbg("Entered");
667
668         g_signal_connect(master,
669                         "handle-get-modems",
670                         G_CALLBACK(on_master_get_modems),
671                         master_data);
672
673         g_signal_connect(master,
674                         "handle-set-alwayson",
675                         G_CALLBACK(on_master_set_alwayson),
676                         master_data);
677         return;
678
679 }