Tizen 2.0 beta Release
[framework/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: Hayoon Ko <hayoon.ko@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
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <glib.h>
27
28 #include <tcore.h>
29 #include <hal.h>
30 #include <core_object.h>
31 #include <plugin.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_XBANDSEL_0 0 
70 #define AT_XBANDSEL_1800 1800
71 #define AT_XBANDSEL_1900 1900
72 #define AT_XBANDSEL_850 850
73 #define AT_XBANDSEL_450 450
74 #define AT_XBANDSEL_480 480
75 #define AT_XBANDSEL_750 750
76 #define AT_XBANDSEL_380 380
77 #define AT_XBANDSEL_410 410
78
79 #define MAX_NETWORKS_PREF_PLMN_SUPPORT 150
80 #define MAX_NETWORKS_MANUAL_SEARCH_SUPPORT 20
81
82 static unsigned int lookup_tbl_net_status[] = {
83                 [AT_CREG_STAT_NOT_REG] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
84                 [AT_CREG_STAT_REG_HOME] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
85                 [AT_CREG_STAT_SEARCHING] = NETWORK_SERVICE_DOMAIN_STATUS_SEARCH,
86                 [AT_CREG_STAT_REG_DENIED] = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY,
87                 [AT_CREG_STAT_UNKNOWN] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
88                 [AT_CREG_STAT_REG_ROAM] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
89 };
90
91 static unsigned int lookup_tbl_access_technology[] = {
92         [AT_COPS_ACT_GSM]               = NETWORK_ACT_GSM,
93         [AT_COPS_ACT_GSM_COMPACT]       = NETWORK_ACT_GSM,
94         [AT_COPS_ACT_UTRAN]             = NETWORK_ACT_UTRAN,
95         [AT_COPS_ACT_GSM_EGPRS]         = NETWORK_ACT_EGPRS,
96         [AT_COPS_ACT_UTRAN_HSDPA]       = NETWORK_ACT_UTRAN,
97         [AT_COPS_ACT_UTRAN_HSUPA]       = NETWORK_ACT_UTRAN,
98         [AT_COPS_ACT_UTRAN_HSDPA_HSUPA] = NETWORK_ACT_UTRAN,
99         [AT_COPS_ACT_E_UTRAN]           = NETWORK_ACT_GSM_UTRAN,
100 };
101
102 static gboolean get_serving_network(CoreObject *o, UserRequest *ur);
103
104
105 static void on_confirmation_network_message_send(TcorePending *p, gboolean result, void *user_data)
106 {
107         dbg("on_confirmation_modem_message_send - msg out from queue.\n");
108
109         if (result == FALSE) {
110                 /* Fail */
111                 dbg("SEND FAIL");
112         }
113         else {
114                 dbg("SEND OK");
115         }
116 }
117
118 static void nwk_prepare_and_send_pending_request(TcorePlugin *plugin, char *co_name, const char *at_cmd, const char* prefix,enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback)
119 {
120         TcoreATRequest *req = NULL;
121         TcoreHal *hal;
122         CoreObject *o= NULL;
123         TcorePending *pending = NULL;
124         TReturn ret;
125         
126         o = tcore_plugin_ref_core_object(plugin, co_name);
127         hal = tcore_object_get_hal(o);
128         
129         pending = tcore_pending_new(o, 0);
130         req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
131
132         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
133
134         tcore_pending_set_request_data(pending, 0, req);
135         tcore_pending_set_response_callback(pending, callback, req->cmd);
136         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
137
138         ret = tcore_hal_send_request(hal, pending);
139         return;
140 }
141
142
143 static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *o)
144 {
145         Server *s;
146         Storage *strg;
147         void *handle;
148         char query[255] = {     0, };
149         GHashTableIter iter;
150         gpointer key, value;
151         GHashTable *result = NULL, *row = NULL;
152         struct tcore_network_operator_info *noi = NULL;
153         int count = 0;
154
155         s = tcore_plugin_ref_server(p);
156         strg = tcore_server_find_storage(s, "database");
157
158         handle = tcore_storage_create_handle(strg, "/opt/dbspace/.mcc_mnc_oper_list.db");
159         if (!handle) {
160                 dbg("fail to create database handle");
161                 return;
162         }
163
164         snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list");
165
166         result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
167                         (GDestroyNotify) g_hash_table_destroy);
168
169         tcore_storage_read_query_database(strg, handle, query, NULL, result, 4);
170
171         g_hash_table_iter_init(&iter, result);
172         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
173                 row = value;
174
175                 noi = calloc(sizeof(struct tcore_network_operator_info), 1);
176
177                 snprintf(noi->mcc, 4, "%s", (char *)g_hash_table_lookup(row, "1"));
178                 snprintf(noi->mnc, 4, "%s",  (char *)g_hash_table_lookup(row, "2"));
179                 snprintf(noi->name, 41, "%s",  (char *)g_hash_table_lookup(row, "3"));
180                 snprintf(noi->country, 4, "%s",  (char *)g_hash_table_lookup(row, "0"));
181
182                 tcore_network_operator_info_add(o, noi);
183
184                 count++;
185         }
186
187         dbg("count = %d", count);
188
189         g_hash_table_destroy(result);
190
191         tcore_storage_remove_handle(strg, handle);
192 }
193
194 static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type,
195                 int domain, int act, int cs_status, int ps_status)
196 {
197         enum telephony_network_service_type ret;
198
199         ret = prev_type;
200
201         switch (act) {
202                 case NETWORK_ACT_UNKNOWN:
203                         ret = NETWORK_SERVICE_TYPE_UNKNOWN;
204                         break;
205
206                 case NETWORK_ACT_GSM:
207                         if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE && domain == NETWORK_SERVICE_DOMAIN_CS)
208                                 ret = NETWORK_SERVICE_TYPE_2_5G_EDGE;
209                         else
210                                 ret = NETWORK_SERVICE_TYPE_2G;
211                         break;
212
213                 case NETWORK_ACT_EGPRS:
214                         return NETWORK_SERVICE_TYPE_2_5G_EDGE;
215                         break;
216
217                 case NETWORK_ACT_UMTS:
218                         ret = NETWORK_SERVICE_TYPE_3G;
219                         break;
220
221         }
222
223         if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) {
224                 ret = NETWORK_SERVICE_TYPE_NO_SERVICE;
225         }
226         else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) 
227         {
228                 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) 
229                 {
230                         /* no change */
231                 }
232                 else 
233                 {
234                         ret = NETWORK_SERVICE_TYPE_SEARCH;
235                 }
236         }
237         else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) 
238         {
239                 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) 
240                 {
241                         /* no change */
242                 }
243                 else 
244                 {
245                         ret = NETWORK_SERVICE_TYPE_EMERGENCY;
246                 }
247         }
248
249         return ret;
250 }
251
252 static void _ps_set(TcorePlugin *p, int status)
253 {
254         GSList *co_list = NULL;
255
256         co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_PS);
257         do {
258                 CoreObject *o = NULL;
259                 o = (CoreObject *) co_list->data;
260                 if (!o)
261                         break;
262
263                 if (status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
264                         tcore_ps_set_online(o, TRUE);
265                 }
266                 else {
267                         tcore_ps_set_online(o, FALSE);
268                 }
269         } while ((co_list = g_slist_next(co_list)));
270
271         g_slist_free(co_list);
272 }
273
274 static void on_timeout_search_network(TcorePending *p, void *user_data)
275 {
276         UserRequest *ur;
277         struct tresp_network_search resp;
278
279         dbg("TIMEOUT !!!!! pending=%p", p);
280
281         memset(&resp, 0, sizeof(struct tresp_network_search));
282
283         resp.list_count = 0;
284
285         ur = tcore_pending_ref_user_request(p);
286         if (ur) {
287                 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &resp);
288         }
289 }
290
291 static void on_response_set_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data)
292 {
293         UserRequest *ur;
294         const TcoreATResponse *atResp = data;
295        //GSList *tokens = NULL;
296         //char * line = NULL;
297         struct tresp_network_set_plmn_selection_mode resp = {0};
298         
299         if(atResp->success > 0)
300         {
301                 dbg("RESPONSE OK");
302                 resp.result = TCORE_RETURN_SUCCESS;
303         }
304         else
305         {
306                 dbg("RESPONSE NOK");
307                 resp.result = TCORE_RETURN_FAILURE;
308         }
309
310         ur = tcore_pending_ref_user_request(p);
311         if (ur) {
312                 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_set_plmn_selection_mode), &resp);
313         }
314 }
315
316 static void on_response_get_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data)
317 {
318         UserRequest *ur;
319         struct tresp_network_get_plmn_selection_mode resp = {0};
320         const TcoreATResponse *atResp = data;
321        GSList *tokens = NULL;
322         char * line = NULL;
323         int mode = 0;
324
325         resp.result = TCORE_RETURN_FAILURE;
326
327         if(atResp->success > 0)
328         {
329                 dbg("RESPONSE OK");
330                 /* Format of output 
331                 +COPS: <mode>[,<format>,<oper>[,< AcT>]]
332                 */
333                 
334                 if(atResp->lines)
335                         {
336                                 line = (char*)atResp->lines->data;
337                                 tokens = tcore_at_tok_new(line);
338                                 if (g_slist_length(tokens) < 1){
339                                 msg("invalid message");
340                                 goto OUT;
341                                 }
342                                 mode = atoi(tcore_at_tok_nth(tokens, 0));
343                                 dbg("mode = %d", mode);
344                         
345                                 switch(mode) {
346                                         case AT_COPS_MODE_AUTOMATIC:
347                                                 resp.mode = NETWORK_SELECT_MODE_GLOBAL_AUTOMATIC;
348                                                 break;
349                                         case AT_COPS_MODE_MANUAL:
350                                         case AT_COPS_MODE_MANUAL_AUTOMATIC:
351                                                 resp.mode = NETWORK_SELECT_MODE_GSM_MANUAL;
352                                                 break;
353                                         case AT_COPS_MODE_DEREGISTER:
354                                         case AT_COPS_MODE_SET_ONLY:
355                                                 resp.result = TCORE_RETURN_FAILURE;
356                                         goto OUT;
357                                 }
358                         resp.result = TCORE_RETURN_SUCCESS;
359                         }
360         }
361         else
362         {
363                 dbg("RESPONSE NOK");
364                 resp.result = TCORE_RETURN_FAILURE;
365         }
366
367 OUT:
368         ur = tcore_pending_ref_user_request(p);
369         if (ur) {
370                 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_get_plmn_selection_mode), &resp);
371         }
372
373         if(tokens != NULL)
374                 tcore_at_tok_free(tokens);
375
376         return;
377
378 }
379
380 static void on_response_search_network(TcorePending *p, int data_len, const void *data, void *user_data)
381 {
382         UserRequest *ur;
383         struct tresp_network_search resp;
384         int i = 0, ctr =0;
385         char* line=NULL;
386         const TcoreATResponse *atResp = data;
387        GSList *tokens = NULL;
388        GSList *network_token = NULL;
389         int AcT=0 , stat = 0;
390         char* cp_plmn =NULL;
391         char* temp_plmn_info =NULL;
392         char *pResp = NULL;
393         int num_network_avail = 0;
394
395         memset(&resp, 0, sizeof(struct tresp_network_search));
396         resp.result = TCORE_RETURN_FAILURE;
397         resp.list_count = 0;
398
399         if(atResp->success > 0)
400         {
401                 dbg("RESPONSE OK");
402                 if(atResp->lines) {
403                         line = (char*)atResp->lines->data;
404                         tokens = tcore_at_tok_new(line);
405                         num_network_avail = g_slist_length(tokens);
406                         dbg(" length of tokens is %d\n", num_network_avail);
407                         if (num_network_avail < 1) {
408                                 msg("invalid message");
409                                 goto OUT;
410                         }
411                 }
412                                         
413                 resp.result = TCORE_RETURN_SUCCESS;
414                 /*
415                  *      +COPS: [list of supported (<stat>,long alphanumeric <oper>,short alphanumeric <oper>,numeric <oper>[,<AcT>])s]
416                  *             [,,(list of supported <mode>s),(list of supported <format>s)]
417                 */
418                         
419                 /* (2,"IND airtel","airtel","40445",2,),(1,"IND airtel","airtel","40445",0,),(3,"TATA DOCOMO","TATA DO","405034",2,) */
420                         
421                 for(i=0; ((i<num_network_avail) && (i<MAX_NETWORKS_MANUAL_SEARCH_SUPPORT)); i++)
422                         {
423                         /* (2,"IND airtel","airtel","40445",2,) */
424                         network_token = tcore_at_tok_new(g_slist_nth_data(tokens, i));
425
426                         pResp = (tcore_at_tok_nth(network_token, 0));
427                         if(pResp != NULL){
428                                 dbg("status : %s",pResp);
429                                 resp.list[i].status = (enum telephony_network_plmn_status)atoi(pResp);
430                         }
431
432                         if (pResp = (tcore_at_tok_nth(network_token, 1)))
433                         { /* Long Aplha name */
434                                 dbg("Long Aplha name : %s",pResp);
435                                 
436                                 if(strlen(pResp) > 0)
437                                         /* Strip off starting quote & ending quote */
438                                         strncpy(resp.list[i].name, pResp+1, strlen(pResp)-2);
439                         }
440                         else if (pResp = (tcore_at_tok_nth(network_token, 2)))
441                         { 
442                                 dbg("Short Aplha name : %s",pResp);
443                                 /* Short Aplha name */
444                                 /* Strip off starting quote & ending quote */
445                                 if(strlen(pResp) > 0)
446                                         strncpy(resp.list[i].name, pResp+1, strlen(pResp)-2);
447                         }
448
449                         /* PLMN ID */
450                         pResp = tcore_at_tok_nth(network_token, 3);
451                         if(pResp != NULL)
452                         {
453                                 dbg("PLMN ID : %s",pResp);
454                                 if(strlen(pResp) > 0){
455                                         temp_plmn_info = malloc((strlen(pResp) - 2)+1); /* 1 extra character for NULL storage */
456                                         memset(temp_plmn_info, 0x00, strlen(pResp) -2+1);
457                                         
458                                         /* Strip off starting quotes & ending quotes */
459                                         strncpy(temp_plmn_info, pResp+1, strlen(pResp)-2);
460                                 }
461                         }
462
463                         /* Decode PLMN ID from Hexa String to Hexa bytes */
464                         //cp_plmn = util_hexStringToBytes(temp_plmn_info);
465                 
466                         memcpy(resp.list[i].plmn, temp_plmn_info, 6);
467                                         if (resp.list[i].plmn[5] == '#')
468                                                 resp.list[i].plmn[5] = '\0';
469
470                         /* Parse Access Technology */
471                         if(pResp = tcore_at_tok_nth(tokens, 4))
472                         {
473                                 if(strlen(pResp) > 0){
474                                         AcT = atoi(pResp);
475                                 
476                                         if (0 == AcT)
477                                                 resp.list[i].act = NETWORK_ACT_GSM;
478                                         else if(2 == AcT)
479                                                 resp.list[i].act = NETWORK_ACT_UMTS;
480                                 }
481                         }
482
483                         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, AcT);
484                         resp.list_count++;
485
486                         tcore_at_tok_free(network_token);
487                         free(temp_plmn_info);
488                         //free(cp_plmn);
489                 }
490         }
491         else
492         {
493                         dbg("RESPONSE NOK");
494                         resp.result = TCORE_RETURN_FAILURE;
495         }
496
497 OUT:
498         ur = tcore_pending_ref_user_request(p);
499         if (ur) {
500                 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &resp);
501         }
502         tcore_at_tok_free(tokens);
503         return;
504 }
505
506 static void on_response_set_service_domain(TcorePending *p, int data_len, const void *data, void *user_data)
507 {
508         dbg("Entry");
509
510         dbg("Exit");
511         return;
512 }
513
514 static void on_response_get_service_domain(TcorePending *p, int data_len, const void *data, void *user_data)
515 {
516         dbg("Entry");
517
518         dbg("Exit");
519         return;
520 }
521
522 static void on_response_set_band(TcorePending *p, int data_len, const void *data, void *user_data)
523 {
524         UserRequest *ur;
525         struct tresp_network_set_band resp;
526
527         char* line=NULL;
528         const TcoreATResponse *atResp = data;
529
530         dbg("On Response Set Band");
531         if(atResp->success > 0)
532         {
533                 dbg("Response OK");
534                 resp.result = TCORE_RETURN_SUCCESS;
535         }else
536         {
537                 dbg("Response NOK");
538                 resp.result = TCORE_RETURN_FAILURE;
539         }
540
541         ur = tcore_pending_ref_user_request(p);
542         if (ur) {
543                 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_BAND, sizeof(struct tresp_network_set_band), &resp);
544         }
545 }
546
547 static void on_response_get_band(TcorePending *p, int data_len, const void *data, void *user_data)
548 {
549         dbg("Entry");
550
551         dbg("Exit");
552         return;
553 }
554
555 static void on_response_set_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data)
556 {
557         dbg("Entry");
558
559         dbg("Exit");
560         return;
561 }
562
563 static void on_response_get_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data)
564 {
565         UserRequest *ur;
566         int i = 0, ctr =0;
567         char* line=NULL;
568         const TcoreATResponse *atResp = data;
569        GSList *tokens = NULL;
570         char* cp_plmn =NULL;
571         char temp_plmn_info[17] = {0};
572         char *pResp = NULL;
573         int num_network_avail = 0;
574         int plmn_format = 0;
575         
576         struct tresp_network_get_preferred_plmn resp = {0};
577         int total_lines = 0;
578         int GSM_AcT2 = 0, GSM_Compact_AcT2= 0, UTRAN_AcT2 = 0;
579
580         dbg("Entry");
581
582         if(atResp->success > 0)
583         {
584                 dbg("RESPONSE OK");
585                 if(atResp->lines) {
586                         total_lines = g_slist_length(atResp->lines);
587                         dbg("Total number of network present in Preferred PLMN list is %d\n", total_lines);
588
589                         if (total_lines < 1) {
590                                 msg("invalid message");
591                                 goto OUT;
592                         }
593
594                         if (total_lines >= MAX_NETWORKS_PREF_PLMN_SUPPORT)
595                                 total_lines = MAX_NETWORKS_PREF_PLMN_SUPPORT;
596                         
597 /*
598 +COPL: <index1>,<format>,<oper1>[,<GSM_AcT1>,<GSM_Compact_AcT1>,<UTRAN_AcT1>,<E-UTRAN_AcT1>] [<CR><LF>
599 +CPOL: <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>,<E-UTRAN_AcT2>]
600 */
601
602                         resp.result = TCORE_RETURN_SUCCESS;
603
604                         for (i=0; i<total_lines; i++) {
605                                 /* Take each line response at a time & parse it */
606                                 line = tcore_at_tok_nth(atResp->lines, i);
607                                 tokens = tcore_at_tok_new(line);
608
609                                 /* <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>,<E-UTRAN_AcT2>] */
610
611                                 /* EF Index */
612                                 if (pResp = tcore_at_tok_nth(tokens, 0))
613                                 {
614                                         dbg("Index : %s",pResp);                                        
615                                         resp.list[i].ef_index = atoi(pResp);
616                                 }
617                                 /* Format */
618                                 if(pResp = tcore_at_tok_nth(tokens, 1))
619                                 {
620                                         dbg("format : %s",pResp);
621                                         plmn_format = atoi(pResp);
622                                 }
623
624                                 /* Operator PLMN ID */
625                                 if(pResp = tcore_at_tok_nth(tokens, 2));
626                                 {
627                                         dbg("plmn ID : %s",pResp);
628
629                                         if(strlen(pResp) > 0){
630                                                 strncmp(temp_plmn_info, pResp+1, strlen(pResp)-2);
631                                         
632                                                 //Get only PLMN ID
633                                                 if (plmn_format == 2)
634                                                 {
635                                                         //cp_plmn = util_hexStringToBytes(temp_plmn_info);
636                                                 
637                                                         if (strncmp((char *)temp_plmn_info, "000000", 6) == 0)
638                                                                 continue;
639                                 
640                                                         memcpy(resp.list[i].plmn, temp_plmn_info, 6);
641                                                         if (resp.list[i].plmn[5] == '#')
642                                                                 resp.list[i].plmn[5] = '\0';
643
644                                                         //free(cp_plmn);
645                                                 }
646                                         }
647                                 }
648
649                                 if(pResp = tcore_at_tok_nth(tokens, 3)){
650                                         dbg("GSM_AcT2  : %s",pResp);
651                                         GSM_AcT2 = atoi(pResp);
652                                 }
653                                         
654                                 if(pResp = tcore_at_tok_nth(tokens, 4)){
655                                         dbg("GSM_Compact AcT2  : %s",pResp);
656                                         GSM_Compact_AcT2 = atoi(pResp);
657                                 }
658         
659                                 if(pResp = tcore_at_tok_nth(tokens, 5)){
660                                         dbg("UTRAN_AcT2  : %s",pResp);
661                                         UTRAN_AcT2 = atoi(pResp);
662                                 }
663
664                                 if(UTRAN_AcT2 && (GSM_AcT2 ||GSM_Compact_AcT2))
665                                         resp.list[i].act = NETWORK_ACT_GSM_UTRAN;
666                                 else if (UTRAN_AcT2)
667                                         resp.list[i].act = NETWORK_ACT_UMTS;
668                                 else if (GSM_AcT2 || GSM_Compact_AcT2)
669                                         resp.list[i].act = NETWORK_ACT_GPRS;
670
671                                 (resp.list_count)++;
672
673                                 tcore_at_tok_free(tokens);
674                         }
675                 }
676         }
677 OUT:
678         ur = tcore_pending_ref_user_request(p);
679         if (ur) {
680                 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PREFERRED_PLMN, sizeof(struct tresp_network_get_preferred_plmn), &resp);
681         }
682         dbg("Exit");
683         return;
684 }
685
686 static void on_response_set_order(TcorePending *p, int data_len, const void *data, void *user_data)
687 {
688         dbg("Entry");
689
690         dbg("Exit");
691         return;
692 }
693
694 static void on_response_get_order(TcorePending *p, int data_len, const void *data, void *user_data)
695 {
696         dbg("Entry");
697
698         dbg("Exit");
699         return;
700 }
701
702 static void on_response_set_power_on_attach(TcorePending *p, int data_len, const void *data, void *user_data)
703 {
704         dbg("Entry");
705
706         dbg("Exit");
707         return;
708 }
709
710 static void on_response_get_power_on_attach(TcorePending *p, int data_len, const void *data, void *user_data)
711 {
712         dbg("Entry");
713
714         dbg("Exit");
715         return;
716 }
717
718 static void on_response_set_cancel_manual_search(TcorePending *p, int data_len, const void *data, void *user_data)
719 {
720         dbg("Entry");
721
722         dbg("Exit");
723         return;
724 }
725
726
727 static void on_response_get_serving_network(TcorePending *p, int data_len, const void *data, void *user_data)
728 {
729         const TcoreATResponse* resp = data;
730         UserRequest *ur;
731         struct tresp_network_get_serving_network Tresp = {0};
732         char plmn[7] = {0};
733         char *long_plmn_name, *short_plmn_name = NULL;
734         CoreObject *o;
735         GSList *tokens=NULL;
736         const char *line;
737         int network_mode = -1;
738         int plmn_format = -1;
739         enum telephony_network_access_technology AcT = NETWORK_ACT_UNKNOWN;
740         struct tnoti_network_identity noti ={0};
741         char *pResp = NULL;
742         int nol, count =0;
743
744         o = tcore_pending_ref_core_object(p);
745
746         if(resp->success <= 0){
747                 dbg("RESPONSE NOK");
748
749                 ur = tcore_pending_ref_user_request(p);
750                 if (ur) {
751                         Tresp.result = TCORE_RETURN_FAILURE;            
752                         tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp);
753                 }
754
755                 return;
756         }else{
757         dbg("RESPONSE OK");
758                 nol = g_slist_length(resp->lines);
759                 dbg("nol : %d", nol);
760
761                 for(count =0; count < nol; count++){
762                         //parse each line 
763                                 line = g_slist_nth_data(resp->lines, count);
764                 tokens = tcore_at_tok_new(line);
765                         dbg("line %d start---------------",count);
766                         //mode
767                 if (pResp = tcore_at_tok_nth(tokens, 0)){
768                         dbg("mode  : %s",pResp);
769                         network_mode = atoi(pResp);
770                 }
771
772                         //format (optional)                     
773                 if(pResp = tcore_at_tok_nth(tokens, 1))
774                 {
775                         dbg("format  : %s",pResp);
776                                         if(strlen(pResp)>0)
777                         plmn_format = atoi(pResp);
778                 }
779
780                         //plmn 
781                 switch(plmn_format)
782                 {
783                         case AT_COPS_FORMAT_LONG_ALPHANUMERIC: 
784                                 if(pResp = tcore_at_tok_nth(tokens, 2))
785                                 {               
786                                         dbg("long PLMN  : %s",pResp);
787                                         if(strlen(pResp) > 0){
788                                                 long_plmn_name = malloc((strlen(pResp) - 2)+1); /* 1 extra character for NULL storage */
789                                                 memset(long_plmn_name, 0x00, strlen(pResp) -2+1);
790                                                 /* Strip off starting quotes & ending quotes */
791                                                 strncpy(long_plmn_name, pResp+1, strlen(pResp)-2);
792
793                                                 //set network name into po
794                                                 tcore_network_set_network_name(o,TCORE_NETWORK_NAME_TYPE_FULL,long_plmn_name);
795                                         }
796                                 }
797                                 break;
798                 
799                                 case AT_COPS_FORMAT_SHORT_ALPHANUMERIC:
800                                         if(pResp = tcore_at_tok_nth(tokens, 2))
801                                         {
802                                                 dbg("short PLMN  : %s",pResp);
803                                                 if(strlen(pResp)>0){
804                                                         short_plmn_name = malloc((strlen(pResp) - 2)+1); /* 1 extra character for NULL storage */
805                                                         memset(short_plmn_name, 0x00, strlen(pResp) -2+1);
806                                                         /* Strip off starting quotes & ending quotes */
807                                                         strncpy(short_plmn_name, pResp+1, strlen(pResp)-2);
808                                                         
809                                                         //set network name into po                                                      
810                                                         tcore_network_set_network_name(o,TCORE_NETWORK_NAME_TYPE_SHORT,short_plmn_name);                                                        
811                                                 }
812                                         }                                       
813                                 break;
814
815                                 case AT_COPS_FORMAT_NUMERIC:
816                                         if(pResp = tcore_at_tok_nth(tokens, 2))
817                                         {
818                                                 dbg("numeric : %s", pResp);
819                                                 if(strlen(pResp)>0){
820                                                         memset(plmn, 0, 7);
821                                                         /* Strip off starting quotes & ending quotes */
822                                                         strncpy(plmn, pResp+1, strlen(pResp)-2);                                                        
823
824                                                         tcore_network_set_plmn(o,plmn);
825                                                 }
826                                         }
827                                 break;
828         
829                                 default:
830                                 break;
831                         }
832
833                         //act 
834                         if(pResp = tcore_at_tok_nth(tokens, 3))
835                         {               
836                                 if(strlen(pResp)>0){
837                                         dbg("act  : %s",pResp);                                         
838                                          AcT = lookup_tbl_access_technology[atoi(pResp)];
839                                         dbg("AcT  : %d",AcT);   
840
841                                         tcore_network_set_access_technology(o, AcT);
842                                 }
843                         }
844
845                         tcore_at_tok_free(tokens);
846                 }
847
848                 memcpy(Tresp.plmn, plmn, 7);
849                 tcore_network_get_access_technology(o, &(Tresp.act)); 
850                 tcore_network_get_lac(o, &(Tresp.gsm.lac)); 
851
852                 ur = tcore_pending_ref_user_request(p);
853                 if (ur) {
854                         Tresp.result = TCORE_RETURN_SUCCESS;            
855                         tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp);
856                 }
857                 else
858                 {
859                         /* Network change noti */
860                         struct tnoti_network_change network_change;
861
862                         memset(&network_change, 0, sizeof(struct tnoti_network_change));
863                         memcpy(network_change.plmn, plmn, 7);
864                         tcore_network_get_access_technology(o, &(network_change.act));
865                         tcore_network_get_lac(o, &(network_change.gsm.lac));
866
867                         tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(p)), tcore_pending_ref_core_object(p),
868                                 TNOTI_NETWORK_CHANGE, sizeof(struct tnoti_network_change), &network_change);
869
870                         dbg("dbg.. network_change.plmn  : %s",network_change.plmn);
871                         dbg("dbg.. network_change.act  : %d",network_change.act);                                               
872                         dbg("dbg.. network_change.gsm.lac  : %d",network_change.gsm.lac);
873
874
875                         if((AT_COPS_MODE_DEREGISTER !=network_mode) &&
876                                 (AT_COPS_MODE_SET_ONLY != network_mode)){
877                                 /*Network identity noti*/
878                                 memset(&noti, 0, sizeof(struct tnoti_network_change));
879                                 if(long_plmn_name)
880                                         memcpy(noti.full_name, long_plmn_name, MIN(33, strlen(long_plmn_name)) );
881                                 if(short_plmn_name)
882                                         memcpy(noti.short_name, short_plmn_name, MIN(17, strlen(long_plmn_name)) );
883                                 memcpy(noti.plmn, plmn,7);
884                                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), 
885                                         o, TNOTI_NETWORK_IDENTITY,      sizeof(struct tnoti_network_identity), &noti);          
886
887                                 dbg("dbg.. noti.short_name  : %s",noti.short_name);
888                                 dbg("dbg.. noti.full_name  : %s",noti.full_name);                                               
889                                 dbg("dbg.. noti.plmn  : %s",noti.plmn); 
890                         }
891                 }
892
893                 if(long_plmn_name)
894                         free(long_plmn_name);
895                 if(short_plmn_name)
896                         free(short_plmn_name);
897         }
898
899         return;
900
901 }
902
903 static gboolean on_event_ps_network_regist(CoreObject *o, const void *data, void *user_data)
904 {
905         struct tnoti_network_registration_status regist_status;
906         enum telephony_network_service_domain_status cs_status;
907         enum telephony_network_service_domain_status ps_status;
908         enum telephony_network_service_type service_type;
909         enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
910         struct tnoti_network_location_cellinfo net_lac_cell_info = {0};
911         struct tnoti_ps_protocol_status noti = {0};
912         int ret;
913         unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_PS;
914         int stat= 0, AcT=0;
915         unsigned int lac=0xffff, ci=0xffff;
916         unsigned int rac = 0xffff;
917         GSList* tokens = NULL;
918         char* pResp;
919         char *line = NULL;
920         GSList *lines = NULL;
921
922         lines = (GSList*)data;
923         if (1 != g_slist_length(lines)) {
924                 dbg("unsolicited msg but multiple line");
925             goto OUT;
926         }
927         line  = (char*)(lines->data);
928         dbg("+CGREG NOTI RECEIVED");
929
930 /*
931 +CREG: <stat> [[,<lac>,<ci>[AcT]]
932
933 Possible values of <stat> can be
934 0 Not registered, ME is not currently searching a new operator to register to
935 1 Registered, home network
936 2 Not registered, but ME is currently searching a new operator to register
937 3 Registration denied
938 4 Unknown
939 5 Registered, in roaming
940
941 <lac>
942 string type; two byte location area code in hexadecimal format (e.g. ï¿½00C3�)
943
944 <ci>
945 string type; four byte cell ID in hexadecimal format (e.g. ï¿½0000A13F�)
946
947 <ACT>
948 0 GSM
949 2 UTRAN
950 3 GSM w/EGPRS
951 4 UTRAN w/HSDPA
952 5 UTRAN w/HSUPA
953 6 UTRAN w/HSDPA and HSUPA
954 Note: <Act> is supporting from R7 and above Protocol Stack.
955
956 <rac>: is R7 and above feature, string type; one byte routing area code in hexadecimal format.
957 */
958         if (line!=NULL)
959         {
960                 tokens = tcore_at_tok_new(line);
961                 if(g_slist_length(tokens) < 1) {
962                         msg("invalid message");
963                         goto OUT;
964                 }
965
966                 if(!(pResp = g_slist_nth_data(tokens, 0)))
967                 {
968                         dbg("No  STAT in +CGREG");
969                         goto OUT;
970                 }
971                 else
972                 {
973                         stat = atoi(pResp);     
974                         if(pResp = g_slist_nth_data(tokens, 1))
975                                 lac = atoi(pResp);
976
977                         if((pResp = g_slist_nth_data(tokens, 2)))
978                                 ci = atoi(pResp);
979                         else
980                                 dbg("No ci in +CGREG");
981                                 
982                         if(pResp = g_slist_nth_data(tokens, 3))
983                                 AcT = atoi(pResp);
984                         else
985                                 dbg("No AcT in +CGREG");
986                         
987                         if(pResp = g_slist_nth_data(tokens, 4))
988                                 rac = atoi(pResp);
989                         else
990                                 dbg("No rac in +CGREG");
991                 }
992
993
994                 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d, rac = 0x%x", stat, lac, ci, AcT, rac);
995
996                 ps_status = lookup_tbl_net_status[stat];
997                 
998                 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status);
999                 _ps_set(tcore_object_ref_plugin(o), ps_status);
1000                         
1001                 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
1002
1003                 act = lookup_tbl_access_technology[AcT];
1004                 tcore_network_set_access_technology(o, act);
1005
1006                 if (stat == AT_CREG_STAT_REG_ROAM)
1007                         tcore_network_set_roaming_state(o, TRUE);
1008                 else
1009                         tcore_network_set_roaming_state(o, FALSE);
1010
1011                 tcore_network_get_service_type(o, &service_type);
1012                 dbg("prev_service_type = 0x%x", service_type);
1013                 service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status);
1014                 dbg("new_service_type = 0x%x", service_type);
1015                 tcore_network_set_service_type(o, service_type);
1016
1017                 tcore_network_set_lac(o, lac);
1018                 tcore_network_set_cell_id(o, ci);
1019                 tcore_network_set_rac(o, rac);
1020
1021                 net_lac_cell_info.lac = lac;
1022                 net_lac_cell_info.cell_id = ci;
1023
1024                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO,
1025                                 sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info);
1026
1027                 regist_status.cs_domain_status = cs_status;
1028                 regist_status.ps_domain_status = ps_status;
1029                 regist_status.service_type = service_type;
1030                 regist_status.roaming_status = tcore_network_get_roaming_state(o);
1031
1032                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
1033                                 TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), &regist_status);
1034
1035                 if(service_type == NETWORK_SERVICE_TYPE_HSDPA)
1036                         noti.status = TELEPHONY_HSDPA_ON;
1037                 else
1038                         noti.status = TELEPHONY_HSDPA_OFF;
1039                 
1040                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_PS_PROTOCOL_STATUS,
1041                 sizeof(struct tnoti_ps_protocol_status), &noti);
1042
1043                 /* Get PLMN ID needed to application */
1044                 //get_serving_network(o, NULL);
1045
1046
1047         }
1048         else
1049         {
1050                 dbg("Response NOK");
1051         }
1052
1053 OUT:
1054         if(NULL!=tokens)
1055         tcore_at_tok_free(tokens);
1056         return TRUE;
1057 }
1058
1059 static gboolean on_event_cs_network_regist(CoreObject *o, const void *event_info, void *user_data)
1060 {
1061         GSList *lines = NULL;
1062         char *line = NULL;
1063         struct tnoti_network_registration_status regist_status;
1064         enum telephony_network_service_domain_status cs_status;
1065         enum telephony_network_service_domain_status ps_status;
1066         enum telephony_network_service_type service_type;
1067         enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
1068         struct tnoti_network_location_cellinfo net_lac_cell_info = {0};
1069
1070         int ret;
1071         unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_CS;
1072         int stat= 0, AcT=0;
1073         unsigned int lac=0xffff, ci=0xffff;
1074         GSList* tokens = NULL;
1075         char* pResp;
1076
1077         lines = (GSList*)event_info;
1078         if (1 != g_slist_length(lines)) {
1079                 dbg("unsolicited msg but multiple line");
1080             goto OUT;
1081         }
1082         line  = (char*)(lines->data);
1083
1084         dbg("+CREG NOTI RECEIVED");
1085
1086 /*
1087 +CREG: <stat> [[,<lac>,<ci>[AcT]]
1088
1089 Possible values of <stat> can be
1090 0 Not registered, ME is not currently searching a new operator to register to
1091 1 Registered, home network
1092 2 Not registered, but ME is currently searching a new operator to register
1093 3 Registration denied
1094 4 Unknown
1095 5 Registered, in roaming
1096
1097 <lac>
1098 string type; two byte location area code in hexadecimal format (e.g. ï¿½00C3�)
1099
1100 <ci>
1101 string type; four byte cell ID in hexadecimal format (e.g. ï¿½0000A13F�)
1102
1103 <ACT>
1104 0 GSM
1105 2 UTRAN
1106 3 GSM w/EGPRS
1107 4 UTRAN w/HSDPA
1108 5 UTRAN w/HSUPA
1109 6 UTRAN w/HSDPA and HSUPA
1110 Note: <Act> is supporting from R7 and above Protocol Stack.
1111 */
1112         if (line!=NULL)
1113         {
1114                 tokens = tcore_at_tok_new(line);
1115                 if(g_slist_length(tokens) < 1) {
1116                         msg("invalid message");
1117                         goto OUT;
1118                 }
1119
1120                 if(!(pResp = g_slist_nth_data(tokens, 0)))
1121                 {
1122                         dbg("No  STAT in +CREG");
1123                         goto OUT;
1124                 }
1125                 else
1126                 {
1127                         stat = atoi(pResp);     
1128                         if(pResp = g_slist_nth_data(tokens, 1))
1129                                 lac = atoi(pResp);
1130
1131                         if((pResp = g_slist_nth_data(tokens, 2)))
1132                                 ci = atoi(pResp);
1133                         else
1134                                 dbg("No ci in +CREG");
1135                                 
1136                         if(pResp = g_slist_nth_data(tokens, 3))
1137                                 AcT = atoi(pResp);
1138                         else
1139                                 dbg("No AcT in +CREG");
1140                 }
1141
1142
1143                 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d", stat, lac, ci, AcT);
1144
1145                 cs_status = lookup_tbl_net_status[stat];
1146                 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, cs_status);
1147
1148         //      tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
1149                 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status);
1150
1151                 act = lookup_tbl_access_technology[AcT];
1152                 tcore_network_set_access_technology(o, act);
1153
1154                 if (stat == AT_CREG_STAT_REG_ROAM)
1155                         tcore_network_set_roaming_state(o, TRUE);
1156                 else
1157                         tcore_network_set_roaming_state(o, FALSE);
1158
1159                 tcore_network_get_service_type(o, &service_type);
1160                 dbg("prev_service_type = 0x%x", service_type);
1161                 service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status);
1162                 dbg("new_service_type = 0x%x", service_type);
1163                 tcore_network_set_service_type(o, service_type);
1164
1165                 tcore_network_set_lac(o, lac);
1166                 tcore_network_set_cell_id(o, ci);
1167
1168                 net_lac_cell_info.lac = lac;
1169                 net_lac_cell_info.cell_id = ci;
1170
1171                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO,
1172                                 sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info);
1173
1174                 regist_status.cs_domain_status = cs_status;
1175                 regist_status.ps_domain_status = ps_status;
1176                 regist_status.service_type = service_type;
1177                 regist_status.roaming_status = tcore_network_get_roaming_state(o);
1178
1179                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
1180                                 TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), &regist_status);
1181
1182                 /* Get PLMN ID needed to application */
1183                 if((NETWORK_SERVICE_DOMAIN_STATUS_FULL == cs_status )||
1184                         NETWORK_SERVICE_DOMAIN_STATUS_FULL ==ps_status )
1185                 get_serving_network(o, NULL);
1186         }
1187         else
1188         {
1189                 dbg("Response NOK");
1190         }
1191
1192 OUT:
1193         if(NULL!=tokens)
1194         tcore_at_tok_free(tokens);
1195         return TRUE;
1196
1197 }
1198
1199 static gboolean on_event_network_icon_info(CoreObject *o, const void *event_info, void *user_data)
1200 {
1201         struct tnoti_network_icon_info net_icon_info = {0};
1202         char *line = NULL;
1203         
1204         int rssi = 0, battery = 0;
1205         char * rssiToken = NULL;
1206         char *batteryToken = NULL;
1207         GSList* tokens = NULL;
1208         GSList *lines = NULL;
1209
1210         lines = (GSList*)event_info;
1211         if (1 != g_slist_length(lines)) {
1212                 dbg("unsolicited msg but multiple line");
1213             goto OUT;
1214         }
1215         line = (char*)(lines->data);
1216         dbg("+XCIEV Network Icon Info Noti Recieve");
1217         memset(&net_icon_info, 0, sizeof(struct tnoti_network_icon_info));
1218
1219         if(line != NULL)
1220         {
1221                 dbg("Response OK");
1222         
1223                 tokens = tcore_at_tok_new(line);
1224                 if (g_slist_length(tokens) != 2) {
1225                         msg("invalid message");
1226                         goto OUT;
1227                 }
1228
1229                 rssiToken = (char *)g_slist_nth_data(tokens, 0);
1230
1231                 if (strlen(rssiToken)>0)
1232                 {
1233                         net_icon_info.type = NETWORK_ICON_INFO_RSSI;
1234                         net_icon_info.rssi= atoi(g_slist_nth_data(tokens, 0));
1235                         dbg("rssi level : %d",net_icon_info.rssi);
1236                 }
1237                 else
1238                 {
1239                         dbg("No rssi value");
1240                 }
1241                 
1242                 batteryToken = (char *)g_slist_nth_data(tokens,1);
1243                 if (strlen(batteryToken)>0)
1244                 {
1245                         net_icon_info.type = NETWORK_ICON_INFO_BATTERY;
1246                         net_icon_info.battery= 1 + atoi(g_slist_nth_data(tokens, 1)); // 1 level added for proper battery indication
1247                         dbg("battery level : %d",net_icon_info.battery);
1248                 }
1249                 else
1250                 {
1251                         dbg("No battery level recieved");
1252                 }
1253                 
1254                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_ICON_INFO,
1255                                 sizeof(struct tnoti_network_icon_info), &net_icon_info);
1256         }
1257         else
1258         {
1259                 dbg("Response NOK");            
1260         }
1261
1262
1263 OUT:
1264         if(NULL!=tokens)
1265         tcore_at_tok_free(tokens);
1266         return TRUE;
1267         
1268 }
1269
1270 static gboolean on_event_network_time_info(CoreObject *o, const void *event_info, void *user_data)
1271 {
1272         struct tnoti_network_timeinfo net_time_info = {0};
1273         int gmtoff;
1274         char *line = NULL;
1275         GSList* tokens = NULL;
1276         char *time= NULL, *time_zone_variance = NULL;
1277         GSList *lines = NULL;
1278
1279         dbg("Network Time Info Noti Recieved");
1280         memset(&net_time_info, 0, sizeof(struct tnoti_network_icon_info));
1281
1282         lines = (GSList*)event_info;
1283         if (1 != g_slist_length(lines)) {
1284                 dbg("unsolicited msg but multiple line");
1285             goto OUT;
1286         }
1287         line  = (char*)(lines->data);
1288
1289         /*
1290         <time> string type value; format is \93yy/MM/dd,hh:mms\94, wherein characters indicates year, month, day, hour, minutes, seconds.
1291         <timzone_variance> is a string \93GMT+HH:MM\94 or \93GMT-HH:MM\94 e.g. \93GMT+5:30\94
1292         */
1293         dbg("Network time info noti recieved");
1294         
1295         if (line != NULL)
1296         {       
1297                 dbg("Response OK");
1298                         dbg("noti line is %s", line);
1299                         
1300                         tokens = tcore_at_tok_new(line);
1301                         strcpy(time, g_slist_nth_data(tokens, 0));
1302                         strcpy(time_zone_variance , g_slist_nth_data(tokens, 1));
1303
1304                         strncpy(net_time_info.hour,time ,2);
1305                         strncpy(net_time_info.month, time+3, 2);        
1306                         strncpy(net_time_info.day, time+6, 2);
1307                         strncpy(net_time_info.hour, time+9 ,2);
1308                         strncpy(net_time_info.minute, time+12,3);
1309                 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);
1310         }
1311         else
1312         {       
1313                 dbg("line is  NULL");
1314         }
1315 OUT:
1316         if(NULL!=tokens)
1317                 tcore_at_tok_free(tokens);
1318         return TRUE;
1319 }
1320
1321 static gboolean on_event_network_identity(CoreObject *o, const void *event_info, void *user_data)
1322 {
1323         struct tnoti_network_identity noti;
1324         char plmn[7] = { 0, };
1325         int type = 0;
1326         char *tmp;
1327         GSList *lines = NULL;
1328         char *line = NULL;
1329         GSList* tokens = NULL;
1330
1331         dbg("NOTI RECEIVED");
1332         lines = (GSList*)event_info;
1333
1334         if (1 != g_slist_length(lines)) {
1335                 dbg("unsolicited msg but multiple line");
1336             goto OUT;
1337         }
1338
1339         line  = (char*)(lines->data);
1340
1341         memset(&noti, 0, sizeof(struct tnoti_network_identity));
1342         dbg("Network identity noti recieved");
1343
1344         if(line!=NULL)
1345         {
1346                 dbg("Response OK");
1347                         dbg("noti line is %s", line);
1348                         tokens = tcore_at_tok_new(line);
1349                         //noti.type = 0;
1350                         strcpy(noti.plmn, g_slist_nth_data(tokens, 0));
1351                         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_IDENTITY,  sizeof(struct tnoti_network_identity), &noti);                  
1352         }
1353         else
1354         {
1355                 dbg("Response NOK");            
1356         }
1357
1358 OUT:
1359         if(NULL!=tokens)
1360                 tcore_at_tok_free(tokens);
1361         return TRUE;
1362 }
1363
1364
1365 static void on_sim_resp_hook_get_netname(UserRequest *ur, enum tcore_response_command command, unsigned int data_len,
1366                 const void *data, void *user_data)
1367 {
1368         const struct tresp_sim_read *resp = data;
1369         CoreObject *o = user_data;
1370
1371         if (command == TRESP_SIM_GET_SPN) {
1372                 dbg("OK SPN GETTING!!");
1373                 dbg("resp->result = 0x%x", resp->result);
1374                 dbg("resp->data.spn.display_condition = 0x%x", resp->data.spn.display_condition);
1375                 dbg("resp->data.spn.spn = [%s]", resp->data.spn.spn);
1376
1377                 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *)resp->data.spn.spn);
1378
1379                 /**
1380                  * display condition
1381                  *  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
1382                  *          1 = display of registered PLMN name required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
1383                  *  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
1384                  *          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
1385                  */
1386                 if (resp->data.spn.display_condition & 0x01) {
1387                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
1388                 }
1389                 if ((resp->data.spn.display_condition & 0x02) == 0) {
1390                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
1391                 }
1392                 if ((resp->data.spn.display_condition & 0x03) == 0x01) {
1393                         tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
1394                 }
1395         }
1396 }
1397
1398 static enum tcore_hook_return on_hook_sim_init(Server *s, CoreObject *source, enum tcore_notification_command command,
1399                 unsigned int data_len, void *data, void *user_data)
1400 {
1401         const struct tnoti_sim_status *sim = data;
1402         UserRequest *ur = NULL;
1403
1404         if (sim->sim_status == SIM_STATUS_INIT_COMPLETED) {
1405                 ur = tcore_user_request_new(NULL, NULL);
1406                 tcore_user_request_set_command(ur, TREQ_SIM_GET_SPN);
1407                 tcore_user_request_set_response_hook(ur, on_sim_resp_hook_get_netname, user_data);
1408                 tcore_object_dispatch_request(source, ur);
1409         }
1410
1411         return TCORE_HOOK_RETURN_CONTINUE;
1412 }
1413
1414 static TReturn search_network(CoreObject *o, UserRequest *ur)
1415 {
1416         TcorePlugin *p = NULL;
1417         TcoreHal *h = NULL;
1418         TcorePending *pending = NULL;
1419         TcoreATRequest *atreq = NULL;
1420
1421         char*cmd_str = NULL;
1422         dbg("search_network - ENTER!!");
1423         
1424         if (!o || !ur)
1425                 return TCORE_RETURN_EINVAL;
1426
1427         h = tcore_object_get_hal(o);
1428         pending = tcore_pending_new(o, 0);
1429
1430         cmd_str = g_strdup_printf("AT+COPS=?\r");
1431         atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_SINGLELINE);
1432         
1433         tcore_pending_set_request_data(pending, 0, atreq);
1434         //tcore_pending_set_timeout(pending, 60);
1435         //tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
1436         tcore_pending_set_response_callback(pending, on_response_search_network, NULL);
1437         //tcore_pending_set_timeout_callback(pending, on_timeout_search_network, NULL);
1438         tcore_pending_link_user_request(pending, ur);
1439         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
1440
1441         tcore_hal_send_request(h, pending);
1442
1443         return TCORE_RETURN_SUCCESS;
1444 }
1445
1446 static TReturn set_plmn_selection_mode(CoreObject *o, UserRequest *ur)
1447 {
1448         TcorePlugin *p = NULL;
1449         TcoreHal *h = NULL;
1450         TcorePending *pending = NULL;
1451         TcoreATRequest *atreq;
1452         char*cmd_str = NULL;
1453         int format = 0; /* default value for long alphanumeric */
1454         int mode = 0;
1455         char plmn[7];
1456         
1457         const struct treq_network_set_plmn_selection_mode *req_data;
1458
1459
1460         dbg("set_plmn_selection_mode - ENTER!!");
1461
1462         if (!o || !ur)
1463                 return TCORE_RETURN_EINVAL;
1464
1465         req_data = tcore_user_request_ref_data(ur, NULL);
1466         h = tcore_object_get_hal(o);
1467         pending = tcore_pending_new(o, 0);
1468
1469         // Command Format - AT+COPS=[<mode>[,<format>[,<oper>[,< AcT>]]]]       
1470         /* oper parameter format
1471                 - 0 <oper> format presentations are set to long alphanumeric. If Network name not available it displays combination of Mcc and MNC in string format.
1472                 - 1 <oper> format presentation is set to short alphanumeric.
1473                 - 2 <oper> format presentations set to numeric.
1474         */
1475         
1476         switch(req_data->mode) {
1477                 case NETWORK_SELECT_MODE_GSM_MANUAL:
1478                 {
1479                         mode = AT_COPS_MODE_MANUAL;
1480                         format = AT_COPS_FORMAT_NUMERIC;
1481
1482                         memset(plmn, 0, 7);
1483                         memcpy(plmn, req_data->plmn, 6);
1484
1485                         if (strlen(req_data->plmn) == 5) {
1486                                 plmn[5] = '#';
1487                         }               
1488
1489                         cmd_str = g_strdup_printf("AT+COPS=%d,%d,%s\r", mode, format, plmn);
1490                 }
1491                 break;
1492                 
1493                 case NETWORK_SELECT_MODE_GLOBAL_AUTOMATIC:
1494                 default:
1495                         cmd_str = g_strdup("AT+COPS=0\r");
1496                         break;
1497         }
1498
1499         
1500         atreq = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
1501
1502         tcore_pending_set_request_data(pending, 0, atreq);
1503         tcore_pending_set_response_callback(pending, on_response_set_plmn_selection_mode, NULL);
1504         tcore_pending_link_user_request(pending, ur);
1505         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
1506
1507
1508         tcore_hal_send_request(h, pending);
1509
1510         return TCORE_RETURN_SUCCESS;
1511 }
1512
1513 static TReturn get_plmn_selection_mode(CoreObject *o, UserRequest *ur)
1514 {
1515         TcorePlugin *p = NULL;
1516         TcoreHal *h = NULL;
1517         TcorePending *pending = NULL;
1518         TcoreATRequest *atreq;
1519         char*cmd_str = NULL;
1520
1521         dbg("get_plmn_selection_mode - ENTER!!");
1522
1523         if (!o || !ur)
1524                 return TCORE_RETURN_EINVAL;
1525
1526         h = tcore_object_get_hal(o);
1527         pending = tcore_pending_new(o, 0);
1528
1529         cmd_str = g_strdup_printf("AT+COPS?\r");
1530         atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_SINGLELINE);
1531
1532         tcore_pending_set_request_data(pending, 0, atreq);
1533         tcore_pending_set_response_callback(pending, on_response_get_plmn_selection_mode, NULL);
1534         tcore_pending_link_user_request(pending, ur);
1535         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
1536
1537         tcore_hal_send_request(h, pending);
1538
1539         return TCORE_RETURN_SUCCESS;
1540 }
1541
1542
1543 static TReturn set_band(CoreObject *o, UserRequest *ur)
1544 {
1545         TcorePlugin *p = NULL;
1546         TcoreHal *h = NULL;
1547         TcorePending *pending = NULL;
1548         TcoreATRequest *atreq;
1549         char*cmd_str = NULL;
1550         const struct treq_network_set_band *req_data;
1551         int band = 0;
1552         dbg("set_band - ENTER!!");
1553
1554         if (!o || !ur)
1555                 return TCORE_RETURN_EINVAL;
1556
1557         req_data = tcore_user_request_ref_data(ur, NULL);
1558
1559         h = tcore_object_get_hal(o);
1560         pending = tcore_pending_new(o, 0);
1561
1562         switch (req_data->band)
1563         {
1564                 case NETWORK_BAND_TYPE_GSM850:
1565                         band = AT_XBANDSEL_850;
1566                         break;
1567
1568                 case NETWORK_BAND_TYPE_GSM_900_1800:
1569                         band = AT_XBANDSEL_1800; //summerize 900 + 1800
1570                         break;
1571
1572                 case NETWORK_BAND_TYPE_GSM1900:
1573                         band = AT_XBANDSEL_1900;
1574                         break;
1575                 case NETWORK_BAND_TYPE_GSM1800:
1576                         band = AT_XBANDSEL_1800;
1577                         break;
1578                 case NETWORK_BAND_TYPE_GSM_850_1900:
1579                         band = AT_XBANDSEL_1900; //summerize 850 + 1900
1580                         break; 
1581                 default:
1582                         break;
1583         }
1584  
1585         pending = tcore_pending_new(o, 0);
1586
1587         //TODO - Done only for UMTS case, need to do for GSM seperately?
1588         cmd_str = g_strdup_printf("AT+XUBANDSEL=%d", req_data->band);
1589         atreq = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
1590
1591         tcore_pending_set_request_data(pending, 0, atreq);
1592         tcore_pending_set_timeout(pending, 0);
1593         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
1594         tcore_pending_set_response_callback(pending, on_response_set_band, NULL);
1595         tcore_pending_link_user_request(pending, ur);
1596         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
1597
1598
1599         tcore_hal_send_request(h, pending);
1600
1601         return TCORE_RETURN_SUCCESS;
1602 }
1603
1604 static TReturn get_band(CoreObject *o, UserRequest *ur)
1605 {
1606         TcorePlugin *p = NULL;
1607         TcoreHal *h = NULL;
1608         TcorePending *pending = NULL;
1609
1610         TcoreATRequest *atreq;
1611         char*cmd_str = NULL;
1612         dbg("get_band - ENTER!!");
1613
1614         if (!o || !ur)
1615                 return TCORE_RETURN_EINVAL;
1616
1617         h = tcore_object_get_hal(o);
1618         pending = tcore_pending_new(o, 0);
1619
1620         cmd_str = g_strdup_printf("AT+XUBANDSEL?\r");
1621         atreq = tcore_at_request_new(cmd_str, "+XUBANDSEL", TCORE_AT_SINGLELINE);
1622
1623         pending = tcore_pending_new(o, 0);
1624         tcore_pending_set_request_data(pending, 0, atreq);
1625         tcore_pending_set_response_callback(pending, on_response_get_band, NULL);
1626         tcore_pending_link_user_request(pending, ur);
1627         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
1628         tcore_hal_send_request(h, pending);
1629
1630
1631
1632         return TCORE_RETURN_SUCCESS;
1633 }
1634
1635 static TReturn set_preferred_plmn(CoreObject *o, UserRequest *ur)
1636 {
1637         dbg("Entry");
1638
1639         dbg("Exit");
1640         return TCORE_RETURN_SUCCESS; 
1641 }
1642
1643 static TReturn get_preferred_plmn(CoreObject *o, UserRequest *ur)
1644 {
1645         TcorePlugin *p = NULL;
1646         TcoreHal *h = NULL;
1647         TcorePending *pending = NULL;
1648         TcoreATRequest *atreq = NULL;
1649
1650         char*cmd_str = NULL;
1651
1652         dbg("get_preferred_plmn - ENTER!!");
1653
1654         if (!o || !ur)
1655                 return TCORE_RETURN_EINVAL;
1656
1657         h = tcore_object_get_hal(o);
1658         pending = tcore_pending_new(o, 0);
1659
1660         cmd_str = g_strdup_printf("AT+CPOL?\r");
1661         atreq = tcore_at_request_new(cmd_str, "+CPOL", TCORE_AT_MULTILINE);
1662         
1663         tcore_pending_set_request_data(pending, 0, atreq);
1664         tcore_pending_set_response_callback(pending, on_response_get_preferred_plmn, NULL);
1665         tcore_pending_link_user_request(pending, ur);
1666         tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
1667
1668         tcore_hal_send_request(h, pending);
1669
1670         return TCORE_RETURN_SUCCESS;
1671 }
1672
1673
1674 static TReturn set_cancel_manual_search(CoreObject *o, UserRequest *ur)
1675 {
1676         dbg("Entry");
1677
1678         dbg("Exit");
1679         return TCORE_RETURN_SUCCESS;
1680 }
1681
1682 static TReturn get_serving_network(CoreObject *o, UserRequest *ur)
1683 {
1684         TcorePlugin *p = NULL;
1685         TcoreHal *h = NULL;
1686         TcorePending *pending = NULL;
1687         dbg("get_serving_network - ENTER!!");
1688         
1689         if (!o)
1690                 return TCORE_RETURN_EINVAL;
1691
1692         dbg("new pending(AT+COPS?)");
1693
1694         nwk_prepare_and_send_pending_request(tcore_object_ref_plugin(o), "umts_network", "AT+COPS=3,2;+COPS?;+COPS=3,0;+COPS?\r", "+COPS", TCORE_AT_MULTILINE,on_response_get_serving_network);
1695         return TCORE_RETURN_SUCCESS;
1696 }
1697
1698 static struct tcore_network_operations network_ops = {
1699                 .search                                 = search_network,
1700                 .set_plmn_selection_mode        = set_plmn_selection_mode,
1701                 .get_plmn_selection_mode        = get_plmn_selection_mode,
1702                 .set_service_domain             = NULL,
1703                 .get_service_domain             = NULL,
1704                 .set_band                               = set_band,
1705                 .get_band                               = get_band,
1706                 .set_preferred_plmn             = set_preferred_plmn,
1707                 .get_preferred_plmn             = get_preferred_plmn,
1708                 .set_order                              = NULL,
1709                 .get_order                              = NULL,
1710                 .set_power_on_attach            = NULL,
1711                 .get_power_on_attach            = NULL,
1712                 .set_cancel_manual_search       = set_cancel_manual_search,
1713                 .get_serving_network            = get_serving_network,
1714 };
1715
1716 gboolean s_network_init(TcorePlugin *p, TcoreHal *h)
1717 {
1718         CoreObject *o = NULL;
1719
1720         o = tcore_network_new(p, "umts_network", &network_ops, h);
1721         if (!o)
1722                 return FALSE;
1723
1724         tcore_object_add_callback(o,"+CREG", on_event_cs_network_regist, NULL);
1725         tcore_object_add_callback(o,"+CGREG", on_event_ps_network_regist, NULL);
1726         tcore_object_add_callback(o, "+XCIEV", on_event_network_icon_info, NULL);
1727
1728         //XNITZINFO is for <time><timezone variance>
1729         //CTZDST is for <dst>
1730         tcore_object_add_callback(o, "+XNITZINFO", on_event_network_time_info, NULL);
1731         tcore_object_add_callback(o, "+CTZDST", on_event_network_time_info, NULL);
1732
1733         //tcore_object_add_callback(o, "+XCOPS", on_event_network_identity, NULL);
1734
1735         //need to check whether the following is needed
1736
1737         //tcore_server_add_notification_hook(tcore_plugin_ref_server(p), TNOTI_SIM_STATUS, on_hook_sim_init, o);
1738
1739         _insert_mcc_mnc_oper_list(p, o);
1740
1741         return TRUE;
1742 }
1743
1744 void s_network_exit(TcorePlugin *p)
1745 {
1746         CoreObject *o;
1747
1748         o = tcore_plugin_ref_core_object(p, "umts_network");
1749
1750         tcore_network_free(o);
1751 }