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>
31 #include <user_request.h>
33 #include <co_network.h>
41 #include "imc_common.h"
42 #include "imc_network.h"
44 #define AT_CREG_STAT_NOT_REG 0 /* not registered, MT is not currently searching a new operator to register to */
45 #define AT_CREG_STAT_REG_HOME 1 /* registered, home network */
46 #define AT_CREG_STAT_SEARCHING 2 /* not registered, but MT is currently searching a new operator to register to */
47 #define AT_CREG_STAT_REG_DENIED 3 /* registration denied */
48 #define AT_CREG_STAT_UNKNOWN 4 /* unknown */
49 #define AT_CREG_STAT_REG_ROAM 5 /* registered, roaming */
51 #define AT_COPS_MODE_AUTOMATIC 0 /* automatic (<oper> field is ignored) */
52 #define AT_COPS_MODE_MANUAL 1 /* manual (<oper> field shall be present, and <AcT> optionally) */
53 #define AT_COPS_MODE_DEREGISTER 2 /* deregister from network */
54 #define AT_COPS_MODE_SET_ONLY 3 /* set only <format> */
55 #define AT_COPS_MODE_MANUAL_AUTOMATIC 4 /*automatic - manual*/
57 #define AT_COPS_FORMAT_LONG_ALPHANUMERIC 0 /* long format alphanumeric <oper> */
58 #define AT_COPS_FORMAT_SHORT_ALPHANUMERIC 1 /* short format alphanumeric <oper> */
59 #define AT_COPS_FORMAT_NUMERIC 2 /* numeric <oper> */
61 #define AT_COPS_ACT_GSM 0 /* GSM */
62 #define AT_COPS_ACT_GSM_COMPACT 1 /* GSM Compact */
63 #define AT_COPS_ACT_UTRAN 2 /* UTRAN */
64 #define AT_COPS_ACT_GSM_EGPRS 3 /* GSM w/EGPRS */
65 #define AT_COPS_ACT_UTRAN_HSDPA 4 /* UTRAN w/HSDPA */
66 #define AT_COPS_ACT_UTRAN_HSUPA 5 /* UTRAN w/HSUPA */
67 #define AT_COPS_ACT_UTRAN_HSDPA_HSUPA 6 /* UTRAN w/HSDPA and HSUPA */
68 #define AT_COPS_ACT_E_UTRAN 7 /* E-UTRAN */
70 #define AT_GSM_XBANDSEL_AUTOMATIC 0
71 #define AT_GSM_XBANDSEL_1800 1800
72 #define AT_GSM_XBANDSEL_1900 1900
73 #define AT_GSM_XBANDSEL_900 900
74 #define AT_GSM_XBANDSEL_850 850
75 #define AT_GSM_XBANDSEL_450 450
76 #define AT_GSM_XBANDSEL_480 480
77 #define AT_GSM_XBANDSEL_750 750
78 #define AT_GSM_XBANDSEL_380 380
79 #define AT_GSM_XBANDSEL_410 410
82 #define AT_XRAT_DUAL 1
83 #define AT_XRAT_UMTS 2
85 #define MAX_NETWORKS_PREF_PLMN_SUPPORT 150
86 #define MAX_NETWORKS_MANUAL_SEARCH_SUPPORT 20
88 #define VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS "db/telephony/dualsim/default_data_service"
91 IMC_NETWORK_SEARCH_STATE_NO_SEARCH,
92 IMC_NETWORK_SEARCH_STATE_IN_PROGRESS,
93 IMC_NETWORK_SEARCH_STATE_CANCELLED
94 } ImcNetworkSearchState;
97 ImcNetworkSearchState search_state;
100 static unsigned int lookup_tbl_net_status[] = {
101 [AT_CREG_STAT_NOT_REG] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
102 [AT_CREG_STAT_REG_HOME] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
103 [AT_CREG_STAT_SEARCHING] = NETWORK_SERVICE_DOMAIN_STATUS_SEARCH,
104 [AT_CREG_STAT_REG_DENIED] = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY,
105 [AT_CREG_STAT_UNKNOWN] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
106 [AT_CREG_STAT_REG_ROAM] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
109 static unsigned int lookup_tbl_access_technology[] = {
110 [AT_COPS_ACT_GSM] = NETWORK_ACT_GSM,
111 [AT_COPS_ACT_GSM_COMPACT] = NETWORK_ACT_GSM,
112 [AT_COPS_ACT_UTRAN] = NETWORK_ACT_UTRAN,
113 [AT_COPS_ACT_GSM_EGPRS] = NETWORK_ACT_EGPRS,
114 [AT_COPS_ACT_UTRAN_HSDPA] = NETWORK_ACT_UTRAN,
115 [AT_COPS_ACT_UTRAN_HSUPA] = NETWORK_ACT_UTRAN,
116 [AT_COPS_ACT_UTRAN_HSDPA_HSUPA] = NETWORK_ACT_UTRAN,
117 [AT_COPS_ACT_E_UTRAN] = NETWORK_ACT_GSM_UTRAN,
120 static gboolean get_serving_network(CoreObject *o, UserRequest *ur);
123 static void on_confirmation_network_message_send(TcorePending *p, gboolean result, void *user_data)
125 dbg("on_confirmation_modem_message_send - msg out from queue.\n");
127 if (result == FALSE) {
135 static void nwk_prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, UserRequest *ur, TcorePendingResponseCallback callback)
137 TcoreATRequest *req = NULL;
139 TcorePending *pending = NULL;
142 hal = tcore_object_get_hal(co);
144 pending = tcore_pending_new(co, 0);
145 req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
147 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
149 tcore_pending_set_request_data(pending, 0, req);
150 tcore_pending_set_response_callback(pending, callback, req->cmd);
151 tcore_pending_link_user_request(pending, ur);
152 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
154 ret = tcore_hal_send_request(hal, pending);
156 if (ret != TCORE_RETURN_SUCCESS)
157 err("Failed to send AT request - ret: [0x%x]", ret);
163 static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *o)
168 char query[255] = { 0, };
171 GHashTable *result = NULL, *row = NULL;
172 struct tcore_network_operator_info *noi = NULL;
175 s = tcore_plugin_ref_server(p);
176 strg = tcore_server_find_storage(s, "database");
178 handle = tcore_storage_create_handle(strg, "/opt/dbspace/.mcc_mnc_oper_list.db");
180 dbg("fail to create database handle");
184 snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list");
186 result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
187 (GDestroyNotify) g_hash_table_destroy);
189 tcore_storage_read_query_database(strg, handle, query, NULL, result, 4);
191 g_hash_table_iter_init(&iter, result);
192 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
195 noi = calloc(sizeof(struct tcore_network_operator_info), 1);
197 snprintf(noi->mcc, 4, "%s", (char *) g_hash_table_lookup(row, "1"));
198 snprintf(noi->mnc, 4, "%s", (char *) g_hash_table_lookup(row, "2"));
199 snprintf(noi->name, 41, "%s", (char *) g_hash_table_lookup(row, "3"));
200 snprintf(noi->country, 4, "%s", (char *) g_hash_table_lookup(row, "0"));
202 tcore_network_operator_info_add(o, noi);
209 dbg("count = %d", count);
211 g_hash_table_destroy(result);
213 tcore_storage_remove_handle(strg, handle);
216 static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type,
217 int domain, int act, int cs_status, int ps_status)
219 enum telephony_network_service_type ret;
224 case NETWORK_ACT_UNKNOWN:
225 ret = NETWORK_SERVICE_TYPE_UNKNOWN;
228 case NETWORK_ACT_GSM:
229 if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE && domain == NETWORK_SERVICE_DOMAIN_CS)
230 ret = NETWORK_SERVICE_TYPE_2_5G_EDGE;
232 ret = NETWORK_SERVICE_TYPE_2G;
235 case NETWORK_ACT_EGPRS:
236 return NETWORK_SERVICE_TYPE_2_5G_EDGE;
239 case NETWORK_ACT_UMTS:
240 ret = NETWORK_SERVICE_TYPE_3G;
244 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) {
245 ret = NETWORK_SERVICE_TYPE_NO_SERVICE;
246 } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) {
247 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
250 ret = NETWORK_SERVICE_TYPE_SEARCH;
252 } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) {
253 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
256 ret = NETWORK_SERVICE_TYPE_EMERGENCY;
263 static void _ps_set(TcorePlugin *p, int status)
267 co_ps = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_PS);
269 err("No PS Core Object on plugin");
273 if (status == NETWORK_SERVICE_DOMAIN_STATUS_FULL)
274 tcore_ps_set_online(co_ps, TRUE);
276 tcore_ps_set_online(co_ps, FALSE);
279 static void on_timeout_search_network(TcorePending *p, void *user_data)
282 struct tresp_network_search resp;
283 CustomData *custom_data;
285 dbg("TIMEOUT !!!!! pending=%p", p);
287 memset(&resp, 0, sizeof(struct tresp_network_search));
289 resp.result = TCORE_RETURN_FAILURE;
292 custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p));
293 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
295 ur = tcore_pending_ref_user_request(p);
297 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &resp);
301 static void on_response_set_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data)
304 const TcoreATResponse *atResp = data;
305 // GSList *tokens = NULL;
306 // char * line = NULL;
307 struct tresp_network_set_plmn_selection_mode resp = {0};
309 if (atResp->success > 0) {
311 resp.result = TCORE_RETURN_SUCCESS;
314 resp.result = TCORE_RETURN_FAILURE;
317 ur = tcore_pending_ref_user_request(p);
319 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_set_plmn_selection_mode), &resp);
323 static void on_response_get_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data)
326 struct tresp_network_get_plmn_selection_mode resp = {0};
327 const TcoreATResponse *atResp = data;
328 GSList *tokens = NULL;
332 resp.result = TCORE_RETURN_FAILURE;
334 if (atResp->success > 0) {
337 +COPS: <mode>[,<format>,<oper>[,< AcT>]]
341 line = (char *) atResp->lines->data;
342 tokens = tcore_at_tok_new(line);
343 if (g_slist_length(tokens) < 1) {
344 msg("invalid message");
347 mode = atoi(tcore_at_tok_nth(tokens, 0));
348 dbg("mode = %d", mode);
351 case AT_COPS_MODE_AUTOMATIC:
352 resp.mode = NETWORK_SELECT_MODE_AUTOMATIC;
355 case AT_COPS_MODE_MANUAL:
356 case AT_COPS_MODE_MANUAL_AUTOMATIC:
357 resp.mode = NETWORK_SELECT_MODE_MANUAL;
360 case AT_COPS_MODE_DEREGISTER:
361 case AT_COPS_MODE_SET_ONLY:
362 resp.result = TCORE_RETURN_FAILURE;
365 resp.result = TCORE_RETURN_SUCCESS;
369 resp.result = TCORE_RETURN_FAILURE;
373 ur = tcore_pending_ref_user_request(p);
375 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_get_plmn_selection_mode), &resp);
379 tcore_at_tok_free(tokens);
384 static void on_response_search_network(TcorePending *p, int data_len, const void *data, void *user_data)
387 struct tresp_network_search resp;
390 const TcoreATResponse *atResp = data;
391 GSList *tokens = NULL;
392 GSList *network_token = NULL;
394 char *temp_plmn_info = NULL;
395 char *alpha_name = NULL;
397 int num_network_avail = 0;
398 CustomData *custom_data;
400 memset(&resp, 0, sizeof(struct tresp_network_search));
401 resp.result = TCORE_RETURN_FAILURE;
404 custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p));
406 err("Network Search Custom Data is Null");
410 if (atResp->success > 0) {
413 /* If Request is Cancelled then return back SUCCESS/SEARCH_CANCELLED */
414 if (custom_data->search_state
415 == IMC_NETWORK_SEARCH_STATE_CANCELLED) {
416 dbg("Network Search has been Cancelled!!!");
421 line = (char *) atResp->lines->data;
422 tokens = tcore_at_tok_new(line);
423 num_network_avail = g_slist_length(tokens);
424 dbg(" length of tokens is %d\n", num_network_avail);
425 if (num_network_avail < 1) {
426 msg("invalid message");
431 resp.result = TCORE_RETURN_SUCCESS;
434 * +COPS: [list of supported (<stat>,long alphanumeric <oper>,
435 * short alphanumeric <oper>,numeric <oper>[,<AcT>])s]
436 * [,,(list of supported <mode>s),(list of supported <format>s)]
438 for (i = 0; ((i < num_network_avail) && (i < MAX_NETWORKS_MANUAL_SEARCH_SUPPORT)); i++) {
439 network_token = tcore_at_tok_new(g_slist_nth_data(tokens, i));
441 pResp = (tcore_at_tok_nth(network_token, 0));
443 dbg("status : %s", pResp);
444 resp.list[i].status = (enum telephony_network_plmn_status) atoi(pResp);
447 if ((pResp = tcore_at_tok_nth(network_token, 1))) { /* Long Alpha name */
448 dbg("Long Alpha name : %s", pResp);
450 if (strlen(pResp) > 0)
451 /* Strip off starting quote & ending quote */
452 strncpy(resp.list[i].name, pResp + 1, strlen(pResp) - 2);
455 if ((pResp = tcore_at_tok_nth(network_token, 2))) {
456 dbg("Short Aplha name : %s", pResp);
457 /* Short Aplha name */
458 /* Strip off starting quote & ending quote */
459 if (strlen(pResp) > 0)
460 strncpy(resp.list[i].name, pResp + 1, strlen(pResp) - 2);
464 pResp = tcore_at_tok_nth(network_token, 3);
466 dbg("PLMN ID : %s", pResp);
467 temp_plmn_info = tcore_at_tok_extract((const char *)pResp);
468 strncpy(resp.list[i].plmn, temp_plmn_info, 6);
469 resp.list[i].plmn[6] = '\0';
472 /* Parse Access Technology */
473 if ((pResp = tcore_at_tok_nth(network_token, 4))) {
474 if (strlen(pResp) > 0) {
478 resp.list[i].act = NETWORK_ACT_GSM;
480 resp.list[i].act = NETWORK_ACT_UMTS;
484 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);
487 tcore_at_tok_free(network_token);
489 g_free(temp_plmn_info);
493 resp.result = TCORE_RETURN_FAILURE;
497 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
499 ur = tcore_pending_ref_user_request(p);
501 tcore_user_request_send_response(ur,
502 TRESP_NETWORK_SEARCH,
503 sizeof(struct tresp_network_search), &resp);
507 tcore_at_tok_free(tokens);
510 static void on_response_set_umts_band(TcorePending *p, int data_len, const void *data, void *user_data)
512 const TcoreATResponse *atResp = data;
514 dbg("On Response Set UMTS Band");
516 if (atResp->success > 0) {
522 dbg("Wait for response of XRAT before sending final band setting response to AP");
527 static void on_response_set_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data)
529 const TcoreATResponse *atResp = data;
531 dbg("On Response Set GSM Band");
532 if (atResp->success > 0) {
538 dbg("Wait for response of XRAT before sending final band setting response to AP");
542 static void on_response_get_umts_band(TcorePending *p, int data_len, const void *data, void *user_data)
544 const TcoreATResponse *atResp = data;
545 GSList *tokens = NULL;
546 const char *line = NULL;
547 int total_umts_bands = 0;
549 char *band_token = NULL;
550 char umts_band[20] = {0};
551 char umts_band_1 = 0;
552 char umts_band_2 = 0;
553 char umts_band_5 = 0;
554 UserRequest *ur = NULL;
555 struct tresp_network_get_band resp = {0};
557 dbg("Entry on_response_get_umts_band");
559 resp.mode = NETWORK_BAND_MODE_PREFERRED;
560 resp.result = TCORE_RETURN_SUCCESS;
562 if (atResp->success > 0) {
565 line = (char *) atResp->lines->data;
566 tokens = tcore_at_tok_new(line);
567 total_umts_bands = g_slist_length(tokens);
568 dbg("Total UMTS bands enabled are : %d\n", total_umts_bands);
569 if (total_umts_bands < 1) {
578 for (i = 0; i < total_umts_bands; i++) {
579 band_token = tcore_at_tok_nth(tokens, i);
581 if (band_token == NULL)
584 memset(umts_band, 0x00, sizeof(umts_band));
586 if (atoi(band_token) == 0) { /* 0 means UMTS automatic */
587 umts_band_1 = umts_band_2 = umts_band_5 = TRUE;
591 /* Strip off starting quotes & ending quotes */
592 strncpy(umts_band, band_token + 1, strlen(band_token) - 2);
594 if (!strcmp(umts_band, "UMTS_BAND_I")) {
596 } else if (!strcmp(umts_band, "UMTS_BAND_II")) {
598 } else if (!strcmp(umts_band, "UMTS_BAND_II")) {
601 /* Telephony is not interest */
602 dbg("Telephony is not interested in %s band", umts_band);
607 if ((umts_band_1) && (umts_band_2) && (umts_band_5)) {
608 resp.band = NETWORK_BAND_TYPE_WCDMA;
609 } else if (umts_band_1) {
610 resp.band = NETWORK_BAND_TYPE_WCDMA2100;
611 } else if (umts_band_2) {
612 resp.band = NETWORK_BAND_TYPE_WCDMA1900;
613 } else if (umts_band_5) {
614 resp.band = NETWORK_BAND_TYPE_WCDMA850;
616 resp.result = TCORE_RETURN_FAILURE;
619 dbg("Final resp.band sent to TS = %d", resp.band);
621 ur = tcore_pending_ref_user_request(p);
623 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
627 tcore_at_tok_free(tokens);
629 dbg("Exit on_response_get_umts_band");
633 static void on_response_get_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data)
635 struct tresp_network_get_band resp = {0};
636 const TcoreATResponse *atResp = data;
637 GSList *tokens = NULL;
638 int total_gsm_bands = 0;
639 const char *line = NULL;
641 char *band_token = NULL;
642 UserRequest *ur = NULL;
648 dbg("Entry on_response_get_gsm_band");
650 resp.mode = NETWORK_BAND_MODE_PREFERRED;
651 resp.result = TCORE_RETURN_SUCCESS;
653 if (atResp->success > 0) {
656 line = (char *) atResp->lines->data;
657 tokens = tcore_at_tok_new(line);
658 total_gsm_bands = g_slist_length(tokens);
659 dbg("Total GSM bands enabled are : %d\n", total_gsm_bands);
660 if (total_gsm_bands < 1)
665 for (i = 0; i < total_gsm_bands; i++) {
666 band_token = tcore_at_tok_nth(tokens, i);
668 if (band_token == NULL)
671 if (atoi(band_token) == 0) { /* 0 means GSM automatic */
672 gsm_850 = gsm_900 = gsm_1800 = gsm_1900 = TRUE;
676 switch (atoi(band_token)) {
677 case AT_GSM_XBANDSEL_850:
681 case AT_GSM_XBANDSEL_900:
685 case AT_GSM_XBANDSEL_1800:
689 case AT_GSM_XBANDSEL_1900:
700 if (gsm_850 && gsm_900 && gsm_1800 && gsm_1900) {
701 resp.band = NETWORK_BAND_TYPE_GSM;
702 } else if (gsm_850 && gsm_1900) {
703 resp.band = NETWORK_BAND_TYPE_GSM_850_1900;
704 } else if (gsm_900 && gsm_1800) {
705 resp.band = NETWORK_BAND_TYPE_GSM_900_1800;
706 } else if (gsm_1900) {
707 resp.band = NETWORK_BAND_TYPE_GSM1900;
708 } else if (gsm_850) {
709 resp.band = NETWORK_BAND_TYPE_GSM850;
710 } else if (gsm_1800) {
711 resp.band = NETWORK_BAND_TYPE_GSM1800;
712 } else if (gsm_900) {
713 resp.band = NETWORK_BAND_TYPE_GSM900;
715 resp.result = TCORE_RETURN_FAILURE;
718 dbg("Final resp.band sent to TS = %d", resp.band);
720 ur = tcore_pending_ref_user_request(p);
722 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
726 tcore_at_tok_free(tokens);
728 dbg("Exit on_response_get_gsm_band");
733 static void on_response_get_xrat(TcorePending *p, int data_len, const void *data, void *user_data)
736 UserRequest *ur = NULL;
738 TcoreATRequest *atreq;
739 char *cmd_str = NULL;
740 UserRequest *dup_ur = NULL;
741 const TcoreATResponse *atResp = data;
742 const char *line = NULL;
744 GSList *tokens = NULL;
745 TcorePending *pending = NULL;
746 CoreObject *o = NULL;
748 struct tresp_network_get_band resp = {0};
750 dbg("Enter on_response_get_xrat !!");
752 resp.mode = NETWORK_BAND_MODE_PREFERRED;
754 ur = tcore_pending_ref_user_request(p);
755 h = tcore_object_get_hal(tcore_pending_ref_core_object(p));
756 o = tcore_pending_ref_core_object(p);
758 if (atResp->success > 0) {
761 line = (char *) atResp->lines->data;
762 tokens = tcore_at_tok_new(line);
763 if (g_slist_length(tokens) < 1) {
764 msg("invalid message");
769 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
770 cp_xrat = atoi(pResp);
772 if ((cp_xrat == AT_XRAT_DUAL)) { /* mode is Dual, send reply to Telephony */
773 resp.result = TCORE_RETURN_SUCCESS;
774 resp.band = NETWORK_BAND_TYPE_ANY;
776 ur = tcore_pending_ref_user_request(p);
778 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
781 } else if ((cp_xrat == AT_XRAT_UMTS)) {
782 /* Get UMTS Band Information */
783 dup_ur = tcore_user_request_ref(ur); /* duplicate user request for AT+XUBANDSEL */
784 cmd_str = g_strdup_printf("AT+XUBANDSEL?");
785 atreq = tcore_at_request_new(cmd_str, "+XUBANDSEL", TCORE_AT_SINGLELINE);
786 pending = tcore_pending_new(o, 0);
787 tcore_pending_set_request_data(pending, 0, atreq);
788 tcore_pending_set_response_callback(pending, on_response_get_umts_band, NULL);
789 tcore_pending_link_user_request(pending, ur);
790 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
791 tcore_hal_send_request(h, pending);
793 } else if ((cp_xrat == AT_XRAT_UMTS)) {
794 /* Get GSM Band Information */
795 dup_ur = tcore_user_request_ref(ur); /* duplicate user request for AT+XBANDSEL */
796 cmd_str = g_strdup_printf("AT+XBANDSEL?");
797 atreq = tcore_at_request_new(cmd_str, "+XBANDSEL", TCORE_AT_SINGLELINE);
798 pending = tcore_pending_new(o, 0);
799 tcore_pending_set_request_data(pending, 0, atreq);
800 tcore_pending_set_response_callback(pending, on_response_get_gsm_band, NULL);
801 tcore_pending_link_user_request(pending, dup_ur);
802 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
803 tcore_hal_send_request(h, pending);
810 resp.result = TCORE_RETURN_FAILURE;
811 resp.band = NETWORK_BAND_TYPE_ANY;
813 ur = tcore_pending_ref_user_request(p);
815 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp);
821 tcore_at_tok_free(tokens);
823 dbg("Exit on_response_get_xrat !!");
829 static void on_response_set_xrat(TcorePending *p, int data_len, const void *data, void *user_data)
831 UserRequest *ur = NULL;
832 struct tresp_network_set_band resp = {0};
833 const TcoreATResponse *atResp = data;
835 dbg("On Response Set XRAT");
837 if (atResp->success > 0) {
839 resp.result = TCORE_RETURN_SUCCESS;
842 resp.result = TCORE_RETURN_FAILURE;
845 ur = tcore_pending_ref_user_request(p);
847 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_BAND, sizeof(struct tresp_network_set_band), &resp);
853 static void on_response_set_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data)
855 UserRequest *ur = NULL;
856 struct tresp_network_set_preferred_plmn resp = {0};
857 const TcoreATResponse *atResp = data;
859 dbg("ENTER on_response_set_preferred_plmn");
861 if (atResp->success > 0) {
863 resp.result = TCORE_RETURN_SUCCESS;
866 resp.result = TCORE_RETURN_FAILURE;
869 ur = tcore_pending_ref_user_request(p);
871 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PREFERRED_PLMN, sizeof(struct tresp_network_set_preferred_plmn), &resp);
874 dbg("Exit on_response_set_preferred_plmn");
878 static void on_response_get_nitz_name(TcorePending *p, int data_len, const void *data, void *user_data)
880 const TcoreATResponse *atResp = data;
881 GSList *tokens = NULL;
882 const char *line = NULL;
883 CoreObject *o = NULL;
884 struct tnoti_network_identity noti;
887 int net_name_type = 0;
889 char *net_name = NULL;
891 dbg("Entry on_response_get_nitz_name (+XCOPS)");
892 o = tcore_pending_ref_core_object(p);
893 if (atResp->success > 0) {
897 nol = g_slist_length(atResp->lines);
899 msg("invalid message");
903 memset(¬i, 0, sizeof(struct tnoti_network_identity));
905 for (count = 0; count < nol; count++) {
907 line = g_slist_nth_data(atResp->lines, count);
908 tokens = tcore_at_tok_new(line);
909 dbg("line %d start---------------", count);
911 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
912 net_name_type = atoi(pResp);
913 dbg("Net name type : %d", net_name_type);
915 switch (net_name_type) {
916 case 0: /* plmn_id (mcc, mnc) */
917 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
918 if (strlen(pResp) > 0) {
919 net_name = tcore_at_tok_extract((const char *)pResp);
920 strncpy(noti.plmn, net_name, 6);
926 case 5: /* Short NITZ name*/
927 case 3: /* Short Network Name (CPHS) */
928 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
929 if (strlen(pResp) > 0) {
930 net_name = tcore_at_tok_extract((const char *)pResp);
931 strncpy(noti.short_name, net_name, 16);
932 noti.short_name[16] = '\0';
937 case 6: /* Full NITZ name */
938 case 4: /* Long Network Name (CPHS) */
939 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
940 if (strlen(pResp) > 0) {
941 net_name = tcore_at_tok_extract((const char *)pResp);
942 strncpy(noti.full_name, net_name, 32);
943 noti.full_name[32] = '\0';
956 tcore_at_tok_free(tokens);
959 dbg("plmn <%s> short NITZ name<%s> full NITZ name<%s>",
960 noti.plmn, noti.short_name, noti.full_name);
961 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_IDENTITY,
962 sizeof(struct tnoti_network_identity), ¬i);
969 dbg("Exit on_response_get_nitz_name");
972 static void on_response_get_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data)
977 const TcoreATResponse *atResp = data;
978 GSList *tokens = NULL;
982 struct tresp_network_get_preferred_plmn resp = {0};
984 int GSM_AcT2 = 0, GSM_Compact_AcT2 = 0, UTRAN_AcT2 = 0;
988 if (atResp->success > 0) {
991 total_lines = g_slist_length(atResp->lines);
992 dbg("Total number of network present in Preferred PLMN list is %d\n", total_lines);
994 if (total_lines < 1) {
995 msg("invalid message");
999 if (total_lines >= MAX_NETWORKS_PREF_PLMN_SUPPORT)
1000 total_lines = MAX_NETWORKS_PREF_PLMN_SUPPORT;
1003 +CPOL: <index1>,<format>,<oper1>[,<GSM_AcT1>,<GSM_Compact_AcT1>,<UTRAN_AcT1>,<E-UTRAN_AcT1>] [<CR><LF>
1004 +CPOL: <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>,<E-UTRAN_AcT2>]
1006 resp.result = TCORE_RETURN_SUCCESS;
1008 for (i = 0; i < total_lines; i++) {
1009 /* Take each line response at a time & parse it */
1010 line = tcore_at_tok_nth(atResp->lines, i);
1011 tokens = tcore_at_tok_new(line);
1013 /* <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>,<E-UTRAN_AcT2>] */
1016 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
1017 dbg("Index : %s", pResp);
1018 resp.list[i].ef_index = atoi(pResp);
1021 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
1022 dbg("format : %s", pResp);
1023 plmn_format = atoi(pResp);
1026 /* Operator PLMN ID */
1027 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
1028 dbg("plmn ID : %s", pResp);
1030 if (strlen(pResp) > 0) {
1033 oper = tcore_at_tok_extract((const char *)pResp);
1034 dbg("operator <%s>", oper);
1037 if (plmn_format == 2) {
1038 strncpy(resp.list[i].plmn, oper, 6);
1039 resp.list[i].plmn[6] = '\0';
1046 if ((pResp = tcore_at_tok_nth(tokens, 3))) {
1047 dbg("GSM_AcT2 : %s", pResp);
1048 GSM_AcT2 = atoi(pResp);
1051 if ((pResp = tcore_at_tok_nth(tokens, 4))) {
1052 dbg("GSM_Compact AcT2 : %s", pResp);
1053 GSM_Compact_AcT2 = atoi(pResp);
1056 if ((pResp = tcore_at_tok_nth(tokens, 5))) {
1057 dbg("UTRAN_AcT2 : %s", pResp);
1058 UTRAN_AcT2 = atoi(pResp);
1061 if (UTRAN_AcT2 && (GSM_AcT2 || GSM_Compact_AcT2))
1062 resp.list[i].act = NETWORK_ACT_GSM_UTRAN;
1063 else if (UTRAN_AcT2)
1064 resp.list[i].act = NETWORK_ACT_UMTS;
1065 else if (GSM_AcT2 || GSM_Compact_AcT2)
1066 resp.list[i].act = NETWORK_ACT_GPRS;
1068 (resp.list_count)++;
1070 tcore_at_tok_free(tokens);
1074 dbg("RESPONSE NOT OK");
1075 // TODO: CMEE error mapping is required.
1076 resp.result = TCORE_RETURN_FAILURE;
1080 ur = tcore_pending_ref_user_request(p);
1082 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PREFERRED_PLMN, sizeof(struct tresp_network_get_preferred_plmn), &resp);
1088 static void on_response_get_serving_network(TcorePending *p, int data_len, const void *data, void *user_data)
1090 const TcoreATResponse *resp = data;
1092 struct tresp_network_get_serving_network Tresp = {0};
1093 char *long_plmn_name = NULL;
1094 char *short_plmn_name = NULL;
1095 char *plmn_id = NULL;
1097 GSList *tokens = NULL;
1099 int network_mode = -1;
1100 int plmn_format = -1;
1102 struct tnoti_network_identity noti;
1106 o = tcore_pending_ref_core_object(p);
1108 if (resp->success <= 0) {
1109 dbg("RESPONSE NOK");
1111 ur = tcore_pending_ref_user_request(p);
1113 Tresp.result = TCORE_RETURN_FAILURE;
1114 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp);
1120 nol = g_slist_length(resp->lines);
1121 dbg("nol : %d", nol);
1123 for (count = 0; count < nol; count++) {
1125 line = g_slist_nth_data(resp->lines, count);
1126 tokens = tcore_at_tok_new(line);
1127 dbg("line %d start---------------", count);
1129 if ((pResp = tcore_at_tok_nth(tokens, 0))) {
1130 dbg("mode : %s", pResp);
1131 network_mode = atoi(pResp);
1134 // format (optional)
1135 if ((pResp = tcore_at_tok_nth(tokens, 1))) {
1136 dbg("format : %s", pResp);
1137 if (strlen(pResp) > 0)
1138 plmn_format = atoi(pResp);
1142 switch (plmn_format) {
1143 case AT_COPS_FORMAT_LONG_ALPHANUMERIC:
1144 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
1145 dbg("long PLMN : %s", pResp);
1146 if (strlen(pResp) > 0) {
1147 long_plmn_name = tcore_at_tok_extract((const char *)pResp);
1149 // set network name into po
1150 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_FULL, long_plmn_name);
1155 case AT_COPS_FORMAT_SHORT_ALPHANUMERIC:
1156 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
1157 dbg("short PLMN : %s", pResp);
1158 if (strlen(pResp) > 0) {
1159 short_plmn_name = tcore_at_tok_extract((const char *)pResp);
1161 // set network name into po
1162 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SHORT, short_plmn_name);
1167 case AT_COPS_FORMAT_NUMERIC:
1168 if ((pResp = tcore_at_tok_nth(tokens, 2))) {
1169 dbg("numeric : %s", pResp);
1170 if (strlen(pResp) > 0) {
1171 plmn_id = tcore_at_tok_extract((const char *)pResp);
1173 // set plmn id into po
1174 tcore_network_set_plmn(o, plmn_id);
1184 if ((pResp = tcore_at_tok_nth(tokens, 3))) {
1185 dbg("AcT : %s", pResp);
1186 if (strlen(pResp) > 0) {
1188 tcore_network_set_access_technology(o, lookup_tbl_access_technology[AcT]);
1192 tcore_at_tok_free(tokens);
1196 memcpy(Tresp.plmn, plmn_id, strlen(plmn_id));
1197 tcore_network_get_access_technology(o, &(Tresp.act));
1198 tcore_network_get_lac(o, &(Tresp.gsm.lac));
1200 ur = tcore_pending_ref_user_request(p);
1202 Tresp.result = TCORE_RETURN_SUCCESS;
1203 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp);
1205 /* Network change noti */
1206 struct tnoti_network_change network_change;
1208 memset(&network_change, 0, sizeof(struct tnoti_network_change));
1210 memcpy(network_change.plmn, plmn_id, strlen(plmn_id));
1211 tcore_network_get_access_technology(o, &(network_change.act));
1212 tcore_network_get_lac(o, &(network_change.gsm.lac));
1214 tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(p)), tcore_pending_ref_core_object(p),
1215 TNOTI_NETWORK_CHANGE, sizeof(struct tnoti_network_change), &network_change);
1216 dbg("dbg.. network_change.plmn : %s", network_change.plmn);
1217 dbg("dbg.. network_change.act : %d", network_change.act);
1218 dbg("dbg.. network_change.gsm.lac : %d", network_change.gsm.lac);
1220 if ((AT_COPS_MODE_DEREGISTER != network_mode) &&
1221 (AT_COPS_MODE_SET_ONLY != network_mode)) {
1222 /*Network identity noti*/
1223 memset(¬i, 0x0, sizeof(struct tnoti_network_identity));
1225 memcpy(noti.full_name, long_plmn_name, MIN(32, strlen(long_plmn_name)));
1226 if (short_plmn_name)
1227 memcpy(noti.short_name, short_plmn_name, MIN(16, strlen(short_plmn_name)));
1229 memcpy(noti.plmn, plmn_id, strlen(plmn_id)); // plmn_id length is necessarily <= 6
1231 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),
1232 o, TNOTI_NETWORK_IDENTITY, sizeof(struct tnoti_network_identity), ¬i);
1233 dbg("dbg.. noti.short_name : %s", noti.short_name);
1234 dbg("dbg.. noti.full_name : %s", noti.full_name);
1235 dbg("dbg.. noti.plmn : %s", noti.plmn);
1239 g_free(long_plmn_name);
1240 g_free(short_plmn_name);
1246 static void on_response_network_set_mode(TcorePending *p, int data_len, const void *data, void *user_data)
1248 UserRequest *ur = NULL;
1249 struct tresp_network_set_mode resp = {0};
1250 const TcoreATResponse *atResp = data;
1252 dbg("ENTER on_response_network_set_mode");
1254 if (atResp && atResp->success) {
1256 resp.result = TCORE_RETURN_SUCCESS;
1258 err("RESPONSE NOK");
1259 resp.result = TCORE_RETURN_FAILURE;
1262 ur = tcore_pending_ref_user_request(p);
1264 tcore_user_request_send_response(ur,
1265 TRESP_NETWORK_SET_MODE,
1266 sizeof(struct tresp_network_set_mode), &resp);
1270 static void on_response_network_get_mode(TcorePending *p, int data_len, const void *data, void *user_data)
1272 UserRequest *ur = NULL;
1273 struct tresp_network_get_mode resp = {0};
1274 const TcoreATResponse *atResp = data;
1275 GSList *tokens = NULL;
1277 dbg("ENTER on_response_network_get_mode");
1279 resp.result = TCORE_RETURN_FAILURE;
1281 if (atResp && atResp->success) {
1285 if (!atResp->lines) {
1286 err("invalid response received");
1290 line = (char *) atResp->lines->data;
1291 tokens = tcore_at_tok_new(line);
1292 if (g_slist_length(tokens) < 1) {
1293 err("invalid message");
1299 net_mode = atoi(tcore_at_tok_nth(tokens, 0));
1300 dbg("mode = %d", net_mode);
1304 resp.mode = NETWORK_MODE_GSM;
1307 resp.mode = NETWORK_MODE_AUTO;
1310 resp.mode = NETWORK_MODE_WCDMA;
1313 err("Unsupported mode [%d]", net_mode);
1317 resp.result = TCORE_RETURN_SUCCESS;
1319 err("RESPONSE NOK");
1323 ur = tcore_pending_ref_user_request(p);
1325 tcore_user_request_send_response(ur,
1326 TRESP_NETWORK_GET_MODE,
1327 sizeof(struct tresp_network_get_mode), &resp);
1331 tcore_at_tok_free(tokens);
1334 static void on_response_cancel_manual_search(TcorePending *p, int data_len, const void *data, void *user_data)
1336 UserRequest *ur = NULL;
1337 struct tresp_network_set_cancel_manual_search resp = {0};
1338 const TcoreATResponse *atResp = data;
1339 CustomData *custom_data;
1341 dbg("ENTER on_response_cancel_manual_search");
1343 if (atResp->success > 0) {
1345 resp.result = TCORE_RETURN_SUCCESS;
1347 dbg("Response NOK");
1348 resp.result = TCORE_RETURN_FAILURE;
1351 custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p));
1352 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
1354 ur = tcore_pending_ref_user_request(p);
1356 tcore_user_request_send_response(ur,
1357 TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH,
1358 sizeof(struct tresp_network_set_cancel_manual_search), &resp);
1361 dbg("Exit on_response_cancel_manual_search");
1364 static gboolean on_event_ps_network_regist(CoreObject *o, const void *data, void *user_data)
1366 struct tnoti_network_registration_status regist_status;
1367 enum telephony_network_service_domain_status cs_status;
1368 enum telephony_network_service_domain_status ps_status;
1369 enum telephony_network_service_type service_type;
1370 enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
1371 struct tnoti_network_location_cellinfo net_lac_cell_info = {0};
1372 struct tnoti_ps_protocol_status noti = {0};
1373 unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_PS;
1374 int stat = 0, AcT = 0;
1375 unsigned int lac = 0xffff, ci = 0xffff;
1376 unsigned int rac = 0xffff;
1377 GSList *tokens = NULL;
1380 GSList *lines = NULL;
1382 lines = (GSList *) data;
1383 if (1 != g_slist_length(lines)) {
1384 dbg("unsolicited msg but multiple line");
1387 line = (char *) (lines->data);
1388 dbg("+CGREG NOTI RECEIVED");
1391 +CREG: <stat> [[,<lac>,<ci>[AcT]]
1393 Possible values of <stat> can be
1394 0 Not registered, ME is not currently searching a new operator to register to
1395 1 Registered, home network
1396 2 Not registered, but ME is currently searching a new operator to register
1397 3 Registration denied
1399 5 Registered, in roaming
1402 string type; two byte location area code in hexadecimal format (e.g. 00C3)
1405 string type; four byte cell ID in hexadecimal format (e.g. 0000A13F)
1413 6 UTRAN w/HSDPA and HSUPA
1414 Note: <Act> is supporting from R7 and above Protocol Stack.
1416 <rac>: is R7 and above feature, string type; one byte routing area code in hexadecimal format.
1419 tokens = tcore_at_tok_new(line);
1420 if (g_slist_length(tokens) < 1) {
1421 msg("invalid message");
1425 if (!(pResp = g_slist_nth_data(tokens, 0))) {
1426 dbg("No STAT in +CGREG");
1430 if ((pResp = g_slist_nth_data(tokens, 1))) {
1431 pResp = util_removeQuotes(pResp);
1432 lac = strtol(pResp, NULL, 16);
1436 if ((pResp = g_slist_nth_data(tokens, 2))) {
1437 pResp = util_removeQuotes(pResp);
1438 ci = strtol(pResp, NULL, 16);
1441 dbg("No ci in +CGREG");
1444 if ((pResp = g_slist_nth_data(tokens, 3)))
1447 dbg("No AcT in +CGREG");
1449 if ((pResp = g_slist_nth_data(tokens, 4))) {
1450 pResp = util_removeQuotes(pResp);
1451 rac = strtol(pResp, NULL, 16);
1454 dbg("No rac in +CGREG");
1459 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d, rac = 0x%x", stat, lac, ci, AcT, rac);
1461 ps_status = lookup_tbl_net_status[stat];
1463 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status);
1464 _ps_set(tcore_object_ref_plugin(o), ps_status);
1466 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
1468 act = lookup_tbl_access_technology[AcT];
1469 tcore_network_set_access_technology(o, act);
1471 tcore_network_get_service_type(o, &service_type);
1472 dbg("prev_service_type = 0x%x", service_type);
1473 service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status);
1474 dbg("new_service_type = 0x%x", service_type);
1475 tcore_network_set_service_type(o, service_type);
1477 tcore_network_set_lac(o, lac);
1478 tcore_network_set_cell_id(o, ci);
1479 tcore_network_set_rac(o, rac);
1481 net_lac_cell_info.lac = lac;
1482 net_lac_cell_info.cell_id = ci;
1484 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO,
1485 sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info);
1487 regist_status.cs_domain_status = cs_status;
1488 regist_status.ps_domain_status = ps_status;
1489 regist_status.service_type = service_type;
1490 regist_status.roaming_status = tcore_network_get_roaming_state(o);
1492 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
1493 TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(regist_status), ®ist_status);
1495 if (service_type == NETWORK_SERVICE_TYPE_HSDPA)
1496 noti.status = TELEPHONY_HSDPA_ON;
1498 noti.status = TELEPHONY_HSDPA_OFF;
1501 case AT_COPS_ACT_GSM:/*Fall Through*/
1502 case AT_COPS_ACT_GSM_COMPACT:/*Fall Through*/
1503 case AT_COPS_ACT_UTRAN:/*Fall Through*/
1504 case AT_COPS_ACT_GSM_EGPRS:/*Fall Through*/
1505 case AT_COPS_ACT_E_UTRAN:
1507 dbg("Not required for Protocol Status Notification");
1510 case AT_COPS_ACT_UTRAN_HSDPA:
1513 noti.status = TELEPHONY_HSDPA_ON;
1516 case AT_COPS_ACT_UTRAN_HSUPA:
1519 noti.status = TELEPHONY_HSUPA_ON;
1522 case AT_COPS_ACT_UTRAN_HSDPA_HSUPA:
1525 noti.status = TELEPHONY_HSPA_ON;
1535 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_PS_PROTOCOL_STATUS,
1536 sizeof(struct tnoti_ps_protocol_status), ¬i);
1538 /* Get PLMN ID needed to application */
1539 // get_serving_network(o, NULL);
1541 dbg("Response NOK");
1546 tcore_at_tok_free(tokens);
1550 static gboolean on_event_cs_network_regist(CoreObject *o, const void *event_info, void *user_data)
1552 GSList *lines = NULL;
1554 struct tnoti_network_registration_status regist_status;
1555 enum telephony_network_service_domain_status cs_status;
1556 enum telephony_network_service_domain_status ps_status;
1557 enum telephony_network_service_type service_type;
1558 enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
1559 struct tnoti_network_location_cellinfo net_lac_cell_info = {0};
1562 unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_CS;
1563 int stat = 0, AcT = 0;
1564 unsigned int lac = 0xffff, ci = 0xffff;
1565 GSList *tokens = NULL;
1568 lines = (GSList *) event_info;
1569 if (1 != g_slist_length(lines)) {
1570 dbg("unsolicited msg but multiple line");
1573 line = (char *) (lines->data);
1575 dbg("+CREG NOTI RECEIVED");
1578 +CREG: <stat> [[,<lac>,<ci>[AcT]]
1580 Possible values of <stat> can be
1581 0 Not registered, ME is not currently searching a new operator to register to
1582 1 Registered, home network
1583 2 Not registered, but ME is currently searching a new operator to register
1584 3 Registration denied
1586 5 Registered, in roaming
1589 string type; two byte location area code in hexadecimal format (e.g. 00C3)
1592 string type; four byte cell ID in hexadecimal format (e.g. 0000A13F)
1600 6 UTRAN w/HSDPA and HSUPA
1601 Note: <Act> is supporting from R7 and above Protocol Stack.
1604 tokens = tcore_at_tok_new(line);
1605 if (g_slist_length(tokens) < 1) {
1606 msg("invalid message");
1610 if (!(pResp = g_slist_nth_data(tokens, 0))) {
1611 dbg("No STAT in +CREG");
1615 if ((pResp = g_slist_nth_data(tokens, 1))) {
1616 pResp = util_removeQuotes(pResp);
1617 lac = strtol(pResp, NULL, 16);
1621 if ((pResp = g_slist_nth_data(tokens, 2))) {
1622 pResp = util_removeQuotes(pResp);
1623 ci = strtol(pResp, NULL, 16);
1626 dbg("No ci in +CREG");
1629 if ((pResp = g_slist_nth_data(tokens, 3)))
1632 dbg("No AcT in +CREG");
1636 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d", stat, lac, ci, AcT);
1638 cs_status = lookup_tbl_net_status[stat];
1639 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, cs_status);
1641 // tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
1642 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status);
1644 act = lookup_tbl_access_technology[AcT];
1645 tcore_network_set_access_technology(o, act);
1647 if (stat == AT_CREG_STAT_REG_ROAM) {
1648 tcore_network_set_roaming_state(o, TRUE);
1649 }else if ((stat == AT_CREG_STAT_REG_DENIED) && (TRUE == tcore_network_get_roaming_state(o))) {
1650 dbg("Ignore roaming set with REG_DENIED when previous state is REG_ROAM");
1652 tcore_network_set_roaming_state(o, FALSE);
1655 tcore_network_get_service_type(o, &service_type);
1656 dbg("prev_service_type = 0x%x", service_type);
1657 service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status);
1658 dbg("new_service_type = 0x%x", service_type);
1659 tcore_network_set_service_type(o, service_type);
1661 tcore_network_set_lac(o, lac);
1662 tcore_network_set_cell_id(o, ci);
1664 net_lac_cell_info.lac = lac;
1665 net_lac_cell_info.cell_id = ci;
1667 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO,
1668 sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info);
1670 regist_status.cs_domain_status = cs_status;
1671 regist_status.ps_domain_status = ps_status;
1672 regist_status.service_type = service_type;
1673 regist_status.roaming_status = tcore_network_get_roaming_state(o);
1675 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
1676 TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), ®ist_status);
1678 /* Get PLMN ID needed to application */
1679 if ((NETWORK_SERVICE_DOMAIN_STATUS_FULL == cs_status) ||
1680 NETWORK_SERVICE_DOMAIN_STATUS_FULL == ps_status)
1681 get_serving_network(o, NULL);
1683 dbg("Response NOK");
1688 tcore_at_tok_free(tokens);
1692 static gboolean on_event_network_icon_info(CoreObject *o, const void *event_info, void *user_data)
1694 struct tnoti_network_icon_info net_icon_info = {0};
1696 char *rssiToken = NULL;
1697 char *batteryToken = NULL;
1698 GSList *tokens = NULL;
1699 GSList *lines = NULL;
1701 lines = (GSList *) event_info;
1702 if (1 != g_slist_length(lines)) {
1703 dbg("unsolicited msg but multiple line");
1706 line = (char *) (lines->data);
1707 dbg("+XCIEV Network Icon Info Noti Recieve");
1708 memset(&net_icon_info, 0, sizeof(struct tnoti_network_icon_info));
1713 tokens = tcore_at_tok_new(line);
1714 if (g_slist_length(tokens) != 2) {
1715 msg("invalid message");
1719 rssiToken = (char *) g_slist_nth_data(tokens, 0);
1721 if (strlen(rssiToken) > 0) {
1722 net_icon_info.type = NETWORK_ICON_INFO_RSSI;
1723 net_icon_info.rssi = atoi(g_slist_nth_data(tokens, 0));
1724 dbg("rssi level : %d", net_icon_info.rssi);
1727 batteryToken = (char *) g_slist_nth_data(tokens, 1);
1728 if (strlen(batteryToken) > 0) {
1729 net_icon_info.type = NETWORK_ICON_INFO_BATTERY;
1730 net_icon_info.battery = atoi(g_slist_nth_data(tokens, 1));
1731 dbg("battery level : %d", net_icon_info.battery);
1734 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_ICON_INFO,
1735 sizeof(struct tnoti_network_icon_info), &net_icon_info);
1737 dbg("Response NOK");
1743 tcore_at_tok_free(tokens);
1748 static gboolean on_event_network_ctzv_time_info(CoreObject *o, const void *event_info, void *user_data)
1750 struct tnoti_network_timeinfo net_time_info = {0};
1752 GSList *tokens = NULL;
1754 char *time_zone = NULL;
1755 GSList *lines = NULL;
1756 char ptime_param[20] = {0};
1757 UserRequest *ur = NULL;
1758 dbg("Enter : on_event_network_ctzv_time_info");
1760 lines = (GSList *) event_info;
1761 if (1 != g_slist_length(lines)) {
1762 dbg("unsolicited msg but multiple line");
1765 line = (char *) (lines->data);
1769 <tz> integer value indicating the time zone (e.g. -22 or +34)
1770 <time> string type value; format is yy/MM/dd,hh:mms, wherein characters indicates year, month, day, hour,
1773 dbg("Network time info (+CTZV) recieved");
1776 gchar *plmn_str = NULL;
1778 dbg("noti line is %s", line);
1780 tokens = tcore_at_tok_new(line);
1782 if (g_slist_length(tokens) < 2) {
1783 msg("invalid message");
1787 if ((time_zone = g_slist_nth_data(tokens, 0))) {
1788 net_time_info.gmtoff = atoi(time_zone) * 15; /* TZ in minutes */
1791 plmn_str = tcore_network_get_plmn(o);
1792 if (plmn_str != NULL) {
1793 g_strlcpy(net_time_info.plmn, plmn_str, sizeof(net_time_info.plmn));
1797 if ((time = g_slist_nth_data(tokens, 1)) && (strlen(time) > 18)) {
1798 strncpy(ptime_param, time + 1, 2); /* skip past initial quote (") */
1799 net_time_info.year = atoi(ptime_param);
1801 strncpy(ptime_param, time + 4, 2); /* skip slash (/) after year param */
1802 net_time_info.month = atoi(ptime_param);
1804 strncpy(ptime_param, time + 7, 2); /* skip past slash (/) after month param */
1805 net_time_info.day = atoi(ptime_param);
1807 strncpy(ptime_param, time + 10, 2); /* skip past comma (,) after day param */
1808 net_time_info.hour = atoi(ptime_param);
1810 strncpy(ptime_param, time + 13, 2); /* skip past colon (:) after hour param */
1811 net_time_info.minute = atoi(ptime_param);
1813 strncpy(ptime_param, time + 16, 2); /* skip past colon (:) after minute param */
1814 net_time_info.second = atoi(ptime_param);
1816 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);
1818 dbg("new pending(AT+XOPS=0/5/6 for Nitz PLMN name)");
1820 /* Get NITZ name and plmn_id via AT+XCOPS = 0/5/6 */
1821 nwk_prepare_and_send_pending_request(o, "AT+XCOPS=0;+XCOPS=5;+XCOPS=6", "+XCOPS", TCORE_AT_MULTILINE, ur, on_response_get_nitz_name);
1823 dbg("line is NULL");
1828 tcore_at_tok_free(tokens);
1830 dbg("Exit: on_event_network_ctzv_time_info");
1834 static void on_sim_resp_hook_get_netname(UserRequest *ur, enum tcore_response_command command, unsigned int data_len,
1835 const void *data, void *user_data)
1837 const struct tresp_sim_read *resp = data;
1838 CoreObject *o = user_data;
1840 if (command == TRESP_SIM_GET_SPN) {
1841 dbg("OK SPN GETTING!!");
1842 dbg("resp->result = 0x%x", resp->result);
1843 dbg("resp->data.spn.display_condition = 0x%x", resp->data.spn.display_condition);
1844 dbg("resp->data.spn.spn = [%s]", resp->data.spn.spn);
1846 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *) resp->data.spn.spn);
1850 * 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
1851 * 1 = display of registered PLMN name required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
1852 * 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
1853 * 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
1855 if (resp->data.spn.display_condition & 0x01) {
1856 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
1858 if ((resp->data.spn.display_condition & 0x02) == 0) {
1859 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
1861 if ((resp->data.spn.display_condition & 0x03) == 0x01) {
1862 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
1865 // fallback in case no SPN name is provided
1866 if (resp->data.spn.spn[0] == '\0')
1867 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
1871 static enum tcore_hook_return on_hook_sim_init(Server *s, CoreObject *source, enum tcore_notification_command command,
1872 unsigned int data_len, void *data, void *user_data)
1874 const struct tnoti_sim_status *sim = data;
1875 UserRequest *ur = NULL;
1877 if (sim->sim_status == SIM_STATUS_INIT_COMPLETED) {
1878 ur = tcore_user_request_new(NULL, NULL);
1879 tcore_user_request_set_command(ur, TREQ_SIM_GET_SPN);
1880 tcore_user_request_set_response_hook(ur, on_sim_resp_hook_get_netname, user_data);
1881 tcore_object_dispatch_request(source, ur);
1884 return TCORE_HOOK_RETURN_CONTINUE;
1887 static TReturn search_network(CoreObject *o, UserRequest *ur)
1890 TcorePending *pending = NULL;
1891 TcoreATRequest *atreq = NULL;
1892 CustomData *custom_data;
1893 char *cmd_str = NULL;
1895 dbg("search_network - ENTER!!");
1898 return TCORE_RETURN_EINVAL;
1900 custom_data = tcore_object_ref_user_data(o);
1901 if (custom_data->search_state
1902 == IMC_NETWORK_SEARCH_STATE_IN_PROGRESS) {
1903 warn("Network Search: [ALREADY IN PROGRESS]");
1904 return TCORE_RETURN_FAILURE;
1907 h = tcore_object_get_hal(o);
1908 if(FALSE == tcore_hal_get_power_state(h)){
1909 dbg("cp not ready/n");
1910 return TCORE_RETURN_ENOSYS;
1913 pending = tcore_pending_new(o, 0);
1915 cmd_str = g_strdup_printf("AT+COPS=?");
1916 atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_SINGLELINE);
1918 tcore_pending_set_request_data(pending, 0, atreq);
1919 tcore_pending_set_timeout(pending, 60);
1920 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
1921 tcore_pending_set_response_callback(pending, on_response_search_network, NULL);
1922 tcore_pending_set_timeout_callback(pending, on_timeout_search_network, NULL);
1923 tcore_pending_link_user_request(pending, ur);
1924 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
1926 tcore_hal_send_request(h, pending);
1929 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_IN_PROGRESS;
1930 dbg("Search State: [IN PROGRESS]");
1932 return TCORE_RETURN_SUCCESS;
1935 static TReturn set_plmn_selection_mode(CoreObject *o, UserRequest *ur)
1938 TcorePending *pending = NULL;
1939 TcoreATRequest *atreq;
1940 char *cmd_str = NULL;
1941 int format = 0; /* default value for long alphanumeric */
1946 const struct treq_network_set_plmn_selection_mode *req_data = NULL;
1949 dbg("set_plmn_selection_mode - ENTER!!");
1952 return TCORE_RETURN_EINVAL;
1954 req_data = tcore_user_request_ref_data(ur, NULL);
1955 h = tcore_object_get_hal(o);
1956 if(FALSE == tcore_hal_get_power_state(h)){
1957 dbg("cp not ready/n");
1958 return TCORE_RETURN_ENOSYS;
1960 pending = tcore_pending_new(o, 0);
1962 // Command Format - AT+COPS=[<mode>[,<format>[,<oper>[,< AcT>]]]]
1963 /* oper parameter format
1964 - 0 <oper> format presentations are set to long alphanumeric. If Network name not available it displays combination of Mcc and MNC in string format.
1965 - 1 <oper> format presentation is set to short alphanumeric.
1966 - 2 <oper> format presentations set to numeric.
1969 if ((req_data->act == NETWORK_ACT_GSM) || (req_data->act == NETWORK_ACT_EGPRS))
1974 switch (req_data->mode) {
1975 case NETWORK_SELECT_MODE_MANUAL:
1977 mode = AT_COPS_MODE_MANUAL;
1978 format = AT_COPS_FORMAT_NUMERIC;
1981 memcpy(plmn, req_data->plmn, 6);
1983 if (strlen(req_data->plmn) == 6) {
1988 cmd_str = g_strdup_printf("AT+COPS=%d,%d,\"%s\",%d", mode, format, plmn, act);
1992 case NETWORK_SELECT_MODE_AUTOMATIC:
1994 cmd_str = g_strdup("AT+COPS=0");
1999 atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_NO_RESULT);
2001 tcore_pending_set_request_data(pending, 0, atreq);
2002 tcore_pending_set_response_callback(pending, on_response_set_plmn_selection_mode, NULL);
2003 tcore_pending_link_user_request(pending, ur);
2004 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2006 tcore_hal_send_request(h, pending);
2008 return TCORE_RETURN_SUCCESS;
2011 static TReturn get_plmn_selection_mode(CoreObject *o, UserRequest *ur)
2014 TcorePending *pending = NULL;
2015 TcoreATRequest *atreq;
2016 char *cmd_str = NULL;
2018 dbg("get_plmn_selection_mode - ENTER!!");
2021 return TCORE_RETURN_EINVAL;
2023 h = tcore_object_get_hal(o);
2024 if(FALSE == tcore_hal_get_power_state(h)){
2025 dbg("cp not ready/n");
2026 return TCORE_RETURN_ENOSYS;
2028 pending = tcore_pending_new(o, 0);
2030 cmd_str = g_strdup_printf("AT+COPS?");
2031 atreq = tcore_at_request_new(cmd_str, "+COPS", TCORE_AT_SINGLELINE);
2033 tcore_pending_set_request_data(pending, 0, atreq);
2034 tcore_pending_set_response_callback(pending, on_response_get_plmn_selection_mode, NULL);
2035 tcore_pending_link_user_request(pending, ur);
2036 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2038 tcore_hal_send_request(h, pending);
2040 return TCORE_RETURN_SUCCESS;
2044 static TReturn set_band(CoreObject *o, UserRequest *ur)
2047 TcorePending *pending = NULL;
2048 TcorePending *pending_gsm = NULL;
2049 TcorePending *pending_umts = NULL;
2050 TcoreATRequest *atreq;
2051 char *cmd_str = NULL;
2052 const struct treq_network_set_band *req_data;
2053 gboolean set_gsm_band = 0;
2054 gboolean set_umts_band = 0;
2056 int gsm_band2 = 255;
2057 char *umts_band = NULL;
2058 UserRequest *dup_ur_gsm = NULL;
2059 UserRequest *dup_ur_umts = NULL;
2061 dbg("set_band - ENTER!!");
2064 return TCORE_RETURN_EINVAL;
2066 req_data = tcore_user_request_ref_data(ur, NULL);
2067 h = tcore_object_get_hal(o);
2068 if(FALSE == tcore_hal_get_power_state(h)){
2069 dbg("cp not ready/n");
2070 return TCORE_RETURN_ENOSYS;
2073 dbg("set_band - called with band = %d", req_data->band);
2075 switch (req_data->band) {
2076 case NETWORK_BAND_TYPE_GSM850:
2077 gsm_band = AT_GSM_XBANDSEL_850;
2078 set_gsm_band = TRUE;
2081 case NETWORK_BAND_TYPE_GSM_900_1800:
2082 gsm_band = AT_GSM_XBANDSEL_900;
2083 gsm_band2 = AT_GSM_XBANDSEL_1800;
2084 set_gsm_band = TRUE;
2087 case NETWORK_BAND_TYPE_GSM1900:
2088 gsm_band = AT_GSM_XBANDSEL_1900;
2089 set_gsm_band = TRUE;
2092 case NETWORK_BAND_TYPE_GSM1800:
2093 gsm_band = AT_GSM_XBANDSEL_1800;
2094 set_gsm_band = TRUE;
2097 case NETWORK_BAND_TYPE_GSM_850_1900:
2098 gsm_band = AT_GSM_XBANDSEL_850;
2099 gsm_band2 = AT_GSM_XBANDSEL_1900;
2100 set_gsm_band = TRUE;
2103 case NETWORK_BAND_TYPE_ANY:
2104 gsm_band = AT_GSM_XBANDSEL_AUTOMATIC;
2105 set_umts_band = TRUE;
2106 set_gsm_band = TRUE;
2109 case NETWORK_BAND_TYPE_WCDMA:
2110 set_umts_band = TRUE;
2113 case NETWORK_BAND_TYPE_WCDMA2100:
2114 umts_band = "UMTS_BAND_I";
2115 set_umts_band = TRUE;
2118 case NETWORK_BAND_TYPE_WCDMA1900:
2119 umts_band = "UMTS_BAND_II";
2120 set_umts_band = TRUE;
2123 case NETWORK_BAND_TYPE_WCDMA850:
2124 umts_band = "UMTS_BAND_V";
2125 set_umts_band = TRUE;
2132 dbg("set_band > set_umts_band = %d, set_gsm_band = %d", set_umts_band, set_gsm_band);
2134 if (set_umts_band == TRUE) {
2135 if ((req_data->band == NETWORK_BAND_TYPE_WCDMA) || (req_data->band == NETWORK_BAND_TYPE_ANY))
2136 cmd_str = g_strdup_printf("AT+XUBANDSEL=0");
2138 cmd_str = g_strdup_printf("AT+XUBANDSEL=%s", umts_band);
2140 atreq = tcore_at_request_new(cmd_str, "+XUBANDSEL", TCORE_AT_NO_RESULT);
2141 pending_umts = tcore_pending_new(o, 0);
2143 tcore_pending_set_request_data(pending_umts, 0, atreq);
2144 tcore_pending_set_priority(pending_umts, TCORE_PENDING_PRIORITY_DEFAULT);
2145 tcore_pending_set_response_callback(pending_umts, on_response_set_umts_band, NULL);
2147 /* duplicate user request for UMTS Band setting AT command for same UR */
2148 dup_ur_umts = tcore_user_request_ref(ur);
2149 tcore_pending_link_user_request(pending_umts, dup_ur_umts);
2150 tcore_pending_set_send_callback(pending_umts, on_confirmation_network_message_send, NULL);
2152 tcore_hal_send_request(h, pending_umts);
2156 if (set_gsm_band == TRUE) {
2157 dbg("Entered set_gsm_band");
2158 if (gsm_band2 == 255)
2159 cmd_str = g_strdup_printf("AT+XBANDSEL=%d", gsm_band);
2161 cmd_str = g_strdup_printf("AT+XBANDSEL=%d,%d", gsm_band, gsm_band2);
2163 dbg("Command string: %s", cmd_str);
2164 atreq = tcore_at_request_new(cmd_str, "+XBANDSEL", TCORE_AT_NO_RESULT);
2165 pending_gsm = tcore_pending_new(o, 0);
2167 tcore_pending_set_request_data(pending_gsm, 0, atreq);
2168 tcore_pending_set_priority(pending_gsm, TCORE_PENDING_PRIORITY_DEFAULT);
2169 tcore_pending_set_response_callback(pending_gsm, on_response_set_gsm_band, NULL);
2171 /* duplicate user request for GSM Band setting AT command for same UR */
2172 dup_ur_gsm = tcore_user_request_ref(ur);
2173 tcore_pending_link_user_request(pending_gsm, dup_ur_gsm);
2174 tcore_pending_set_send_callback(pending_gsm, on_confirmation_network_message_send, NULL);
2176 tcore_hal_send_request(h, pending_gsm);
2180 /* Lock device to specific RAT as requested by application */
2182 AT+XRAT=<Act>[,<PreferredAct>]
2183 <AcT> indicates the radio access technology and may be
2185 1 GSM / UMTS Dual mode
2188 if ((set_umts_band == TRUE) && (set_gsm_band == TRUE)) {
2189 cmd_str = g_strdup_printf("AT+XRAT=%d", AT_XRAT_DUAL);
2190 } else if (set_umts_band == TRUE) {
2191 cmd_str = g_strdup_printf("AT+XRAT=%d", AT_XRAT_UMTS);
2193 cmd_str = g_strdup_printf("AT+XRAT=%d", AT_XRAT_GSM);
2195 atreq = tcore_at_request_new(cmd_str, "+XRAT", TCORE_AT_NO_RESULT);
2196 pending = tcore_pending_new(o, 0);
2198 tcore_pending_set_request_data(pending, 0, atreq);
2199 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
2200 tcore_pending_set_response_callback(pending, on_response_set_xrat, NULL);
2201 tcore_pending_link_user_request(pending, ur);
2202 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2204 tcore_hal_send_request(h, pending);
2206 return TCORE_RETURN_SUCCESS;
2209 static TReturn get_band(CoreObject *o, UserRequest *ur)
2212 TcorePending *pending = NULL;
2213 TcoreATRequest *atreq;
2214 char *cmd_str = NULL;
2215 dbg("get_band - ENTER!!");
2218 return TCORE_RETURN_EINVAL;
2220 h = tcore_object_get_hal(o);
2221 if(FALSE == tcore_hal_get_power_state(h)){
2222 dbg("cp not ready/n");
2223 return TCORE_RETURN_ENOSYS;
2226 /* Get RAT Information Information. Based on RAT read response, we will get specific RAT bands only */
2227 cmd_str = g_strdup_printf("AT+XRAT?");
2228 atreq = tcore_at_request_new(cmd_str, "+XRAT", TCORE_AT_SINGLELINE);
2229 pending = tcore_pending_new(o, 0);
2230 tcore_pending_set_request_data(pending, 0, atreq);
2231 tcore_pending_set_response_callback(pending, on_response_get_xrat, NULL);
2232 tcore_pending_link_user_request(pending, ur);
2233 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2234 tcore_hal_send_request(h, pending);
2237 return TCORE_RETURN_SUCCESS;
2240 static TReturn set_preferred_plmn(CoreObject *o, UserRequest *ur)
2243 TcorePending *pending = NULL;
2244 TcoreATRequest *atreq = NULL;
2245 struct treq_network_set_preferred_plmn *req_data = NULL;
2246 char *cmd_str = NULL;
2247 int format = 2; /* Alway use numeric format, as application gives data in this default format */
2249 int gsm_compact_act = 0;
2253 return TCORE_RETURN_EINVAL;
2255 h = tcore_object_get_hal(o);
2256 if(FALSE == tcore_hal_get_power_state(h)){
2257 dbg("cp not ready/n");
2258 return TCORE_RETURN_ENOSYS;
2261 req_data = (struct treq_network_set_preferred_plmn *) tcore_user_request_ref_data(ur, NULL);
2262 pending = tcore_pending_new(o, 0);
2264 dbg("Entry set_preferred_plmn");
2267 [<index>][,<format>[,<oper>[,<GSM_AcT>,
2268 <GSM_Compact_AcT>,<UTRAN_AcT>]]]
2271 if ((req_data->act == NETWORK_ACT_GSM) || (req_data->act == NETWORK_ACT_GPRS) || (req_data->act == NETWORK_ACT_EGPRS))
2273 else if ((req_data->act == NETWORK_ACT_UMTS) || (req_data->act == NETWORK_ACT_UTRAN))
2275 else if (req_data->act == NETWORK_ACT_GSM_UTRAN)
2276 gsm_act = utran_act = TRUE;
2278 if (strlen(req_data->plmn) > 6) {
2279 req_data->plmn[6] = '\0';
2280 } else if (strlen(req_data->plmn) == 6) {
2281 if (req_data->plmn[5] == '#') {
2282 req_data->plmn[5] = '\0';
2285 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);
2287 dbg("cmd_str - %s", cmd_str);
2288 atreq = tcore_at_request_new(cmd_str, "+CPOL", TCORE_AT_NO_RESULT);
2290 tcore_pending_set_request_data(pending, 0, atreq);
2291 tcore_pending_set_response_callback(pending, on_response_set_preferred_plmn, NULL);
2292 tcore_pending_link_user_request(pending, ur);
2293 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2295 tcore_hal_send_request(h, pending);
2299 dbg("Exit set_preferred_plmn");
2301 return TCORE_RETURN_SUCCESS;
2304 static TReturn get_preferred_plmn(CoreObject *o, UserRequest *ur)
2307 TcorePending *pending = NULL;
2308 TcoreATRequest *atreq = NULL;
2310 char *cmd_str = NULL;
2312 dbg("get_preferred_plmn - ENTER!!");
2315 return TCORE_RETURN_EINVAL;
2317 h = tcore_object_get_hal(o);
2318 if(FALSE == tcore_hal_get_power_state(h)){
2319 dbg("cp not ready/n");
2320 return TCORE_RETURN_ENOSYS;
2323 pending = tcore_pending_new(o, 0);
2325 cmd_str = g_strdup_printf("AT+CPOL=,2;+CPOL?");
2326 atreq = tcore_at_request_new(cmd_str, "+CPOL", TCORE_AT_MULTILINE);
2328 tcore_pending_set_request_data(pending, 0, atreq);
2329 tcore_pending_set_response_callback(pending, on_response_get_preferred_plmn, NULL);
2330 tcore_pending_link_user_request(pending, ur);
2331 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2333 tcore_hal_send_request(h, pending);
2337 dbg("get_preferred_plmn - EXIT!!");
2339 return TCORE_RETURN_SUCCESS;
2342 static TReturn cancel_manual_search (CoreObject *o, UserRequest *ur)
2345 TcorePending *pending = NULL;
2346 TcoreATRequest *atreq = NULL;
2347 CustomData *custom_data;
2349 dbg("cancel_manual_search - ENTER!!");
2352 return TCORE_RETURN_EINVAL;
2354 h = tcore_object_get_hal(o);
2355 if (FALSE == tcore_hal_get_power_state(h)) {
2356 dbg("cp not ready/n");
2357 return TCORE_RETURN_ENOSYS;
2360 custom_data = tcore_object_ref_user_data(o);
2361 if (custom_data->search_state
2362 == IMC_NETWORK_SEARCH_STATE_IN_PROGRESS) {
2363 dbg("Search in Progress...");
2365 pending = tcore_pending_new(o, 0);
2366 atreq = tcore_at_request_new("\e", NULL, TCORE_AT_NO_RESULT);
2368 tcore_pending_set_request_data(pending, 0, atreq);
2369 tcore_pending_set_response_callback(pending, on_response_cancel_manual_search, NULL);
2370 tcore_pending_link_user_request(pending, ur);
2371 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
2373 /*Set the Search State to Cancelled*/
2374 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_CANCELLED;
2375 dbg("Search State: [CANCELLED]");
2377 dbg("No Search in Progress...");
2380 return TCORE_RETURN_SUCCESS;
2383 static TReturn get_serving_network(CoreObject *o, UserRequest *ur)
2385 dbg("get_serving_network - ENTER!!");
2388 return TCORE_RETURN_EINVAL;
2390 if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2391 dbg("cp not ready/n");
2392 return TCORE_RETURN_ENOSYS;
2395 dbg("new pending(AT+COPS?)");
2397 nwk_prepare_and_send_pending_request(o, "AT+COPS=3,2;+COPS?;+COPS=3,0;+COPS?", "+COPS", TCORE_AT_MULTILINE, ur, on_response_get_serving_network);
2398 return TCORE_RETURN_SUCCESS;
2401 static TReturn network_set_mode(CoreObject *o, UserRequest *ur)
2403 struct treq_network_set_mode *set_mode = NULL;
2404 TReturn ret = TCORE_RETURN_EINVAL;
2408 dbg("network_set_mode - ENTER!!");
2410 set_mode = (struct treq_network_set_mode *)tcore_user_request_ref_data(ur, NULL);
2412 switch (set_mode->mode) {
2413 case NETWORK_MODE_AUTO:
2416 case NETWORK_MODE_GSM:
2419 case NETWORK_MODE_WCDMA:
2422 case NETWORK_MODE_LTE:
2424 err("Unsupported mode: [%d]", set_mode->mode);
2430 at_cmd = g_strdup_printf("AT+XRAT=%d,2", act); //PreferredAct is UMTS
2433 at_cmd = g_strdup_printf("AT+XRAT=%d", act);
2435 /* Send Request to modem */
2436 ret = tcore_prepare_and_send_at_request(o,
2440 on_response_network_set_mode, NULL,
2441 on_confirmation_network_message_send, NULL,
2448 static TReturn network_get_mode(CoreObject *o, UserRequest *ur)
2452 dbg("network_get_mode - ENTER!!");
2454 /* Send Request to modem */
2455 ret = tcore_prepare_and_send_at_request(o,
2456 "AT+XRAT?", "+XRAT",
2457 TCORE_AT_SINGLELINE,
2459 on_response_network_get_mode, NULL,
2460 on_confirmation_network_message_send, NULL,
2466 static TReturn set_default_subscription(CoreObject *co, UserRequest *ur)
2468 struct treq_network_set_default_subscription *req_data = NULL;
2470 Storage *strg = NULL;
2471 TReturn ret = TCORE_RETURN_FAILURE;
2472 TcorePlugin *plugin = tcore_object_ref_plugin(co);
2476 server = tcore_plugin_ref_server(plugin);
2477 strg = tcore_server_find_storage(server, "vconf");
2479 req_data = (struct treq_network_set_default_subscription *) tcore_user_request_ref_data(ur, NULL);
2480 dbg("'default' Subscription for CS (Voice): [%d]", req_data->default_subs);
2482 /* Update VCONF through Storage - req_data->current_network is aligned to VCONFKEY values */
2483 if (tcore_storage_set_int(strg,
2484 STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_SERVICE_INT, req_data->default_subs)) {
2485 struct tresp_network_set_default_subs resp_data = {0, };
2486 struct tnoti_network_default_subs default_subs_noti_data = {0, };
2491 resp_data.result = TCORE_RETURN_SUCCESS;
2492 ret = tcore_user_request_send_response(ur,
2493 TRESP_NETWORK_SET_DEFAULT_SUBSCRIPTION,
2494 sizeof(struct tresp_network_set_default_subs), &resp_data);
2498 default_subs_noti_data.default_subs = req_data->default_subs;
2499 tcore_server_send_notification(tcore_plugin_ref_server(plugin), co,
2500 TNOTI_NETWORK_DEFAULT_SUBSCRIPTION,
2501 sizeof(struct tnoti_network_default_subs), &default_subs_noti_data);
2504 dbg("ret: [0x%x]", ret);
2508 static TReturn get_default_subscription(CoreObject *co, UserRequest *ur)
2510 struct tresp_network_get_default_subs resp_data = {0, };
2511 TReturn ret = TCORE_RETURN_FAILURE;
2513 Storage *strg = NULL;
2514 TcorePlugin *plugin = tcore_object_ref_plugin(co);
2518 server = tcore_plugin_ref_server(plugin);
2519 strg = tcore_server_find_storage(server, "vconf");
2521 /* VCONFKEY is aligned to req_data->current_network type */
2522 resp_data.default_subs = tcore_storage_get_int(strg,
2523 STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_SERVICE_INT);
2525 resp_data.result = TCORE_RETURN_SUCCESS;
2528 ret = tcore_user_request_send_response(ur,
2529 TRESP_NETWORK_GET_DEFAULT_SUBSCRIPTION,
2530 sizeof(struct tresp_network_get_default_subs), &resp_data);
2532 dbg("ret: [0x%x]", ret);
2536 static TReturn get_default_data_subscription(CoreObject *co, UserRequest *ur)
2538 struct tresp_network_get_default_data_subs resp = {0,};
2540 int subscription = -1;
2544 ret = vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS , &subscription);
2546 err("vconf_get_int() failed - DDS");
2547 resp.result = TCORE_RETURN_FAILURE;
2549 resp.result = TCORE_RETURN_SUCCESS;
2550 resp.default_subs = subscription;
2551 if (subscription == NETWORK_DEFAULT_DATA_SUBS_UNKNOWN)
2552 resp.default_subs = NETWORK_DEFAULT_DATA_SUBS_UNKNOWN;
2555 if( TCORE_RETURN_SUCCESS == tcore_user_request_send_response(ur,
2556 TRESP_NETWORK_GET_DEFAULT_DATA_SUBSCRIPTION,
2557 sizeof(struct tresp_network_get_default_data_subs), &resp)){
2558 tcore_user_request_unref(ur);
2560 return TCORE_RETURN_SUCCESS;
2563 static struct tcore_network_operations network_ops = {
2564 .search = search_network,
2565 .set_plmn_selection_mode = set_plmn_selection_mode,
2566 .get_plmn_selection_mode = get_plmn_selection_mode,
2567 .set_service_domain = NULL,
2568 .get_service_domain = NULL,
2569 .set_band = set_band,
2570 .get_band = get_band,
2571 .set_preferred_plmn = set_preferred_plmn,
2572 .get_preferred_plmn = get_preferred_plmn,
2575 .set_power_on_attach = NULL,
2576 .get_power_on_attach = NULL,
2577 .set_cancel_manual_search = cancel_manual_search,
2578 .get_serving_network = get_serving_network,
2579 .set_mode = network_set_mode,
2580 .get_mode = network_get_mode,
2581 .set_default_subscription = set_default_subscription,
2582 .get_default_subscription = get_default_subscription,
2583 .set_default_data_subscription = NULL,
2584 .get_default_data_subscription =get_default_data_subscription,
2587 gboolean imc_network_init(TcorePlugin *cp, CoreObject *co_network)
2589 CustomData *custom_data;
2592 /* Set operations */
2593 tcore_network_set_ops(co_network, &network_ops);
2596 custom_data = g_malloc0(sizeof(CustomData));
2597 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
2599 tcore_object_link_user_data(co_network, custom_data);
2601 tcore_object_add_callback(co_network, "+CREG", on_event_cs_network_regist, NULL);
2602 tcore_object_add_callback(co_network, "+CGREG", on_event_ps_network_regist, NULL);
2603 tcore_object_add_callback(co_network, "+XCIEV", on_event_network_icon_info, NULL);
2605 /* +CTZV: <tz>,<time> */
2606 tcore_object_add_callback(co_network, "+CTZV", on_event_network_ctzv_time_info, NULL);
2608 tcore_server_add_notification_hook(tcore_plugin_ref_server(cp), TNOTI_SIM_STATUS, on_hook_sim_init, co_network);
2610 _insert_mcc_mnc_oper_list(cp, co_network);
2617 void imc_network_exit(TcorePlugin *cp, CoreObject *co_network)
2619 CustomData *custom_data;
2621 custom_data = tcore_object_ref_user_data(co_network);
2622 if (custom_data != NULL)
2623 g_free(custom_data);