Set telephony ready at proper time
[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 <glib-object.h>
29 #include <gio/gio.h>
30
31 #include <tcore.h>
32 #include <server.h>
33 #include <plugin.h>
34 #include <hal.h>
35 #include <communicator.h>
36 #include <storage.h>
37 #include <queue.h>
38 #include <user_request.h>
39 #include <co_network.h>
40 #include <co_sim.h>
41 #include <co_ps.h>
42
43 #ifndef PLUGIN_VERSION
44 #define PLUGIN_VERSION 1
45 #endif
46
47 #include "generated-code.h"
48 #include "common.h"
49
50 static void set_telephony_ready(Server *server)
51 {
52         static Storage *strg;
53         gboolean rv;
54
55         strg = tcore_server_find_storage(server, "vconf");
56         rv = tcore_storage_set_bool(strg, STORAGE_KEY_TELEPHONY_READY, TRUE);
57
58         dbg("Set Telephony Ready (TRUE) to registry - %s", rv ? "SUCCESS"
59                                                                 : "FAIL");
60 }
61
62 static void add_modem(struct custom_data *ctx, TcorePlugin *p)
63 {
64         TelephonyObjectSkeleton *object;
65         CoreObject *co_sim;
66         char *path = NULL;
67         const char *cp_name;
68         dbg("Entry");
69
70         /* Get CP Name */
71         cp_name = tcore_server_get_cp_name_by_plugin(p);
72         if (cp_name == NULL) {
73                 err("CP Name is NULL");
74                 return;
75         }
76
77         path = g_strdup_printf("%s/%s", MY_DBUS_PATH, cp_name);
78         dbg("PATH: [%s]", path);
79
80         object = g_hash_table_lookup(ctx->objects, path);
81         if (object == NULL) {
82                 /* Create new DBUS Interface object */
83                 object = telephony_object_skeleton_new(path);
84
85                 /* Insert the Object to DBUS interfaces HASH Table */
86                 dbg("New DBUS Interface object created!!! (object = %p)", object);
87                 if (object == NULL)
88                         goto OUT;
89
90                 g_hash_table_insert(ctx->objects, g_strdup(path), object);
91         } else
92                 dbg("DBUS Interface object already created!!! (object = %p)", object);
93
94
95         /* Add DBUS Interfaces for all Modules supported */
96
97         /* MODEM */
98         dbus_plugin_setup_modem_interface(object, ctx);
99
100         /* CALL */
101         if (tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL) != NULL)
102                 dbus_plugin_setup_call_interface(object, ctx);
103
104         /* NETWORK */
105         if (tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_NETWORK) != NULL)
106                 dbus_plugin_setup_network_interface(object, ctx);
107
108         /* SS */
109         if (tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SS) != NULL)
110                 dbus_plugin_setup_ss_interface(object, ctx);
111
112         /* SMS */
113         if (tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SMS) != NULL)
114                 dbus_plugin_setup_sms_interface(object, ctx);
115
116         /* SIM */
117         co_sim = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SIM);
118         if (co_sim != NULL)
119                 dbus_plugin_setup_sim_interface(object, ctx);
120
121         /* SAT */
122         if ((co_sim != NULL) && (tcore_sim_get_status(co_sim) >= SIM_STATUS_INITIALIZING))
123                 if (tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SAT) != NULL)
124                         dbus_plugin_setup_sat_interface(object, ctx);
125
126         /* PHONEBOOK */
127         if (tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_PHONEBOOK) != NULL)
128                 dbus_plugin_setup_phonebook_interface(object, ctx);
129
130         /* SAP */
131         if (tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SAP) != NULL)
132                 dbus_plugin_setup_sap_interface(object, ctx);
133
134         /* GPS */
135         if (tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_GPS) != NULL)
136                 dbus_plugin_setup_gps_interface(object, ctx);
137
138         /* Export the Object to Manager */
139         g_dbus_object_manager_server_export(ctx->manager, G_DBUS_OBJECT_SKELETON(object));
140
141         if (g_dbus_object_manager_server_get_connection (ctx->manager) != NULL)
142                 set_telephony_ready(ctx->server);
143
144 OUT:
145         /* Freeing memory */
146         g_free(path);
147 }
148
149 static gboolean refresh_object(gpointer user_data)
150 {
151         struct custom_data *ctx = user_data;
152         GSList *plugins;
153         GSList *cur;
154         TcorePlugin *p;
155         CoreObject *co;
156         dbg("Entry");
157
158         if (ctx->manager == NULL) {
159                 err("not ready..");
160                 return FALSE;
161         }
162
163         plugins = tcore_server_ref_plugins(ctx->server);
164         if (plugins == NULL)
165                 return FALSE;
166
167         cur = plugins;
168         for (cur = plugins; cur; cur = cur->next) {
169                 p = cur->data;
170                 /* AT Standard Plug-in is not considered */
171                 if ((p == NULL)
172                                 || (strcmp(tcore_plugin_ref_plugin_name(p), "AT") == 0)) {
173                         dbg("Plug-in Name: [%s]", tcore_plugin_ref_plugin_name(p));
174                         continue;
175                 }
176
177                 co = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_MODEM);
178                 if (co == NULL)
179                         continue;
180
181                 /* Add modem */
182                 add_modem(ctx, p);
183         }
184
185         return FALSE;
186 }
187
188 static TReturn send_response(Communicator *comm, UserRequest *ur, enum tcore_response_command command, unsigned int data_len, const void *data)
189 {
190         struct custom_data *ctx = NULL;
191         const struct tcore_user_info *ui;
192
193         dbg("Response Command = [0x%x], data_len = %d", command, data_len);
194
195         ctx = tcore_communicator_ref_user_data(comm);
196         if (ctx == NULL) {
197                 dbg("user_data is NULL");
198                 return FALSE;
199         }
200
201         ui = tcore_user_request_ref_user_info(ur);
202
203         switch (command & (TCORE_RESPONSE | 0x0FF00000)) {
204                 case TRESP_CALL:
205                         dbus_plugin_call_response(ctx, ur, ui->user_data, command, data_len, data);
206                         break;
207
208                 case TRESP_SS:
209                         dbus_plugin_ss_response(ctx, ur, ui->user_data, command, data_len, data);
210                         break;
211
212                 case TRESP_PS:
213                         break;
214
215                 case TRESP_SIM:
216                         dbus_plugin_sim_response(ctx, ur, ui->user_data, command, data_len, data);
217                         break;
218
219                 case TRESP_SAP:
220                         dbus_plugin_sap_response(ctx, ur, ui->user_data, command, data_len, data);
221                         break;
222
223                 case TRESP_PHONEBOOK:
224                         dbus_plugin_phonebook_response(ctx, ur, ui->user_data, command, data_len, data);
225                         break;
226
227                 case TRESP_MODEM:
228                         dbus_plugin_modem_response(ctx, ur, ui->user_data, command, data_len, data);
229                         break;
230
231                 case TRESP_SMS:
232                         dbus_plugin_sms_response(ctx, ur, ui->user_data, command, data_len, data);
233                         break;
234
235                 case TRESP_SAT:
236                         dbus_plugin_sat_response(ctx, ur, ui->user_data, command, data_len, data);
237                         break;
238                 case TRESP_CUSTOM:
239                         break;
240
241                 case TRESP_NETWORK:
242                         dbus_plugin_network_response(ctx, ur, ui->user_data, command, data_len, data);
243                         break;
244
245                 case TRESP_GPS:
246                         dbus_plugin_gps_response(ctx, ur, ui->user_data, command, data_len, data);
247                         break;
248
249                 default:
250                         warn("unknown command (0x%x)", command);
251                         break;
252         }
253
254         return FALSE;
255 }
256
257 static TReturn send_notification(Communicator *comm, CoreObject *source, enum tcore_notification_command command, unsigned int data_len, const void *data)
258 {
259         struct custom_data *ctx = NULL;
260         TelephonyObjectSkeleton *object;
261         TcorePlugin *p;
262         const char *cp_name;
263         char *path = NULL;
264
265         dbg("Notification!!! (command = 0x%x, data_len = %d)", command, data_len);
266
267         ctx = tcore_communicator_ref_user_data(comm);
268         if (ctx == NULL) {
269                 dbg("user_data is NULL");
270                 return TCORE_RETURN_FAILURE;
271         }
272
273         /*
274          * Modem binary is not embedded in the platform. Telephony needs to
275          * be set to ready for pwlock. This is temporary solution for
276          * tizen_2.1.
277          * This problem needs to be addressed in pwlock in the future.
278          */
279         if (command == TNOTI_SERVER_MODEM_ERR) {
280                 err("Modem interface plugin init failed");
281                 set_telephony_ready(ctx->server);
282
283                 return TCORE_RETURN_SUCCESS;
284         }
285
286         if (command == TNOTI_SERVER_ADDED_PLUGIN)
287                 p = (TcorePlugin *)data;
288         else
289                 p = tcore_object_ref_plugin(source);
290
291         cp_name = tcore_server_get_cp_name_by_plugin(p);
292         if (cp_name == NULL)
293                 return TCORE_RETURN_FAILURE;
294         dbg("CP Name: [%s]", cp_name);
295
296         if (cp_name) {
297                 path = g_strdup_printf("%s/%s", MY_DBUS_PATH, cp_name);
298         }
299         else {
300                 path = g_strdup_printf("%s", MY_DBUS_PATH);
301         }
302         dbg("PATH: [%s]", path);
303
304         object = g_hash_table_lookup(ctx->objects, path);
305         dbg("DBUS interface Object = [0x%x]", object);
306
307         switch (command & (TCORE_NOTIFICATION | 0x0FF00000)) {
308                 case TNOTI_CALL:
309                         dbus_plugin_call_notification(ctx, cp_name, object, command, data_len, data);
310                         break;
311
312                 case TNOTI_SS:
313                         dbus_plugin_ss_notification(ctx, cp_name, object, command, data_len, data);
314                         break;
315
316                 case TNOTI_PS:
317                         break;
318
319                 case TNOTI_SIM:
320                         dbus_plugin_sim_notification(ctx, cp_name, object, command, data_len, data);
321                         break;
322
323                 case TNOTI_SAP:
324                         dbus_plugin_sap_notification(ctx, cp_name, object, command, data_len, data);
325                         break;
326
327                 case TNOTI_PHONEBOOK:
328                         dbus_plugin_phonebook_notification(ctx, cp_name, object, command, data_len, data);
329                         break;
330
331                 case TNOTI_MODEM:
332                         dbus_plugin_modem_notification(ctx, cp_name, object, command, data_len, data);
333                         break;
334
335                 case TNOTI_SMS:
336                         dbus_plugin_sms_notification(ctx, cp_name, object, command, data_len, data);
337                         break;
338
339                 case TNOTI_SAT:
340                         dbus_plugin_sat_notification(ctx, cp_name, object, command, data_len, data);
341                         break;
342                 case TNOTI_CUSTOM:
343                         break;
344
345                 case TNOTI_NETWORK:
346                         dbus_plugin_network_notification(ctx, cp_name, object, command, data_len, data);
347                         break;
348
349                 case TNOTI_GPS:
350                         dbus_plugin_gps_notification(ctx, cp_name, object, command, data_len, data);
351                         break;
352
353                 case TNOTI_SERVER:
354                         dbg("Server Notification");
355                         if (command == TNOTI_SERVER_ADDED_PLUGIN) {
356                                 dbg("Plug-in is added... Refresh the context");
357                                 g_idle_add(refresh_object, ctx);
358                         }
359                         break;
360
361                 default:
362                         warn("unknown command (0x%x)", command);
363                         break;
364         }
365
366         return FALSE;
367 }
368
369
370 static gboolean
371 on_manager_getmodems (TelephonyManager *mgr,
372                 GDBusMethodInvocation  *invocation,
373                 gpointer                user_data)
374 {
375         struct custom_data *ctx = user_data;
376         GSList *cp_name_list;
377         gchar **list;
378         const char *name = NULL;
379         int count;
380         dbg("Entry");
381
382         cp_name_list = tcore_server_get_cp_name_list(ctx->server);
383         if (cp_name_list == NULL) {
384                 telephony_manager_complete_get_modems(mgr, invocation, &name);
385                 return TRUE;
386         }
387
388         count = g_slist_length(cp_name_list);
389         if (count == 0) {
390                 err("No Modems present");
391                 telephony_manager_complete_get_modems(mgr, invocation, &name);
392                 return TRUE;
393         }
394
395         dbg("count: %d", count);
396         list = g_try_malloc0(sizeof(gchar *) * (count+1));
397         if (list == NULL) {
398                 err("Failed to allocate memory");
399                 g_slist_free_full(cp_name_list, g_free);
400
401                 telephony_manager_complete_get_modems(mgr, invocation, &name);
402                 return TRUE;
403         }
404
405         count = 0;
406         for ( ; cp_name_list ; cp_name_list = cp_name_list->next) {
407                 name = cp_name_list->data;
408                 if (name == NULL)
409                         continue;
410
411                 list[count] = g_strdup(name);
412                 dbg("list[%d]: %s", count, list[count]);
413                 count++;
414         }
415
416         telephony_manager_complete_get_modems(mgr, invocation, (const gchar **)list);
417
418         /* Free memory */
419         for (;count >= 0; count--)
420                 g_free(list[count]);
421
422         g_free(list);
423
424         /* Freeing the received list of CP names */
425         g_slist_free_full(cp_name_list, g_free);
426
427         return TRUE;
428 }
429
430 static void on_bus_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data)
431 {
432         struct custom_data *ctx = user_data;
433         TelephonyManager *mgr;
434
435         info("DBUS Registered");
436
437         /* Add interface to default object path */
438         mgr = telephony_manager_skeleton_new();
439         g_signal_connect (mgr,
440                         "handle-get-modems",
441                         G_CALLBACK (on_manager_getmodems),
442                         ctx); /* user_data */
443
444         g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(mgr), conn, MY_DBUS_PATH, NULL);
445
446         g_dbus_object_manager_server_set_connection (ctx->manager, conn);
447
448         dbg("Aquire DBUS - COMPLETE");
449
450         /* Refresh Object */
451         g_idle_add(refresh_object, ctx);
452 }
453
454 struct tcore_communitor_operations ops = {
455         .send_response = send_response,
456         .send_notification = send_notification,
457 };
458
459 static gboolean on_load()
460 {
461         dbg("i'm load!");
462
463         return TRUE;
464 }
465
466 static gboolean on_init(TcorePlugin *p)
467 {
468         Communicator *comm;
469         struct custom_data *data;
470         guint id;
471
472         if (p == NULL)
473                 return FALSE;
474
475         dbg("i'm init!");
476
477         data = calloc(sizeof(struct custom_data), 1);
478         if (data == NULL) {
479                 return FALSE;
480         }
481
482         data->plugin = p;
483
484         comm = tcore_communicator_new(p, "dbus", &ops);
485         tcore_communicator_link_user_data(comm, data);
486
487         data->comm = comm;
488         data->server = tcore_plugin_ref_server(p);
489
490         data->objects = g_hash_table_new(g_str_hash, g_str_equal);
491         data->cached_sat_main_menu = NULL;
492
493         dbg("data = %p", data);
494
495         id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
496                         MY_DBUS_SERVICE,
497                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
498                         on_bus_acquired,
499                         NULL, NULL,
500                         data,
501                         NULL);
502
503         data->manager = g_dbus_object_manager_server_new (MY_DBUS_PATH);
504
505         g_idle_add(refresh_object, data);
506
507         return TRUE;
508 }
509
510 static void on_unload(TcorePlugin *p)
511 {
512         struct custom_data *data;
513         Communicator *comm;
514
515         if (p == NULL)
516                 return;
517
518         dbg("i'm unload");
519
520         comm = tcore_server_find_communicator(tcore_plugin_ref_server(p), "dbus");
521         if (comm == NULL)
522                 return;
523
524         data = tcore_communicator_ref_user_data(comm);
525         if (data == NULL)
526                 return;
527
528         g_hash_table_destroy(data->objects);
529
530         free(data);
531 }
532
533 struct tcore_plugin_define_desc plugin_define_desc =
534 {
535         .name = "NEW_DBUS_COMMUNICATOR",
536         .priority = TCORE_PLUGIN_PRIORITY_HIGH,
537         .version = PLUGIN_VERSION,
538         .load = on_load,
539         .init = on_init,
540         .unload = on_unload
541 };