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