tizen 2.3.1 release
[framework/telephony/tel-plugin-dbus_tapi.git] / src / desc-dbus.c
1 /*
2  * tel-plugin-dbus-tapi
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Ja-young Gu <jygu@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 #include <stdio.h>
22 #include <string.h>
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <time.h>
27 #include <glib.h>
28 #include <gio/gio.h>
29
30 #include <tcore.h>
31 #include <server.h>
32 #include <plugin.h>
33 #include <hal.h>
34 #include <communicator.h>
35 #include <storage.h>
36 #include <queue.h>
37 #include <user_request.h>
38 #include <co_network.h>
39 #include <co_sim.h>
40 #include <co_ps.h>
41
42 #include "sat_ui_support.h"
43
44 #ifndef PLUGIN_VERSION
45 #define PLUGIN_VERSION 1
46 #endif
47
48 #include "generated-code.h"
49 #include "common.h"
50
51 static void add_modem(struct custom_data *ctx, TcorePlugin *p)
52 {
53         TelephonyObjectSkeleton *object;
54         char *path = NULL;
55         GSList *co_list;
56         const char *cp_name;
57
58         dbg("Entry");
59
60         /* Get CP Name */
61         cp_name = tcore_server_get_cp_name_by_plugin(p);
62         if (cp_name == NULL) {
63                 err("CP Name is NULL");
64                 return;
65         }
66
67         path = g_strdup_printf("%s/%s", MY_DBUS_PATH, cp_name);
68         dbg("PATH: [%s]", path);
69
70         object = g_hash_table_lookup(ctx->objects, path);
71         if (object) {
72                 dbg("DBUS interface object already created (object: %p)", object);
73                 goto OUT;
74         }
75
76         object = telephony_object_skeleton_new(path);
77         dbg("New DBUS object created (object: [%p])", object);
78         g_hash_table_insert(ctx->objects, g_strdup(path), object);
79
80         /* Add interfaces */
81         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_MODEM);
82         if (co_list) {
83                 g_slist_free(co_list);
84                 dbus_plugin_setup_modem_interface(object, ctx);
85         }
86
87         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_CALL);
88         if (co_list) {
89                 g_slist_free(co_list);
90                 dbus_plugin_setup_call_interface(object, ctx);
91         }
92
93         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_NETWORK);
94         if (co_list) {
95                 g_slist_free(co_list);
96                 dbus_plugin_setup_network_interface(object, ctx);
97         }
98
99         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_SS);
100         if (co_list) {
101                 g_slist_free(co_list);
102                 dbus_plugin_setup_ss_interface(object, ctx);
103         }
104
105         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_SMS);
106         if (co_list) {
107                 g_slist_free(co_list);
108                 dbus_plugin_setup_sms_interface(object, ctx);
109         }
110
111         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_SAT);
112         if (co_list) {
113                 g_slist_free(co_list);
114                 dbus_plugin_setup_sat_interface(object, ctx);
115         }
116
117         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_PHONEBOOK);
118         if (co_list) {
119                 g_slist_free(co_list);
120                 dbus_plugin_setup_phonebook_interface(object, ctx);
121         }
122
123         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_SAP);
124         if (co_list) {
125                 g_slist_free(co_list);
126                 dbus_plugin_setup_sap_interface(object, ctx);
127         }
128
129         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_SIM);
130         if (co_list) {
131                 g_slist_free(co_list);
132                 dbus_plugin_setup_sim_interface(object, ctx);
133         }
134
135         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_GPS);
136         if (co_list) {
137                 g_slist_free(co_list);
138                 dbus_plugin_setup_gps_interface(object, ctx);
139         }
140         dbus_plugin_setup_oem_interface(object, ctx);
141         /* Export the Object to Manager */
142         g_dbus_object_manager_server_export (ctx->manager, G_DBUS_OBJECT_SKELETON (object));
143
144
145 OUT:
146         /* Freeing memory */
147         g_free(path);
148 }
149
150 static void refresh_object(struct custom_data *ctx)
151 {
152         GSList *modem_plg_list;
153         TcorePlugin *modem_plg;
154         GSList *cur;
155
156         if (!ctx->manager) {
157                 dbg("Telephony not ready...");
158                 return;
159         }
160
161         modem_plg_list = tcore_server_get_modem_plugin_list(ctx->server);
162         for (cur = modem_plg_list; cur; cur = cur->next) {
163                 modem_plg = cur->data;
164                 if (modem_plg == NULL) {
165                         dbg("No Modem Plug-in");
166                         continue;
167                 }
168
169                 /* Add modem */
170                 add_modem(ctx, modem_plg);
171         }
172         g_slist_free(modem_plg_list);
173 }
174
175 static TReturn send_response(Communicator *comm, UserRequest *ur, enum tcore_response_command command, unsigned int data_len, const void *data)
176 {
177         struct custom_data *ctx = NULL;
178         struct dbus_request_info *dbus_info;
179         gboolean ret = FALSE;
180
181         dbg("Response Command = [0x%x], data_len = %d", command, data_len);
182
183
184         ctx = tcore_communicator_ref_user_data(comm);
185         if (!ctx) {
186                 dbg("user_data is NULL");
187                 return TCORE_RETURN_EINVAL;
188         }
189
190         dbus_info = (struct dbus_request_info *)tcore_user_request_ref_user_info(ur);
191         if (!dbus_info) {
192                 dbg("dbus_info is NULL");
193                 return TCORE_RETURN_EINVAL;
194         }
195
196         if (!data) {
197                 g_dbus_method_invocation_return_error (dbus_info->invocation,
198                                 G_DBUS_ERROR,
199                                 G_DBUS_ERROR_FAILED,
200                                 "Request failed");
201                 return TCORE_RETURN_SUCCESS;
202         }
203
204         switch (command & (TCORE_RESPONSE | 0x0FF00000)) {
205                 case TRESP_CALL:
206                         ret = dbus_plugin_call_response(ctx, ur, dbus_info, command, data_len, data);
207                         break;
208
209                 case TRESP_SS:
210                         ret = dbus_plugin_ss_response(ctx, ur, dbus_info, command, data_len, data);
211                         break;
212
213                 case TRESP_PS:
214                         break;
215
216                 case TRESP_SIM:
217                         ret = dbus_plugin_sim_response(ctx, ur, dbus_info, command, data_len, data);
218                         break;
219
220                 case TRESP_SAP:
221                         ret = dbus_plugin_sap_response(ctx, ur, dbus_info, command, data_len, data);
222                         break;
223
224                 case TRESP_PHONEBOOK:
225                         ret = dbus_plugin_phonebook_response(ctx, ur, dbus_info, command, data_len, data);
226                         break;
227
228                 case TRESP_MODEM:
229                         ret = dbus_plugin_modem_response(ctx, ur, dbus_info, command, data_len, data);
230                         break;
231
232                 case TRESP_SMS:
233                         ret = dbus_plugin_sms_response(ctx, ur, dbus_info, command, data_len, data);
234                         break;
235
236                 case TRESP_SAT:
237                         ret = dbus_plugin_sat_response(ctx, ur, dbus_info, command, data_len, data);
238                         break;
239
240                 case TRESP_CUSTOM:
241                         ret = dbus_plugin_oem_response(ctx, ur, dbus_info, command, data_len, data);
242                         break;
243
244                 case TRESP_NETWORK:
245                         ret = dbus_plugin_network_response(ctx, ur, dbus_info, command, data_len, data);
246                         break;
247
248                 case TRESP_GPS:
249                         ret = dbus_plugin_gps_response(ctx, ur, dbus_info, command, data_len, data);
250                         break;
251
252                 default:
253                         warn("unknown command (0x%x)", command);
254                         break;
255         }
256
257         if (ret == TRUE)
258                 return TCORE_RETURN_SUCCESS;
259         else
260                 return TCORE_RETURN_FAILURE;
261 }
262
263 static TReturn send_notification(Communicator *comm, CoreObject *source, enum tcore_notification_command command, unsigned int data_len, const void *data)
264 {
265         struct custom_data *ctx = NULL;
266         unsigned int noti = 0;
267         gboolean ret = FALSE;
268
269         ctx = tcore_communicator_ref_user_data(comm);
270         if (ctx == NULL) {
271                 err("user_data is NULL");
272                 return TCORE_RETURN_EINVAL;
273         }
274
275         noti = (command & (TCORE_NOTIFICATION | 0x0FF00000));
276
277         /*
278          * Notifications are classified into -
279          *      Server (System) notifications
280          *      Module notifications
281          */
282         if (noti == TNOTI_SERVER) {
283                 dbg("Server (System) Notification");
284
285                 switch (command) {
286                 case TNOTI_SERVER_ADDED_MODEM_PLUGIN: {
287                         const char *cp_name;
288
289                         cp_name = tcore_server_get_cp_name_by_plugin((TcorePlugin*)data);
290                         dbg("Modem Plug-in (%s) is added... Exporting interfaces for the modem", cp_name);
291                         add_modem(ctx, (TcorePlugin*)data);
292
293                         ret = TRUE;
294                         break;
295                 }
296
297                 case TNOTI_SERVER_ADDED_MODEM_PLUGIN_COMPLETED: {
298                         Storage *strg;
299                         gboolean b_set;
300                         int *count;
301
302                         if (data == NULL) {
303                                 err("data is NULL");
304                                 break;
305                         }
306
307                         count = (int *)data;
308                         dbg("[%d] Modem plug-ins are added...", *count);
309
310                         strg = tcore_server_find_storage(ctx->server, "vconf");
311
312                         b_set = tcore_storage_set_int(strg, STORAGE_KEY_TELEPHONY_SIM_SLOT_COUNT, *count);
313                         if (b_set == FALSE) {
314                                 err("Fail to set the sim slot count vconf");
315
316                                 /* Reset STORAGE_KEY_TELEPHONY_READY */
317                                 b_set = tcore_storage_set_bool(strg, STORAGE_KEY_TELEPHONY_READY, FALSE);
318                                 warn("Reset TELEPHONY_READY!!!");
319                         } else {
320                                 if (ctx->name_acquired == TRUE
321                                         && tcore_storage_get_bool(strg, STORAGE_KEY_TELEPHONY_READY) == FALSE) {
322                                         b_set = tcore_storage_set_bool(strg, STORAGE_KEY_TELEPHONY_READY, TRUE);
323                                         if (b_set == FALSE) {
324                                                 err("Fail to set telephony ready");
325
326                                                 /* Reset STORAGE_KEY_TELEPHONY_SIM_SLOT_COUNT */
327                                                 b_set = tcore_storage_set_int(strg, STORAGE_KEY_TELEPHONY_SIM_SLOT_COUNT, -1);
328                                                 warn("Reset STORAGE_KEY_TELEPHONY_SIM_SLOT_COUNT!!!");
329                                         } else {
330 #ifdef ENABLE_KPI_LOGS
331                                                 TIME_CHECK("Setting VCONFKEY_TELEPHONY_READY to TRUE");
332 #else
333                                                 msg("Setting VCONFKEY_TELEPHONY_READY to TRUE");
334 #endif
335                                         }
336                                 }
337                                 dbg("Bus acquired...[%s]", (ctx->name_acquired)?"YES":"NO" );
338                         }
339                         ret = TRUE;
340                         break;
341                 }
342
343                 default:
344                         warn("Unsupported System notification: (0x%x)", command);
345                         break;
346                 }
347         }
348         else {
349                 TelephonyObjectSkeleton *object;
350                 const char *cp_name;
351                 char *path;
352
353                 cp_name = tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(source));
354                 if (cp_name == NULL) {
355                         err("CP name is NULL");
356                         return TCORE_RETURN_FAILURE;
357                 }
358
359                 path = g_strdup_printf("%s/%s", MY_DBUS_PATH, cp_name);
360
361                 /* Look-up Hash table for Object */
362                 object = g_hash_table_lookup(ctx->objects, path);
363
364                 dbg("[%s]:(cmd[0x%x] data[%p] len[%d] obj[%p])",
365                         cp_name, command, data, data_len, object);
366
367                 g_free(path);
368                 if (object == NULL) {
369                         err("Object is NOT defined!!!");
370                         return TCORE_RETURN_FAILURE;
371                 }
372
373                 switch (noti) {
374                 case TNOTI_CALL:
375                         ret = dbus_plugin_call_notification(ctx, source, object, command, data_len, data);
376                         break;
377
378                 case TNOTI_SS:
379                         ret = dbus_plugin_ss_notification(ctx, source, object, command, data_len, data);
380                         break;
381
382                 case TNOTI_PS:
383                         warn("PS Notification (0x%x)... Not handled!!!", noti);
384                         break;
385
386                 case TNOTI_SIM:
387                         ret = dbus_plugin_sim_notification(ctx, source, object, command, data_len, data);
388                         break;
389
390                 case TNOTI_SAP:
391                         ret = dbus_plugin_sap_notification(ctx, source, object, command, data_len, data);
392                         break;
393
394                 case TNOTI_PHONEBOOK:
395                         ret = dbus_plugin_phonebook_notification(ctx, source, object, command, data_len, data);
396                         break;
397
398                 case TNOTI_MODEM:
399                         ret = dbus_plugin_modem_notification(ctx, source, object, command, data_len, data);
400                         break;
401
402                 case TNOTI_SMS:
403                         ret = dbus_plugin_sms_notification(ctx, source, object, command, data_len, data);
404                         break;
405
406                 case TNOTI_SAT:
407                         ret = dbus_plugin_sat_notification(ctx, source, object, command, data_len, data);
408                         break;
409
410                 case TNOTI_NETWORK:
411                         ret = dbus_plugin_network_notification(ctx, source, object, command, data_len, data);
412                         break;
413
414                 case TNOTI_GPS:
415                         ret = dbus_plugin_gps_notification(ctx, source, object, command, data_len, data);
416                         break;
417
418                 default:
419                         if ((command & (TCORE_NOTIFICATION | 0x0F000000)) == (TNOTI_CUSTOM)) {
420                                 dbg("Custom Notification: [0x%x]", command);
421                                 ret = dbus_plugin_oem_notification(ctx, source, object, command, data_len, data);
422                         } else {
423                                 warn("Unknown/Unhandled Notification: [0x%x]", command);
424                         }
425
426                         break;
427                 }
428         }
429
430         if (ret == TRUE)
431                 return TCORE_RETURN_SUCCESS;
432         else
433                 return TCORE_RETURN_FAILURE;
434 }
435
436
437 static gboolean
438 on_manager_getmodems (TelephonyManager *mgr,
439                 GDBusMethodInvocation  *invocation,
440                 gpointer                user_data)
441 {
442         struct custom_data *ctx = user_data;
443         GSList *cp_name_list;
444         gchar **list;
445         const char *name = NULL;
446         int count;
447         dbg("Entry");
448
449         cp_name_list = tcore_server_get_cp_name_list(ctx->server);
450         if (cp_name_list == NULL) {
451                 telephony_manager_complete_get_modems(mgr, invocation, &name);
452                 return TRUE;
453         }
454
455         count = g_slist_length(cp_name_list);
456         list = g_try_malloc0(sizeof(gchar *) * (count+1));
457         if (list == NULL) {
458                 err("Memory allocation failed!!");
459                 telephony_manager_complete_get_modems(mgr, invocation, &name);
460                 g_slist_free_full(cp_name_list, g_free);
461                 return TRUE;
462         }
463
464         count = 0;
465         for ( ; cp_name_list ; cp_name_list = cp_name_list->next) {
466                 name = cp_name_list->data;
467                 list[count] = g_strdup(name);
468                 dbg("list[%d]: %s", count, list[count]);
469                 count++;
470         }
471
472         telephony_manager_complete_get_modems(mgr, invocation, (const gchar **)list);
473
474         /* Free memory */
475         for (;count >= 0; count--)
476                 g_free(list[count]);
477
478         g_free(list);
479
480         /* Freeing the received list of CP names */
481         g_slist_free_full(cp_name_list, g_free);
482
483         return TRUE;
484 }
485
486 static void on_name_lost(GDBusConnection *conn, const gchar *name, gpointer user_data)
487 {
488         info("Lost the name %s on the session bus\n", name);
489 }
490
491 static void on_name_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
492 {
493         struct custom_data *ctx = user_data;
494         Storage *strg;
495         gboolean b_set;
496         int count;
497
498         ctx->name_acquired = TRUE; /* Setting Bus acquried flag after Bus name is acquired */
499
500         info("Acquired the name %s on the session bus", name);
501         strg = tcore_server_find_storage(ctx->server, "vconf");
502
503         count = tcore_storage_get_int(strg, STORAGE_KEY_TELEPHONY_SIM_SLOT_COUNT);
504         if (count < 0) {
505                 err("SIM slot count not yet set");
506         } else {
507                 if (tcore_storage_get_bool(strg, STORAGE_KEY_TELEPHONY_READY) == FALSE) {
508                         b_set = tcore_storage_set_bool(strg, STORAGE_KEY_TELEPHONY_READY, TRUE);
509                         if (b_set == FALSE) {
510                                 err("Fail to set telephony ready");
511
512                                 /* Reset STORAGE_KEY_TELEPHONY_SIM_SLOT_COUNT */
513                                 b_set = tcore_storage_set_int(strg, STORAGE_KEY_TELEPHONY_SIM_SLOT_COUNT, -1);
514                                 warn("Reset STORAGE_KEY_TELEPHONY_SIM_SLOT_COUNT!!!");
515                         } else {
516 #ifdef ENABLE_KPI_LOGS
517                                 TIME_CHECK("Setting VCONFKEY_TELEPHONY_READY to TRUE");
518 #else
519                                 msg("Setting VCONFKEY_TELEPHONY_READY to TRUE");
520 #endif
521                         }
522                 }
523         }
524 }
525
526 static void on_bus_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
527 {
528         struct custom_data *ctx = user_data;
529
530         info("dbus registered");
531
532         refresh_object(ctx);
533
534         /* Add interface to default object path */
535         ctx->mgr = telephony_manager_skeleton_new();
536         g_signal_connect (ctx->mgr,
537                         "handle-get-modems",
538                         G_CALLBACK (on_manager_getmodems),
539                         ctx); /* user_data */
540
541         g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(ctx->mgr), conn, MY_DBUS_PATH, NULL);
542
543         g_dbus_object_manager_server_set_connection (ctx->manager, conn);
544
545         dbg("Aquire DBUS - COMPLETE");
546
547
548 }
549
550 struct tcore_communitor_operations ops = {
551         .send_response = send_response,
552         .send_notification = send_notification,
553 };
554
555 static gboolean on_load()
556 {
557         dbg("i'm load!");
558
559         return TRUE;
560 }
561
562 static gboolean on_init(TcorePlugin *p)
563 {
564         Communicator *comm;
565         struct custom_data *data;
566         guint id;
567
568         if (!p)
569                 return FALSE;
570
571         dbg("i'm init!");
572
573         data = calloc(1, sizeof(struct custom_data));
574         if (!data) {
575                 return FALSE;
576         }
577
578         data->plugin = p;
579
580         comm = tcore_communicator_new(p, "dbus", &ops);
581         tcore_communicator_link_user_data(comm, data);
582
583         data->comm = comm;
584         data->server = tcore_plugin_ref_server(p);
585
586         data->objects = g_hash_table_new(g_str_hash, g_str_equal);
587         data->cached_data = NULL;
588
589         dbg("data = %p", data);
590
591         id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
592                         MY_DBUS_SERVICE,
593                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
594                         on_bus_acquired,
595                         on_name_acquired, on_name_lost,
596                         data,
597                         NULL);
598
599         data->owner_id = id;
600         dbg("owner id=[%d]", data->owner_id);
601
602         data->manager = g_dbus_object_manager_server_new (MY_DBUS_PATH);
603         refresh_object(data);
604
605         return TRUE;
606 }
607
608 static void on_unload(TcorePlugin *p)
609 {
610         struct custom_data *data = 0;
611         Communicator *comm = 0;
612         Server *s = tcore_plugin_ref_server(p);
613         GSList *list = NULL;
614         struct cached_data *object = NULL;
615
616         if (!p)
617                 return;
618
619         dbg("i'm unload");
620
621         comm = tcore_server_find_communicator(s, "dbus");
622         if (!comm)
623                 return;
624
625         data = tcore_communicator_ref_user_data(comm);
626         if (!data)
627                 return;
628
629         if(data->owner_id > 0) {
630                 g_bus_unown_name(data->owner_id);
631         }
632
633         g_hash_table_destroy(data->objects);
634
635         for (list = data->cached_data; list; list = list->next) {
636                 object = (struct cached_data *)list->data;
637                 if (object == NULL)
638                         continue;
639
640                 g_variant_unref(object->cached_sat_main_menu);
641                 g_free(object->cp_name);
642                 g_free(object);
643         }
644         g_slist_free(data->cached_data);
645
646         free(data);
647
648         tcore_server_remove_communicator(s, comm);
649 }
650
651 EXPORT_API struct tcore_plugin_define_desc plugin_define_desc =
652 {
653         .name = "NEW_DBUS_COMMUNICATOR",
654         .priority = TCORE_PLUGIN_PRIORITY_HIGH,
655         .version = PLUGIN_VERSION,
656         .load = on_load,
657         .init = on_init,
658         .unload = on_unload
659 };