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