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