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