Code Sync up from tizen_2.4
[platform/core/telephony/tel-plugin-imc.git] / src / imc_network.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Harish Bishnoi <hbishnoi@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
25 #include <glib.h>
26
27 #include <tcore.h>
28 #include <hal.h>
29 #include <core_object.h>
30 #include <plugin.h>
31 #include <user_request.h>
32 #include <queue.h>
33 #include <co_network.h>
34 #include <co_ps.h>
35 #include <server.h>
36 #include <storage.h>
37 #include <util.h>
38 #include <at.h>
39 #include <vconf.h>
40
41 #include "imc_common.h"
42 #include "imc_network.h"
43
44 #define AT_CREG_STAT_NOT_REG    0 /* not registered, MT is not currently searching a new operator to register to */
45 #define AT_CREG_STAT_REG_HOME   1 /* registered, home network */
46 #define AT_CREG_STAT_SEARCHING  2 /* not registered, but MT is currently searching a new operator to register to */
47 #define AT_CREG_STAT_REG_DENIED 3 /* registration denied */
48 #define AT_CREG_STAT_UNKNOWN    4 /* unknown */
49 #define AT_CREG_STAT_REG_ROAM   5 /* registered, roaming */
50
51 #define AT_COPS_MODE_AUTOMATIC  0 /* automatic (<oper> field is ignored) */
52 #define AT_COPS_MODE_MANUAL 1 /* manual (<oper> field shall be present, and <AcT> optionally) */
53 #define AT_COPS_MODE_DEREGISTER 2 /* deregister from network */
54 #define AT_COPS_MODE_SET_ONLY   3 /* set only <format> */
55 #define AT_COPS_MODE_MANUAL_AUTOMATIC 4 /*automatic - manual*/
56
57 #define AT_COPS_FORMAT_LONG_ALPHANUMERIC    0 /* long format alphanumeric <oper> */
58 #define AT_COPS_FORMAT_SHORT_ALPHANUMERIC   1 /* short format alphanumeric <oper> */
59 #define AT_COPS_FORMAT_NUMERIC          2 /* numeric <oper> */
60
61 #define AT_COPS_ACT_GSM         0   /* GSM */
62 #define AT_COPS_ACT_GSM_COMPACT     1   /* GSM Compact */
63 #define AT_COPS_ACT_UTRAN       2   /* UTRAN */
64 #define AT_COPS_ACT_GSM_EGPRS       3   /* GSM w/EGPRS */
65 #define AT_COPS_ACT_UTRAN_HSDPA     4   /* UTRAN w/HSDPA */
66 #define AT_COPS_ACT_UTRAN_HSUPA     5   /* UTRAN w/HSUPA */
67 #define AT_COPS_ACT_UTRAN_HSDPA_HSUPA   6   /* UTRAN w/HSDPA and HSUPA */
68 #define AT_COPS_ACT_E_UTRAN     7   /* E-UTRAN */
69
70 #define AT_GSM_XBANDSEL_AUTOMATIC 0
71 #define AT_GSM_XBANDSEL_1800 1800
72 #define AT_GSM_XBANDSEL_1900 1900
73 #define AT_GSM_XBANDSEL_900 900
74 #define AT_GSM_XBANDSEL_850 850
75 #define AT_GSM_XBANDSEL_450 450
76 #define AT_GSM_XBANDSEL_480 480
77 #define AT_GSM_XBANDSEL_750 750
78 #define AT_GSM_XBANDSEL_380 380
79 #define AT_GSM_XBANDSEL_410 410
80
81 #define AT_XRAT_GSM 0
82 #define AT_XRAT_DUAL 1
83 #define AT_XRAT_UMTS 2
84
85 #define MAX_NETWORKS_PREF_PLMN_SUPPORT 150
86 #define MAX_NETWORKS_MANUAL_SEARCH_SUPPORT 20
87
88 #define VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS  "db/telephony/dualsim/default_data_service"
89
90 typedef enum {
91         IMC_NETWORK_SEARCH_STATE_NO_SEARCH,
92         IMC_NETWORK_SEARCH_STATE_IN_PROGRESS,
93         IMC_NETWORK_SEARCH_STATE_CANCELLED
94 } ImcNetworkSearchState;
95
96 typedef struct {
97         ImcNetworkSearchState search_state;
98 } CustomData;
99
100 static unsigned int lookup_tbl_net_status[] = {
101         [AT_CREG_STAT_NOT_REG] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
102         [AT_CREG_STAT_REG_HOME] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
103         [AT_CREG_STAT_SEARCHING] = NETWORK_SERVICE_DOMAIN_STATUS_SEARCH,
104         [AT_CREG_STAT_REG_DENIED] = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY,
105         [AT_CREG_STAT_UNKNOWN] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
106         [AT_CREG_STAT_REG_ROAM] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
107 };
108
109 static unsigned int lookup_tbl_access_technology[] = {
110         [AT_COPS_ACT_GSM] = NETWORK_ACT_GSM,
111         [AT_COPS_ACT_GSM_COMPACT] = NETWORK_ACT_GSM,
112         [AT_COPS_ACT_UTRAN] = NETWORK_ACT_UTRAN,
113         [AT_COPS_ACT_GSM_EGPRS] = NETWORK_ACT_EGPRS,
114         [AT_COPS_ACT_UTRAN_HSDPA] = NETWORK_ACT_UTRAN,
115         [AT_COPS_ACT_UTRAN_HSUPA] = NETWORK_ACT_UTRAN,
116         [AT_COPS_ACT_UTRAN_HSDPA_HSUPA] = NETWORK_ACT_UTRAN,
117         [AT_COPS_ACT_E_UTRAN] = NETWORK_ACT_GSM_UTRAN,
118 };
119
120 static gboolean get_serving_network(CoreObject *o, UserRequest *ur);
121
122
123 static void on_confirmation_network_message_send(TcorePending *p, gboolean result, void *user_data)
124 {
125         dbg("on_confirmation_modem_message_send - msg out from queue.\n");
126
127         if (result == FALSE) {
128                 /* Fail */
129                 dbg("SEND FAIL");
130         } else {
131                 dbg("SEND OK");
132         }
133 }
134
135 static void nwk_prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, UserRequest *ur, TcorePendingResponseCallback callback)
136 {
137         TcoreATRequest *req = NULL;
138         TcoreHal *hal;
139         TcorePending *pending = NULL;
140         TReturn ret;
141
142         hal = tcore_object_get_hal(co);
143
144         pending = tcore_pending_new(co, 0);
145         req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
146
147         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
148
149         tcore_pending_set_request_data(pending, 0, req);
150         tcore_pending_set_response_callback(pending, callback, req->cmd);
151         tcore_pending_link_user_request(pending, ur);
152         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
153
154         ret = tcore_hal_send_request(hal, pending);
155
156         if (ret != TCORE_RETURN_SUCCESS)
157                 err("Failed to send AT request - ret: [0x%x]", ret);
158
159         return;
160 }
161
162
163 static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *o)
164 {
165         Server *s;
166         Storage *strg;
167         void *handle;
168         char query[255] = { 0, };
169         GHashTableIter iter;
170         gpointer key, value;
171         GHashTable *result = NULL, *row = NULL;
172         struct tcore_network_operator_info *noi = NULL;
173         int count = 0;
174
175         s = tcore_plugin_ref_server(p);
176         strg = tcore_server_find_storage(s, "database");
177
178         handle = tcore_storage_create_handle(strg, "/opt/dbspace/.mcc_mnc_oper_list.db");
179         if (!handle) {
180                 dbg("fail to create database handle");
181                 return;
182         }
183
184         snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list");
185
186         result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
187                                                                    (GDestroyNotify) g_hash_table_destroy);
188
189         tcore_storage_read_query_database(strg, handle, query, NULL, result, 4);
190
191         g_hash_table_iter_init(&iter, result);
192         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
193                 row = value;
194
195                 noi = calloc(sizeof(struct tcore_network_operator_info), 1);
196
197                 snprintf(noi->mcc, 4, "%s", (char *) g_hash_table_lookup(row, "1"));
198                 snprintf(noi->mnc, 4, "%s", (char *) g_hash_table_lookup(row, "2"));
199                 snprintf(noi->name, 41, "%s", (char *) g_hash_table_lookup(row, "3"));
200                 snprintf(noi->country, 4, "%s", (char *) g_hash_table_lookup(row, "0"));
201
202                 tcore_network_operator_info_add(o, noi);
203                 g_free(noi);
204                 noi = NULL;
205
206                 count++;
207         }
208
209         dbg("count = %d", count);
210
211         g_hash_table_destroy(result);
212
213         tcore_storage_remove_handle(strg, handle);
214 }
215
216 static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type,
217                                                                                                                          int domain, int act, int cs_status, int ps_status)
218 {
219         enum telephony_network_service_type ret;
220
221         ret = prev_type;
222
223         switch (act) {
224         case NETWORK_ACT_UNKNOWN:
225                 ret = NETWORK_SERVICE_TYPE_UNKNOWN;
226                 break;
227
228         case NETWORK_ACT_GSM:
229                 if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE && domain == NETWORK_SERVICE_DOMAIN_CS)
230                         ret = NETWORK_SERVICE_TYPE_2_5G_EDGE;
231                 else
232                         ret = NETWORK_SERVICE_TYPE_2G;
233                 break;
234
235         case NETWORK_ACT_EGPRS:
236                 return NETWORK_SERVICE_TYPE_2_5G_EDGE;
237                 break;
238
239         case NETWORK_ACT_UMTS:
240                 ret = NETWORK_SERVICE_TYPE_3G;
241                 break;
242         }
243
244         if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) {
245                 ret = NETWORK_SERVICE_TYPE_NO_SERVICE;
246         } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) {
247                 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
248                         /* no change */
249                 } else {
250                         ret = NETWORK_SERVICE_TYPE_SEARCH;
251                 }
252         } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) {
253                 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
254                         /* no change */
255                 } else {
256                         ret = NETWORK_SERVICE_TYPE_EMERGENCY;
257                 }
258         }
259
260         return ret;
261 }
262
263 static void _ps_set(TcorePlugin *p, int status)
264 {
265         CoreObject *co_ps;
266
267         co_ps = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_PS);
268         if (co_ps == NULL) {
269                 err("No PS Core Object on plugin");
270                 return;
271         }
272
273         if (status == NETWORK_SERVICE_DOMAIN_STATUS_FULL)
274                 tcore_ps_set_online(co_ps, TRUE);
275         else
276                 tcore_ps_set_online(co_ps, FALSE);
277 }
278
279 static void on_timeout_search_network(TcorePending *p, void *user_data)
280 {
281         UserRequest *ur;
282         struct tresp_network_search resp;
283         CustomData *custom_data;
284
285         dbg("TIMEOUT !!!!! pending=%p", p);
286
287         memset(&resp, 0, sizeof(struct tresp_network_search));
288
289         resp.result = TCORE_RETURN_FAILURE;
290         resp.list_count = 0;
291
292         custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p));
293         custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
294
295         ur = tcore_pending_ref_user_request(p);
296         if (ur) {
297                 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &resp);
298         }
299 }
300
301 static void on_response_set_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data)
302 {
303         UserRequest *ur;
304         const TcoreATResponse *atResp = data;
305         // GSList *tokens = NULL;
306         // char * line = NULL;
307         struct tresp_network_set_plmn_selection_mode resp = {0};
308
309         if (atResp->success > 0) {
310                 dbg("RESPONSE OK");
311                 resp.result = TCORE_RETURN_SUCCESS;
312         } else {
313                 dbg("RESPONSE NOK");
314                 resp.result = TCORE_RETURN_FAILURE;
315         }
316
317         ur = tcore_pending_ref_user_request(p);
318         if (ur) {
319                 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_set_plmn_selection_mode), &resp);
320         }
321 }
322
323 static void on_response_get_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data)
324 {
325         UserRequest *ur;
326         struct tresp_network_get_plmn_selection_mode resp = {0};
327         const TcoreATResponse *atResp = data;
328         GSList *tokens = NULL;
329         char *line = NULL;
330         int mode = 0;
331
332         resp.result = TCORE_RETURN_FAILURE;
333
334         if (atResp->success > 0) {
335                 dbg("RESPONSE OK");
336                 /* Format of output
337                 +COPS: <mode>[,<format>,<oper>[,< AcT>]]
338                 */
339
340                 if (atResp->lines) {
341                         line = (char *) atResp->lines->data;
342                         tokens = tcore_at_tok_new(line);
343                         if (g_slist_length(tokens) < 1) {
344                                 msg("invalid message");
345                                 goto OUT;
346                         }
347                         mode = atoi(tcore_at_tok_nth(tokens, 0));
348                         dbg("mode = %d", mode);
349
350                         switch (mode) {
351                         case AT_COPS_MODE_AUTOMATIC:
352                                 resp.mode = NETWORK_SELECT_MODE_AUTOMATIC;
353                                 break;
354
355                         case AT_COPS_MODE_MANUAL:
356                         case AT_COPS_MODE_MANUAL_AUTOMATIC:
357                                 resp.mode = NETWORK_SELECT_MODE_MANUAL;
358                                 break;
359
360                         case AT_COPS_MODE_DEREGISTER:
361                         case AT_COPS_MODE_SET_ONLY:
362                                 resp.result = TCORE_RETURN_FAILURE;
363                                 goto OUT;
364                         }
365                         resp.result = TCORE_RETURN_SUCCESS;
366                 }
367         } else {
368                 dbg("RESPONSE NOK");
369                 resp.result = TCORE_RETURN_FAILURE;
370         }
371
372 OUT:
373         ur = tcore_pending_ref_user_request(p);
374         if (ur) {
375                 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_get_plmn_selection_mode), &resp);
376         }
377
378         if (tokens != NULL)
379                 tcore_at_tok_free(tokens);
380
381         return;
382 }
383
384 static void on_response_search_network(TcorePending *p, int data_len, const void *data, void *user_data)
385 {
386         UserRequest *ur;
387         struct tresp_network_search resp;
388         int i = 0;
389         char *line = NULL;
390         const TcoreATResponse *atResp = data;
391         GSList *tokens = NULL;
392         GSList *network_token = NULL;
393         int AcT = 0;
394         char *temp_plmn_info = NULL;
395         char *alpha_name = NULL;
396         char *pResp = NULL;
397         int num_network_avail = 0;
398         CustomData *custom_data;
399
400         memset(&resp, 0, sizeof(struct tresp_network_search));
401         resp.result = TCORE_RETURN_FAILURE;
402         resp.list_count = 0;
403
404         custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p));
405         if (!custom_data) {
406                 err("Network Search Custom Data is Null");
407                 return;
408         }
409
410         if (atResp->success > 0) {
411                 dbg("RESPONSE OK");
412
413                 /* If Request is Cancelled then return back SUCCESS/SEARCH_CANCELLED */
414                 if (custom_data->search_state
415                                 == IMC_NETWORK_SEARCH_STATE_CANCELLED) {
416                         dbg("Network Search has been Cancelled!!!");
417                         goto OUT;
418                 }
419
420                 if (atResp->lines) {
421                         line = (char *) atResp->lines->data;
422                         tokens = tcore_at_tok_new(line);
423                         num_network_avail = g_slist_length(tokens);
424                         dbg(" length of tokens is %d\n", num_network_avail);
425                         if (num_network_avail < 1) {
426                                 msg("invalid message");
427                                 goto OUT;
428                         }
429                 }
430
431                 resp.result = TCORE_RETURN_SUCCESS;
432
433                 /*
434                  * +COPS: [list of supported (<stat>,long alphanumeric <oper>,
435                  *      short alphanumeric <oper>,numeric <oper>[,<AcT>])s]
436                  *      [,,(list of supported <mode>s),(list of supported <format>s)]
437                  */
438                 for (i = 0; ((i < num_network_avail) && (i < MAX_NETWORKS_MANUAL_SEARCH_SUPPORT)); i++) {
439                         network_token = tcore_at_tok_new(g_slist_nth_data(tokens, i));
440
441                         pResp = (tcore_at_tok_nth(network_token, 0));
442                         if (pResp != NULL) {
443                                 dbg("status : %s", pResp);
444                                 resp.list[i].status = (enum telephony_network_plmn_status) atoi(pResp);
445                         }
446
447                         if ((pResp = tcore_at_tok_nth(network_token, 1))) {     /* Long Alpha name */
448                                 dbg("Long Alpha name : %s", pResp);
449
450                                 if (strlen(pResp) > 0)
451                                         /* Strip off starting quote & ending quote */
452                                         strncpy(resp.list[i].name, pResp + 1, strlen(pResp) - 2);
453                         }
454
455                         if ((pResp = tcore_at_tok_nth(network_token, 2))) {
456                                 dbg("Short Aplha name : %s", pResp);
457                                 /* Short Aplha name */
458                                 /* Strip off starting quote & ending quote */
459                                 if (strlen(pResp) > 0)
460                                         strncpy(resp.list[i].name, pResp + 1, strlen(pResp) - 2);
461                         }
462
463                         /* PLMN ID */
464                         pResp = tcore_at_tok_nth(network_token, 3);
465                         if (pResp != NULL) {
466                                 dbg("PLMN ID : %s", pResp);
467                                 temp_plmn_info = tcore_at_tok_extract((const char *)pResp);
468                                 strncpy(resp.list[i].plmn, temp_plmn_info, 6);
469                                 resp.list[i].plmn[6] = '\0';
470                         }
471
472                         /* Parse Access Technology */
473                         if ((pResp = tcore_at_tok_nth(network_token, 4))) {
474                                 if (strlen(pResp) > 0) {
475                                         AcT = atoi(pResp);
476
477                                         if (0 == AcT)
478                                                 resp.list[i].act = NETWORK_ACT_GSM;
479                                         else if (2 == AcT)
480                                                 resp.list[i].act = NETWORK_ACT_UMTS;
481                                 }
482                         }
483
484                         dbg("Operator [%d] :: stat = %d, Name =%s, plmnId = %s, AcT=%d\n", resp.list_count, resp.list[i].status, resp.list[i].name, resp.list[i].plmn, resp.list[i].act);
485                         resp.list_count++;
486
487                         tcore_at_tok_free(network_token);
488                         g_free(alpha_name);
489                         g_free(temp_plmn_info);
490                 }
491         } else {
492                 dbg("RESPONSE NOK");
493                 resp.result = TCORE_RETURN_FAILURE;
494         }
495
496 OUT:
497         custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
498
499         ur = tcore_pending_ref_user_request(p);
500         if (ur) {
501                 tcore_user_request_send_response(ur,
502                         TRESP_NETWORK_SEARCH,
503                         sizeof(struct tresp_network_search), &resp);
504         }
505
506         /* Free tokens */
507         tcore_at_tok_free(tokens);
508 }
509
510 static void on_response_set_umts_band(TcorePending *p, int data_len, const void *data, void *user_data)
511 {
512         const TcoreATResponse *atResp = data;
513
514         dbg("On Response Set UMTS Band");
515
516         if (atResp->success > 0) {
517                 dbg("Response OK");
518         } else {
519                 dbg("Response NOK");
520         }
521
522         dbg("Wait for response of XRAT before sending final band setting response to AP");
523         return;
524 }
525
526
527 static void on_response_set_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data)
528 {
529         const TcoreATResponse *atResp = data;
530
531         dbg("On Response Set GSM Band");
532         if (atResp->success > 0) {
533                 dbg("Response OK");
534         } else {
535                 dbg("Response NOK");
536         }
537
538         dbg("Wait for response of XRAT before sending final band setting response to AP");
539         return;
540 }
541
542 static void on_response_get_umts_band(TcorePending *p, int data_len, const void *data, void *user_data)
543 {
544         const TcoreATResponse *atResp = data;
545         GSList *tokens = NULL;
546         const char *line = NULL;
547         int total_umts_bands = 0;
548         int i = 0;
549         char *band_token = NULL;
550         char umts_band[20] = {0};
551         char umts_band_1 = 0;
552         char umts_band_2 = 0;
553         char umts_band_5 = 0;
554         UserRequest *ur = NULL;
555         struct tresp_network_get_band resp = {0};
556
557         dbg("Entry on_response_get_umts_band");
558
559         resp.mode = NETWORK_BAND_MODE_PREFERRED;
560         resp.result = TCORE_RETURN_SUCCESS;
561
562         if (atResp->success > 0) {
563                 dbg("RESPONSE OK");
564                 if (atResp->lines) {
565                         line = (char *) atResp->lines->data;
566                         tokens = tcore_at_tok_new(line);
567                         total_umts_bands = g_slist_length(tokens);
568                         dbg("Total UMTS bands enabled are : %d\n", total_umts_bands);
569                         if (total_umts_bands < 1) {
570                                 goto OUT;
571                         }
572                 }
573         } else {
574                 dbg("RESPONSE NOK");
575                 goto OUT;
576         }
577
578         for (i = 0; i < total_umts_bands; i++) {
579                 band_token = tcore_at_tok_nth(tokens, i);
580
581                 if (band_token == NULL)
582                         continue;
583
584                 memset(umts_band, 0x00, sizeof(umts_band));
585
586                 if (atoi(band_token) == 0) { /* 0 means UMTS automatic */
587                         umts_band_1 = umts_band_2 = umts_band_5 = TRUE;
588                         break;
589                 }
590
591                 /* Strip off starting quotes & ending quotes */
592                 strncpy(umts_band, band_token + 1, strlen(band_token) - 2);
593
594                 if (!strcmp(umts_band, "UMTS_BAND_I")) {
595                         umts_band_1 = TRUE;
596                 } else if (!strcmp(umts_band, "UMTS_BAND_II")) {
597                         umts_band_2 = TRUE;
598                 } else if (!strcmp(umts_band, "UMTS_BAND_II")) {
599                         umts_band_5 = TRUE;
600                 } else {
601                         /* Telephony is not interest */
602                         dbg("Telephony is not interested in %s band", umts_band);
603                 }
604         }
605
606 OUT:
607         if ((umts_band_1) && (umts_band_2) && (umts_band_5)) {
608                 resp.band = NETWORK_BAND_TYPE_WCDMA;
609         } else if (umts_band_1) {
610                 resp.band = NETWORK_BAND_TYPE_WCDMA2100;
611         } else if (umts_band_2) {
612                 resp.band = NETWORK_BAND_TYPE_WCDMA1900;
613         } else if (umts_band_5) {
614                 resp.band = NETWORK_BAND_TYPE_WCDMA850;
615         } else {
616                 resp.result = TCORE_RETURN_FAILURE;
617         }
618
619         dbg("Final resp.band sent to TS = %d", resp.band);
620
621         ur = tcore_pending_ref_user_request(p);
622         if (ur) {
623                 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
624         }
625
626         if (tokens != NULL)
627                 tcore_at_tok_free(tokens);
628
629         dbg("Exit on_response_get_umts_band");
630         return;
631 }
632
633 static void on_response_get_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data)
634 {
635         struct tresp_network_get_band resp = {0};
636         const TcoreATResponse *atResp = data;
637         GSList *tokens = NULL;
638         int total_gsm_bands = 0;
639         const char *line = NULL;
640         int i = 0;
641         char *band_token = NULL;
642         UserRequest *ur = NULL;
643         int gsm_850 = 0;
644         int gsm_900 = 0;
645         int gsm_1800 = 0;
646         int gsm_1900 = 0;
647
648         dbg("Entry on_response_get_gsm_band");
649
650         resp.mode = NETWORK_BAND_MODE_PREFERRED;
651         resp.result = TCORE_RETURN_SUCCESS;
652
653         if (atResp->success > 0) {
654                 dbg("RESPONSE OK");
655                 if (atResp->lines) {
656                         line = (char *) atResp->lines->data;
657                         tokens = tcore_at_tok_new(line);
658                         total_gsm_bands = g_slist_length(tokens);
659                         dbg("Total GSM bands enabled are : %d\n", total_gsm_bands);
660                         if (total_gsm_bands < 1)
661                                 goto OUT;
662                 }
663         }
664
665         for (i = 0; i < total_gsm_bands; i++) {
666                 band_token = tcore_at_tok_nth(tokens, i);
667
668                 if (band_token == NULL)
669                         continue;
670
671                 if (atoi(band_token) == 0) { /* 0 means GSM automatic */
672                         gsm_850 = gsm_900 = gsm_1800 = gsm_1900 = TRUE;
673                         break;
674                 }
675
676                 switch (atoi(band_token)) {
677                 case AT_GSM_XBANDSEL_850:
678                         gsm_850 = TRUE;
679                         break;
680
681                 case AT_GSM_XBANDSEL_900:
682                         gsm_900 = TRUE;
683                         break;
684
685                 case AT_GSM_XBANDSEL_1800:
686                         gsm_1800 = TRUE;
687                         break;
688
689                 case AT_GSM_XBANDSEL_1900:
690                         gsm_1900 = TRUE;
691                         break;
692
693                 default:
694                         break;
695                 }
696         }
697
698 OUT:
699
700         if (gsm_850 && gsm_900 && gsm_1800 && gsm_1900) {
701                 resp.band = NETWORK_BAND_TYPE_GSM;
702         } else if (gsm_850 && gsm_1900) {
703                 resp.band = NETWORK_BAND_TYPE_GSM_850_1900;
704         } else if (gsm_900 && gsm_1800) {
705                 resp.band = NETWORK_BAND_TYPE_GSM_900_1800;
706         } else if (gsm_1900) {
707                 resp.band = NETWORK_BAND_TYPE_GSM1900;
708         } else if (gsm_850) {
709                 resp.band = NETWORK_BAND_TYPE_GSM850;
710         } else if (gsm_1800) {
711                 resp.band = NETWORK_BAND_TYPE_GSM1800;
712         } else if (gsm_900) {
713                 resp.band = NETWORK_BAND_TYPE_GSM900;
714         } else {
715                 resp.result = TCORE_RETURN_FAILURE;
716         }
717
718         dbg("Final resp.band sent to TS = %d", resp.band);
719
720         ur = tcore_pending_ref_user_request(p);
721         if (ur) {
722                 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
723         }
724
725         if (tokens != NULL)
726                 tcore_at_tok_free(tokens);
727
728         dbg("Exit on_response_get_gsm_band");
729         return;
730 }
731
732
733 static void on_response_get_xrat(TcorePending *p, int data_len, const void *data, void *user_data)
734 {
735         TcoreHal *h = NULL;
736         UserRequest *ur = NULL;
737
738         TcoreATRequest *atreq;
739         char *cmd_str = NULL;
740         UserRequest *dup_ur = NULL;
741         const TcoreATResponse *atResp = data;
742         const char *line = NULL;
743         char *pResp = NULL;
744         GSList *tokens = NULL;
745         TcorePending *pending = NULL;
746         CoreObject *o = NULL;
747         int cp_xrat = 0;
748         struct tresp_network_get_band resp = {0};
749
750         dbg("Enter on_response_get_xrat !!");
751
752         resp.mode = NETWORK_BAND_MODE_PREFERRED;
753
754         ur = tcore_pending_ref_user_request(p);
755         h = tcore_object_get_hal(tcore_pending_ref_core_object(p));
756         o = tcore_pending_ref_core_object(p);
757
758         if (atResp->success > 0) {
759                 dbg("RESPONSE OK");
760                 if (atResp->lines) {
761                         line = (char *) atResp->lines->data;
762                         tokens = tcore_at_tok_new(line);
763                         if (g_slist_length(tokens) < 1) {
764                                 msg("invalid message");
765                                 goto OUT;
766                         }
767                 }
768
769                 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
770                         cp_xrat = atoi(pResp);
771
772                         if ((cp_xrat == AT_XRAT_DUAL)) {   /* mode is Dual, send reply to Telephony */
773                                 resp.result = TCORE_RETURN_SUCCESS;
774                                 resp.band = NETWORK_BAND_TYPE_ANY;
775
776                                 ur = tcore_pending_ref_user_request(p);
777                                 if (ur) {
778                                         tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
779                                 }
780                                 goto OUT;
781                         } else if ((cp_xrat == AT_XRAT_UMTS)) {
782                                 /* Get UMTS Band Information */
783                                 dup_ur = tcore_user_request_ref(ur); /* duplicate user request for AT+XUBANDSEL */
784                                 cmd_str = g_strdup_printf("AT+XUBANDSEL?");
785                                 atreq = tcore_at_request_new(cmd_str, "+XUBANDSEL", TCORE_AT_SINGLELINE);
786                                 pending = tcore_pending_new(o, 0);
787                                 tcore_pending_set_request_data(pending, 0, atreq);
788                                 tcore_pending_set_response_callback(pending, on_response_get_umts_band, NULL);
789                                 tcore_pending_link_user_request(pending, ur);
790                                 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
791                                 tcore_hal_send_request(h, pending);
792                                 g_free(cmd_str);
793                         } else if ((cp_xrat == AT_XRAT_UMTS)) {
794                                 /* Get GSM Band Information */
795                                 dup_ur = tcore_user_request_ref(ur); /* duplicate user request for AT+XBANDSEL */
796                                 cmd_str = g_strdup_printf("AT+XBANDSEL?");
797                                 atreq = tcore_at_request_new(cmd_str, "+XBANDSEL", TCORE_AT_SINGLELINE);
798                                 pending = tcore_pending_new(o, 0);
799                                 tcore_pending_set_request_data(pending, 0, atreq);
800                                 tcore_pending_set_response_callback(pending, on_response_get_gsm_band, NULL);
801                                 tcore_pending_link_user_request(pending, dup_ur);
802                                 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
803                                 tcore_hal_send_request(h, pending);
804                                 g_free(cmd_str);
805                         }
806                 }
807         } else {
808                 dbg("RESPONSE NOK");
809
810                 resp.result = TCORE_RETURN_FAILURE;
811                 resp.band = NETWORK_BAND_TYPE_ANY;
812
813                 ur = tcore_pending_ref_user_request(p);
814                 if (ur) {
815                         tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
816                 }
817         }
818 OUT:
819
820         if (tokens != NULL)
821                 tcore_at_tok_free(tokens);
822
823         dbg("Exit on_response_get_xrat !!");
824
825         return;
826 }
827
828
829 static void on_response_set_xrat(TcorePending *p, int data_len, const void *data, void *user_data)
830 {
831         UserRequest *ur = NULL;
832         struct tresp_network_set_band resp = {0};
833         const TcoreATResponse *atResp = data;
834
835         dbg("On Response Set XRAT");
836
837         if (atResp->success > 0) {
838                 dbg("Response OK");
839                 resp.result = TCORE_RETURN_SUCCESS;
840         } else {
841                 dbg("Response NOK");
842                 resp.result = TCORE_RETURN_FAILURE;
843         }
844
845         ur = tcore_pending_ref_user_request(p);
846         if (ur) {
847                 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_BAND, sizeof(struct tresp_network_set_band), &resp);
848         }
849
850         return;
851 }
852
853 static void on_response_set_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data)
854 {
855         UserRequest *ur = NULL;
856         struct tresp_network_set_preferred_plmn resp = {0};
857         const TcoreATResponse *atResp = data;
858
859         dbg("ENTER on_response_set_preferred_plmn");
860
861         if (atResp->success > 0) {
862                 dbg("Response OK");
863                 resp.result = TCORE_RETURN_SUCCESS;
864         } else {
865                 dbg("Response NOK");
866                 resp.result = TCORE_RETURN_FAILURE;
867         }
868
869         ur = tcore_pending_ref_user_request(p);
870         if (ur) {
871                 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PREFERRED_PLMN, sizeof(struct tresp_network_set_preferred_plmn), &resp);
872         }
873
874         dbg("Exit on_response_set_preferred_plmn");
875         return;
876 }
877
878 static void on_response_get_nitz_name(TcorePending *p, int data_len, const void *data, void *user_data)
879 {
880         const TcoreATResponse *atResp = data;
881         GSList *tokens = NULL;
882         const char *line = NULL;
883         CoreObject *o = NULL;
884         struct tnoti_network_identity noti;
885         int nol = 0;
886         int count = 0;
887         int net_name_type = 0;
888         char *pResp = NULL;
889         char *net_name = NULL;
890
891         dbg("Entry on_response_get_nitz_name (+XCOPS)");
892         o = tcore_pending_ref_core_object(p);
893         if (atResp->success > 0) {
894                 dbg("RESPONSE OK");
895
896                 if (atResp->lines) {
897                         nol = g_slist_length(atResp->lines);
898                         if (nol > 3) {
899                                 msg("invalid message");
900                                 goto OUT;
901                         }
902
903                         memset(&noti, 0, sizeof(struct tnoti_network_identity));
904
905                         for (count = 0; count < nol; count++) {
906                                 // parse each line
907                                 line = g_slist_nth_data(atResp->lines, count);
908                                 tokens = tcore_at_tok_new(line);
909                                 dbg("line %d start---------------", count);
910
911                                 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
912                                         net_name_type = atoi(pResp);
913                                         dbg("Net name type  : %d", net_name_type);
914
915                                         switch (net_name_type) {
916                                         case 0: /* plmn_id (mcc, mnc) */
917                                                 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
918                                                         if (strlen(pResp) > 0) {
919                                                                 net_name = tcore_at_tok_extract((const char *)pResp);
920                                                                 strncpy(noti.plmn, net_name, 6);
921                                                                 noti.plmn[6] = '\0';
922                                                         }
923                                                 }
924                                                 break;
925
926                                         case 5: /* Short NITZ name*/
927                                         case 3: /* Short Network Name (CPHS) */
928                                                 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
929                                                         if (strlen(pResp) > 0) {
930                                                                 net_name = tcore_at_tok_extract((const char *)pResp);
931                                                                 strncpy(noti.short_name, net_name, 16);
932                                                                 noti.short_name[16] = '\0';
933                                                         }
934                                                 }
935                                                 break;
936
937                                         case 6: /* Full NITZ name */
938                                         case 4: /* Long Network Name (CPHS) */
939                                                 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
940                                                         if (strlen(pResp) > 0) {
941                                                                 net_name = tcore_at_tok_extract((const char *)pResp);
942                                                                 strncpy(noti.full_name, net_name, 32);
943                                                                 noti.full_name[32] = '\0';
944                                                         }
945                                                 }
946                                                 break;
947
948                                         default:
949                                                 break;
950                                         }
951
952                                         g_free(net_name);
953                                         net_name = NULL;
954                                 }
955
956                                 tcore_at_tok_free(tokens);
957                         }
958
959                         dbg("plmn <%s> short NITZ name<%s> full NITZ name<%s>",
960                                 noti.plmn, noti.short_name, noti.full_name);
961                         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_IDENTITY,
962                                                                                    sizeof(struct tnoti_network_identity), &noti);
963                 }
964         } else {
965                 dbg("RESPONSE NOK");
966         }
967
968 OUT:
969         dbg("Exit on_response_get_nitz_name");
970 }
971
972 static void on_response_get_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data)
973 {
974         UserRequest *ur;
975         int i = 0;
976         char *line = NULL;
977         const TcoreATResponse *atResp = data;
978         GSList *tokens = NULL;
979         char *pResp = NULL;
980         int plmn_format = 0;
981
982         struct tresp_network_get_preferred_plmn resp = {0};
983         int total_lines = 0;
984         int GSM_AcT2 = 0, GSM_Compact_AcT2 = 0, UTRAN_AcT2 = 0;
985
986         dbg("Entry");
987
988         if (atResp->success > 0) {
989                 dbg("RESPONSE OK");
990                 if (atResp->lines) {
991                         total_lines = g_slist_length(atResp->lines);
992                         dbg("Total number of network present in Preferred PLMN list is %d\n", total_lines);
993
994                         if (total_lines < 1) {
995                                 msg("invalid message");
996                                 goto OUT;
997                         }
998
999                         if (total_lines >= MAX_NETWORKS_PREF_PLMN_SUPPORT)
1000                                 total_lines = MAX_NETWORKS_PREF_PLMN_SUPPORT;
1001
1002 /*
1003 +CPOL: <index1>,<format>,<oper1>[,<GSM_AcT1>,<GSM_Compact_AcT1>,<UTRAN_AcT1>,<E-UTRAN_AcT1>] [<CR><LF>
1004 +CPOL: <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>,<E-UTRAN_AcT2>]
1005 */
1006                         resp.result = TCORE_RETURN_SUCCESS;
1007
1008                         for (i = 0; i < total_lines; i++) {
1009                                 /* Take each line response at a time & parse it */
1010                                 line = tcore_at_tok_nth(atResp->lines, i);
1011                                 tokens = tcore_at_tok_new(line);
1012
1013                                 /* <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>,<E-UTRAN_AcT2>] */
1014
1015                                 /* EF Index */
1016                                 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
1017                                         dbg("Index : %s", pResp);
1018                                         resp.list[i].ef_index = atoi(pResp);
1019                                 }
1020                                 /* Format */
1021                                 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
1022                                         dbg("format : %s", pResp);
1023                                         plmn_format = atoi(pResp);
1024                                 }
1025
1026                                 /* Operator PLMN ID */
1027                                 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
1028                                         dbg("plmn ID : %s", pResp);
1029
1030                                         if (strlen(pResp) > 0) {
1031                                                 char *oper;
1032
1033                                                 oper = tcore_at_tok_extract((const char *)pResp);
1034                                                 dbg("operator <%s>", oper);
1035
1036                                                 // Get only PLMN ID
1037                                                 if (plmn_format == 2) {
1038                                                         strncpy(resp.list[i].plmn, oper, 6);
1039                                                         resp.list[i].plmn[6] = '\0';
1040                                                 }
1041
1042                                                 g_free (oper);
1043                                         }
1044                                 }
1045
1046                                 if ((pResp = tcore_at_tok_nth(tokens, 3))) {
1047                                         dbg("GSM_AcT2  : %s", pResp);
1048                                         GSM_AcT2 = atoi(pResp);
1049                                 }
1050
1051                                 if ((pResp = tcore_at_tok_nth(tokens, 4))) {
1052                                         dbg("GSM_Compact AcT2  : %s", pResp);
1053                                         GSM_Compact_AcT2 = atoi(pResp);
1054                                 }
1055
1056                                 if ((pResp = tcore_at_tok_nth(tokens, 5))) {
1057                                         dbg("UTRAN_AcT2  : %s", pResp);
1058                                         UTRAN_AcT2 = atoi(pResp);
1059                                 }
1060
1061                                 if (UTRAN_AcT2 && (GSM_AcT2 || GSM_Compact_AcT2))
1062                                         resp.list[i].act = NETWORK_ACT_GSM_UTRAN;
1063                                 else if (UTRAN_AcT2)
1064                                         resp.list[i].act = NETWORK_ACT_UMTS;
1065                                 else if (GSM_AcT2 || GSM_Compact_AcT2)
1066                                         resp.list[i].act = NETWORK_ACT_GPRS;
1067
1068                                 (resp.list_count)++;
1069
1070                                 tcore_at_tok_free(tokens);
1071                         }
1072                 }
1073         } else {
1074                 dbg("RESPONSE NOT OK");
1075                 // TODO: CMEE error mapping is required.
1076                 resp.result = TCORE_RETURN_FAILURE;
1077         }
1078
1079 OUT:
1080         ur = tcore_pending_ref_user_request(p);
1081         if (ur) {
1082                 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PREFERRED_PLMN, sizeof(struct tresp_network_get_preferred_plmn), &resp);
1083         }
1084         dbg("Exit");
1085         return;
1086 }
1087
1088 static void on_response_get_serving_network(TcorePending *p, int data_len, const void *data, void *user_data)
1089 {
1090         const TcoreATResponse *resp = data;
1091         UserRequest *ur;
1092         struct tresp_network_get_serving_network Tresp = {0};
1093         char *long_plmn_name = NULL;
1094         char *short_plmn_name = NULL;
1095         char *plmn_id = NULL;
1096         CoreObject *o;
1097         GSList *tokens = NULL;
1098         const char *line;
1099         int network_mode = -1;
1100         int plmn_format = -1;
1101         int AcT = -1;
1102         struct tnoti_network_identity noti;
1103         char *pResp = NULL;
1104         int nol, count = 0;
1105
1106         o = tcore_pending_ref_core_object(p);
1107
1108         if (resp->success <= 0) {
1109                 dbg("RESPONSE NOK");
1110
1111                 ur = tcore_pending_ref_user_request(p);
1112                 if (ur) {
1113                         Tresp.result = TCORE_RETURN_FAILURE;
1114                         tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp);
1115                 }
1116
1117                 return;
1118         } else {
1119                 dbg("RESPONSE OK");
1120                 nol = g_slist_length(resp->lines);
1121                 dbg("nol : %d", nol);
1122
1123                 for (count = 0; count < nol; count++) {
1124                         // parse each line
1125                         line = g_slist_nth_data(resp->lines, count);
1126                         tokens = tcore_at_tok_new(line);
1127                         dbg("line %d start---------------", count);
1128                         // mode
1129                         if ((pResp = tcore_at_tok_nth(tokens, 0))) {
1130                                 dbg("mode  : %s", pResp);
1131                                 network_mode = atoi(pResp);
1132                         }
1133
1134                         // format (optional)
1135                         if ((pResp = tcore_at_tok_nth(tokens, 1))) {
1136                                 dbg("format  : %s", pResp);
1137                                 if (strlen(pResp) > 0)
1138                                         plmn_format = atoi(pResp);
1139                         }
1140
1141                         // plmn
1142                         switch (plmn_format) {
1143                         case AT_COPS_FORMAT_LONG_ALPHANUMERIC:
1144                                 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
1145                                         dbg("long PLMN  : %s", pResp);
1146                                         if (strlen(pResp) > 0) {
1147                                                 long_plmn_name = tcore_at_tok_extract((const char *)pResp);
1148
1149                                                 // set network name into po
1150                                                 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_FULL, long_plmn_name);
1151                                         }
1152                                 }
1153                                 break;
1154
1155                         case AT_COPS_FORMAT_SHORT_ALPHANUMERIC:
1156                                 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
1157                                         dbg("short PLMN  : %s", pResp);
1158                                         if (strlen(pResp) > 0) {
1159                                                 short_plmn_name = tcore_at_tok_extract((const char *)pResp);
1160
1161                                                 // set network name into po
1162                                                 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SHORT, short_plmn_name);
1163                                         }
1164                                 }
1165                                 break;
1166
1167                         case AT_COPS_FORMAT_NUMERIC:
1168                                 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
1169                                         dbg("numeric : %s", pResp);
1170                                         if (strlen(pResp) > 0) {
1171                                                 plmn_id = tcore_at_tok_extract((const char *)pResp);
1172
1173                                                 // set plmn id into po
1174                                                 tcore_network_set_plmn(o, plmn_id);
1175                                         }
1176                                 }
1177                                 break;
1178
1179                         default:
1180                                 break;
1181                         }
1182
1183                         // act
1184                         if ((pResp = tcore_at_tok_nth(tokens, 3))) {
1185                                 dbg("AcT  : %s", pResp);
1186                                 if (strlen(pResp) > 0) {
1187                                         AcT = atoi(pResp);
1188                                         tcore_network_set_access_technology(o, lookup_tbl_access_technology[AcT]);
1189                                 }
1190                         }
1191
1192                         tcore_at_tok_free(tokens);
1193                 }
1194
1195                 if(plmn_id)
1196                         memcpy(Tresp.plmn, plmn_id, strlen(plmn_id));
1197                 tcore_network_get_access_technology(o, &(Tresp.act));
1198                 tcore_network_get_lac(o, &(Tresp.gsm.lac));
1199
1200                 ur = tcore_pending_ref_user_request(p);
1201                 if (ur) {
1202                         Tresp.result = TCORE_RETURN_SUCCESS;
1203                         tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp);
1204                 } else {
1205                         /* Network change noti */
1206                         struct tnoti_network_change network_change;
1207
1208                         memset(&network_change, 0, sizeof(struct tnoti_network_change));
1209                         if(plmn_id)
1210                                 memcpy(network_change.plmn, plmn_id, strlen(plmn_id));
1211                         tcore_network_get_access_technology(o, &(network_change.act));
1212                         tcore_network_get_lac(o, &(network_change.gsm.lac));
1213
1214                         tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(p)), tcore_pending_ref_core_object(p),
1215                                                                                 TNOTI_NETWORK_CHANGE, sizeof(struct tnoti_network_change), &network_change);
1216                         dbg("dbg.. network_change.plmn  : %s", network_change.plmn);
1217                         dbg("dbg.. network_change.act  : %d", network_change.act);
1218                         dbg("dbg.. network_change.gsm.lac  : %d", network_change.gsm.lac);
1219
1220                         if ((AT_COPS_MODE_DEREGISTER != network_mode) &&
1221                                 (AT_COPS_MODE_SET_ONLY != network_mode)) {
1222                                 /*Network identity noti*/
1223                                 memset(&noti, 0x0, sizeof(struct tnoti_network_identity));
1224                                 if (long_plmn_name)
1225                                         memcpy(noti.full_name, long_plmn_name, MIN(32, strlen(long_plmn_name)));
1226                                 if (short_plmn_name)
1227                                         memcpy(noti.short_name, short_plmn_name, MIN(16, strlen(short_plmn_name)));
1228                                 if (plmn_id)
1229                                         memcpy(noti.plmn, plmn_id, strlen(plmn_id)); // plmn_id length is necessarily <= 6
1230
1231                                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),
1232                                                                 o, TNOTI_NETWORK_IDENTITY, sizeof(struct tnoti_network_identity), &noti);
1233                                 dbg("dbg.. noti.short_name  : %s", noti.short_name);
1234                                 dbg("dbg.. noti.full_name  : %s", noti.full_name);
1235                                 dbg("dbg.. noti.plmn  : %s", noti.plmn);
1236                         }
1237                 }
1238
1239                 g_free(long_plmn_name);
1240                 g_free(short_plmn_name);
1241                 g_free(plmn_id);
1242         }
1243         return;
1244 }
1245
1246 static void on_response_network_set_mode(TcorePending *p, int data_len, const void *data, void *user_data)
1247 {
1248         UserRequest *ur = NULL;
1249         struct tresp_network_set_mode resp = {0};
1250         const TcoreATResponse *atResp = data;
1251
1252         dbg("ENTER on_response_network_set_mode");
1253
1254         if (atResp && atResp->success) {
1255                 dbg("RESPONSE OK");
1256                 resp.result = TCORE_RETURN_SUCCESS;
1257         } else {
1258                 err("RESPONSE NOK");
1259                 resp.result = TCORE_RETURN_FAILURE;
1260         }
1261
1262         ur = tcore_pending_ref_user_request(p);
1263         if (ur) {
1264                 tcore_user_request_send_response(ur,
1265                         TRESP_NETWORK_SET_MODE,
1266                         sizeof(struct tresp_network_set_mode), &resp);
1267         }
1268 }
1269
1270 static void on_response_network_get_mode(TcorePending *p, int data_len, const void *data, void *user_data)
1271 {
1272         UserRequest *ur = NULL;
1273         struct tresp_network_get_mode resp = {0};
1274         const TcoreATResponse *atResp = data;
1275         GSList *tokens = NULL;
1276
1277         dbg("ENTER on_response_network_get_mode");
1278
1279         resp.result = TCORE_RETURN_FAILURE;
1280
1281         if (atResp && atResp->success) {
1282                 const gchar *line;
1283                 gint net_mode;
1284
1285                 if (!atResp->lines) {
1286                         err("invalid response received");
1287                         goto END;
1288                 }
1289
1290                 line = (char *) atResp->lines->data;
1291                 tokens = tcore_at_tok_new(line);
1292                 if (g_slist_length(tokens) < 1) {
1293                         err("invalid message");
1294                         goto END;
1295                 }
1296
1297                 dbg("RESPONSE OK");
1298
1299                 net_mode = atoi(tcore_at_tok_nth(tokens, 0));
1300                 dbg("mode = %d", net_mode);
1301
1302                 switch (net_mode) {
1303                 case 0:
1304                         resp.mode = NETWORK_MODE_GSM;
1305                 break;
1306                 case 1:
1307                         resp.mode = NETWORK_MODE_AUTO;
1308                 break;
1309                 case 2:
1310                         resp.mode = NETWORK_MODE_WCDMA;
1311                 break;
1312                 default:
1313                         err("Unsupported  mode [%d]", net_mode);
1314                         goto END;
1315                 }
1316
1317                 resp.result = TCORE_RETURN_SUCCESS;
1318         } else {
1319                 err("RESPONSE NOK");
1320         }
1321
1322 END:
1323         ur = tcore_pending_ref_user_request(p);
1324         if (ur) {
1325                 tcore_user_request_send_response(ur,
1326                         TRESP_NETWORK_GET_MODE,
1327                         sizeof(struct tresp_network_get_mode), &resp);
1328         }
1329
1330         /* Free resource*/
1331         tcore_at_tok_free(tokens);
1332 }
1333
1334 static void on_response_cancel_manual_search(TcorePending *p, int data_len, const void *data, void *user_data)
1335 {
1336         UserRequest *ur = NULL;
1337         struct tresp_network_set_cancel_manual_search resp = {0};
1338         const TcoreATResponse *atResp = data;
1339         CustomData *custom_data;
1340
1341         dbg("ENTER on_response_cancel_manual_search");
1342
1343         if (atResp->success > 0) {
1344                 dbg("Response OK");
1345                 resp.result = TCORE_RETURN_SUCCESS;
1346         } else {
1347                 dbg("Response NOK");
1348                 resp.result = TCORE_RETURN_FAILURE;
1349         }
1350
1351         custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p));
1352         custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
1353
1354         ur = tcore_pending_ref_user_request(p);
1355         if (ur) {
1356                 tcore_user_request_send_response(ur,
1357                         TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH,
1358                         sizeof(struct tresp_network_set_cancel_manual_search), &resp);
1359         }
1360
1361         dbg("Exit on_response_cancel_manual_search");
1362 }
1363
1364 static gboolean on_event_ps_network_regist(CoreObject *o, const void *data, void *user_data)
1365 {
1366         struct tnoti_network_registration_status regist_status;
1367         enum telephony_network_service_domain_status cs_status;
1368         enum telephony_network_service_domain_status ps_status;
1369         enum telephony_network_service_type service_type;
1370         enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
1371         struct tnoti_network_location_cellinfo net_lac_cell_info = {0};
1372         struct tnoti_ps_protocol_status noti = {0};
1373         unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_PS;
1374         int stat = 0, AcT = 0;
1375         unsigned int lac = 0xffff, ci = 0xffff;
1376         unsigned int rac = 0xffff;
1377         GSList *tokens = NULL;
1378         char *pResp;
1379         char *line = NULL;
1380         GSList *lines = NULL;
1381
1382         lines = (GSList *) data;
1383         if (1 != g_slist_length(lines)) {
1384                 dbg("unsolicited msg but multiple line");
1385                 goto OUT;
1386         }
1387         line = (char *) (lines->data);
1388         dbg("+CGREG NOTI RECEIVED");
1389
1390 /*
1391 +CREG: <stat> [[,<lac>,<ci>[AcT]]
1392
1393 Possible values of <stat> can be
1394 0 Not registered, ME is not currently searching a new operator to register to
1395 1 Registered, home network
1396 2 Not registered, but ME is currently searching a new operator to register
1397 3 Registration denied
1398 4 Unknown
1399 5 Registered, in roaming
1400
1401 <lac>
1402 string type; two byte location area code in hexadecimal format (e.g. 00C3)
1403
1404 <ci>
1405 string type; four byte cell ID in hexadecimal format (e.g. 0000A13F)
1406
1407 <ACT>
1408 0 GSM
1409 2 UTRAN
1410 3 GSM w/EGPRS
1411 4 UTRAN w/HSDPA
1412 5 UTRAN w/HSUPA
1413 6 UTRAN w/HSDPA and HSUPA
1414 Note: <Act> is supporting from R7 and above Protocol Stack.
1415
1416 <rac>: is R7 and above feature, string type; one byte routing area code in hexadecimal format.
1417 */
1418         if (line != NULL) {
1419                 tokens = tcore_at_tok_new(line);
1420                 if (g_slist_length(tokens) < 1) {
1421                         msg("invalid message");
1422                         goto OUT;
1423                 }
1424
1425                 if (!(pResp = g_slist_nth_data(tokens, 0))) {
1426                         dbg("No  STAT in +CGREG");
1427                         goto OUT;
1428                 } else {
1429                         stat = atoi(pResp);
1430                         if ((pResp = g_slist_nth_data(tokens, 1))) {
1431                                 pResp = util_removeQuotes(pResp);
1432                                 lac = strtol(pResp, NULL, 16);
1433                                 g_free(pResp);
1434                         }
1435
1436                         if ((pResp = g_slist_nth_data(tokens, 2))) {
1437                                 pResp = util_removeQuotes(pResp);
1438                                 ci = strtol(pResp, NULL, 16);
1439                                 g_free(pResp);
1440                         } else {
1441                                 dbg("No ci in +CGREG");
1442                         }
1443
1444                         if ((pResp = g_slist_nth_data(tokens, 3)))
1445                                 AcT = atoi(pResp);
1446                         else
1447                                 dbg("No AcT in +CGREG");
1448
1449                         if ((pResp = g_slist_nth_data(tokens, 4))) {
1450                                 pResp = util_removeQuotes(pResp);
1451                                 rac = strtol(pResp, NULL, 16);
1452                                 g_free(pResp);
1453                         } else {
1454                                 dbg("No rac in +CGREG");
1455                         }
1456                 }
1457
1458
1459                 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d, rac = 0x%x", stat, lac, ci, AcT, rac);
1460
1461                 ps_status = lookup_tbl_net_status[stat];
1462
1463                 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status);
1464                 _ps_set(tcore_object_ref_plugin(o), ps_status);
1465
1466                 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
1467
1468                 act = lookup_tbl_access_technology[AcT];
1469                 tcore_network_set_access_technology(o, act);
1470
1471                 tcore_network_get_service_type(o, &service_type);
1472                 dbg("prev_service_type = 0x%x", service_type);
1473                 service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status);
1474                 dbg("new_service_type = 0x%x", service_type);
1475                 tcore_network_set_service_type(o, service_type);
1476
1477                 tcore_network_set_lac(o, lac);
1478                 tcore_network_set_cell_id(o, ci);
1479                 tcore_network_set_rac(o, rac);
1480
1481                 net_lac_cell_info.lac = lac;
1482                 net_lac_cell_info.cell_id = ci;
1483
1484                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO,
1485                                                                            sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info);
1486
1487                 regist_status.cs_domain_status = cs_status;
1488                 regist_status.ps_domain_status = ps_status;
1489                 regist_status.service_type = service_type;
1490                 regist_status.roaming_status = tcore_network_get_roaming_state(o);
1491
1492                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
1493                                                                            TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(regist_status), &regist_status);
1494 #if 0
1495                 if (service_type == NETWORK_SERVICE_TYPE_HSDPA)
1496                         noti.status = TELEPHONY_HSDPA_ON;
1497                 else
1498                         noti.status = TELEPHONY_HSDPA_OFF;
1499 #else
1500                 switch(AcT){
1501                         case AT_COPS_ACT_GSM:/*Fall Through*/
1502                         case AT_COPS_ACT_GSM_COMPACT:/*Fall Through*/
1503                         case AT_COPS_ACT_UTRAN:/*Fall Through*/
1504                         case AT_COPS_ACT_GSM_EGPRS:/*Fall Through*/
1505                         case AT_COPS_ACT_E_UTRAN:
1506                         {
1507                                 dbg("Not required for Protocol Status Notification");
1508                                 goto OUT;
1509                         }
1510                         case AT_COPS_ACT_UTRAN_HSDPA:
1511                         {
1512                                 dbg("HSDPA");
1513                                 noti.status = TELEPHONY_HSDPA_ON;
1514                                 break;
1515                         }
1516                         case AT_COPS_ACT_UTRAN_HSUPA:
1517                         {
1518                                 dbg("HSUPA");
1519                                 noti.status = TELEPHONY_HSUPA_ON;
1520                                 break;
1521                         }
1522                         case AT_COPS_ACT_UTRAN_HSDPA_HSUPA:
1523                         {
1524                                 dbg("HSPA");
1525                                 noti.status = TELEPHONY_HSPA_ON;
1526                                 break;
1527                         }
1528                         default:
1529                         {
1530                                 dbg("Ignore");
1531                                 goto OUT;
1532                         }
1533                 }
1534 #endif
1535                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_PS_PROTOCOL_STATUS,
1536                                                                            sizeof(struct tnoti_ps_protocol_status), &noti);
1537
1538                 /* Get PLMN ID needed to application */
1539                 // get_serving_network(o, NULL);
1540         } else {
1541                 dbg("Response NOK");
1542         }
1543
1544 OUT:
1545         if (NULL != tokens)
1546                 tcore_at_tok_free(tokens);
1547         return TRUE;
1548 }
1549
1550 static gboolean on_event_cs_network_regist(CoreObject *o, const void *event_info, void *user_data)
1551 {
1552         GSList *lines = NULL;
1553         char *line = NULL;
1554         struct tnoti_network_registration_status regist_status;
1555         enum telephony_network_service_domain_status cs_status;
1556         enum telephony_network_service_domain_status ps_status;
1557         enum telephony_network_service_type service_type;
1558         enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
1559         struct tnoti_network_location_cellinfo net_lac_cell_info = {0};
1560
1561
1562         unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_CS;
1563         int stat = 0, AcT = 0;
1564         unsigned int lac = 0xffff, ci = 0xffff;
1565         GSList *tokens = NULL;
1566         char *pResp;
1567
1568         lines = (GSList *) event_info;
1569         if (1 != g_slist_length(lines)) {
1570                 dbg("unsolicited msg but multiple line");
1571                 goto OUT;
1572         }
1573         line = (char *) (lines->data);
1574
1575         dbg("+CREG NOTI RECEIVED");
1576
1577 /*
1578 +CREG: <stat> [[,<lac>,<ci>[AcT]]
1579
1580 Possible values of <stat> can be
1581 0 Not registered, ME is not currently searching a new operator to register to
1582 1 Registered, home network
1583 2 Not registered, but ME is currently searching a new operator to register
1584 3 Registration denied
1585 4 Unknown
1586 5 Registered, in roaming
1587
1588 <lac>
1589 string type; two byte location area code in hexadecimal format (e.g. 00C3)
1590
1591 <ci>
1592 string type; four byte cell ID in hexadecimal format (e.g. 0000A13F)
1593
1594 <ACT>
1595 0 GSM
1596 2 UTRAN
1597 3 GSM w/EGPRS
1598 4 UTRAN w/HSDPA
1599 5 UTRAN w/HSUPA
1600 6 UTRAN w/HSDPA and HSUPA
1601 Note: <Act> is supporting from R7 and above Protocol Stack.
1602 */
1603         if (line != NULL) {
1604                 tokens = tcore_at_tok_new(line);
1605                 if (g_slist_length(tokens) < 1) {
1606                         msg("invalid message");
1607                         goto OUT;
1608                 }
1609
1610                 if (!(pResp = g_slist_nth_data(tokens, 0))) {
1611                         dbg("No  STAT in +CREG");
1612                         goto OUT;
1613                 } else {
1614                         stat = atoi(pResp);
1615                         if ((pResp = g_slist_nth_data(tokens, 1))) {
1616                                 pResp = util_removeQuotes(pResp);
1617                                 lac = strtol(pResp, NULL, 16);
1618                                 g_free(pResp);
1619                         }
1620
1621                         if ((pResp = g_slist_nth_data(tokens, 2))) {
1622                                 pResp = util_removeQuotes(pResp);
1623                                 ci = strtol(pResp, NULL, 16);
1624                                 g_free(pResp);
1625                         } else {
1626                                 dbg("No ci in +CREG");
1627                         }
1628
1629                         if ((pResp = g_slist_nth_data(tokens, 3)))
1630                                 AcT = atoi(pResp);
1631                         else
1632                                 dbg("No AcT in +CREG");
1633                 }
1634
1635
1636                 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d", stat, lac, ci, AcT);
1637
1638                 cs_status = lookup_tbl_net_status[stat];
1639                 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, cs_status);
1640
1641                 // tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
1642                 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status);
1643
1644                 act = lookup_tbl_access_technology[AcT];
1645                 tcore_network_set_access_technology(o, act);
1646
1647                 if (stat == AT_CREG_STAT_REG_ROAM) {
1648                         tcore_network_set_roaming_state(o, TRUE);
1649                 }else if ((stat == AT_CREG_STAT_REG_DENIED) && (TRUE == tcore_network_get_roaming_state(o))) {
1650                         dbg("Ignore roaming set with REG_DENIED when previous state is REG_ROAM");
1651                 }else {
1652                         tcore_network_set_roaming_state(o, FALSE);
1653                 }
1654
1655                 tcore_network_get_service_type(o, &service_type);
1656                 dbg("prev_service_type = 0x%x", service_type);
1657                 service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status);
1658                 dbg("new_service_type = 0x%x", service_type);
1659                 tcore_network_set_service_type(o, service_type);
1660
1661                 tcore_network_set_lac(o, lac);
1662                 tcore_network_set_cell_id(o, ci);
1663
1664                 net_lac_cell_info.lac = lac;
1665                 net_lac_cell_info.cell_id = ci;
1666
1667                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO,
1668                                                                            sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info);
1669
1670                 regist_status.cs_domain_status = cs_status;
1671                 regist_status.ps_domain_status = ps_status;
1672                 regist_status.service_type = service_type;
1673                 regist_status.roaming_status = tcore_network_get_roaming_state(o);
1674
1675                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
1676                                                                            TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), &regist_status);
1677
1678                 /* Get PLMN ID needed to application */
1679                 if ((NETWORK_SERVICE_DOMAIN_STATUS_FULL == cs_status) ||
1680                         NETWORK_SERVICE_DOMAIN_STATUS_FULL == ps_status)
1681                         get_serving_network(o, NULL);
1682         } else {
1683                 dbg("Response NOK");
1684         }
1685
1686 OUT:
1687         if (NULL != tokens)
1688                 tcore_at_tok_free(tokens);
1689         return TRUE;
1690 }
1691
1692 static gboolean on_event_network_icon_info(CoreObject *o, const void *event_info, void *user_data)
1693 {
1694         struct tnoti_network_icon_info net_icon_info = {0};
1695         char *line = NULL;
1696         char *rssiToken = NULL;
1697         char *batteryToken = NULL;
1698         GSList *tokens = NULL;
1699         GSList *lines = NULL;
1700
1701         lines = (GSList *) event_info;
1702         if (1 != g_slist_length(lines)) {
1703                 dbg("unsolicited msg but multiple line");
1704                 goto OUT;
1705         }
1706         line = (char *) (lines->data);
1707         dbg("+XCIEV Network Icon Info Noti Recieve");
1708         memset(&net_icon_info, 0, sizeof(struct tnoti_network_icon_info));
1709
1710         if (line != NULL) {
1711                 dbg("Response OK");
1712
1713                 tokens = tcore_at_tok_new(line);
1714                 if (g_slist_length(tokens) != 2) {
1715                         msg("invalid message");
1716                         goto OUT;
1717                 }
1718
1719                 rssiToken = (char *) g_slist_nth_data(tokens, 0);
1720
1721                 if (strlen(rssiToken) > 0) {
1722                         net_icon_info.type = NETWORK_ICON_INFO_RSSI;
1723                         net_icon_info.rssi = atoi(g_slist_nth_data(tokens, 0));
1724                         dbg("rssi level : %d", net_icon_info.rssi);
1725                 }
1726
1727                 batteryToken = (char *) g_slist_nth_data(tokens, 1);
1728                 if (strlen(batteryToken) > 0) {
1729                         net_icon_info.type = NETWORK_ICON_INFO_BATTERY;
1730                         net_icon_info.battery = atoi(g_slist_nth_data(tokens, 1));
1731                         dbg("battery level : %d", net_icon_info.battery);
1732                 }
1733
1734                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_ICON_INFO,
1735                                                                            sizeof(struct tnoti_network_icon_info), &net_icon_info);
1736         } else {
1737                 dbg("Response NOK");
1738         }
1739
1740
1741 OUT:
1742         if (NULL != tokens)
1743                 tcore_at_tok_free(tokens);
1744
1745         return TRUE;
1746 }
1747
1748 static gboolean on_event_network_ctzv_time_info(CoreObject *o, const void *event_info, void *user_data)
1749 {
1750         struct tnoti_network_timeinfo net_time_info = {0};
1751         char *line = NULL;
1752         GSList *tokens = NULL;
1753         char *time = NULL;
1754         char *time_zone = NULL;
1755         GSList *lines = NULL;
1756         char ptime_param[20] = {0};
1757         UserRequest *ur = NULL;
1758         dbg("Enter : on_event_network_ctzv_time_info");
1759
1760         lines = (GSList *) event_info;
1761         if (1 != g_slist_length(lines)) {
1762                 dbg("unsolicited msg but multiple line");
1763                 goto OUT;
1764         }
1765         line = (char *) (lines->data);
1766
1767 /*
1768 +CTZV: <tz>,<time>
1769 <tz> integer value indicating the time zone (e.g. -22 or +34)
1770 <time> string type value; format is yy/MM/dd,hh:mms, wherein characters indicates year, month, day, hour,
1771 minutes, seconds.*/
1772
1773         dbg("Network time info (+CTZV) recieved");
1774
1775         if (line != NULL) {
1776                 gchar *plmn_str = NULL;
1777                 dbg("Response OK");
1778                 dbg("noti line is %s", line);
1779
1780                 tokens = tcore_at_tok_new(line);
1781
1782                 if (g_slist_length(tokens) < 2) {
1783                         msg("invalid message");
1784                         goto OUT;
1785                 }
1786
1787                 if ((time_zone = g_slist_nth_data(tokens, 0))) {
1788                         net_time_info.gmtoff = atoi(time_zone) * 15; /* TZ in minutes */
1789                 }
1790
1791                 plmn_str = tcore_network_get_plmn(o);
1792                 if (plmn_str != NULL) {
1793                         g_strlcpy(net_time_info.plmn, plmn_str, sizeof(net_time_info.plmn));
1794                         g_free(plmn_str);
1795                 }
1796
1797                 if ((time = g_slist_nth_data(tokens, 1)) && (strlen(time) > 18)) {
1798                         strncpy(ptime_param, time + 1, 2); /* skip past initial quote (") */
1799                         net_time_info.year = atoi(ptime_param);
1800
1801                         strncpy(ptime_param, time + 4, 2); /* skip slash (/) after year param */
1802                         net_time_info.month = atoi(ptime_param);
1803
1804                         strncpy(ptime_param, time + 7, 2); /* skip past slash (/) after month param */
1805                         net_time_info.day = atoi(ptime_param);
1806
1807                         strncpy(ptime_param, time + 10, 2); /* skip past comma (,) after day param */
1808                         net_time_info.hour = atoi(ptime_param);
1809
1810                         strncpy(ptime_param, time + 13, 2); /* skip past colon (:) after hour param */
1811                         net_time_info.minute = atoi(ptime_param);
1812
1813                         strncpy(ptime_param, time + 16, 2); /* skip past colon (:) after minute param */
1814                         net_time_info.second = atoi(ptime_param);
1815                 }
1816                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_TIMEINFO, sizeof(struct tnoti_network_timeinfo), &net_time_info);
1817
1818                 dbg("new pending(AT+XOPS=0/5/6 for Nitz PLMN name)");
1819
1820                 /* Get NITZ name and plmn_id via AT+XCOPS = 0/5/6 */
1821                 nwk_prepare_and_send_pending_request(o, "AT+XCOPS=0;+XCOPS=5;+XCOPS=6", "+XCOPS", TCORE_AT_MULTILINE, ur, on_response_get_nitz_name);
1822         } else {
1823                 dbg("line is  NULL");
1824         }
1825
1826 OUT:
1827         if (NULL != tokens)
1828                 tcore_at_tok_free(tokens);
1829
1830         dbg("Exit: on_event_network_ctzv_time_info");
1831         return TRUE;
1832 }
1833
1834 static void on_sim_resp_hook_get_netname(UserRequest *ur, enum tcore_response_command command, unsigned int data_len,
1835                                                                                  const void *data, void *user_data)
1836 {
1837         const struct tresp_sim_read *resp = data;
1838         CoreObject *o = user_data;
1839
1840         if (command == TRESP_SIM_GET_SPN) {
1841                 dbg("OK SPN GETTING!!");
1842                 dbg("resp->result = 0x%x", resp->result);
1843                 dbg("resp->data.spn.display_condition = 0x%x", resp->data.spn.display_condition);
1844                 dbg("resp->data.spn.spn = [%s]", resp->data.spn.spn);
1845
1846                 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *) resp->data.spn.spn);
1847
1848                 /**
1849                  * display condition
1850                  *  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
1851                  *          1 = display of registered PLMN name required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
1852                  *  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
1853                  *          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
1854                  */
1855                 if (resp->data.spn.display_condition & 0x01) {
1856                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
1857                 }
1858                 if ((resp->data.spn.display_condition & 0x02) == 0) {
1859                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
1860                 }
1861                 if ((resp->data.spn.display_condition & 0x03) == 0x01) {
1862                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
1863                 }
1864
1865                 // fallback in case no SPN name is provided
1866                 if (resp->data.spn.spn[0] == '\0')
1867                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
1868         }
1869 }
1870
1871 static enum tcore_hook_return on_hook_sim_init(Server *s, CoreObject *source, enum tcore_notification_command command,
1872                                                                                            unsigned int data_len, void *data, void *user_data)
1873 {
1874         const struct tnoti_sim_status *sim = data;
1875         UserRequest *ur = NULL;
1876
1877         if (sim->sim_status == SIM_STATUS_INIT_COMPLETED) {
1878                 ur = tcore_user_request_new(NULL, NULL);
1879                 tcore_user_request_set_command(ur, TREQ_SIM_GET_SPN);
1880                 tcore_user_request_set_response_hook(ur, on_sim_resp_hook_get_netname, user_data);
1881                 tcore_object_dispatch_request(source, ur);
1882         }
1883
1884         return TCORE_HOOK_RETURN_CONTINUE;
1885 }
1886
1887 static TReturn search_network(CoreObject *o, UserRequest *ur)
1888 {
1889         TcoreHal *h = NULL;
1890         TcorePending *pending = NULL;
1891         TcoreATRequest *atreq = NULL;
1892         CustomData *custom_data;
1893         char *cmd_str = NULL;
1894
1895         dbg("search_network - ENTER!!");
1896
1897         if (!o || !ur)
1898                 return TCORE_RETURN_EINVAL;
1899
1900         custom_data = tcore_object_ref_user_data(o);
1901         if (custom_data->search_state
1902                         == IMC_NETWORK_SEARCH_STATE_IN_PROGRESS) {
1903                 warn("Network Search: [ALREADY IN PROGRESS]");
1904                 return TCORE_RETURN_FAILURE;
1905         }
1906
1907         h = tcore_object_get_hal(o);
1908         if(FALSE == tcore_hal_get_power_state(h)){
1909                 dbg("cp not ready/n");
1910                 return TCORE_RETURN_ENOSYS;
1911         }
1912
1913         pending = tcore_pending_new(o, 0);
1914
1915         cmd_str = g_strdup_printf("AT+COPS=?");
1916         atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_SINGLELINE);
1917
1918         tcore_pending_set_request_data(pending, 0, atreq);
1919         tcore_pending_set_timeout(pending, 60);
1920         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
1921         tcore_pending_set_response_callback(pending, on_response_search_network, NULL);
1922         tcore_pending_set_timeout_callback(pending, on_timeout_search_network, NULL);
1923         tcore_pending_link_user_request(pending, ur);
1924         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
1925
1926         tcore_hal_send_request(h, pending);
1927         g_free(cmd_str);
1928
1929         custom_data->search_state = IMC_NETWORK_SEARCH_STATE_IN_PROGRESS;
1930         dbg("Search State: [IN PROGRESS]");
1931
1932         return TCORE_RETURN_SUCCESS;
1933 }
1934
1935 static TReturn set_plmn_selection_mode(CoreObject *o, UserRequest *ur)
1936 {
1937         TcoreHal *h = NULL;
1938         TcorePending *pending = NULL;
1939         TcoreATRequest *atreq;
1940         char *cmd_str = NULL;
1941         int format = 0; /* default value for long alphanumeric */
1942         int mode = 0;
1943         char plmn[7] = {0};
1944         int act = 0;
1945
1946         const struct treq_network_set_plmn_selection_mode *req_data = NULL;
1947
1948
1949         dbg("set_plmn_selection_mode - ENTER!!");
1950
1951         if (!o || !ur)
1952                 return TCORE_RETURN_EINVAL;
1953
1954         req_data = tcore_user_request_ref_data(ur, NULL);
1955         h = tcore_object_get_hal(o);
1956         if(FALSE == tcore_hal_get_power_state(h)){
1957                 dbg("cp not ready/n");
1958                 return TCORE_RETURN_ENOSYS;
1959         }
1960         pending = tcore_pending_new(o, 0);
1961
1962         // Command Format - AT+COPS=[<mode>[,<format>[,<oper>[,< AcT>]]]]
1963         /* oper parameter format
1964             - 0 <oper> format presentations are set to long alphanumeric. If Network name not available it displays combination of Mcc and MNC in string format.
1965             - 1 <oper> format presentation is set to short alphanumeric.
1966             - 2 <oper> format presentations set to numeric.
1967         */
1968
1969         if ((req_data->act == NETWORK_ACT_GSM) || (req_data->act == NETWORK_ACT_EGPRS))
1970                 act = 0;
1971         else
1972                 act = 2;
1973
1974         switch (req_data->mode) {
1975         case NETWORK_SELECT_MODE_MANUAL:
1976         {
1977                 mode = AT_COPS_MODE_MANUAL;
1978                 format = AT_COPS_FORMAT_NUMERIC;
1979
1980                 memset(plmn, 0, 7);
1981                 memcpy(plmn, req_data->plmn, 6);
1982
1983                 if (strlen(req_data->plmn) == 6) {
1984                         if (plmn[5] == '#')
1985                                 plmn[5] = 0;
1986                 }
1987
1988                 cmd_str = g_strdup_printf("AT+COPS=%d,%d,\"%s\",%d", mode, format, plmn, act);
1989         }
1990         break;
1991
1992         case NETWORK_SELECT_MODE_AUTOMATIC:
1993         default:
1994                 cmd_str = g_strdup("AT+COPS=0");
1995                 break;
1996         }
1997
1998
1999         atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_NO_RESULT);
2000
2001         tcore_pending_set_request_data(pending, 0, atreq);
2002         tcore_pending_set_response_callback(pending, on_response_set_plmn_selection_mode, NULL);
2003         tcore_pending_link_user_request(pending, ur);
2004         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2005
2006         tcore_hal_send_request(h, pending);
2007         g_free(cmd_str);
2008         return TCORE_RETURN_SUCCESS;
2009 }
2010
2011 static TReturn get_plmn_selection_mode(CoreObject *o, UserRequest *ur)
2012 {
2013         TcoreHal *h = NULL;
2014         TcorePending *pending = NULL;
2015         TcoreATRequest *atreq;
2016         char *cmd_str = NULL;
2017
2018         dbg("get_plmn_selection_mode - ENTER!!");
2019
2020         if (!o || !ur)
2021                 return TCORE_RETURN_EINVAL;
2022
2023         h = tcore_object_get_hal(o);
2024         if(FALSE == tcore_hal_get_power_state(h)){
2025                 dbg("cp not ready/n");
2026                 return TCORE_RETURN_ENOSYS;
2027         }
2028         pending = tcore_pending_new(o, 0);
2029
2030         cmd_str = g_strdup_printf("AT+COPS?");
2031         atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_SINGLELINE);
2032
2033         tcore_pending_set_request_data(pending, 0, atreq);
2034         tcore_pending_set_response_callback(pending, on_response_get_plmn_selection_mode, NULL);
2035         tcore_pending_link_user_request(pending, ur);
2036         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2037
2038         tcore_hal_send_request(h, pending);
2039         g_free(cmd_str);
2040         return TCORE_RETURN_SUCCESS;
2041 }
2042
2043
2044 static TReturn set_band(CoreObject *o, UserRequest *ur)
2045 {
2046         TcoreHal *h = NULL;
2047         TcorePending *pending = NULL;
2048         TcorePending *pending_gsm = NULL;
2049         TcorePending *pending_umts = NULL;
2050         TcoreATRequest *atreq;
2051         char *cmd_str = NULL;
2052         const struct treq_network_set_band *req_data;
2053         gboolean set_gsm_band = 0;
2054         gboolean set_umts_band = 0;
2055         int gsm_band = 255;
2056         int gsm_band2 = 255;
2057         char *umts_band = NULL;
2058         UserRequest *dup_ur_gsm = NULL;
2059         UserRequest *dup_ur_umts = NULL;
2060
2061         dbg("set_band - ENTER!!");
2062
2063         if (!o || !ur)
2064                 return TCORE_RETURN_EINVAL;
2065
2066         req_data = tcore_user_request_ref_data(ur, NULL);
2067         h = tcore_object_get_hal(o);
2068         if(FALSE == tcore_hal_get_power_state(h)){
2069                 dbg("cp not ready/n");
2070                 return TCORE_RETURN_ENOSYS;
2071         }
2072
2073         dbg("set_band - called with band = %d", req_data->band);
2074
2075         switch (req_data->band) {
2076         case NETWORK_BAND_TYPE_GSM850:
2077                 gsm_band = AT_GSM_XBANDSEL_850;
2078                 set_gsm_band = TRUE;
2079                 break;
2080
2081         case NETWORK_BAND_TYPE_GSM_900_1800:
2082                 gsm_band = AT_GSM_XBANDSEL_900;
2083                 gsm_band2 = AT_GSM_XBANDSEL_1800;
2084                 set_gsm_band = TRUE;
2085                 break;
2086
2087         case NETWORK_BAND_TYPE_GSM1900:
2088                 gsm_band = AT_GSM_XBANDSEL_1900;
2089                 set_gsm_band = TRUE;
2090                 break;
2091
2092         case NETWORK_BAND_TYPE_GSM1800:
2093                 gsm_band = AT_GSM_XBANDSEL_1800;
2094                 set_gsm_band = TRUE;
2095                 break;
2096
2097         case NETWORK_BAND_TYPE_GSM_850_1900:
2098                 gsm_band = AT_GSM_XBANDSEL_850;
2099                 gsm_band2 = AT_GSM_XBANDSEL_1900;
2100                 set_gsm_band = TRUE;
2101                 break;
2102
2103         case NETWORK_BAND_TYPE_ANY:
2104                 gsm_band = AT_GSM_XBANDSEL_AUTOMATIC;
2105                 set_umts_band = TRUE;
2106                 set_gsm_band = TRUE;
2107                 break;
2108
2109         case NETWORK_BAND_TYPE_WCDMA:
2110                 set_umts_band = TRUE;
2111                 break;
2112
2113         case NETWORK_BAND_TYPE_WCDMA2100:
2114                 umts_band = "UMTS_BAND_I";
2115                 set_umts_band = TRUE;
2116                 break;
2117
2118         case NETWORK_BAND_TYPE_WCDMA1900:
2119                 umts_band = "UMTS_BAND_II";
2120                 set_umts_band = TRUE;
2121                 break;
2122
2123         case NETWORK_BAND_TYPE_WCDMA850:
2124                 umts_band = "UMTS_BAND_V";
2125                 set_umts_band = TRUE;
2126                 break;
2127
2128         default:
2129                 break;
2130         }
2131
2132         dbg("set_band > set_umts_band = %d, set_gsm_band = %d", set_umts_band, set_gsm_band);
2133
2134         if (set_umts_band == TRUE) {
2135                 if ((req_data->band == NETWORK_BAND_TYPE_WCDMA) || (req_data->band == NETWORK_BAND_TYPE_ANY))
2136                         cmd_str = g_strdup_printf("AT+XUBANDSEL=0");
2137                 else
2138                         cmd_str = g_strdup_printf("AT+XUBANDSEL=%s", umts_band);
2139
2140                 atreq = tcore_at_request_new(cmd_str, "+XUBANDSEL", TCORE_AT_NO_RESULT);
2141                 pending_umts = tcore_pending_new(o, 0);
2142
2143                 tcore_pending_set_request_data(pending_umts, 0, atreq);
2144                 tcore_pending_set_priority(pending_umts, TCORE_PENDING_PRIORITY_DEFAULT);
2145                 tcore_pending_set_response_callback(pending_umts, on_response_set_umts_band, NULL);
2146
2147                 /* duplicate user request for UMTS Band setting AT command for same UR */
2148                 dup_ur_umts = tcore_user_request_ref(ur);
2149                 tcore_pending_link_user_request(pending_umts, dup_ur_umts);
2150                 tcore_pending_set_send_callback(pending_umts, on_confirmation_network_message_send, NULL);
2151
2152                 tcore_hal_send_request(h, pending_umts);
2153                 g_free(cmd_str);
2154         }
2155
2156         if (set_gsm_band == TRUE) {
2157                 dbg("Entered set_gsm_band");
2158                 if (gsm_band2 == 255)
2159                         cmd_str = g_strdup_printf("AT+XBANDSEL=%d", gsm_band);
2160                 else
2161                         cmd_str = g_strdup_printf("AT+XBANDSEL=%d,%d", gsm_band, gsm_band2);
2162
2163                 dbg("Command string: %s", cmd_str);
2164                 atreq = tcore_at_request_new(cmd_str, "+XBANDSEL", TCORE_AT_NO_RESULT);
2165                 pending_gsm = tcore_pending_new(o, 0);
2166
2167                 tcore_pending_set_request_data(pending_gsm, 0, atreq);
2168                 tcore_pending_set_priority(pending_gsm, TCORE_PENDING_PRIORITY_DEFAULT);
2169                 tcore_pending_set_response_callback(pending_gsm, on_response_set_gsm_band, NULL);
2170
2171                 /* duplicate user request for GSM Band setting AT command for same UR */
2172                 dup_ur_gsm = tcore_user_request_ref(ur);
2173                 tcore_pending_link_user_request(pending_gsm, dup_ur_gsm);
2174                 tcore_pending_set_send_callback(pending_gsm, on_confirmation_network_message_send, NULL);
2175
2176                 tcore_hal_send_request(h, pending_gsm);
2177                 g_free(cmd_str);
2178         }
2179
2180         /* Lock device to specific RAT as requested by application */
2181 /*
2182 AT+XRAT=<Act>[,<PreferredAct>]
2183 <AcT> indicates the radio access technology and may be
2184 0 GSM single mode
2185 1 GSM / UMTS Dual mode
2186 2 UTRAN (UMTS)
2187 */
2188         if ((set_umts_band == TRUE) && (set_gsm_band == TRUE)) {
2189                 cmd_str = g_strdup_printf("AT+XRAT=%d", AT_XRAT_DUAL);
2190         } else if (set_umts_band == TRUE) {
2191                 cmd_str = g_strdup_printf("AT+XRAT=%d", AT_XRAT_UMTS);
2192         } else {
2193                 cmd_str = g_strdup_printf("AT+XRAT=%d", AT_XRAT_GSM);
2194         }
2195         atreq = tcore_at_request_new(cmd_str, "+XRAT", TCORE_AT_NO_RESULT);
2196         pending = tcore_pending_new(o, 0);
2197
2198         tcore_pending_set_request_data(pending, 0, atreq);
2199         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
2200         tcore_pending_set_response_callback(pending, on_response_set_xrat, NULL);
2201         tcore_pending_link_user_request(pending, ur);
2202         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2203
2204         tcore_hal_send_request(h, pending);
2205         g_free(cmd_str);
2206         return TCORE_RETURN_SUCCESS;
2207 }
2208
2209 static TReturn get_band(CoreObject *o, UserRequest *ur)
2210 {
2211         TcoreHal *h = NULL;
2212         TcorePending *pending = NULL;
2213         TcoreATRequest *atreq;
2214         char *cmd_str = NULL;
2215         dbg("get_band - ENTER!!");
2216
2217         if (!o || !ur)
2218                 return TCORE_RETURN_EINVAL;
2219
2220         h = tcore_object_get_hal(o);
2221         if(FALSE == tcore_hal_get_power_state(h)){
2222                 dbg("cp not ready/n");
2223                 return TCORE_RETURN_ENOSYS;
2224         }
2225
2226         /* Get RAT Information Information. Based on RAT read response, we will get specific RAT bands only */
2227         cmd_str = g_strdup_printf("AT+XRAT?");
2228         atreq = tcore_at_request_new(cmd_str, "+XRAT", TCORE_AT_SINGLELINE);
2229         pending = tcore_pending_new(o, 0);
2230         tcore_pending_set_request_data(pending, 0, atreq);
2231         tcore_pending_set_response_callback(pending, on_response_get_xrat, NULL);
2232         tcore_pending_link_user_request(pending, ur);
2233         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2234         tcore_hal_send_request(h, pending);
2235
2236         g_free(cmd_str);
2237         return TCORE_RETURN_SUCCESS;
2238 }
2239
2240 static TReturn set_preferred_plmn(CoreObject *o, UserRequest *ur)
2241 {
2242         TcoreHal *h = NULL;
2243         TcorePending *pending = NULL;
2244         TcoreATRequest *atreq = NULL;
2245         struct treq_network_set_preferred_plmn *req_data = NULL;
2246         char *cmd_str = NULL;
2247         int format = 2; /* Alway use numeric format, as application gives data in this default format */
2248         int gsm_act = 0;
2249         int gsm_compact_act = 0;
2250         int utran_act = 0;
2251
2252         if (!o || !ur)
2253                 return TCORE_RETURN_EINVAL;
2254
2255         h = tcore_object_get_hal(o);
2256         if(FALSE == tcore_hal_get_power_state(h)){
2257                 dbg("cp not ready/n");
2258                 return TCORE_RETURN_ENOSYS;
2259         }
2260
2261         req_data = (struct treq_network_set_preferred_plmn *) tcore_user_request_ref_data(ur, NULL);
2262         pending = tcore_pending_new(o, 0);
2263
2264         dbg("Entry set_preferred_plmn");
2265 /*
2266 AT+CPOL=
2267 [<index>][,<format>[,<oper>[,<GSM_AcT>,
2268 <GSM_Compact_AcT>,<UTRAN_AcT>]]]
2269  */
2270
2271         if ((req_data->act == NETWORK_ACT_GSM) || (req_data->act == NETWORK_ACT_GPRS) || (req_data->act == NETWORK_ACT_EGPRS))
2272                 gsm_act = TRUE;
2273         else if ((req_data->act == NETWORK_ACT_UMTS) || (req_data->act == NETWORK_ACT_UTRAN))
2274                 utran_act = TRUE;
2275         else if (req_data->act == NETWORK_ACT_GSM_UTRAN)
2276                 gsm_act = utran_act = TRUE;
2277
2278         if (strlen(req_data->plmn) > 6) {
2279                 req_data->plmn[6] = '\0';
2280         } else if (strlen(req_data->plmn) == 6) {
2281                 if (req_data->plmn[5] == '#') {
2282                         req_data->plmn[5] = '\0';
2283                 }
2284         }
2285         cmd_str = g_strdup_printf("AT+CPOL=%d,%d,\"%s\",%d,%d,%d", req_data->ef_index + 1, format, req_data->plmn, gsm_act, gsm_compact_act, utran_act);
2286
2287         dbg("cmd_str - %s", cmd_str);
2288         atreq = tcore_at_request_new(cmd_str, "+CPOL", TCORE_AT_NO_RESULT);
2289
2290         tcore_pending_set_request_data(pending, 0, atreq);
2291         tcore_pending_set_response_callback(pending, on_response_set_preferred_plmn, NULL);
2292         tcore_pending_link_user_request(pending, ur);
2293         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2294
2295         tcore_hal_send_request(h, pending);
2296
2297         g_free(cmd_str);
2298
2299         dbg("Exit set_preferred_plmn");
2300
2301         return TCORE_RETURN_SUCCESS;
2302 }
2303
2304 static TReturn get_preferred_plmn(CoreObject *o, UserRequest *ur)
2305 {
2306         TcoreHal *h = NULL;
2307         TcorePending *pending = NULL;
2308         TcoreATRequest *atreq = NULL;
2309
2310         char *cmd_str = NULL;
2311
2312         dbg("get_preferred_plmn - ENTER!!");
2313
2314         if (!o || !ur)
2315                 return TCORE_RETURN_EINVAL;
2316
2317         h = tcore_object_get_hal(o);
2318         if(FALSE == tcore_hal_get_power_state(h)){
2319                 dbg("cp not ready/n");
2320                 return TCORE_RETURN_ENOSYS;
2321         }
2322
2323         pending = tcore_pending_new(o, 0);
2324
2325         cmd_str = g_strdup_printf("AT+CPOL=,2;+CPOL?");
2326         atreq = tcore_at_request_new(cmd_str, "+CPOL", TCORE_AT_MULTILINE);
2327
2328         tcore_pending_set_request_data(pending, 0, atreq);
2329         tcore_pending_set_response_callback(pending, on_response_get_preferred_plmn, NULL);
2330         tcore_pending_link_user_request(pending, ur);
2331         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2332
2333         tcore_hal_send_request(h, pending);
2334
2335         g_free(cmd_str);
2336
2337         dbg("get_preferred_plmn - EXIT!!");
2338
2339         return TCORE_RETURN_SUCCESS;
2340 }
2341
2342 static TReturn cancel_manual_search (CoreObject *o, UserRequest *ur)
2343 {
2344         TcoreHal *h = NULL;
2345         TcorePending *pending = NULL;
2346         TcoreATRequest *atreq = NULL;
2347         CustomData *custom_data;
2348
2349         dbg("cancel_manual_search - ENTER!!");
2350
2351         if (!o || !ur)
2352                 return TCORE_RETURN_EINVAL;
2353
2354         h = tcore_object_get_hal(o);
2355         if (FALSE == tcore_hal_get_power_state(h)) {
2356                 dbg("cp not ready/n");
2357                 return TCORE_RETURN_ENOSYS;
2358         }
2359
2360         custom_data = tcore_object_ref_user_data(o);
2361         if (custom_data->search_state
2362                         == IMC_NETWORK_SEARCH_STATE_IN_PROGRESS) {
2363                 dbg("Search in Progress...");
2364
2365                 pending = tcore_pending_new(o, 0);
2366                 atreq = tcore_at_request_new("\e", NULL, TCORE_AT_NO_RESULT);
2367
2368                 tcore_pending_set_request_data(pending, 0, atreq);
2369                 tcore_pending_set_response_callback(pending, on_response_cancel_manual_search, NULL);
2370                 tcore_pending_link_user_request(pending, ur);
2371                 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2372
2373                 /*Set the Search State to Cancelled*/
2374                 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_CANCELLED;
2375                 dbg("Search State: [CANCELLED]");
2376         } else {
2377                 dbg("No Search in Progress...");
2378         }
2379
2380         return TCORE_RETURN_SUCCESS;
2381 }
2382
2383 static TReturn get_serving_network(CoreObject *o, UserRequest *ur)
2384 {
2385         dbg("get_serving_network - ENTER!!");
2386
2387         if (!o)
2388                 return TCORE_RETURN_EINVAL;
2389
2390         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2391                 dbg("cp not ready/n");
2392                 return TCORE_RETURN_ENOSYS;
2393         }
2394
2395         dbg("new pending(AT+COPS?)");
2396
2397         nwk_prepare_and_send_pending_request(o, "AT+COPS=3,2;+COPS?;+COPS=3,0;+COPS?", "+COPS", TCORE_AT_MULTILINE, ur, on_response_get_serving_network);
2398         return TCORE_RETURN_SUCCESS;
2399 }
2400
2401 static TReturn network_set_mode(CoreObject *o, UserRequest *ur)
2402 {
2403         struct treq_network_set_mode *set_mode = NULL;
2404         TReturn ret = TCORE_RETURN_EINVAL;
2405         int act;
2406         gchar *at_cmd;
2407
2408         dbg("network_set_mode - ENTER!!");
2409
2410         set_mode = (struct treq_network_set_mode *)tcore_user_request_ref_data(ur, NULL);
2411
2412         switch (set_mode->mode) {
2413         case NETWORK_MODE_AUTO:
2414                 act = 1;
2415         break;
2416         case NETWORK_MODE_GSM:
2417                 act = 0;
2418         break;
2419         case NETWORK_MODE_WCDMA:
2420                 act = 2;
2421         break;
2422         case NETWORK_MODE_LTE:
2423         default:
2424                 err("Unsupported  mode: [%d]", set_mode->mode);
2425                 return ret;
2426         }
2427
2428         if (act == 1)
2429                 /* AT-Command */
2430                 at_cmd = g_strdup_printf("AT+XRAT=%d,2", act); //PreferredAct is UMTS
2431         else
2432                 /* AT-Command */
2433                 at_cmd = g_strdup_printf("AT+XRAT=%d", act);
2434
2435         /* Send Request to modem */
2436         ret = tcore_prepare_and_send_at_request(o,
2437                 at_cmd, NULL,
2438                 TCORE_AT_NO_RESULT,
2439                 ur,
2440                 on_response_network_set_mode, NULL,
2441                 on_confirmation_network_message_send, NULL,
2442                 0, NULL, NULL);
2443
2444         g_free(at_cmd);
2445         return ret;
2446 }
2447
2448 static TReturn network_get_mode(CoreObject *o, UserRequest *ur)
2449 {
2450         TReturn ret;
2451
2452         dbg("network_get_mode - ENTER!!");
2453
2454         /* Send Request to modem */
2455         ret = tcore_prepare_and_send_at_request(o,
2456                 "AT+XRAT?", "+XRAT",
2457                 TCORE_AT_SINGLELINE,
2458                 ur,
2459                 on_response_network_get_mode, NULL,
2460                 on_confirmation_network_message_send, NULL,
2461                 0, NULL, NULL);
2462
2463         return ret;
2464 }
2465
2466 static TReturn set_default_subscription(CoreObject *co, UserRequest *ur)
2467 {
2468         struct treq_network_set_default_subscription *req_data = NULL;
2469         Server *server;
2470         Storage *strg = NULL;
2471         TReturn ret = TCORE_RETURN_FAILURE;
2472         TcorePlugin *plugin = tcore_object_ref_plugin(co);
2473
2474         dbg("Enter");
2475
2476         server = tcore_plugin_ref_server(plugin);
2477         strg = tcore_server_find_storage(server, "vconf");
2478
2479         req_data = (struct treq_network_set_default_subscription *) tcore_user_request_ref_data(ur, NULL);
2480         dbg("'default' Subscription for CS (Voice): [%d]", req_data->default_subs);
2481
2482         /* Update VCONF through Storage - req_data->current_network is aligned to VCONFKEY values */
2483         if (tcore_storage_set_int(strg,
2484                         STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_SERVICE_INT, req_data->default_subs)) {
2485                 struct tresp_network_set_default_subs resp_data = {0, };
2486                 struct tnoti_network_default_subs default_subs_noti_data = {0, };
2487
2488                 /*
2489                  * Send Response
2490                  */
2491                 resp_data.result = TCORE_RETURN_SUCCESS;
2492                 ret = tcore_user_request_send_response(ur,
2493                         TRESP_NETWORK_SET_DEFAULT_SUBSCRIPTION,
2494                         sizeof(struct tresp_network_set_default_subs), &resp_data);
2495                 /*
2496                  * Send Notification
2497                  */
2498                 default_subs_noti_data.default_subs = req_data->default_subs;
2499                 tcore_server_send_notification(tcore_plugin_ref_server(plugin), co,
2500                         TNOTI_NETWORK_DEFAULT_SUBSCRIPTION,
2501                         sizeof(struct tnoti_network_default_subs), &default_subs_noti_data);
2502         }
2503
2504         dbg("ret: [0x%x]", ret);
2505         return ret;
2506 }
2507
2508 static TReturn get_default_subscription(CoreObject *co, UserRequest *ur)
2509 {
2510         struct tresp_network_get_default_subs resp_data = {0, };
2511         TReturn ret = TCORE_RETURN_FAILURE;
2512         Server *server;
2513         Storage *strg = NULL;
2514         TcorePlugin *plugin = tcore_object_ref_plugin(co);
2515
2516         dbg("Enter");
2517
2518         server = tcore_plugin_ref_server(plugin);
2519         strg = tcore_server_find_storage(server, "vconf");
2520
2521         /* VCONFKEY is aligned to req_data->current_network type */
2522         resp_data.default_subs = tcore_storage_get_int(strg,
2523                         STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_SERVICE_INT);
2524
2525         resp_data.result = TCORE_RETURN_SUCCESS;
2526
2527         /* Send Response */
2528         ret = tcore_user_request_send_response(ur,
2529                 TRESP_NETWORK_GET_DEFAULT_SUBSCRIPTION,
2530                 sizeof(struct tresp_network_get_default_subs), &resp_data);
2531
2532         dbg("ret: [0x%x]", ret);
2533         return ret;
2534 }
2535
2536 static TReturn get_default_data_subscription(CoreObject *co, UserRequest *ur)
2537 {
2538         struct tresp_network_get_default_data_subs resp = {0,};
2539         int ret;
2540         int subscription = -1;
2541
2542         dbg("Enter");
2543
2544         ret = vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS , &subscription);
2545         if (ret < 0) {
2546                 err("vconf_get_int() failed - DDS");
2547                 resp.result = TCORE_RETURN_FAILURE;
2548         } else {
2549                 resp.result = TCORE_RETURN_SUCCESS;
2550                 resp.default_subs = subscription;
2551                 if (subscription == NETWORK_DEFAULT_DATA_SUBS_UNKNOWN)
2552                         resp.default_subs = NETWORK_DEFAULT_DATA_SUBS_UNKNOWN;
2553         }
2554
2555         if( TCORE_RETURN_SUCCESS ==  tcore_user_request_send_response(ur,
2556                         TRESP_NETWORK_GET_DEFAULT_DATA_SUBSCRIPTION,
2557                         sizeof(struct tresp_network_get_default_data_subs), &resp)){
2558                         tcore_user_request_unref(ur);
2559         }
2560         return TCORE_RETURN_SUCCESS;
2561 }
2562
2563 static struct tcore_network_operations network_ops = {
2564         .search = search_network,
2565         .set_plmn_selection_mode = set_plmn_selection_mode,
2566         .get_plmn_selection_mode = get_plmn_selection_mode,
2567         .set_service_domain = NULL,
2568         .get_service_domain = NULL,
2569         .set_band = set_band,
2570         .get_band = get_band,
2571         .set_preferred_plmn = set_preferred_plmn,
2572         .get_preferred_plmn = get_preferred_plmn,
2573         .set_order = NULL,
2574         .get_order = NULL,
2575         .set_power_on_attach = NULL,
2576         .get_power_on_attach = NULL,
2577         .set_cancel_manual_search = cancel_manual_search,
2578         .get_serving_network = get_serving_network,
2579         .set_mode = network_set_mode,
2580         .get_mode = network_get_mode,
2581         .set_default_subscription = set_default_subscription,
2582         .get_default_subscription = get_default_subscription,
2583         .set_default_data_subscription = NULL,
2584         .get_default_data_subscription =get_default_data_subscription,
2585 };
2586
2587 gboolean imc_network_init(TcorePlugin *cp, CoreObject *co_network)
2588 {
2589         CustomData *custom_data;
2590         dbg("Enter");
2591
2592         /* Set operations */
2593         tcore_network_set_ops(co_network, &network_ops);
2594
2595         /* Custom data */
2596         custom_data = g_malloc0(sizeof(CustomData));
2597         custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
2598
2599         tcore_object_link_user_data(co_network, custom_data);
2600
2601         tcore_object_add_callback(co_network, "+CREG", on_event_cs_network_regist, NULL);
2602         tcore_object_add_callback(co_network, "+CGREG", on_event_ps_network_regist, NULL);
2603         tcore_object_add_callback(co_network, "+XCIEV", on_event_network_icon_info, NULL);
2604
2605         /* +CTZV: <tz>,<time> */
2606         tcore_object_add_callback(co_network, "+CTZV", on_event_network_ctzv_time_info, NULL);
2607
2608         tcore_server_add_notification_hook(tcore_plugin_ref_server(cp), TNOTI_SIM_STATUS, on_hook_sim_init, co_network);
2609
2610         _insert_mcc_mnc_oper_list(cp, co_network);
2611
2612         dbg("Exit");
2613
2614         return TRUE;
2615 }
2616
2617 void imc_network_exit(TcorePlugin *cp, CoreObject *co_network)
2618 {
2619         CustomData *custom_data;
2620
2621         custom_data = tcore_object_ref_user_data(co_network);
2622         if (custom_data != NULL)
2623                 g_free(custom_data);
2624
2625         dbg("Exit");
2626 }