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