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