Modify ps_status to no-service in emulator
[platform/core/telephony/tel-plugin-atmodem.git] / src / s_network.c
1 /*
2  * tel-plugin-atmodem
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hayoon Ko <hayoon.ko@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 <stdlib.h>
23 #include <string.h>
24 #include <glib.h>
25
26 #include <tzplatform_config.h>
27 #include <tcore.h>
28 #include <hal.h>
29 #include <core_object.h>
30 #include <plugin.h>
31 #include <queue.h>
32 #include <co_ps.h>
33 #include <co_network.h>
34 #include <server.h>
35 #include <storage.h>
36 #include <at.h>
37
38 #include "s_common.h"
39 #include "s_network.h"
40
41 #define ATMODEM_NETWORK_BASE_16 16
42 #define MCC_MNC_OPER_LIST_DB    tzplatform_mkpath(TZ_SYS_DB, ".mcc_mnc_oper_list.db")
43
44 typedef enum {
45         ATMDOEM_NETWORK_ACT_GSM, /* GSM */
46         ATMDOEM_NETWORK_ACT_GSM_COMPACT, /* GSM Compact */
47         ATMDOEM_NETWORK_ACT_UTRAN, /* UTRAN */
48         ATMDOEM_NETWORK_ACT_GSM_EGPRS, /* GSM w/EGPRS */
49         ATMDOEM_NETWORK_ACT_UTRAN_HSDPA, /* UTRAN w/HSDPA */
50         ATMDOEM_NETWORK_ACT_UTRAN_HSUPA, /* UTRAN w/HSUPA */
51         ATMDOEM_NETWORK_ACT_UTRAN_HSDPA_HSUPA, /* UTRAN w/HSDPA and HSUPA */
52         ATMDOEM_NETWORK_ACT_E_UTRAN, /* E-UTRAN */
53 } AtmodemNetworkAct;
54
55 #define AT_CREG_STAT_NOT_REG            0 /* not registered, MT is not currently searching a new operator to register to */
56 #define AT_CREG_STAT_REG_HOME   1 /* registered, home network */
57 #define AT_CREG_STAT_SEARCHING  2 /* not registered, but MT is currently searching a new operator to register to */
58 #define AT_CREG_STAT_REG_DENIED 3 /* registration denied */
59 #define AT_CREG_STAT_UNKNOWN            4 /* unknown */
60 #define AT_CREG_STAT_REG_ROAM   5 /* registered, roaming */
61
62 #if 0
63 static unsigned int lookup_tbl_net_status[] = {
64         [AT_CREG_STAT_NOT_REG] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
65         [AT_CREG_STAT_REG_HOME] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
66         [AT_CREG_STAT_SEARCHING] = NETWORK_SERVICE_DOMAIN_STATUS_SEARCH,
67         [AT_CREG_STAT_REG_DENIED] = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY,
68         [AT_CREG_STAT_UNKNOWN] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
69         [AT_CREG_STAT_REG_ROAM] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
70 };
71 #endif
72
73 #define AT_COPS_MODE_AUTOMATIC  0 /* automatic (<oper> field is ignored) */
74 #define AT_COPS_MODE_MANUAL             1 /* manual (<oper> field shall be present, and <AcT> optionally) */
75 #define AT_COPS_MODE_DEREGISTER 2 /* deregister from network */
76 #define AT_COPS_MODE_SET_ONLY           3 /* set only <format> */
77
78 #define AT_COPS_FORMAT_LONG_ALPHANUMERIC        0 /* long format alphanumeric <oper> */
79 #define AT_COPS_FORMAT_SHORT_ALPHANUMERIC       1 /* short format alphanumeric <oper> */
80 #define AT_COPS_FORMAT_NUMERIC          2 /* numeric <oper> */
81
82 #define AT_COPS_ACT_GSM                 0 /* GSM */
83 #define AT_COPS_ACT_GSM_COMPACT         1 /* GSM Compact */
84 #define AT_COPS_ACT_UTRAN                       2 /* UTRAN */
85 #define AT_COPS_ACT_GSM_EGPRS                   3 /* GSM w/EGPRS */
86 #define AT_COPS_ACT_UTRAN_HSDPA         4 /* UTRAN w/HSDPA */
87 #define AT_COPS_ACT_UTRAN_HSUPA         5 /* UTRAN w/HSUPA */
88 #define AT_COPS_ACT_UTRAN_HSDPA_HSUPA   6 /* UTRAN w/HSDPA and HSUPA */
89 #define AT_COPS_ACT_E_UTRAN                     7 /* E-UTRAN */
90 #define AT_COPS_ACT_MAX                         8
91
92 static unsigned int lookup_tbl_access_technology[] = {
93         [AT_COPS_ACT_GSM] = NETWORK_ACT_GSM,
94         [AT_COPS_ACT_GSM_COMPACT] = NETWORK_ACT_GSM,
95         [AT_COPS_ACT_UTRAN] = NETWORK_ACT_UTRAN,
96         [AT_COPS_ACT_GSM_EGPRS] = NETWORK_ACT_EGPRS,
97         [AT_COPS_ACT_UTRAN_HSDPA] = NETWORK_ACT_UTRAN,
98         [AT_COPS_ACT_UTRAN_HSUPA] = NETWORK_ACT_UTRAN,
99         [AT_COPS_ACT_UTRAN_HSDPA_HSUPA] = NETWORK_ACT_UTRAN,
100         [AT_COPS_ACT_E_UTRAN] = NETWORK_ACT_GSM_UTRAN,
101 };
102
103 static gboolean get_serving_network(CoreObject *o, UserRequest *ur);
104
105 static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *co_network)
106 {
107         Server *s;
108         Storage *strg;
109         void *handle;
110         char query[255] = {0, };
111         GHashTableIter iter;
112         gpointer key, value;
113         GHashTable *result = NULL, *row = NULL;
114         struct tcore_network_operator_info *noi = NULL;
115         int count = 0;
116
117         s = tcore_plugin_ref_server(p);
118         strg = tcore_server_find_storage(s, "database");
119
120         handle = tcore_storage_create_handle(strg, MCC_MNC_OPER_LIST_DB);
121         if (!handle) {
122                 err("fail to create database handle");
123                 return;
124         }
125
126         snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list");
127
128         result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
129                         (GDestroyNotify) g_hash_table_destroy);
130
131         tcore_storage_read_query_database(strg, handle, query, NULL, result, 4);
132
133         g_hash_table_iter_init(&iter, result);
134         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
135                 row = value;
136                 noi = g_try_malloc0(sizeof(struct tcore_network_operator_info));
137                 if (noi == NULL) {
138                         err("Memory allocation failed!!");
139                         continue;
140                 }
141                 snprintf(noi->mcc, 4, "%s", (const char *)(g_hash_table_lookup(row, "1")));
142                 snprintf(noi->mnc, 4, "%s", (const char *)(g_hash_table_lookup(row, "2")));
143                 snprintf(noi->name, 41, "%s", (const char *)(g_hash_table_lookup(row, "3")));
144                 snprintf(noi->country, 4, "%s", (const char *)(g_hash_table_lookup(row, "0")));
145
146                 tcore_network_operator_info_add(co_network, noi);
147                 g_free(noi);
148                 noi = NULL;
149
150                 count++;
151         }
152
153         dbg("count = %d", count);
154
155         g_hash_table_destroy(result);
156
157         tcore_storage_remove_handle(strg, handle);
158 }
159
160 static enum telephony_network_service_domain_status __atmodem_network_map_stat(guint stat)
161 {
162         switch (stat) {
163         case 0:
164                 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
165         case 1:
166                 return NETWORK_SERVICE_DOMAIN_STATUS_FULL;
167         case 2:
168                 return NETWORK_SERVICE_DOMAIN_STATUS_SEARCH;
169         case 3:
170                 return NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY;
171         case 4:
172                 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
173         case 5:
174                 return NETWORK_SERVICE_DOMAIN_STATUS_FULL;
175         default:
176                 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
177         }
178 }
179
180 static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type,
181         int act, int cs_status, int ps_status)
182 {
183         enum telephony_network_service_type ret;
184
185         ret = prev_type;
186
187         switch (act) {
188         case NETWORK_ACT_NOT_SPECIFIED:
189                 ret = NETWORK_SERVICE_TYPE_UNKNOWN;
190         break;
191
192         case NETWORK_ACT_GSM:
193                 if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE)
194                         ret = NETWORK_SERVICE_TYPE_2_5G_EDGE;
195                 else
196                         ret = NETWORK_SERVICE_TYPE_2G;
197         break;
198
199         case NETWORK_ACT_IS95A:
200         case NETWORK_ACT_IS95B:
201                 ret = NETWORK_SERVICE_TYPE_2G;
202         break;
203
204         case NETWORK_ACT_CDMA_1X:
205         case NETWORK_ACT_GPRS:
206                 ret = NETWORK_SERVICE_TYPE_2_5G;
207         break;
208
209         case NETWORK_ACT_EGPRS:
210                 return NETWORK_SERVICE_TYPE_2_5G_EDGE;
211
212         case NETWORK_ACT_UMTS:
213                 ret = NETWORK_SERVICE_TYPE_3G;
214         break;
215
216         case NETWORK_ACT_EVDO_REV0:
217         case NETWORK_ACT_CDMA_1X_EVDO_REV0:
218         case NETWORK_ACT_EVDO_REVA:
219         case NETWORK_ACT_CDMA_1X_EVDO_REVA:
220         case NETWORK_ACT_EVDV:
221                 ret = NETWORK_SERVICE_TYPE_3G;
222         break;
223
224         default:
225                 /*Do Nothing*/
226                 dbg("Default Case executed.");
227         break;
228         }
229
230         if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO
231                         && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) {
232                 ret = NETWORK_SERVICE_TYPE_NO_SERVICE;
233         } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH
234                         || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) {
235                 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL
236                                 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
237                         /* no change */
238                 } else {
239                         ret = NETWORK_SERVICE_TYPE_SEARCH;
240                 }
241         } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY
242                         || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) {
243                 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL
244                                 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
245                         /* no change */
246                 } else {
247                         ret = NETWORK_SERVICE_TYPE_EMERGENCY;
248                 }
249         }
250
251         return ret;
252 }
253
254 /* Notifications */
255 static gboolean on_notification_atmodem_cs_network_info(CoreObject *co_network,
256         const void *event_info, void *user_data)
257 {
258         GSList *lines = NULL;
259         gchar *line = NULL;
260
261         dbg("Network notification - CS network info: [+CREG]");
262
263         lines = (GSList *)event_info;
264         if (g_slist_length(lines) != 1) {
265                 err("+CREG unsolicited message expected to be Single line "
266                         "but received multiple lines");
267                 return TRUE;
268         }
269
270         line = (char *) (lines->data);
271         if (line != NULL) {
272                 struct tnoti_network_registration_status registration_status = {0, };
273                 struct tnoti_network_location_cellinfo cell_info = {0, };
274                 GSList *tokens = NULL;
275                 gchar *token_str;
276                 guint stat = 0, act = 0, lac = 0, ci = 0;
277
278                 /*
279                  * Tokenize
280                  *
281                  * +CREG: <stat>[, <lac>, <ci>[, <AcT>]]
282                  */
283                 tokens = tcore_at_tok_new(line);
284                 if (g_slist_length(tokens) < 1) {
285                         err("Invalid notification message");
286                         goto out;
287                 }
288
289                 /* <stat> */
290                 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
291                         err("No <stat> in +CREG");
292                         goto out;
293                 }
294                 stat = __atmodem_network_map_stat(atoi(token_str)); /*TODO : Confirm*/
295                 (void)tcore_network_set_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, stat);
296
297                 /* <lac> */
298                 if ((token_str = g_slist_nth_data(tokens, 1))) {
299                         token_str = tcore_at_tok_extract((const char *)token_str);
300                         if (token_str != NULL) {
301                                 lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
302
303                                 /* Update Location Area Code (lac) information */
304                                 (void)tcore_network_set_lac(co_network, lac);
305                                 g_free(token_str);
306                         } else {
307                                 err("No <lac>");
308                         }
309                 } else {
310                         dbg("No <lac> in +CREG");
311                         (void)tcore_network_get_lac(co_network, &lac);
312                 }
313
314                 /* <ci> */
315                 if ((token_str = g_slist_nth_data(tokens, 2))) {
316                         token_str = tcore_at_tok_extract((const char *)token_str);
317                         if (token_str != NULL) {
318                                 ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
319                                 /* Update Cell ID (ci) information */
320                                 (void)tcore_network_set_cell_id(co_network, ci);
321                                 g_free(token_str);
322                         } else {
323                                 err("No <ci>");
324                         }
325                 } else {
326                         dbg("No <ci> in +CREG");
327                         (void)tcore_network_get_cell_id(co_network, &ci);
328                 }
329
330                 /* <AcT> */
331                 if ((token_str = g_slist_nth_data(tokens, 3))) {
332                         gint idx = atoi(token_str);
333                         if (idx >= 0 && idx < AT_COPS_ACT_MAX)
334                                 act = lookup_tbl_access_technology[idx];
335                         else
336                                 act = NETWORK_ACT_UNKNOWN;
337                         (void)tcore_network_set_access_technology(co_network, act);
338                 } else {
339                         dbg("No <AcT> in +CREG");
340                         (void)tcore_network_get_access_technology(co_network, &act);
341                 }
342                 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d", stat, lac, ci, act);
343
344                 /* Send Notification - Network (CS) Registration status */
345                 registration_status.cs_domain_status = stat;
346
347                 tcore_network_get_service_status(co_network,
348                         TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &registration_status.ps_domain_status);
349
350                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
351                         co_network,
352                         TNOTI_NETWORK_REGISTRATION_STATUS,
353                         sizeof(struct tnoti_network_registration_status), &registration_status);
354
355 #if 0 /* TODO : Implement Roaming State */
356                 switch (stat) {
357                 case TEL_NETWORK_REG_STATUS_ROAMING:
358                         roam_state = TRUE; /* no break */
359                 case TEL_NETWORK_REG_STATUS_REGISTERED:
360                          Fetch Network name - Internal request
361                         (void)__atmodem_network_fetch_nw_name(co_network,
362                                 __on_response_atmodem_network_fetch_nw_name_internal, NULL);
363                 break;
364
365                 default:
366                 break;
367                 }
368
369                 tcore_network_set_roaming_state(co_network, roam_state);
370 #endif
371
372                 /* Send Notification - Cell info */
373                 cell_info.lac = (gint)lac;
374                 cell_info.cell_id = (gint)ci;
375
376                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
377                         co_network,
378                         TNOTI_NETWORK_LOCATION_CELLINFO,
379                         sizeof(struct tnoti_network_location_cellinfo), &cell_info);
380
381 out:
382                 /* Free resource */
383                 tcore_at_tok_free(tokens);
384         }
385
386         return TRUE;
387 }
388
389 static gboolean on_notification_atmodem_ps_network_info(CoreObject *co_network,
390         const void *event_info, void *user_data)
391 {
392         GSList *lines = NULL;
393         gchar *line = NULL;
394
395         dbg("Network notification - PS network info: [+CGREG]");
396
397         lines = (GSList *)event_info;
398         if (g_slist_length(lines) != 1) {
399                 err("+CGREG unsolicited message expected to be Single line "
400                         "but received multiple lines");
401                 return TRUE;
402         }
403
404         line = (char *) (lines->data);
405         if (line != NULL) {
406                 struct tnoti_network_registration_status registration_status = {0, };
407                 struct tnoti_network_location_cellinfo cell_info = {0, };
408                 enum telephony_network_service_type service_type = 0;
409                 GSList *tokens = NULL;
410                 gchar *token_str;
411                 guint act = 0, lac = 0, ci = 0, rac = 0;
412                 enum telephony_network_service_domain_status cs_status;
413                 enum telephony_network_service_domain_status ps_status;
414
415                 /*
416                  * Tokenize
417                  *
418                  * +CGREG: <stat>[, <lac>, <ci>[, <AcT>, <rac>]]
419                  */
420                 tokens = tcore_at_tok_new(line);
421                 if (g_slist_length(tokens) < 1) {
422                         err("Invalid notification message");
423                         goto out;
424                 }
425
426                 /* <stat> */
427                 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
428                         err("No <stat> in +CGREG");
429                         goto out;
430                 }
431                 /* Emulator does not support ps doamin. so ps_status should be set no-service */
432                 /* ps_status = __atmodem_network_map_stat(atoi(token_str)); */
433                 ps_status = NETWORK_SERVICE_DOMAIN_STATUS_NO;
434                 (void)tcore_network_set_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status);
435
436                 /* <lac> */
437                 if ((token_str = g_slist_nth_data(tokens, 1))) {
438                         token_str = tcore_at_tok_extract((const char *)token_str);
439                         if (token_str != NULL) {
440                                 lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
441                                 /* Update Location Area Code (lac) information */
442                                 (void)tcore_network_set_lac(co_network, lac);
443                                 g_free(token_str);
444                         } else {
445                                 err("No <lac>");
446                         }
447                 } else {
448                         dbg("No <lac> in +CGREG");
449                         (void)tcore_network_get_lac(co_network, &lac);
450                 }
451
452                 /* <ci> */
453                 if ((token_str = g_slist_nth_data(tokens, 2))) {
454                         token_str = tcore_at_tok_extract((const char *)token_str);
455                         if (token_str != NULL) {
456                                 ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
457                                 /* Update Cell ID (ci) information */
458                                 (void)tcore_network_set_cell_id(co_network, ci);
459                                 g_free(token_str);
460                         } else {
461                                 err("No <ci>");
462                         }
463                 } else {
464                         dbg("No <ci> in +CGREG");
465                         (void)tcore_network_get_cell_id(co_network, &ci);
466                 }
467
468                 /* <AcT> */
469                 if ((token_str = g_slist_nth_data(tokens, 3))) {
470                         gint idx = atoi(token_str);
471                         if (idx >= 0 && idx < AT_COPS_ACT_MAX)
472                                 act = lookup_tbl_access_technology[idx];
473                         else
474                                 act = NETWORK_ACT_UNKNOWN;
475                         (void)tcore_network_set_access_technology(co_network, act);
476                 } else {
477                         dbg("No <AcT> in +CGREG");
478                         (void)tcore_network_get_access_technology(co_network, &act);
479                 }
480
481                 /* <rac> */
482                 if ((token_str = g_slist_nth_data(tokens, 4))) {
483                         token_str = tcore_at_tok_extract((const char *)token_str);
484                         if (token_str != NULL) {
485                                 rac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
486                                 /* Update Routing Area Code (rac) information */
487                                 (void)tcore_network_set_rac(co_network, rac);
488                                 g_free(token_str);
489                         } else {
490                                 err("No <rac>");
491                         }
492                 } else {
493                         err("No <rac> in +CGREG");
494                         (void)tcore_network_get_rac(co_network, &rac);
495                 }
496                 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d <rac>: 0x%x", ps_status, lac, ci, act, rac);
497
498                 /* Send Notification - Network (PS) Registration status */
499                 registration_status.ps_domain_status = ps_status;
500
501                 (void)tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
502
503                 service_type = _get_service_type(service_type, act, cs_status, ps_status);
504                 dbg("service_type = %d", service_type);
505                 registration_status.service_type = service_type;
506                 tcore_network_set_service_type(co_network, service_type);
507
508                 (void)tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT,  &registration_status.cs_domain_status);
509
510                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
511                         co_network,
512                         TNOTI_NETWORK_REGISTRATION_STATUS,
513                         sizeof(struct tnoti_network_registration_status), &registration_status);
514
515 #if 0 /* TODO : Implement roaming state */
516                  Set Roaming state
517                 if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING)
518                         roam_state = TRUE;
519
520                 tcore_network_set_roaming_state(co_network, roam_state);
521 #endif
522
523                 /* Send Notification - Cell info */
524                 cell_info.lac = lac;
525                 cell_info.cell_id = ci;
526
527                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
528                         co_network,
529                         TNOTI_NETWORK_LOCATION_CELLINFO,
530                         sizeof(struct tnoti_network_location_cellinfo), &cell_info);
531
532                 get_serving_network(co_network, NULL);
533
534 out:
535                 /* Free resource */
536                 tcore_at_tok_free(tokens);
537         }
538
539         return TRUE;
540 }
541
542 static gboolean on_notification_atmodem_network_rssi(CoreObject *co_network,
543         const void *event_info, void *user_data)
544 {
545         GSList *lines;
546         const gchar *line = NULL;
547
548         dbg("Network notification - Icon (rssi) info: [+CIEV]");
549
550         lines = (GSList *)event_info;
551         if (g_slist_length(lines) != 1) {
552                 err("+CIEV unsolicited message expected to be "
553                         "Single line but received multiple lines");
554                 return TRUE;
555         }
556
557         line = (const char *)lines->data;
558         if (line != NULL) {
559                 GSList *tokens;
560                 guint descriptor;
561                 guint value;
562                 static struct tnoti_network_icon_info net_icon_info = {0xff, 0, 0, 0};
563
564                 tokens = tcore_at_tok_new(line);
565
566                 /* <desc> */
567                 descriptor = atoi(g_slist_nth_data(tokens, 0));
568                 dbg("Descriptor: [%s]", (descriptor == 10 ? "RSSI"
569                         : (descriptor == 15 ? "Battery" : "Unknown")));
570
571                 /* <value> */
572                 value = atoi(g_slist_nth_data(tokens, 1));
573
574                 switch (descriptor) {
575                 case 10:
576                         dbg("RSSI Level: [%d]", value);
577                         net_icon_info.type = NETWORK_ICON_INFO_RSSI;
578                         net_icon_info.rssi = value;
579
580                         /* Send Notification - Network Rssi */
581                         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
582                                 co_network,
583                                 TNOTI_NETWORK_ICON_INFO,
584                                 sizeof(struct tnoti_network_icon_info),
585                                 &net_icon_info);
586                         break;
587                 case 15:
588                         dbg("Battery Level: [%d]", value);
589                         break;
590                 default:
591                         warn("Unknown descriptor: [%d]", descriptor);
592                         break;
593                 }
594
595                 /* Free resource */
596                 tcore_at_tok_free(tokens);
597         }
598
599         return TRUE;
600 }
601
602 static void __on_response_atmodem_network_registration(TcorePending *p,
603         int data_len, const void *data, void *user_data)
604 {
605         const struct tcore_at_response *at_resp = data;
606         dbg("Entry");
607
608         if (at_resp && at_resp->success)
609                 dbg("Network Registration - [OK]");
610         else
611                 err("Network Registration - [NOK]");
612 }
613
614 static void __atmodem_network_register_to_network(CoreObject *co_network)
615 {
616         TReturn ret;
617
618         /* Send Request to modem */
619         ret = tcore_prepare_and_send_at_request(co_network,
620                 "AT+COPS=0", NULL,
621                 TCORE_AT_NO_RESULT,
622                 NULL,
623                 __on_response_atmodem_network_registration, NULL,
624                 on_send_at_request, NULL, 0, NULL, NULL);
625         dbg("Sending Network Registration request: [%s]",
626                 (ret == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
627 }
628
629 static void on_sim_resp_hook_get_netname(UserRequest *ur, enum tcore_response_command command, unsigned int data_len,
630                 const void *data, void *user_data)
631 {
632         const struct tresp_sim_read *resp = data;
633         CoreObject *o = user_data;
634         struct tnoti_network_registration_status regist_status;
635         struct tnoti_network_identity network_identity;
636         gchar *plmn = NULL;
637
638         if (command == TRESP_SIM_GET_SPN) {
639                 dbg("OK SPN GETTING!!");
640                 dbg("resp->result = 0x%x", resp->result);
641                 dbg("resp->data.spn.display_condition = 0x%x", resp->data.spn.display_condition);
642                 dbg("resp->data.spn.spn = [%s]", resp->data.spn.spn);
643
644                 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *)resp->data.spn.spn);
645
646                 /**
647                  * display condition
648                  *  bit[0]: 0 = display of registered PLMN name not required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
649                  *          1 = display of registered PLMN name required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
650                  *  bit[1]: 0 = display of the service provider name is required when registered PLMN is neither HPLMN nor a PLMN in the service provider PLMN list
651                  *          1 = display of the service provider name is not required when registered PLMN is neither HPLMN nor a PLMN in the service provider PLMN list
652                  */
653                 if (resp->data.spn.display_condition & 0x01)
654                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
655
656                 if ((resp->data.spn.display_condition & 0x02) == 0)
657                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
658
659                 if ((resp->data.spn.display_condition & 0x03) == 0x01)
660                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
661         }
662
663         tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &regist_status.cs_domain_status);
664         tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &regist_status.ps_domain_status);
665         tcore_network_get_service_type(o, &regist_status.service_type);
666         regist_status.roaming_status = tcore_network_get_roaming_state(o);
667
668         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
669                         TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), &regist_status);
670
671         memset(&network_identity, 0x00, sizeof(struct tnoti_network_identity));
672
673         plmn = tcore_network_get_plmn(o);
674         if (plmn) {
675                 dbg("plmn = %s", plmn);
676                 g_strlcpy(network_identity.plmn, plmn, sizeof(network_identity.plmn));
677                 g_free(plmn);
678         }
679         g_strlcpy(network_identity.short_name, "SDK", sizeof(network_identity.short_name));
680         g_strlcpy(network_identity.full_name, "SDK", sizeof(network_identity.full_name));
681
682         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),
683                                                                 o,
684                                                                 TNOTI_NETWORK_IDENTITY,
685                                                                 sizeof(struct tnoti_network_identity), &network_identity);
686 }
687
688 /* Hooks */
689 static enum tcore_hook_return on_hook_sim_init(Server *s, CoreObject *source,
690         enum tcore_notification_command command,
691         unsigned int data_len, void *data, void *user_data)
692 {
693         const struct tnoti_sim_status *sim = data;
694         UserRequest *ur = NULL;
695
696         if (sim->sim_status == SIM_STATUS_INIT_COMPLETED) {
697                 CoreObject *co_network = (CoreObject *)user_data;
698                 dbg("SIM Initialized!!! Attach to Network");
699
700                 /*
701                  * TODO - Check for selection_mode
702                  *      Need to check if it is Manual or Automatic and based on
703                  *      that need to initiate Network Registration accordingly.
704                  */
705                 __atmodem_network_register_to_network(co_network);
706
707                 /* Need to get SPN when sim initialization complete */
708                 ur = tcore_user_request_new(NULL, NULL);
709                 tcore_user_request_set_command(ur, TREQ_SIM_GET_SPN);
710                 tcore_user_request_set_response_hook(ur, on_sim_resp_hook_get_netname, user_data);
711                 tcore_object_dispatch_request(source, ur);
712         }
713         return TCORE_HOOK_RETURN_CONTINUE;
714 }
715
716 /* Network Responses */
717 static void on_response_network_search(TcorePending *p,
718         int data_len, const void *data, void *user_data)
719 {
720         const struct tcore_at_response *at_resp = data;
721         struct tresp_network_search nw_resp;
722         UserRequest *ur = NULL;
723         int count;
724         GSList *tokens = NULL;
725
726         dbg("Enter");
727
728         memset(&nw_resp, 0x0, sizeof(struct tresp_network_search));
729         nw_resp.result = TCORE_RETURN_FAILURE;
730
731         if (at_resp && at_resp->success) {
732                 const gchar *line;
733                 GSList *net_token = NULL;
734                 gchar *resp;
735
736                 if (!at_resp->lines) {
737                         err("invalid response received");
738                         goto END;
739                 }
740
741                 line = (char *) at_resp->lines->data;
742                 tokens = tcore_at_tok_new(line);
743                 nw_resp.list_count = g_slist_length(tokens);
744                 if (nw_resp.list_count < 1) {
745                         err("invalid message");
746                         goto END;
747                 }
748
749                 dbg("RESPONSE OK");
750                 count = 0;
751                 for (count = 0; count < nw_resp.list_count; count++) {
752                         net_token = tcore_at_tok_new(g_slist_nth_data(tokens, count));
753                         if (NULL == net_token)
754                                 continue;
755
756                         /* Status */
757                         resp = tcore_at_tok_nth(net_token, 0);
758                         if (resp != NULL) {
759                                 nw_resp.list[count].status = atoi(resp);
760                                 dbg("Status: [%d]", nw_resp.list[count].status);
761                         }
762
763                         /* Name */
764                         if ((resp = tcore_at_tok_nth(net_token, 1))) {
765                                 gchar *name = NULL;
766
767                                 name = tcore_at_tok_extract(resp);
768                                 dbg("name: [%s]", resp);
769
770                                 g_strlcpy(nw_resp.list[count].name, name, 41);
771                                 /* Emulator gives network name as # terminated string*/
772                                 if (nw_resp.list[count].name[5] == '#')
773                                         nw_resp.list[count].name[5] = '\0';
774
775                                 g_free(name);
776                         }
777
778                         /* Short Alpha name */
779                         if ((resp = tcore_at_tok_nth(net_token, 2))) {
780                                 /* Short Alpha name
781                                 dbg("Short Alpha name[%s]", resp);
782                                 plmn_list.network_list[count].network_identity.short_name =
783                                         tcore_at_tok_extract(resp); */
784                         }
785
786                         /* PLMN ID */
787                         if ((resp = tcore_at_tok_nth(net_token, 3))) {
788                                 char *plmn = NULL;
789
790                                 plmn = tcore_at_tok_extract(resp);
791                                 dbg("PLMN ID: [%s]", resp);
792
793                                 g_strlcpy(nw_resp.list[count].plmn, plmn, 6);
794
795                                 g_free(plmn);
796                         }
797
798                         /* Parse Access Technology */
799                         if ((resp = tcore_at_tok_nth(tokens, 4))) {
800                                 if (strlen(resp) > 0) {
801                                         gint act = atoi(resp);
802                                         dbg("AcT: [%d]", act);
803                                         if (act >= 0 && act < AT_COPS_ACT_MAX)
804                                                 nw_resp.list[count].act = lookup_tbl_access_technology[act];
805                                         else
806                                                 nw_resp.list[count].act = NETWORK_ACT_UNKNOWN;
807                                 }
808                         } else {
809                                         nw_resp.list[count].act = NETWORK_ACT_UMTS;
810                         }
811
812                         dbg("[%d] Status: [%d] name: [%s] PLMN: [%s] AcT: [%d]",
813                                         count,
814                                         nw_resp.list[count].status,
815                                         nw_resp.list[count].name,
816                                         nw_resp.list[count].plmn,
817                                         nw_resp.list[count].act);
818
819                         tcore_at_tok_free(net_token);
820                 }
821
822                 nw_resp.result = TCORE_RETURN_SUCCESS;
823         } else {
824                 err("RESPONSE NOK");
825                 if (at_resp)
826                         err("CME Error[%s]", (char *)(at_resp->lines ? at_resp->lines->data : "Unknown"));
827         }
828
829         ur = tcore_pending_ref_user_request(p);
830         if (ur) {
831                 tcore_user_request_send_response(ur,
832                         TRESP_NETWORK_SEARCH,
833                         sizeof(struct tresp_network_search), &nw_resp);
834         } else {
835                 err("ur is NULL");
836         }
837
838 END:
839         dbg("Network search : [%s]",
840                 (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
841
842         tcore_at_tok_free(tokens);
843 }
844
845 static void on_response_network_get_plmn_selection_mode(TcorePending *p,
846         int data_len, const void *data, void *user_data)
847 {
848         const struct tcore_at_response *at_resp = data;
849         struct tresp_network_get_plmn_selection_mode nw_resp = {0, };
850         UserRequest *ur = NULL;
851         GSList *tokens = NULL;
852
853         dbg("Enter");
854
855         nw_resp.result = TCORE_RETURN_FAILURE; /* TODO - CME Error mapping required. */
856
857         if (at_resp && at_resp->success) {
858                 const gchar *line;
859                 gint mode;
860
861                 if (!at_resp->lines) {
862                         err("invalid response received");
863                         goto END;
864                 }
865
866                 line = (char *) at_resp->lines->data;
867                 tokens = tcore_at_tok_new(line);
868                 if (g_slist_length(tokens) < 1) {
869                         msg("invalid message");
870                         goto END;
871                 }
872                 dbg("RESPONSE OK");
873
874                 mode = atoi(tcore_at_tok_nth(tokens, 0));
875                 if (mode == 0)
876                         nw_resp.mode = NETWORK_SELECT_MODE_AUTOMATIC;
877                 else if (mode == 1)
878                         nw_resp.mode  = NETWORK_SELECT_MODE_MANUAL;
879
880                 dbg("selection mode[%d]", nw_resp.mode);
881                 nw_resp.result = TCORE_RETURN_SUCCESS;
882         } else {
883                 err("RESPONSE NOK");
884         }
885
886         ur = tcore_pending_ref_user_request(p);
887         if (ur) {
888                 tcore_user_request_send_response(ur,
889                         TRESP_NETWORK_GET_PLMN_SELECTION_MODE,
890                         sizeof(struct tresp_network_get_plmn_selection_mode), &nw_resp);
891         } else {
892                 err("ur is NULL");
893         }
894
895 END:
896         dbg("Get selection mode : [%s]",
897                         (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
898
899         /* Free resource*/
900         tcore_at_tok_free(tokens);
901 }
902
903 static void on_response_network_set_plmn_selection_mode(TcorePending *p,
904         int data_len, const void *data, void *user_data)
905 {
906         const struct tcore_at_response *at_resp = data;
907         struct tresp_network_set_plmn_selection_mode nw_resp;
908         UserRequest *ur = NULL;
909
910         dbg("Enter");
911
912         if (at_resp) {
913                 if (at_resp->success) {
914                         dbg("RESPONSE OK");
915                         nw_resp.result = TCORE_RETURN_SUCCESS;
916                 } else {
917                         err("RESPONSE NOK");
918                         if (at_resp->lines)
919                                 err("CME Error[%s]", (char *)at_resp->lines->data);
920                                 nw_resp.result = TCORE_RETURN_FAILURE;
921                 }
922         } else {
923                 err("Response: [NOK]");
924         }
925
926         ur = tcore_pending_ref_user_request(p);
927         if (ur) {
928                 tcore_user_request_send_response(ur,
929                         TRESP_NETWORK_SET_PLMN_SELECTION_MODE,
930                         sizeof(struct tresp_network_set_plmn_selection_mode), &nw_resp);
931         } else {
932                 err("ur is NULL");
933         }
934 }
935
936 static void on_response_network_get_serving_network(TcorePending *p,
937         int data_len, const void *data, void *user_data)
938 {
939         const struct tcore_at_response *at_resp = data;
940         struct tresp_network_get_serving_network nw_resp = {0, };
941         enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
942         UserRequest *ur = NULL;
943         GSList *tokens = NULL;
944         char *plmn = NULL;
945         CoreObject *co_network = tcore_pending_ref_core_object(p);
946         guint lac = 0;
947
948         dbg("Enter");
949
950         if (at_resp && at_resp->success) {
951                 const gchar *line;
952                 int num_lines, count;
953                 char *local_data = NULL;
954
955                 if (!at_resp->lines) {
956                         err("invalid response received");
957                         nw_resp.result = TCORE_RETURN_FAILURE;
958                         goto END;
959                 }
960
961                 dbg("RESPONSE OK");
962                 nw_resp.result = TCORE_RETURN_SUCCESS;
963
964                 num_lines = g_slist_length(at_resp->lines);
965                 dbg("number of lines: %d", num_lines);
966
967                 for (count = 0; count < num_lines; count++) {
968                         line = g_slist_nth_data(at_resp->lines, count);
969                         tokens = tcore_at_tok_new(line);
970                         /* mode */
971                         if ((local_data = tcore_at_tok_nth(tokens, 0)))
972                                 dbg("mode  : %s", local_data);
973
974                         /* format */
975                         if ((local_data = tcore_at_tok_nth(tokens, 1)))
976                                 dbg("format  : %s", local_data);
977
978                         /*plmn */
979                         if ((plmn = tcore_at_tok_nth(tokens, 2))) {
980                                 dbg("plmn  : %s", plmn);
981                                 g_strlcpy(nw_resp.plmn, plmn, 6);
982                                 tcore_network_set_plmn(co_network, nw_resp.plmn);
983                                 if (!g_strcmp0(nw_resp.plmn, "11111")) {
984                                         /* In case of emulator, need to show "SDK" on indicator instead of "11111" */
985                                         tcore_network_set_network_name(co_network, TCORE_NETWORK_NAME_TYPE_FULL, "SDK");
986                                 }
987                         }
988
989                         /* act */
990                         if ((local_data = tcore_at_tok_nth(tokens, 3))) {
991                                 gint idx = atoi(local_data);
992                                 dbg("AcT  : %s", local_data);
993                                 if (idx >= 0 && idx < AT_COPS_ACT_MAX)
994                                         act = lookup_tbl_access_technology[idx];
995                                 else
996                                         act = NETWORK_ACT_UNKNOWN;
997                         }
998                         nw_resp.act = act;
999
1000                         (void)tcore_network_get_lac(co_network, &lac);
1001                         dbg("lac  : %x", lac);
1002
1003                         nw_resp.gsm.lac = lac;
1004
1005                         tcore_at_tok_free(tokens);
1006                 }
1007         }
1008
1009         ur = tcore_pending_ref_user_request(p);
1010         if (ur) {
1011                 tcore_user_request_send_response(ur,
1012                         TRESP_NETWORK_GET_SERVING_NETWORK,
1013                         sizeof(struct tresp_network_get_serving_network), &nw_resp);
1014         } else {
1015                 struct tnoti_network_change network_change;
1016
1017                 memset(&network_change, 0, sizeof(struct tnoti_network_change));
1018                 memcpy(network_change.plmn, nw_resp.plmn, 6);
1019                 network_change.act = act;
1020                 network_change.gsm.lac = lac;
1021
1022                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(p)),
1023                                                                         tcore_pending_ref_core_object(p),
1024                                                                         TNOTI_NETWORK_CHANGE,
1025                                                                         sizeof(struct tnoti_network_change), &network_change);
1026                 }
1027
1028 END:
1029         dbg("Get serving network : [%s]",
1030                         (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
1031 }
1032
1033 /* Requests */
1034 static TReturn search_network(CoreObject *co_network, UserRequest *ur)
1035 {
1036         TReturn ret = TCORE_RETURN_FAILURE;
1037
1038         dbg("Entry");
1039
1040         /* Send Request to modem */
1041         ret = tcore_prepare_and_send_at_request(co_network,
1042                 "AT+COPS=?", "+COPS",
1043                 TCORE_AT_SINGLELINE,
1044                 ur,
1045                 on_response_network_search, NULL,
1046                 on_send_at_request, NULL,
1047                 0, NULL, NULL);
1048         dbg("ret: [0x%x]", ret);
1049
1050         return ret;
1051 }
1052
1053
1054 static TReturn set_plmn_selection_mode(CoreObject *co_network, UserRequest *ur)
1055 {
1056         gchar *at_cmd;
1057         struct treq_network_set_plmn_selection_mode *mode_info = NULL;
1058         TReturn ret = TCORE_RETURN_FAILURE;
1059
1060         dbg("Entry");
1061
1062         mode_info = (struct treq_network_set_plmn_selection_mode *)tcore_user_request_ref_data(ur, 0);
1063
1064         if (mode_info->mode == NETWORK_SELECT_MODE_AUTOMATIC) {
1065                 at_cmd = g_strdup_printf("AT+COPS=0");
1066                 dbg(" Mode - Automatic: -- %s", at_cmd);
1067         } else {
1068                 gint act;
1069
1070                 switch (mode_info->act) {
1071                 case NETWORK_ACT_GSM:
1072                 case NETWORK_ACT_GPRS:
1073                 case NETWORK_ACT_EGPRS:
1074                         act = 0;
1075                 break;
1076
1077                 case NETWORK_ACT_UMTS:
1078                 case NETWORK_ACT_GSM_UTRAN:
1079                         act = 2;
1080                 break;
1081
1082                 default:
1083                         err("Unsupported AcT: [%d]", mode_info->act);
1084                         return ret;
1085                 }
1086                 at_cmd = g_strdup_printf("AT+COPS=1, 2, \"%s\", %d", mode_info->plmn, act);
1087         }
1088
1089         /* Send Request to modem */
1090         ret = tcore_prepare_and_send_at_request(co_network, at_cmd, NULL,
1091                 TCORE_AT_NO_RESULT,
1092                 ur,
1093                 on_response_network_set_plmn_selection_mode, NULL,
1094                 on_send_at_request, NULL, 0, NULL, NULL);
1095         dbg("ret: [0x%x]", ret);
1096
1097         /* Free resources */
1098         g_free(at_cmd);
1099
1100         return ret;
1101 }
1102
1103 static TReturn get_plmn_selection_mode(CoreObject *co_network, UserRequest *ur)
1104 {
1105         TReturn ret = TCORE_RETURN_FAILURE;
1106
1107         dbg("Entry");
1108
1109         /* Send Request to modem */
1110         ret = tcore_prepare_and_send_at_request(co_network,
1111                 "AT+COPS?", "+COPS",
1112                 TCORE_AT_SINGLELINE,
1113                 ur,
1114                 on_response_network_get_plmn_selection_mode, NULL,
1115                 on_send_at_request, NULL, 0, NULL, NULL);
1116         dbg("ret: [0x%x]", ret);
1117
1118         return ret;
1119 }
1120
1121 static TReturn get_serving_network(CoreObject *co_network, UserRequest *ur)
1122 {
1123         TReturn ret = TCORE_RETURN_FAILURE;
1124
1125         dbg("Entry");
1126
1127         /* Send Request to modem */
1128         ret = tcore_prepare_and_send_at_request(co_network,
1129                 "AT+COPS?", "+COPS",
1130                 TCORE_AT_SINGLELINE,
1131                 ur,
1132                 on_response_network_get_serving_network, NULL,
1133                 on_send_at_request, NULL, 0, NULL, NULL);
1134         dbg("ret: [0x%x]", ret);
1135
1136         return ret;
1137 }
1138
1139 static TReturn get_default_subscription(CoreObject *co, UserRequest *ur)
1140 {
1141         struct tresp_network_get_default_subs resp_data = {0, };
1142         TReturn ret = TCORE_RETURN_FAILURE;
1143         Server *server;
1144         Storage *strg = NULL;
1145         TcorePlugin *plugin = tcore_object_ref_plugin(co);
1146
1147         dbg("Enter");
1148
1149         server = tcore_plugin_ref_server(plugin);
1150         strg = tcore_server_find_storage(server, "vconf");
1151
1152         /* VCONFKEY is aligned to req_data->current_network type */
1153         resp_data.default_subs = tcore_storage_get_int(strg,
1154                         STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_SERVICE_INT);
1155
1156         resp_data.result = TCORE_RETURN_SUCCESS;
1157
1158         /* Send Response */
1159         ret = tcore_user_request_send_response(ur,
1160                 TRESP_NETWORK_GET_DEFAULT_SUBSCRIPTION,
1161                 sizeof(struct tresp_network_get_default_subs), &resp_data);
1162
1163         dbg("ret: [0x%x]", ret);
1164         return ret;
1165 }
1166
1167 static TReturn get_default_data_subscription(CoreObject *co, UserRequest *ur)
1168 {
1169         struct tresp_network_get_default_data_subs resp = {0, };
1170         Server *server;
1171         Storage *strg = NULL;
1172         TcorePlugin *plugin = tcore_object_ref_plugin(co);
1173         TReturn ret;
1174
1175         dbg("Enter");
1176
1177         server = tcore_plugin_ref_server(plugin);
1178         strg = tcore_server_find_storage(server, "vconf");
1179
1180         resp.default_subs = tcore_storage_get_int(strg, STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_DATA_SERVICE_INT);
1181         dbg("Defualt data Subscription: [%d]", resp.default_subs);
1182
1183         resp.result = TCORE_RETURN_SUCCESS;
1184
1185         ret = tcore_user_request_send_response(ur,
1186                 TRESP_NETWORK_GET_DEFAULT_DATA_SUBSCRIPTION,
1187                 sizeof(struct tresp_network_get_default_data_subs), &resp);
1188         if (TCORE_RETURN_SUCCESS ==  ret)
1189                 tcore_user_request_unref(ur);
1190
1191         return ret;
1192 }
1193
1194 /** Network operations */
1195 static struct tcore_network_operations network_ops = {
1196         .search = search_network,
1197         .set_plmn_selection_mode = set_plmn_selection_mode,
1198         .get_plmn_selection_mode = get_plmn_selection_mode,
1199         .set_service_domain = NULL,
1200         .get_service_domain = NULL,
1201         .set_band = NULL,
1202         .get_band = NULL,
1203         .set_preferred_plmn = NULL,
1204         .get_preferred_plmn = NULL,
1205         .set_order = NULL,
1206         .get_order = NULL,
1207         .set_power_on_attach = NULL,
1208         .get_power_on_attach = NULL,
1209         .set_cancel_manual_search = NULL,
1210         .get_serving_network = get_serving_network,
1211         .get_default_subscription = get_default_subscription,
1212         .get_default_data_subscription = get_default_data_subscription,
1213 };
1214
1215 gboolean s_network_init(TcorePlugin *p, TcoreHal *h)
1216 {
1217         CoreObject *co_network;
1218
1219         co_network = tcore_network_new(p, "umts_network", &network_ops, h);
1220         if (!co_network) {
1221                 err("Core object is NULL");
1222                 return FALSE;
1223         }
1224
1225         /* Add Callbacks */
1226         tcore_object_add_callback(co_network,
1227                 "+CREG:",
1228                 on_notification_atmodem_cs_network_info, NULL);
1229         tcore_object_add_callback(co_network,
1230                 "+CGREG:",
1231                 on_notification_atmodem_ps_network_info, NULL);
1232         tcore_object_add_callback(co_network,
1233                 "+CIEV:",
1234                 on_notification_atmodem_network_rssi, NULL);
1235
1236         /* Add notification hook */
1237         tcore_server_add_notification_hook(tcore_plugin_ref_server(p),
1238                 TNOTI_SIM_STATUS,
1239                 on_hook_sim_init, co_network);
1240
1241         _insert_mcc_mnc_oper_list(p, co_network);
1242
1243         return TRUE;
1244 }
1245
1246 void s_network_exit(TcorePlugin *p)
1247 {
1248         CoreObject *co_network;
1249
1250         if (!p) {
1251                 err("Plugin is NULL");
1252                 return;
1253         }
1254
1255         co_network = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_NETWORK);
1256
1257         tcore_network_free(co_network);
1258 }
1259