Tizen 2.1 base
[framework/telephony/tel-plugin-packetservice.git] / src / 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  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <unistd.h>
23
24 #include "ps-master.h"
25
26 #include "ps.h"
27 #include "ps-error.h"
28
29 #include <server.h>
30 #include <plugin.h>
31 #include <storage.h>
32 #include <hal.h>
33
34 #define PS_MASTER_PATH  "/"
35 #define PROP_DEFAULT            FALSE
36 #define PROP_DEFAULT_STR        NULL
37 #define BOOL2STRING(a)          ((a==TRUE) ? ("TRUE"):("FALSE"))
38
39 /*Properties*/
40
41 enum {
42         PROP_MASTER_O,
43         PROP_MASTER_PLUGIN,
44         PROP_MASTER_CONN,
45         PROP_MASTER_PATH
46 };
47
48 enum {
49          SIG_MASTER_MODEM_ADDED,
50          SIG_MASTER_MODEM_REMOVED,
51          SIG_MASTER_LAST
52 };
53
54 static guint32 signals[SIG_MASTER_LAST] = {0,};
55
56 struct PsMasterClass {
57         GObjectClass parent;
58
59         void (*modem_added)(PsMaster *master, gchar *modem_path);
60         void (*modem_removed)(PsMaster *master, gchar *modem_path);
61 };
62
63 struct PsMaster {
64         GObject parent;
65
66         //member variable
67         gchar *path;
68         TcorePlugin *plg;
69         DBusGConnection *conn;
70         GHashTable *modems;
71 };
72
73 G_DEFINE_TYPE(PsMaster, ps_master, G_TYPE_OBJECT);
74
75 /*Function Declaration*/
76 static void __ps_master_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
77 static void __ps_master_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
78
79 gboolean ps_iface_master_get_modems(PsMaster *master, DBusGMethodInvocation *context);
80 gboolean ps_iface_master_get_profile_list(PsMaster *master, DBusGMethodInvocation *context);
81 gboolean ps_iface_master_add_profile(PsMaster *master, GHashTable *profile_property, gboolean *result, GError **error);
82 gboolean ps_iface_master_reset_profile(PsMaster *master, gboolean *result, GError **error);
83
84 static void __ps_master_emit_modem_added_signal(PsMaster *master, gpointer modem);
85 /*static void __ps_master_emit_modem_removed_signal(PsMaster *master, gpointer modem);*/
86
87 static void __remove_modem(gpointer data);
88 static void __ps_master_register_key_callback(gpointer master, enum tcore_storage_key key);
89 static void __ps_master_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data);
90
91 #include "ps-iface-master-glue.h"
92
93 static void ps_master_init(PsMaster *master)
94 {
95         dbg("ps master init");
96         master->plg = NULL;
97         master->conn = NULL;
98         master->path = PROP_DEFAULT_STR;
99         master->modems = g_hash_table_new_full(g_str_hash,g_str_equal, g_free, __remove_modem);
100         return;
101 }
102
103 static void ps_master_class_init(PsMasterClass *klass)
104 {
105         GObjectClass *object_class = G_OBJECT_CLASS(klass);
106
107         dbg("class_init");
108
109         //set property
110         object_class->get_property = __ps_master_get_property;
111         object_class->set_property = __ps_master_set_property;
112
113         //register class to dbus
114         dbus_g_object_type_install_info(PS_TYPE_MASTER, &dbus_glib_ps_iface_master_object_info);
115
116         //add properties
117         g_object_class_install_property(
118                         object_class,
119                         PROP_MASTER_PLUGIN,
120                         g_param_spec_pointer("plg", "PLUGIN", "Plug in Object",
121                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
122
123         g_object_class_install_property(
124                         object_class,
125                         PROP_MASTER_CONN,
126                         g_param_spec_boxed("conn", "CONNECTION", "DBus connection", DBUS_TYPE_G_CONNECTION,
127                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
128
129         g_object_class_install_property(
130                         object_class,
131                         PROP_MASTER_PATH,
132                         g_param_spec_string("path", "Path", "Object path", NULL,
133                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
134
135         //add signal handler
136         signals[SIG_MASTER_MODEM_ADDED] = g_signal_new("modem-added", G_OBJECT_CLASS_TYPE(klass),
137                         G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(PsMasterClass, modem_added), NULL, NULL,
138                         g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
139
140         signals[SIG_MASTER_MODEM_REMOVED] = g_signal_new("modem-removed", G_OBJECT_CLASS_TYPE(klass),
141                         G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(PsMasterClass, modem_removed), NULL, NULL,
142                         g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, DBUS_TYPE_G_OBJECT_PATH);
143
144         return;
145 }
146
147 static void __ps_master_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
148 {
149         return;
150 }
151
152 static void __ps_master_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
153 {
154         PsMaster *master = PS_MASTER(object);
155
156         switch (prop_id) {
157                 case PROP_MASTER_PLUGIN: {
158                         master->plg = g_value_get_pointer(value);
159                         msg("master(%p) set plg(%p)", master, master->plg);
160                 }
161                         break;
162                 case PROP_MASTER_CONN: {
163                         master->conn = g_value_get_boxed(value);
164                         msg("master(%p) set conn(%p)", master, master->conn);
165                 }
166                         break;
167                 case PROP_MASTER_PATH: {
168                         if (master->path) g_free(master->path);
169                         master->path = g_value_dup_string(value);
170                         msg("master(%p) set path(%s)", master, master->path);
171                 }
172                         break;
173                 default:
174                         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
175                         break;
176         } //swtich end
177
178         return;
179 }
180
181 gboolean ps_iface_master_get_modems(PsMaster *master, DBusGMethodInvocation *context)
182 {
183         GError *error = NULL;
184         GHashTableIter iter;
185         gpointer key, value;
186         GHashTable *modems;
187
188         dbg("master get modems interface");
189
190         if (master->modems == NULL) {
191                 g_set_error(&error, PS_ERROR, PS_ERR_INTERNAL, "master(%p) does not have modems", master);
192                 dbus_g_method_return_error(context, error);
193                 return FALSE;
194         }
195
196         modems = g_hash_table_new_full(g_direct_hash, g_str_equal, g_free,
197                         (GDestroyNotify) g_hash_table_destroy);
198
199         g_hash_table_iter_init(&iter, master->modems);
200         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
201                 gchar *path = NULL;
202                 GHashTable *properties = NULL;
203                 gboolean rv = FALSE;
204
205                 properties = g_hash_table_new(g_str_hash, g_str_equal);
206                 rv = _ps_modem_get_properties(value, properties);
207                 if (rv != TRUE) {
208                         g_set_error(&error, PS_ERROR, PS_ERR_INTERNAL, "fail to get properties modem(%p)",
209                                         value);
210                         dbus_g_method_return_error(context, error);
211                         g_hash_table_destroy(properties);
212                         g_hash_table_destroy(modems);
213                         return TRUE;
214                 }
215
216                 path = _ps_modem_ref_path(value);
217                 g_hash_table_insert(modems, g_strdup(path), properties);
218                 dbg("modem (%p) inserted into hash", value);
219         }
220
221         dbus_g_method_return(context, modems);
222         g_hash_table_destroy(modems);
223
224         return TRUE;
225 }
226
227 gboolean ps_iface_master_get_profile_list(PsMaster *master, DBusGMethodInvocation *context)
228 {
229         int index = 0;
230         GError *error = NULL;
231         GHashTableIter iter;
232         gpointer key, value;
233
234         guint len =0;
235         gchar **strv = NULL;
236         GHashTable *contexts = NULL;
237         GSList *profiles = NULL;
238
239         contexts = _ps_context_ref_hashtable();
240         if (contexts == NULL) {
241                 err("no profiles");
242                 g_set_error(&error, PS_ERROR, PS_ERR_NO_PROFILE, "profile does not exists");
243                 dbus_g_method_return_error(context, error);
244                 return TRUE;
245         }
246
247         g_hash_table_iter_init(&iter, contexts);
248         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
249                 gchar *s_path = NULL;
250
251                 s_path = _ps_context_ref_path(value);
252                 dbg("key(%s), value(%p), path(%s)", (gchar *)key, value, s_path);
253                 if(s_path)
254                         profiles = g_slist_append(profiles, g_strdup((const gchar*)s_path));
255         }
256
257         if (profiles == NULL) {
258                 err("no profiles");
259                 g_set_error(&error, PS_ERROR, PS_ERR_NO_PROFILE, "profile does not exists");
260                 dbus_g_method_return_error(context, error);
261                 return TRUE;
262         }
263
264         len = g_slist_length(profiles);
265         strv = g_new(gchar *, len+1);
266
267         do{
268                 strv[index] = g_strdup(profiles->data);
269                 index++;
270         }while(  (profiles = g_slist_next(profiles)) );
271         strv[index] = NULL;
272
273         dbus_g_method_return(context, strv);
274         g_strfreev(strv);
275         profiles = g_slist_nth(profiles, 0);
276         g_slist_free_full(profiles, g_free);
277         return TRUE;
278 }
279
280 gboolean ps_iface_master_add_profile(PsMaster *master, GHashTable *profile_property,
281                 gboolean *result, GError **error)
282 {
283         GHashTableIter iter;
284         gpointer key, value;
285         gboolean rv = FALSE;
286         gchar *operator = NULL;
287
288         dbg("add profile request");
289
290         g_hash_table_iter_init(&iter, master->modems);
291         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
292                 operator = _ps_modem_ref_operator(value);
293                 if(operator)
294                         break;
295         }
296
297         if(!operator){
298                 dbg("there is no active modem");
299                 g_set_error(error, PS_ERROR, PS_ERR_INTERNAL,"fail to add profile");
300                 *result = FALSE;
301                 return TRUE;
302         }
303
304         rv = _ps_context_add_context(value, operator, profile_property);
305         if(rv != TRUE){
306                 g_set_error(error, PS_ERROR, PS_ERR_INTERNAL,"fail to add profile");
307                 *result = FALSE;
308                 return TRUE;
309         }
310
311         dbg("success to add profile");
312         *result = TRUE;
313
314         return TRUE;
315 }
316
317 gboolean ps_iface_master_reset_profile(PsMaster *master, gboolean *result, GError **error)
318 {
319         GHashTableIter iter;
320         gpointer key, value;
321         gboolean rv = FALSE;
322         int b_check = 0;
323
324         *result = TRUE;
325
326         dbg("reset profile request");
327
328         if (master->modems == NULL) {
329                 dbg("modem does not exist");
330                 g_set_error(error, PS_ERROR, PS_ERR_INTERNAL, "fail to get modem");
331                 *result = FALSE;
332                 return TRUE;
333         }
334
335         b_check = access("/opt/system/csc-default/data/csc-default-data-connection.ini", F_OK);
336         if( b_check != 0 ){
337                 dbg("csc file was not there");
338                 g_set_error(error, PS_ERROR, PS_ERR_INTERNAL, "no csc data file");
339                 *result = FALSE;
340                 return TRUE;
341         }
342
343         g_hash_table_iter_init(&iter, master->modems);
344         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
345                 dbg("key(%s), value(%p) context", key, value);
346                 _ps_modem_processing_power_enable(value, FALSE);
347                 _ps_modem_set_sim_enabled(value, FALSE);
348         }
349
350         _ps_context_reset_hashtable();
351         _ps_context_reset_profile_table();
352         rv = _ps_context_fill_profile_table_from_ini_file();
353
354         g_hash_table_iter_init(&iter, master->modems);
355         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
356                 _ps_get_co_modem_values(value);
357         }
358
359         if(!rv){
360                 dbg("csc data was wrong");
361                 g_set_error(error, PS_ERROR, PS_ERR_INTERNAL, "fail to load csc data");
362                 *result = FALSE;
363         }
364
365         return TRUE;
366 }
367
368 static void __ps_master_emit_modem_added_signal(PsMaster *master, gpointer modem)
369 {
370         GHashTable *properties = NULL;
371
372         properties = g_hash_table_new(g_str_hash, g_str_equal);
373         _ps_modem_get_properties(modem, properties);
374         g_signal_emit(master, signals[SIG_MASTER_MODEM_ADDED], 0, properties);
375         dbg("master (%p) emit the modem(%p) added signal", master, modem);
376         g_hash_table_destroy(properties);
377         return;
378 }
379
380 /*static void __ps_master_emit_modem_removed_signal(PsMaster *master, gpointer modem)
381 {
382         g_signal_emit(master, signals[SIG_MASTER_MODEM_REMOVED], 0, _ps_modem_ref_path(modem));
383         dbg("master (%p) emit the modem(%p) removed signal", master, modem);
384         return;
385 }*/
386
387 static void __remove_modem(gpointer data)
388 {
389         dbg("remove modem (%p)", data);
390         return;
391 }
392
393 static void __ps_master_register_key_callback(gpointer object, enum tcore_storage_key key)
394 {
395         gpointer handle = NULL;
396         PsMaster *master = (PsMaster *) object;
397         Server *s = tcore_plugin_ref_server(master->plg);
398         static Storage *strg;
399
400         strg = tcore_server_find_storage(s, "vconf");
401         handle = tcore_storage_create_handle(strg, "vconf");
402         if (!handle)
403                 err("fail to create vconf handle");
404
405         tcore_storage_set_key_callback(strg, key, __ps_master_storage_key_callback, object);
406
407         return;
408 }
409
410 static void __ps_master_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data)
411 {
412         GVariant *tmp = NULL;
413         GHashTableIter iter;
414         gpointer h_key, h_value;
415         gboolean type_check = FALSE;
416         PsMaster *master = (PsMaster *)user_data;
417
418         dbg("storage key(%d) callback", key);
419         g_return_if_fail(master != NULL);
420
421         tmp = (GVariant *)value;
422         if(!tmp){
423                 err("value is null");
424                 return;
425         }
426
427         type_check = g_variant_is_of_type(tmp, G_VARIANT_TYPE_BOOLEAN);
428         if(!type_check){
429                 err("wrong variant data type");
430                 g_variant_unref(tmp);
431                 return;
432         }
433
434         g_hash_table_iter_init(&iter, master->modems);
435         while (g_hash_table_iter_next(&iter, &h_key, &h_value) == TRUE) {
436                 if(key == KEY_3G_ENABLE){
437                         gboolean data_allowed = g_variant_get_boolean(tmp);
438                         _ps_modem_set_data_allowed(h_value, data_allowed);
439                 }
440                 else if(key == KEY_DATA_ROAMING_SETTING){
441                         gboolean roaming_allowed = g_variant_get_boolean(tmp);
442                         _ps_modem_set_data_roaming_allowed(h_value, roaming_allowed);
443                 }
444         }
445
446         g_variant_unref(tmp);
447         return;
448 }
449
450 gpointer _ps_master_create_master(DBusGConnection *conn, TcorePlugin *p)
451 {
452         guint rv;
453         GObject *object;
454         DBusGProxy *proxy;
455         GError *error = NULL;
456
457         dbg("master object create");
458         g_return_val_if_fail(conn != NULL, NULL);
459
460         proxy = dbus_g_proxy_new_for_name(conn, "org.freedesktop.DBus", "/org/freedesktop/DBus",
461                         "org.freedesktop.DBus");
462
463         if (!dbus_g_proxy_call(proxy, "RequestName", &error, G_TYPE_STRING, PS_DBUS_SERVICE,
464                         G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &rv, G_TYPE_INVALID)) {
465                 err("Failed to acquire service(%s) error(%s)", PS_DBUS_SERVICE, error->message);
466                 return NULL;
467         }
468
469         object = g_object_new(PS_TYPE_MASTER, "plg", p, "conn", conn, "path", PS_MASTER_PATH, NULL);
470         dbus_g_connection_register_g_object(conn, PS_MASTER_PATH, object);
471         msg("master(%p) register dbus path(%s)", object, PS_MASTER_PATH);
472
473         __ps_master_register_key_callback(object, KEY_3G_ENABLE);
474         __ps_master_register_key_callback(object, KEY_DATA_ROAMING_SETTING);
475
476         return object;
477 }
478
479 gboolean _ps_master_create_modems(gpointer object)
480 {
481         Server *s = NULL;
482         GSList *plist = NULL;
483         gpointer modem = NULL, tmp = NULL;
484         PsMaster *master = NULL;
485
486         dbg("create modem objects");
487         g_return_val_if_fail(object != NULL, FALSE);
488
489         master = (PsMaster *) object;
490         s = tcore_plugin_ref_server(master->plg);
491         plist = tcore_server_ref_plugins(s);
492
493         if (NULL == plist) {
494                 dbg("fail to get plugin-in list.");
495                 return FALSE;
496         }
497
498         for (; plist != NULL; plist = g_slist_next(plist)) {
499                 TcorePlugin *p = NULL;
500                 CoreObject *co_modem = NULL;
501                 GSList *modemlists = NULL;
502                 gchar *modem_name = NULL;
503
504                 p = plist->data;
505                 modemlists = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_MODEM);
506                 dbg("plug-in %p, modemlists(%p)", p, modemlists);
507                 if (!modemlists)
508                         continue;
509
510                 co_modem = modemlists->data;
511                 g_slist_free(modemlists);
512
513                 modem_name = g_strdup_printf("/%s", tcore_object_ref_name(co_modem));
514                 tmp = g_hash_table_lookup(master->modems, modem_name);
515                 if (tmp != NULL) {
516                         dbg("modem (%p) already existed", tmp);
517                         continue;
518                 }
519
520                 modem = _ps_modem_create_modem(master->conn, master->plg, master, modem_name, co_modem);
521                 if (modem == NULL) {
522                         dbg("fail to create modem");
523                         return FALSE;
524                 }
525
526                 g_hash_table_insert(master->modems, g_strdup(modem_name), modem);
527                 dbg("modem (%p) created", modem);
528
529                 __ps_master_emit_modem_added_signal(master, modem);
530
531                 g_free(modem_name);
532         }
533
534         return TRUE;
535 }
536
537 gboolean _ps_master_get_storage_value(gpointer object, enum tcore_storage_key key)
538 {
539         Server *s = NULL;
540         Storage *strg = NULL;
541         PsMaster *master = object;
542
543         g_return_val_if_fail(master != NULL, FALSE);
544         s = tcore_plugin_ref_server(master->plg);
545         strg = tcore_server_find_storage(s, "vconf");
546
547         return tcore_storage_get_bool(strg, key);
548 }
549
550 gboolean _ps_master_set_storage_value(gpointer object, enum tcore_storage_key key, gboolean value)
551 {
552         Server *s = NULL;
553         Storage *strg = NULL;
554         PsMaster *master = object;
555
556         g_return_val_if_fail(master != NULL, FALSE);
557         s = tcore_plugin_ref_server(master->plg);
558         strg = tcore_server_find_storage(s, "vconf");
559
560         return tcore_storage_set_bool(strg, key, value);
561 }