4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Harish Bishnoi <hbishnoi@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
29 #include <core_object.h>
32 #include <co_network.h>
40 #include "s_network.h"
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 */
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*/
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> */
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 */
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
80 #define AT_XRAT_DUAL 1
81 #define AT_XRAT_UMTS 2
83 #define MAX_NETWORKS_PREF_PLMN_SUPPORT 150
84 #define MAX_NETWORKS_MANUAL_SEARCH_SUPPORT 20
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,
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,
106 static gboolean get_serving_network(CoreObject *o, UserRequest *ur);
109 static void on_confirmation_network_message_send(TcorePending *p, gboolean result, void *user_data)
111 dbg("on_confirmation_modem_message_send - msg out from queue.\n");
113 if (result == FALSE) {
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)
123 TcoreATRequest *req = NULL;
125 CoreObject *o = NULL;
126 TcorePending *pending = NULL;
129 o = tcore_plugin_ref_core_object(plugin, co_name);
130 hal = tcore_object_get_hal(o);
132 pending = tcore_pending_new(o, 0);
133 req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
135 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
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);
142 ret = tcore_hal_send_request(hal, pending);
147 static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *o)
152 char query[255] = { 0, };
155 GHashTable *result = NULL, *row = NULL;
156 struct tcore_network_operator_info *noi = NULL;
159 s = tcore_plugin_ref_server(p);
160 strg = tcore_server_find_storage(s, "database");
162 handle = tcore_storage_create_handle(strg, "/opt/dbspace/.mcc_mnc_oper_list.db");
164 dbg("fail to create database handle");
168 snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list");
170 result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
171 (GDestroyNotify) g_hash_table_destroy);
173 tcore_storage_read_query_database(strg, handle, query, NULL, result, 4);
175 g_hash_table_iter_init(&iter, result);
176 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
179 noi = calloc(sizeof(struct tcore_network_operator_info), 1);
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"));
186 tcore_network_operator_info_add(o, noi);
191 dbg("count = %d", count);
193 g_hash_table_destroy(result);
195 tcore_storage_remove_handle(strg, handle);
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)
201 enum telephony_network_service_type ret;
206 case NETWORK_ACT_UNKNOWN:
207 ret = NETWORK_SERVICE_TYPE_UNKNOWN;
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;
214 ret = NETWORK_SERVICE_TYPE_2G;
217 case NETWORK_ACT_EGPRS:
218 return NETWORK_SERVICE_TYPE_2_5G_EDGE;
221 case NETWORK_ACT_UMTS:
222 ret = NETWORK_SERVICE_TYPE_3G;
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) {
232 ret = NETWORK_SERVICE_TYPE_SEARCH;
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) {
238 ret = NETWORK_SERVICE_TYPE_EMERGENCY;
245 static void _ps_set(TcorePlugin *p, int status)
247 GSList *co_list = NULL;
249 co_list = tcore_plugin_get_core_objects_bytype(p, CORE_OBJECT_TYPE_PS);
251 CoreObject *o = NULL;
252 o = (CoreObject *) co_list->data;
256 if (status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
257 tcore_ps_set_online(o, TRUE);
259 tcore_ps_set_online(o, FALSE);
261 } while ((co_list = g_slist_next(co_list)));
263 g_slist_free(co_list);
267 static void on_response_set_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data)
270 const TcoreATResponse *atResp = data;
271 // GSList *tokens = NULL;
272 // char * line = NULL;
273 struct tresp_network_set_plmn_selection_mode resp = {0};
275 if (atResp->success > 0) {
277 resp.result = TCORE_RETURN_SUCCESS;
280 resp.result = TCORE_RETURN_FAILURE;
283 ur = tcore_pending_ref_user_request(p);
285 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_set_plmn_selection_mode), &resp);
289 static void on_response_get_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data)
292 struct tresp_network_get_plmn_selection_mode resp = {0};
293 const TcoreATResponse *atResp = data;
294 GSList *tokens = NULL;
298 resp.result = TCORE_RETURN_FAILURE;
300 if (atResp->success > 0) {
303 +COPS: <mode>[,<format>,<oper>[,< AcT>]]
307 line = (char *) atResp->lines->data;
308 tokens = tcore_at_tok_new(line);
309 if (g_slist_length(tokens) < 1) {
310 msg("invalid message");
313 mode = atoi(tcore_at_tok_nth(tokens, 0));
314 dbg("mode = %d", mode);
317 case AT_COPS_MODE_AUTOMATIC:
318 resp.mode = NETWORK_SELECT_MODE_GLOBAL_AUTOMATIC;
321 case AT_COPS_MODE_MANUAL:
322 case AT_COPS_MODE_MANUAL_AUTOMATIC:
323 resp.mode = NETWORK_SELECT_MODE_GSM_MANUAL;
326 case AT_COPS_MODE_DEREGISTER:
327 case AT_COPS_MODE_SET_ONLY:
328 resp.result = TCORE_RETURN_FAILURE;
331 resp.result = TCORE_RETURN_SUCCESS;
335 resp.result = TCORE_RETURN_FAILURE;
339 ur = tcore_pending_ref_user_request(p);
341 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_get_plmn_selection_mode), &resp);
345 tcore_at_tok_free(tokens);
350 static void on_response_search_network(TcorePending *p, int data_len, const void *data, void *user_data)
353 struct tresp_network_search resp;
356 const TcoreATResponse *atResp = data;
357 GSList *tokens = NULL;
358 GSList *network_token = NULL;
360 char *temp_plmn_info = NULL;
362 int num_network_avail = 0;
364 memset(&resp, 0, sizeof(struct tresp_network_search));
365 resp.result = TCORE_RETURN_FAILURE;
368 if (atResp->success > 0) {
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");
381 resp.result = TCORE_RETURN_SUCCESS;
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)]
387 /* (2,"IND airtel","airtel","40445",2,),(1,"IND airtel","airtel","40445",0,),(3,"TATA DOCOMO","TATA DO","405034",2,) */
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));
393 pResp = (tcore_at_tok_nth(network_token, 0));
395 dbg("status : %s", pResp);
396 resp.list[i].status = (enum telephony_network_plmn_status) atoi(pResp);
399 if ((pResp = tcore_at_tok_nth(network_token, 1))) { /* Long Aplha name */
400 dbg("Long Aplha name : %s", pResp);
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);
414 pResp = tcore_at_tok_nth(network_token, 3);
416 dbg("PLMN ID : %s", pResp);
417 temp_plmn_info = util_removeQuotes(pResp);
420 memcpy(resp.list[i].plmn, temp_plmn_info, 6);
421 if (resp.list[i].plmn[5] == '#')
422 resp.list[i].plmn[5] = '\0';
424 /* Parse Access Technology */
425 if ((pResp = tcore_at_tok_nth(tokens, 4))) {
426 if (strlen(pResp) > 0) {
430 resp.list[i].act = NETWORK_ACT_GSM;
432 resp.list[i].act = NETWORK_ACT_UMTS;
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);
439 tcore_at_tok_free(network_token);
443 resp.result = TCORE_RETURN_FAILURE;
447 ur = tcore_pending_ref_user_request(p);
449 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &resp);
453 tcore_at_tok_free(tokens);
456 free(temp_plmn_info);
461 static void on_response_set_umts_band(TcorePending *p, int data_len, const void *data, void *user_data)
463 const TcoreATResponse *atResp = data;
465 dbg("On Response Set UMTS Band");
467 if (atResp->success > 0) {
473 dbg("Wait for response of XRAT before sending final band setting response to AP");
478 static void on_response_set_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data)
480 const TcoreATResponse *atResp = data;
482 dbg("On Response Set GSM Band");
483 if (atResp->success > 0) {
489 dbg("Wait for response of XRAT before sending final band setting response to AP");
493 static void on_response_get_umts_band(TcorePending *p, int data_len, const void *data, void *user_data)
495 const TcoreATResponse *atResp = data;
496 GSList *tokens = NULL;
497 const char *line = NULL;
498 int total_umts_bands = 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};
508 dbg("Entry on_response_get_umts_band");
510 resp.mode = NETWORK_BAND_MODE_PREFERRED;
511 resp.result = TCORE_RETURN_SUCCESS;
513 if (atResp->success > 0) {
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) {
529 for (i = 0; i < total_umts_bands; i++) {
530 band_token = tcore_at_tok_nth(tokens, i);
532 if (band_token == NULL)
535 memset(umts_band, 0x00, sizeof(umts_band));
537 if (atoi(band_token) == 0) { /* 0 means UMTS automatic */
538 umts_band_1 = umts_band_2 = umts_band_5 = TRUE;
542 /* Strip off starting quotes & ending quotes */
543 strncpy(umts_band, band_token + 1, strlen(band_token) - 2);
545 if (!strcmp(umts_band, "UMTS_BAND_I")) {
547 } else if (!strcmp(umts_band, "UMTS_BAND_II")) {
549 } else if (!strcmp(umts_band, "UMTS_BAND_II")) {
552 /* Telephony is not interest */
553 dbg("Telephony is not interested in %s band", umts_band);
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;
567 resp.result = TCORE_RETURN_FAILURE;
570 dbg("Final resp.band sent to TS = %d", resp.band);
572 ur = tcore_pending_ref_user_request(p);
574 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
578 tcore_at_tok_free(tokens);
580 dbg("Exit on_response_get_umts_band");
584 static void on_response_get_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data)
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;
592 char *band_token = NULL;
593 UserRequest *ur = NULL;
599 dbg("Entry on_response_get_gsm_band");
601 resp.mode = NETWORK_BAND_MODE_PREFERRED;
602 resp.result = TCORE_RETURN_SUCCESS;
604 if (atResp->success > 0) {
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)
616 for (i = 0; i < total_gsm_bands; i++) {
617 band_token = tcore_at_tok_nth(tokens, i);
619 if (band_token == NULL)
622 if (atoi(band_token) == 0) { /* 0 means GSM automatic */
623 gsm_850 = gsm_900 = gsm_1800 = gsm_1900 = TRUE;
627 switch (atoi(band_token)) {
628 case AT_GSM_XBANDSEL_850:
632 case AT_GSM_XBANDSEL_900:
636 case AT_GSM_XBANDSEL_1800:
640 case AT_GSM_XBANDSEL_1900:
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;
666 resp.result = TCORE_RETURN_FAILURE;
669 dbg("Final resp.band sent to TS = %d", resp.band);
671 ur = tcore_pending_ref_user_request(p);
673 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
677 tcore_at_tok_free(tokens);
679 dbg("Exit on_response_get_gsm_band");
684 static void on_response_get_xrat(TcorePending *p, int data_len, const void *data, void *user_data)
687 UserRequest *ur = NULL;
689 TcoreATRequest *atreq;
690 char *cmd_str = NULL;
691 UserRequest *dup_ur = NULL;
692 const TcoreATResponse *atResp = data;
693 const char *line = NULL;
695 GSList *tokens = NULL;
696 TcorePending *pending = NULL;
697 CoreObject *o = NULL;
699 struct tresp_network_get_band resp = {0};
701 dbg("Enter on_response_get_xrat !!");
703 resp.mode = NETWORK_BAND_MODE_PREFERRED;
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);
709 if (atResp->success > 0) {
712 line = (char *) atResp->lines->data;
713 tokens = tcore_at_tok_new(line);
714 if (g_slist_length(tokens) < 1) {
715 msg("invalid message");
720 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
721 cp_xrat = atoi(pResp);
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;
727 ur = tcore_pending_ref_user_request(p);
729 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
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);
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);
761 resp.result = TCORE_RETURN_FAILURE;
762 resp.band = NETWORK_BAND_TYPE_ANY;
764 ur = tcore_pending_ref_user_request(p);
766 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
772 tcore_at_tok_free(tokens);
774 dbg("Exit on_response_get_xrat !!");
780 static void on_response_set_xrat(TcorePending *p, int data_len, const void *data, void *user_data)
782 UserRequest *ur = NULL;
783 struct tresp_network_set_band resp = {0};
784 const TcoreATResponse *atResp = data;
786 dbg("On Response Set XRAT");
788 if (atResp->success > 0) {
790 resp.result = TCORE_RETURN_SUCCESS;
793 resp.result = TCORE_RETURN_FAILURE;
796 ur = tcore_pending_ref_user_request(p);
798 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_BAND, sizeof(struct tresp_network_set_band), &resp);
804 static void on_response_set_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data)
806 UserRequest *ur = NULL;
807 struct tresp_network_set_preferred_plmn resp = {0};
808 const TcoreATResponse *atResp = data;
810 dbg("ENTER on_response_set_preferred_plmn");
812 if (atResp->success > 0) {
814 resp.result = TCORE_RETURN_SUCCESS;
817 resp.result = TCORE_RETURN_FAILURE;
820 ur = tcore_pending_ref_user_request(p);
822 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PREFERRED_PLMN, sizeof(struct tresp_network_set_preferred_plmn), &resp);
825 dbg("Exit on_response_set_preferred_plmn");
829 static void on_response_get_nitz_name(TcorePending *p, int data_len, const void *data, void *user_data)
831 const TcoreATResponse *atResp = data;
832 GSList *tokens = NULL;
833 const char *line = NULL;
834 CoreObject *o = NULL;
835 struct tnoti_network_identity noti;
838 int net_name_type = 0;
841 dbg("Entry on_response_get_nitz_name (+XCOPS)");
842 o = tcore_pending_ref_core_object(p);
843 if (atResp->success > 0) {
847 nol = g_slist_length(atResp->lines);
849 msg("invalid message");
853 for (count = 0; count < nol; count++) {
855 line = g_slist_nth_data(atResp->lines, count);
856 tokens = tcore_at_tok_new(line);
857 dbg("line %d start---------------", count);
859 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
860 net_name_type = atoi(pResp);
861 dbg("Net name type : %d", net_name_type);
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 */
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 */
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 */
887 tcore_at_tok_free(tokens);
890 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_IDENTITY,
891 sizeof(struct tnoti_network_identity), ¬i);
898 dbg("Exit on_response_get_nitz_name");
901 static void on_response_get_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data)
906 const TcoreATResponse *atResp = data;
907 GSList *tokens = NULL;
908 char temp_plmn_info[17] = {0};
912 struct tresp_network_get_preferred_plmn resp = {0};
914 int GSM_AcT2 = 0, GSM_Compact_AcT2 = 0, UTRAN_AcT2 = 0;
916 dbg("Entry on_response_get_preferred_plmn");
918 if (atResp->success > 0) {
921 total_lines = g_slist_length(atResp->lines);
922 dbg("Total number of network present in Preferred PLMN list is %d\n", total_lines);
924 if (total_lines < 1) {
925 msg("invalid message");
929 if (total_lines >= MAX_NETWORKS_PREF_PLMN_SUPPORT)
930 total_lines = MAX_NETWORKS_PREF_PLMN_SUPPORT;
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>]
937 resp.result = TCORE_RETURN_SUCCESS;
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);
944 /* <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>,<E-UTRAN_AcT2>] */
947 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
948 dbg("Index : %s", pResp);
949 resp.list[i].ef_index = atoi(pResp);
952 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
953 dbg("format : %s", pResp);
954 plmn_format = atoi(pResp);
957 /* Operator PLMN ID */
958 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
959 dbg("plmn ID : %s", pResp);
961 if (strlen(pResp) > 0) {
962 strncpy(temp_plmn_info, pResp + 1, (strlen(pResp)) - 2);
965 if (plmn_format == 2) {
966 // cp_plmn = util_hexStringToBytes(temp_plmn_info);
968 if (strncmp((char *) temp_plmn_info, "000000", 6) == 0)
971 memcpy(resp.list[i].plmn, temp_plmn_info, 6);
972 if (resp.list[i].plmn[5] == '#')
973 resp.list[i].plmn[5] = '\0';
980 if ((pResp = tcore_at_tok_nth(tokens, 3))) {
981 dbg("GSM_AcT2 : %s", pResp);
982 GSM_AcT2 = atoi(pResp);
985 if ((pResp = tcore_at_tok_nth(tokens, 4))) {
986 dbg("GSM_Compact AcT2 : %s", pResp);
987 GSM_Compact_AcT2 = atoi(pResp);
990 if ((pResp = tcore_at_tok_nth(tokens, 5))) {
991 dbg("UTRAN_AcT2 : %s", pResp);
992 UTRAN_AcT2 = atoi(pResp);
995 if (UTRAN_AcT2 && (GSM_AcT2 || GSM_Compact_AcT2))
996 resp.list[i].act = NETWORK_ACT_GSM_UTRAN;
998 resp.list[i].act = NETWORK_ACT_UMTS;
999 else if (GSM_AcT2 || GSM_Compact_AcT2)
1000 resp.list[i].act = NETWORK_ACT_GPRS;
1002 (resp.list_count)++;
1004 tcore_at_tok_free(tokens);
1009 ur = tcore_pending_ref_user_request(p);
1011 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PREFERRED_PLMN, sizeof(struct tresp_network_get_preferred_plmn), &resp);
1017 static void on_response_get_serving_network(TcorePending *p, int data_len, const void *data, void *user_data)
1019 const TcoreATResponse *resp = data;
1021 struct tresp_network_get_serving_network Tresp = {0};
1023 char *long_plmn_name = NULL;
1024 char *short_plmn_name = NULL;
1026 GSList *tokens = NULL;
1028 int network_mode = -1;
1029 int plmn_format = -1;
1031 struct tnoti_network_identity noti;
1035 o = tcore_pending_ref_core_object(p);
1037 if (resp->success <= 0) {
1038 dbg("RESPONSE NOK");
1040 ur = tcore_pending_ref_user_request(p);
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);
1049 nol = g_slist_length(resp->lines);
1050 dbg("nol : %d", nol);
1052 for (count = 0; count < nol; count++) {
1054 line = g_slist_nth_data(resp->lines, count);
1055 tokens = tcore_at_tok_new(line);
1056 dbg("line %d start---------------", count);
1058 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
1059 dbg("mode : %s", pResp);
1060 network_mode = atoi(pResp);
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);
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);
1078 // set network name into po
1079 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_FULL, long_plmn_name);
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);
1090 // set network name into po
1091 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SHORT, short_plmn_name);
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) {
1102 /* Strip off starting quotes & ending quotes */
1103 strncpy(plmn, pResp + 1, strlen(pResp) - 2);
1104 tcore_network_set_plmn(o, plmn);
1114 if ((pResp = tcore_at_tok_nth(tokens, 3))) {
1115 dbg("AcT : %s", pResp);
1116 if (strlen(pResp) > 0) {
1118 tcore_network_set_access_technology(o, lookup_tbl_access_technology[AcT]);
1122 tcore_at_tok_free(tokens);
1125 memcpy(Tresp.plmn, plmn, 7);
1126 tcore_network_get_access_technology(o, &(Tresp.act));
1127 tcore_network_get_lac(o, &(Tresp.gsm.lac));
1129 ur = tcore_pending_ref_user_request(p);
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);
1134 /* Network change noti */
1135 struct tnoti_network_change network_change;
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));
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);
1148 if ((AT_COPS_MODE_DEREGISTER != network_mode) &&
1149 (AT_COPS_MODE_SET_ONLY != network_mode)) {
1150 /*Network identity noti*/
1151 memset(¬i, 0x0, sizeof(struct tnoti_network_change));
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), ¬i);
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);
1165 free(long_plmn_name);
1166 if (short_plmn_name)
1167 free(short_plmn_name);
1172 static gboolean on_event_ps_network_regist(CoreObject *o, const void *data, void *user_data)
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;
1188 GSList *lines = NULL;
1190 lines = (GSList *) data;
1191 if (1 != g_slist_length(lines)) {
1192 dbg("unsolicited msg but multiple line");
1195 line = (char *) (lines->data);
1196 dbg("+CGREG NOTI RECEIVED");
1199 +CREG: <stat> [[,<lac>,<ci>[AcT]]
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
1207 5 Registered, in roaming
1210 string type; two byte location area code in hexadecimal format (e.g. 00C3)
1213 string type; four byte cell ID in hexadecimal format (e.g. 0000A13F)
1221 6 UTRAN w/HSDPA and HSUPA
1222 Note: <Act> is supporting from R7 and above Protocol Stack.
1224 <rac>: is R7 and above feature, string type; one byte routing area code in hexadecimal format.
1227 tokens = tcore_at_tok_new(line);
1228 if (g_slist_length(tokens) < 1) {
1229 msg("invalid message");
1233 if (!(pResp = g_slist_nth_data(tokens, 0))) {
1234 dbg("No STAT in +CGREG");
1238 if ((pResp = g_slist_nth_data(tokens, 1)))
1241 if ((pResp = g_slist_nth_data(tokens, 2)))
1244 dbg("No ci in +CGREG");
1246 if ((pResp = g_slist_nth_data(tokens, 3)))
1249 dbg("No AcT in +CGREG");
1251 if ((pResp = g_slist_nth_data(tokens, 4)))
1254 dbg("No rac in +CGREG");
1258 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d, rac = 0x%x", stat, lac, ci, AcT, rac);
1260 ps_status = lookup_tbl_net_status[stat];
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);
1265 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
1267 act = lookup_tbl_access_technology[AcT];
1268 tcore_network_set_access_technology(o, act);
1270 if (stat == AT_CREG_STAT_REG_ROAM)
1271 tcore_network_set_roaming_state(o, TRUE);
1273 tcore_network_set_roaming_state(o, FALSE);
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);
1281 tcore_network_set_lac(o, lac);
1282 tcore_network_set_cell_id(o, ci);
1283 tcore_network_set_rac(o, rac);
1285 net_lac_cell_info.lac = lac;
1286 net_lac_cell_info.cell_id = ci;
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);
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);
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), ®ist_status);
1299 if (service_type == NETWORK_SERVICE_TYPE_HSDPA)
1300 noti.status = TELEPHONY_HSDPA_ON;
1302 noti.status = TELEPHONY_HSDPA_OFF;
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), ¬i);
1307 /* Get PLMN ID needed to application */
1308 // get_serving_network(o, NULL);
1310 dbg("Response NOK");
1315 tcore_at_tok_free(tokens);
1319 static gboolean on_event_cs_network_regist(CoreObject *o, const void *event_info, void *user_data)
1321 GSList *lines = 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};
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;
1337 lines = (GSList *) event_info;
1338 if (1 != g_slist_length(lines)) {
1339 dbg("unsolicited msg but multiple line");
1342 line = (char *) (lines->data);
1344 dbg("+CREG NOTI RECEIVED");
1347 +CREG: <stat> [[,<lac>,<ci>[AcT]]
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
1355 5 Registered, in roaming
1358 string type; two byte location area code in hexadecimal format (e.g. 00C3)
1361 string type; four byte cell ID in hexadecimal format (e.g. 0000A13F)
1369 6 UTRAN w/HSDPA and HSUPA
1370 Note: <Act> is supporting from R7 and above Protocol Stack.
1373 tokens = tcore_at_tok_new(line);
1374 if (g_slist_length(tokens) < 1) {
1375 msg("invalid message");
1379 if (!(pResp = g_slist_nth_data(tokens, 0))) {
1380 dbg("No STAT in +CREG");
1384 if ((pResp = g_slist_nth_data(tokens, 1)))
1387 if ((pResp = g_slist_nth_data(tokens, 2)))
1390 dbg("No ci in +CREG");
1392 if ((pResp = g_slist_nth_data(tokens, 3)))
1395 dbg("No AcT in +CREG");
1399 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d", stat, lac, ci, AcT);
1401 cs_status = lookup_tbl_net_status[stat];
1402 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, cs_status);
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);
1407 act = lookup_tbl_access_technology[AcT];
1408 tcore_network_set_access_technology(o, act);
1410 if (stat == AT_CREG_STAT_REG_ROAM)
1411 tcore_network_set_roaming_state(o, TRUE);
1413 tcore_network_set_roaming_state(o, FALSE);
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);
1421 tcore_network_set_lac(o, lac);
1422 tcore_network_set_cell_id(o, ci);
1424 net_lac_cell_info.lac = lac;
1425 net_lac_cell_info.cell_id = ci;
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);
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);
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), ®ist_status);
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);
1443 dbg("Response NOK");
1448 tcore_at_tok_free(tokens);
1452 static gboolean on_event_network_icon_info(CoreObject *o, const void *event_info, void *user_data)
1454 struct tnoti_network_icon_info net_icon_info = {0};
1456 char *rssiToken = NULL;
1457 char *batteryToken = NULL;
1458 GSList *tokens = NULL;
1459 GSList *lines = NULL;
1461 lines = (GSList *) event_info;
1462 if (1 != g_slist_length(lines)) {
1463 dbg("unsolicited msg but multiple line");
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));
1473 tokens = tcore_at_tok_new(line);
1474 if (g_slist_length(tokens) != 2) {
1475 msg("invalid message");
1479 rssiToken = (char *) g_slist_nth_data(tokens, 0);
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);
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);
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);
1497 dbg("Response NOK");
1503 tcore_at_tok_free(tokens);
1508 static gboolean on_event_network_ctzv_time_info(CoreObject *o, const void *event_info, void *user_data)
1510 struct tnoti_network_timeinfo net_time_info = {0};
1512 GSList *tokens = 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");
1520 lines = (GSList *) event_info;
1521 if (1 != g_slist_length(lines)) {
1522 dbg("unsolicited msg but multiple line");
1525 line = (char *) (lines->data);
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,
1533 dbg("Network time info (+CTZV) recieved");
1537 dbg("noti line is %s", line);
1539 tokens = tcore_at_tok_new(line);
1541 if (g_slist_length(tokens) < 2) {
1542 msg("invalid message");
1546 if ((time_zone = g_slist_nth_data(tokens, 0))) {
1547 net_time_info.gmtoff = atoi(time_zone) * 15; /* TZ in minutes */
1550 if (tcore_network_get_plmn(o) != NULL)
1551 strcpy(net_time_info.plmn, tcore_network_get_plmn(o));
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);
1557 strncpy(ptime_param, time + 4, 2); /* skip slash (/) after year param */
1558 net_time_info.month = atoi(ptime_param);
1560 strncpy(ptime_param, time + 7, 2); /* skip past slash (/) after month param */
1561 net_time_info.day = atoi(ptime_param);
1563 strncpy(ptime_param, time + 10, 2); /* skip past comma (,) after day param */
1564 net_time_info.hour = atoi(ptime_param);
1566 strncpy(ptime_param, time + 13, 2); /* skip past colon (:) after hour param */
1567 net_time_info.minute = atoi(ptime_param);
1569 strncpy(ptime_param, time + 16, 2); /* skip past colon (:) after minute param */
1570 net_time_info.second = atoi(ptime_param);
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);
1574 dbg("new pending(AT+XOPS=0/5/6 for Nitz PLMN name)");
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);
1579 dbg("line is NULL");
1584 tcore_at_tok_free(tokens);
1586 dbg("Exit: on_event_network_ctzv_time_info");
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)
1593 const struct tresp_sim_read *resp = data;
1594 CoreObject *o = user_data;
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);
1602 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *) resp->data.spn.spn);
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
1611 if (resp->data.spn.display_condition & 0x01) {
1612 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
1614 if ((resp->data.spn.display_condition & 0x02) == 0) {
1615 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
1617 if ((resp->data.spn.display_condition & 0x03) == 0x01) {
1618 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
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)
1626 const struct tnoti_sim_status *sim = data;
1627 UserRequest *ur = NULL;
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);
1636 return TCORE_HOOK_RETURN_CONTINUE;
1639 static TReturn search_network(CoreObject *o, UserRequest *ur)
1642 TcorePending *pending = NULL;
1643 TcoreATRequest *atreq = NULL;
1645 char *cmd_str = NULL;
1646 dbg("search_network - ENTER!!");
1649 return TCORE_RETURN_EINVAL;
1651 h = tcore_object_get_hal(o);
1652 pending = tcore_pending_new(o, 0);
1654 cmd_str = g_strdup_printf("AT+COPS=?");
1655 atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_SINGLELINE);
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);
1663 tcore_hal_send_request(h, pending);
1665 return TCORE_RETURN_SUCCESS;
1668 static TReturn set_plmn_selection_mode(CoreObject *o, UserRequest *ur)
1671 TcorePending *pending = NULL;
1672 TcoreATRequest *atreq;
1673 char *cmd_str = NULL;
1674 int format = 0; /* default value for long alphanumeric */
1679 const struct treq_network_set_plmn_selection_mode *req_data = NULL;
1682 dbg("set_plmn_selection_mode - ENTER!!");
1685 return TCORE_RETURN_EINVAL;
1687 req_data = tcore_user_request_ref_data(ur, NULL);
1688 h = tcore_object_get_hal(o);
1689 pending = tcore_pending_new(o, 0);
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.
1698 if ((req_data->act == NETWORK_ACT_GSM) || (req_data->act == NETWORK_ACT_EGPRS))
1703 switch (req_data->mode) {
1704 case NETWORK_SELECT_MODE_GSM_MANUAL:
1706 mode = AT_COPS_MODE_MANUAL;
1707 format = AT_COPS_FORMAT_NUMERIC;
1710 memcpy(plmn, req_data->plmn, 6);
1712 if (strlen(req_data->plmn) == 6) {
1717 cmd_str = g_strdup_printf("AT+COPS=%d,%d,\"%s\",%d", mode, format, plmn, act);
1721 case NETWORK_SELECT_MODE_GLOBAL_AUTOMATIC:
1723 cmd_str = g_strdup("AT+COPS=0");
1728 atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_NO_RESULT);
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);
1735 tcore_hal_send_request(h, pending);
1737 return TCORE_RETURN_SUCCESS;
1740 static TReturn get_plmn_selection_mode(CoreObject *o, UserRequest *ur)
1743 TcorePending *pending = NULL;
1744 TcoreATRequest *atreq;
1745 char *cmd_str = NULL;
1747 dbg("get_plmn_selection_mode - ENTER!!");
1750 return TCORE_RETURN_EINVAL;
1752 h = tcore_object_get_hal(o);
1753 pending = tcore_pending_new(o, 0);
1755 cmd_str = g_strdup_printf("AT+COPS?");
1756 atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_SINGLELINE);
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);
1763 tcore_hal_send_request(h, pending);
1765 return TCORE_RETURN_SUCCESS;
1769 static TReturn set_band(CoreObject *o, UserRequest *ur)
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;
1781 int gsm_band2 = 255;
1782 char *umts_band = NULL;
1783 UserRequest *dup_ur_gsm = NULL;
1784 UserRequest *dup_ur_umts = NULL;
1786 dbg("set_band - ENTER!!");
1789 return TCORE_RETURN_EINVAL;
1791 req_data = tcore_user_request_ref_data(ur, NULL);
1792 h = tcore_object_get_hal(o);
1794 dbg("set_band - called with band = %d", req_data->band);
1796 switch (req_data->band) {
1797 case NETWORK_BAND_TYPE_GSM850:
1798 gsm_band = AT_GSM_XBANDSEL_850;
1799 set_gsm_band = TRUE;
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;
1808 case NETWORK_BAND_TYPE_GSM1900:
1809 gsm_band = AT_GSM_XBANDSEL_1900;
1810 set_gsm_band = TRUE;
1813 case NETWORK_BAND_TYPE_GSM1800:
1814 gsm_band = AT_GSM_XBANDSEL_1800;
1815 set_gsm_band = TRUE;
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;
1824 case NETWORK_BAND_TYPE_ANY:
1825 gsm_band = AT_GSM_XBANDSEL_AUTOMATIC;
1826 set_umts_band = TRUE;
1827 set_gsm_band = TRUE;
1830 case NETWORK_BAND_TYPE_WCDMA:
1831 set_umts_band = TRUE;
1834 case NETWORK_BAND_TYPE_WCDMA2100:
1835 umts_band = "UMTS_BAND_I";
1836 set_umts_band = TRUE;
1839 case NETWORK_BAND_TYPE_WCDMA1900:
1840 umts_band = "UMTS_BAND_II";
1841 set_umts_band = TRUE;
1844 case NETWORK_BAND_TYPE_WCDMA850:
1845 umts_band = "UMTS_BAND_V";
1846 set_umts_band = TRUE;
1853 dbg("set_band > set_umts_band = %d, set_gsm_band = %d", set_umts_band, set_gsm_band);
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");
1859 cmd_str = g_strdup_printf("AT+XUBANDSEL=%s", umts_band);
1861 atreq = tcore_at_request_new(cmd_str, "+XUBANDSEL", TCORE_AT_NO_RESULT);
1862 pending_umts = tcore_pending_new(o, 0);
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);
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);
1873 tcore_hal_send_request(h, pending_umts);
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);
1882 cmd_str = g_strdup_printf("AT+XBANDSEL=%d,%d", gsm_band, gsm_band2);
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);
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);
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);
1897 tcore_hal_send_request(h, pending_gsm);
1901 /* Lock device to specific RAT as requested by application */
1903 AT+XRAT=<Act>[,<PreferredAct>]
1904 <AcT> indicates the radio access technology and may be
1906 1 GSM / UMTS Dual mode
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);
1914 cmd_str = g_strdup_printf("AT+XRAT=%d", AT_XRAT_GSM);
1916 atreq = tcore_at_request_new(cmd_str, "+XRAT", TCORE_AT_NO_RESULT);
1917 pending = tcore_pending_new(o, 0);
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);
1925 tcore_hal_send_request(h, pending);
1927 return TCORE_RETURN_SUCCESS;
1930 static TReturn get_band(CoreObject *o, UserRequest *ur)
1933 TcorePending *pending = NULL;
1935 TcoreATRequest *atreq;
1936 char *cmd_str = NULL;
1937 dbg("get_band - ENTER!!");
1940 return TCORE_RETURN_EINVAL;
1942 h = tcore_object_get_hal(o);
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);
1955 return TCORE_RETURN_SUCCESS;
1958 static TReturn set_preferred_plmn(CoreObject *o, UserRequest *ur)
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 */
1968 int gsm_compact_act = 0;
1972 return TCORE_RETURN_EINVAL;
1974 req_data = (struct treq_network_set_preferred_plmn *) tcore_user_request_ref_data(ur, NULL);
1975 pending = tcore_pending_new(o, 0);
1977 dbg("Entry set_preferred_plmn");
1979 p = tcore_object_ref_plugin(o);
1980 h = tcore_object_get_hal(o);
1984 [<index>][,<format>[,<oper>[,<GSM_AcT>,
1985 <GSM_Compact_AcT>,<UTRAN_AcT>]]]
1988 if ((req_data->act == NETWORK_ACT_GSM) || (req_data->act == NETWORK_ACT_GPRS) || (req_data->act == NETWORK_ACT_EGPRS))
1990 else if ((req_data->act == NETWORK_ACT_UMTS) || (req_data->act == NETWORK_ACT_UTRAN))
1992 else if (req_data->act == NETWORK_ACT_GSM_UTRAN)
1993 gsm_act = utran_act = TRUE;
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';
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);
2004 dbg("cmd_str - %s", cmd_str);
2005 atreq = tcore_at_request_new(cmd_str, "+CPOL", TCORE_AT_NO_RESULT);
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);
2012 tcore_hal_send_request(h, pending);
2016 dbg("Exit set_preferred_plmn");
2018 return TCORE_RETURN_SUCCESS;
2021 static TReturn get_preferred_plmn(CoreObject *o, UserRequest *ur)
2024 TcorePending *pending = NULL;
2025 TcoreATRequest *atreq = NULL;
2027 char *cmd_str = NULL;
2029 dbg("get_preferred_plmn - ENTER!!");
2032 return TCORE_RETURN_EINVAL;
2034 h = tcore_object_get_hal(o);
2035 pending = tcore_pending_new(o, 0);
2037 cmd_str = g_strdup_printf("AT+CPOL?");
2038 atreq = tcore_at_request_new(cmd_str, "+CPOL", TCORE_AT_MULTILINE);
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);
2045 tcore_hal_send_request(h, pending);
2049 dbg("get_preferred_plmn - EXIT!!");
2051 return TCORE_RETURN_SUCCESS;
2054 static TReturn get_serving_network(CoreObject *o, UserRequest *ur)
2056 dbg("get_serving_network - ENTER!!");
2059 return TCORE_RETURN_EINVAL;
2061 dbg("new pending(AT+COPS?)");
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;
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,
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,
2085 gboolean s_network_init(TcorePlugin *p, TcoreHal *h)
2087 CoreObject *o = NULL;
2089 o = tcore_network_new(p, "umts_network", &network_ops, h);
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);
2097 /* +CTZV: <tz>,<time> */
2098 tcore_object_add_callback(o, "+CTZV", on_event_network_ctzv_time_info, NULL);
2100 tcore_server_add_notification_hook(tcore_plugin_ref_server(p), TNOTI_SIM_STATUS, on_hook_sim_init, o);
2102 _insert_mcc_mnc_oper_list(p, o);
2107 void s_network_exit(TcorePlugin *p)
2111 o = tcore_plugin_ref_core_object(p, "umts_network");
2113 tcore_network_free(o);