X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fimc_network.c;h=0e85fdbaa5836553d0fb6e9c2b7a5063b4eff626;hb=b25625380264e330d9f716acfae51de3a7c618a7;hp=e4b9b7ce4fc62a61b17ab880a202595bc3566e96;hpb=42f7622c520f2718a61812515ddc1b2793c5ec17;p=platform%2Fcore%2Ftelephony%2Ftel-plugin-imc.git diff --git a/src/imc_network.c b/src/imc_network.c index e4b9b7c..0e85fdb 100644 --- a/src/imc_network.c +++ b/src/imc_network.c @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Harish Bishnoi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,21 +25,67 @@ #include #include -#include -#include -#include #include +#include +#include +#include #include +#include +#include +#include #include +#include #include -#include +#include -#include - -#include "imc_network.h" #include "imc_common.h" +#include "imc_network.h" -#define IMC_NETWORK_BASE_16 16 +#define AT_CREG_STAT_NOT_REG 0 /* not registered, MT is not currently searching a new operator to register to */ +#define AT_CREG_STAT_REG_HOME 1 /* registered, home network */ +#define AT_CREG_STAT_SEARCHING 2 /* not registered, but MT is currently searching a new operator to register to */ +#define AT_CREG_STAT_REG_DENIED 3 /* registration denied */ +#define AT_CREG_STAT_UNKNOWN 4 /* unknown */ +#define AT_CREG_STAT_REG_ROAM 5 /* registered, roaming */ + +#define AT_COPS_MODE_AUTOMATIC 0 /* automatic ( field is ignored) */ +#define AT_COPS_MODE_MANUAL 1 /* manual ( field shall be present, and optionally) */ +#define AT_COPS_MODE_DEREGISTER 2 /* deregister from network */ +#define AT_COPS_MODE_SET_ONLY 3 /* set only */ +#define AT_COPS_MODE_MANUAL_AUTOMATIC 4 /*automatic - manual*/ + +#define AT_COPS_FORMAT_LONG_ALPHANUMERIC 0 /* long format alphanumeric */ +#define AT_COPS_FORMAT_SHORT_ALPHANUMERIC 1 /* short format alphanumeric */ +#define AT_COPS_FORMAT_NUMERIC 2 /* numeric */ + +#define AT_COPS_ACT_GSM 0 /* GSM */ +#define AT_COPS_ACT_GSM_COMPACT 1 /* GSM Compact */ +#define AT_COPS_ACT_UTRAN 2 /* UTRAN */ +#define AT_COPS_ACT_GSM_EGPRS 3 /* GSM w/EGPRS */ +#define AT_COPS_ACT_UTRAN_HSDPA 4 /* UTRAN w/HSDPA */ +#define AT_COPS_ACT_UTRAN_HSUPA 5 /* UTRAN w/HSUPA */ +#define AT_COPS_ACT_UTRAN_HSDPA_HSUPA 6 /* UTRAN w/HSDPA and HSUPA */ +#define AT_COPS_ACT_E_UTRAN 7 /* E-UTRAN */ + +#define AT_GSM_XBANDSEL_AUTOMATIC 0 +#define AT_GSM_XBANDSEL_1800 1800 +#define AT_GSM_XBANDSEL_1900 1900 +#define AT_GSM_XBANDSEL_900 900 +#define AT_GSM_XBANDSEL_850 850 +#define AT_GSM_XBANDSEL_450 450 +#define AT_GSM_XBANDSEL_480 480 +#define AT_GSM_XBANDSEL_750 750 +#define AT_GSM_XBANDSEL_380 380 +#define AT_GSM_XBANDSEL_410 410 + +#define AT_XRAT_GSM 0 +#define AT_XRAT_DUAL 1 +#define AT_XRAT_UMTS 2 + +#define MAX_NETWORKS_PREF_PLMN_SUPPORT 150 +#define MAX_NETWORKS_MANUAL_SEARCH_SUPPORT 20 + +#define VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS "db/telephony/dualsim/default_data_service" typedef enum { IMC_NETWORK_SEARCH_STATE_NO_SEARCH, @@ -49,1829 +97,2331 @@ typedef struct { ImcNetworkSearchState search_state; } CustomData; -typedef struct { - CoreObject *co; - TelNetworkResult result; -} ImcNetworkCancelSearch; +static unsigned int lookup_tbl_net_status[] = { + [AT_CREG_STAT_NOT_REG] = NETWORK_SERVICE_DOMAIN_STATUS_NO, + [AT_CREG_STAT_REG_HOME] = NETWORK_SERVICE_DOMAIN_STATUS_FULL, + [AT_CREG_STAT_SEARCHING] = NETWORK_SERVICE_DOMAIN_STATUS_SEARCH, + [AT_CREG_STAT_REG_DENIED] = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY, + [AT_CREG_STAT_UNKNOWN] = NETWORK_SERVICE_DOMAIN_STATUS_NO, + [AT_CREG_STAT_REG_ROAM] = NETWORK_SERVICE_DOMAIN_STATUS_FULL, +}; -static TelNetworkAct __imc_network_map_act(guint act) -{ - /* - * - * 0 GSM - * 2 UTRAN - * 3 GSM w/EGPRS - * 4 UTRAN w/HSDPA - * 5 UTRAN w/HSUPA - * 6 UTRAN w/HSDPA and HSUPA - */ - switch (act) { - case 0: - return TEL_NETWORK_ACT_GSM; - case 2: - return TEL_NETWORK_ACT_UMTS; - case 3: - return TEL_NETWORK_ACT_EGPRS; - case 4: - return TEL_NETWORK_ACT_HSDPA; - case 5: - return TEL_NETWORK_ACT_HSUPA; - case 6: - return TEL_NETWORK_ACT_HSPA; - default: - return TEL_NETWORK_ACT_UNKNOWN; - } -} +static unsigned int lookup_tbl_access_technology[] = { + [AT_COPS_ACT_GSM] = NETWORK_ACT_GSM, + [AT_COPS_ACT_GSM_COMPACT] = NETWORK_ACT_GSM, + [AT_COPS_ACT_UTRAN] = NETWORK_ACT_UTRAN, + [AT_COPS_ACT_GSM_EGPRS] = NETWORK_ACT_EGPRS, + [AT_COPS_ACT_UTRAN_HSDPA] = NETWORK_ACT_UTRAN, + [AT_COPS_ACT_UTRAN_HSUPA] = NETWORK_ACT_UTRAN, + [AT_COPS_ACT_UTRAN_HSDPA_HSUPA] = NETWORK_ACT_UTRAN, + [AT_COPS_ACT_E_UTRAN] = NETWORK_ACT_GSM_UTRAN, +}; -static TelNetworkRegStatus __imc_network_map_stat(guint stat) -{ - /* - * - * 0 Not registered, ME is not currently searching a - * new operator to register to - * 1 Registered, home network - * 2 Not registered, but ME is currently searching a - * new operator to register - * 3 Registration denied - * 4 Unknown - * 5 Registered, in roaming - */ - switch (stat) { - case 0: - return TEL_NETWORK_REG_STATUS_UNREGISTERED; - case 1: - return TEL_NETWORK_REG_STATUS_REGISTERED; - case 2: - return TEL_NETWORK_REG_STATUS_SEARCHING; - case 3: - return TEL_NETWORK_REG_STATUS_DENIED; - case 4: - return TEL_NETWORK_REG_STATUS_UNKNOWN; - case 5: - return TEL_NETWORK_REG_STATUS_ROAMING; - default: - return TEL_NETWORK_REG_STATUS_UNKNOWN; - } -} +static gboolean get_serving_network(CoreObject *o, UserRequest *ur); -static void __on_response_imc_network_registration(TcorePending *p, - guint data_len, const void *data, void *user_data) + +static void on_confirmation_network_message_send(TcorePending *p, gboolean result, void *user_data) { - const TcoreAtResponse *at_resp = data; - dbg("Entry"); + dbg("on_confirmation_modem_message_send - msg out from queue.\n"); - if (at_resp && at_resp->success) { - dbg("Network Registration - [OK]"); + if (result == FALSE) { + /* Fail */ + dbg("SEND FAIL"); } else { - err("Network Registration - [NOK]"); + dbg("SEND OK"); } } -static void __imc_network_register_to_network(CoreObject *co) +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) { - TelReturn ret; + TcoreATRequest *req = NULL; + TcoreHal *hal; + TcorePending *pending = NULL; + TReturn ret; - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - "AT+COPS=0", NULL, - TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, - __on_response_imc_network_registration, NULL, - on_send_imc_request, NULL); - dbg("Sending Network Registration request: [%s]", - (ret == TEL_RETURN_SUCCESS ? "SUCCESS" : "FAIL")); + hal = tcore_object_get_hal(co); + + pending = tcore_pending_new(co, 0); + req = tcore_at_request_new(at_cmd, prefix, at_cmd_type); + + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); + + tcore_pending_set_request_data(pending, 0, req); + tcore_pending_set_response_callback(pending, callback, req->cmd); + tcore_pending_link_user_request(pending, ur); + tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL); + + ret = tcore_hal_send_request(hal, pending); + + if (ret != TCORE_RETURN_SUCCESS) + err("Failed to send AT request - ret: [0x%x]", ret); + + return; } -static TelNetworkResult -__imc_network_convert_cme_error_tel_network_result(const TcoreAtResponse *at_resp) + +static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *o) { - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - const gchar *line; - GSList *tokens = NULL; + Server *s; + Storage *strg; + void *handle; + char query[255] = { 0, }; + GHashTableIter iter; + gpointer key, value; + GHashTable *result = NULL, *row = NULL; + struct tcore_network_operator_info *noi = NULL; + int count = 0; + + s = tcore_plugin_ref_server(p); + strg = tcore_server_find_storage(s, "database"); + + handle = tcore_storage_create_handle(strg, "/opt/dbspace/.mcc_mnc_oper_list.db"); + if (!handle) { + dbg("fail to create database handle"); + return; + } - dbg("Entry"); + snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list"); + + result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + (GDestroyNotify) g_hash_table_destroy); + + tcore_storage_read_query_database(strg, handle, query, NULL, result, 4); + + g_hash_table_iter_init(&iter, result); + while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + row = value; - if (!at_resp || !at_resp->lines) { - err("Invalid response data"); - return result; + noi = calloc(sizeof(struct tcore_network_operator_info), 1); + + snprintf(noi->mcc, 4, "%s", (char *) g_hash_table_lookup(row, "1")); + snprintf(noi->mnc, 4, "%s", (char *) g_hash_table_lookup(row, "2")); + snprintf(noi->name, 41, "%s", (char *) g_hash_table_lookup(row, "3")); + snprintf(noi->country, 4, "%s", (char *) g_hash_table_lookup(row, "0")); + + tcore_network_operator_info_add(o, noi); + g_free(noi); + noi = NULL; + + count++; } - line = (const gchar *)at_resp->lines->data; - tokens = tcore_at_tok_new(line); - if (g_slist_length(tokens) > 0) { - gchar *resp_str; - gint cme_err; + dbg("count = %d", count); - resp_str = g_slist_nth_data(tokens, 0); - if (!resp_str) { - err("Invalid CME Error data"); - tcore_at_tok_free(tokens); - return result; - } - cme_err = atoi(resp_str); - dbg("CME error[%d]", cme_err); + g_hash_table_destroy(result); - switch (cme_err) { - case 3: - result = TEL_NETWORK_RESULT_OPERATION_NOT_PERMITTED; - break; + tcore_storage_remove_handle(strg, handle); +} + +static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type, + int domain, int act, int cs_status, int ps_status) +{ + enum telephony_network_service_type ret; + + ret = prev_type; - case 4: - result = TEL_NETWORK_RESULT_OPERATION_NOT_SUPPORTED; + switch (act) { + case NETWORK_ACT_UNKNOWN: + ret = NETWORK_SERVICE_TYPE_UNKNOWN; break; - case 20: - result = TEL_NETWORK_RESULT_MEMORY_FAILURE; + case NETWORK_ACT_GSM: + if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE && domain == NETWORK_SERVICE_DOMAIN_CS) + ret = NETWORK_SERVICE_TYPE_2_5G_EDGE; + else + ret = NETWORK_SERVICE_TYPE_2G; break; - case 30: - case 31: - result = TEL_NETWORK_RESULT_FAILURE; + case NETWORK_ACT_EGPRS: + return NETWORK_SERVICE_TYPE_2_5G_EDGE; break; - case 50: - result = TEL_NETWORK_RESULT_INVALID_PARAMETER; + case NETWORK_ACT_UMTS: + ret = NETWORK_SERVICE_TYPE_3G; break; + } - default: - result = TEL_NETWORK_RESULT_FAILURE; + if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) { + ret = NETWORK_SERVICE_TYPE_NO_SERVICE; + } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) { + if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) { + /* no change */ + } else { + ret = NETWORK_SERVICE_TYPE_SEARCH; + } + } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) { + if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) { + /* no change */ + } else { + ret = NETWORK_SERVICE_TYPE_EMERGENCY; } } - tcore_at_tok_free(tokens); - return result; + return ret; } -static void __on_response_imc_network_fetch_nw_name_internal(CoreObject *co, - gint result, const void *response, void *user_data) +static void _ps_set(TcorePlugin *p, int status) { - TelNetworkIdentityInfo *identity = (TelNetworkIdentityInfo *)response; + CoreObject *co_ps; + + co_ps = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_PS); + if (co_ps == NULL) { + err("No PS Core Object on plugin"); + return; + } - /* Send notification if result is SUCCESS */ - if (result == TEL_NETWORK_RESULT_SUCCESS) - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_IDENTITY, - sizeof(TelNetworkIdentityInfo), identity); + if (status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) + tcore_ps_set_online(co_ps, TRUE); + else + tcore_ps_set_online(co_ps, FALSE); } -static TcoreHookReturn __on_response_imc_hook_set_flight_mode(CoreObject *co, - gint result, TcoreCommand command, const void *response, const void *user_data) +static void on_timeout_search_network(TcorePending *p, void *user_data) { + UserRequest *ur; + struct tresp_network_search resp; + CustomData *custom_data; - tcore_check_return_value(result == TEL_MODEM_RESULT_SUCCESS, - TCORE_HOOK_RETURN_CONTINUE); + dbg("TIMEOUT !!!!! pending=%p", p); - dbg("Flight mode 'disabled', register to Network"); + memset(&resp, 0, sizeof(struct tresp_network_search)); - /* - * TODO - Check for selection_mode - * Need to check if it is Manual or Automatic and based on - * that need to initiate Network Registratin accordingly. - */ - __imc_network_register_to_network(co); + resp.result = TCORE_RETURN_FAILURE; + resp.list_count = 0; - return TCORE_HOOK_RETURN_CONTINUE; + custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p)); + custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH; + + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &resp); + } } -static void __on_response_imc_network_fetch_nw_name(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_set_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkIdentityInfo identity = {0, }; + UserRequest *ur; + const TcoreATResponse *atResp = data; + // GSList *tokens = NULL; + // char * line = NULL; + struct tresp_network_set_plmn_selection_mode resp = {0}; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; + if (atResp->success > 0) { + dbg("RESPONSE OK"); + resp.result = TCORE_RETURN_SUCCESS; + } else { + dbg("RESPONSE NOK"); + resp.result = TCORE_RETURN_FAILURE; + } - dbg("Enter"); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_set_plmn_selection_mode), &resp); + } +} - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); +static void on_response_get_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur; + struct tresp_network_get_plmn_selection_mode resp = {0}; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + char *line = NULL; + int mode = 0; - if (at_resp && at_resp->success) { - if (at_resp->lines) { - const gchar *line; - GSList *tokens = NULL; - gchar *token_str; - guint i, nol; + resp.result = TCORE_RETURN_FAILURE; - /* Validate that only 3 lines of response is received */ - nol = g_slist_length(at_resp->lines); - if (nol > 3) { - err("Invalid response message"); - imc_destroy_resp_cb_data(resp_cb_data); - return; + if (atResp->success > 0) { + dbg("RESPONSE OK"); + /* Format of output + +COPS: [,,[,< AcT>]] + */ + + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + msg("invalid message"); + goto OUT; } + mode = atoi(tcore_at_tok_nth(tokens, 0)); + dbg("mode = %d", mode); + + switch (mode) { + case AT_COPS_MODE_AUTOMATIC: + resp.mode = NETWORK_SELECT_MODE_AUTOMATIC; + break; + + case AT_COPS_MODE_MANUAL: + case AT_COPS_MODE_MANUAL_AUTOMATIC: + resp.mode = NETWORK_SELECT_MODE_MANUAL; + break; + + case AT_COPS_MODE_DEREGISTER: + case AT_COPS_MODE_SET_ONLY: + resp.result = TCORE_RETURN_FAILURE; + goto OUT; + } + resp.result = TCORE_RETURN_SUCCESS; + } + } else { + dbg("RESPONSE NOK"); + resp.result = TCORE_RETURN_FAILURE; + } - /* Process the Multi-line response */ - for (i = 0; i < nol; i++) { - line = g_slist_nth_data(at_resp->lines, i); +OUT: + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_get_plmn_selection_mode), &resp); + } - /* - * Tokenize - * - * +XCOPS: [,[,]] - */ - dbg(" : [%s]", line); - tokens = tcore_at_tok_new(line); + if (tokens != NULL) + tcore_at_tok_free(tokens); - if ((token_str = tcore_at_tok_nth(tokens, 0))) { - guint type = atoi(token_str); - dbg(" : [%d]", type); + return; +} - switch (type) { - case 0: /* PLMN (mcc, mnc) */ - if ((token_str = tcore_at_tok_nth(tokens, 1))) { - if (strlen(token_str) > 0) { - identity.plmn = tcore_at_tok_extract((const char *)token_str); +static void on_response_search_network(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur; + struct tresp_network_search resp; + int i = 0; + char *line = NULL; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + GSList *network_token = NULL; + int AcT = 0; + char *temp_plmn_info = NULL; + char *alpha_name = NULL; + char *pResp = NULL; + int num_network_avail = 0; + CustomData *custom_data; - /* Update PLMN */ - tcore_network_set_plmn( co, identity.plmn); - } - } - break; + memset(&resp, 0, sizeof(struct tresp_network_search)); + resp.result = TCORE_RETURN_FAILURE; + resp.list_count = 0; - case 1: /* Short Name in ROM (NV-RAM) */ - case 3: /* Short Network Operator Name (CPHS) */ - case 5: /* Short NITZ Name */ - if ((token_str = tcore_at_tok_nth(tokens, 1))) { - if (strlen(token_str) > 0) { - identity.short_name = tcore_at_tok_extract((const char *)token_str); + custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p)); + if (!custom_data) { + err("Network Search Custom Data is Null"); + return; + } + if (atResp->success > 0) { + dbg("RESPONSE OK"); - /* Update Short name */ - tcore_network_set_short_name(co, identity.short_name); - } - } - break; + /* If Request is Cancelled then return back SUCCESS/SEARCH_CANCELLED */ + if (custom_data->search_state + == IMC_NETWORK_SEARCH_STATE_CANCELLED) { + dbg("Network Search has been Cancelled!!!"); + goto OUT; + } - case 2: /* Long Name in ROM (NV-RAM) */ - case 4: /* Long Network Operator Name (CPHS) */ - case 6: /* Full NITZ Name */ - if ((token_str = tcore_at_tok_nth(tokens, 1))) { - if (strlen(token_str) > 0) { - identity.long_name = tcore_at_tok_extract((const char *)token_str); + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + num_network_avail = g_slist_length(tokens); + dbg(" length of tokens is %d\n", num_network_avail); + if (num_network_avail < 1) { + msg("invalid message"); + goto OUT; + } + } - /* Update Long name */ - tcore_network_set_long_name(co, identity.long_name); - } - } - break; + resp.result = TCORE_RETURN_SUCCESS; - default: - break; - } - } + /* + * +COPS: [list of supported (,long alphanumeric , + * short alphanumeric ,numeric [,])s] + * [,,(list of supported s),(list of supported s)] + */ + for (i = 0; ((i < num_network_avail) && (i < MAX_NETWORKS_MANUAL_SEARCH_SUPPORT)); i++) { + network_token = tcore_at_tok_new(g_slist_nth_data(tokens, i)); - /* Free resource */ - tcore_at_tok_free(tokens); + pResp = (tcore_at_tok_nth(network_token, 0)); + if (pResp != NULL) { + dbg("status : %s", pResp); + resp.list[i].status = (enum telephony_network_plmn_status) atoi(pResp); + } + + if ((pResp = tcore_at_tok_nth(network_token, 1))) { /* Long Alpha name */ + dbg("Long Alpha name : %s", pResp); + + if (strlen(pResp) > 0) + /* Strip off starting quote & ending quote */ + strncpy(resp.list[i].name, pResp + 1, strlen(pResp) - 2); + } + + if ((pResp = tcore_at_tok_nth(network_token, 2))) { + dbg("Short Aplha name : %s", pResp); + /* Short Aplha name */ + /* Strip off starting quote & ending quote */ + if (strlen(pResp) > 0) + strncpy(resp.list[i].name, pResp + 1, strlen(pResp) - 2); + } + + /* PLMN ID */ + pResp = tcore_at_tok_nth(network_token, 3); + if (pResp != NULL) { + dbg("PLMN ID : %s", pResp); + temp_plmn_info = tcore_at_tok_extract((const char *)pResp); + strncpy(resp.list[i].plmn, temp_plmn_info, 6); + resp.list[i].plmn[6] = '\0'; + } + + /* Parse Access Technology */ + if ((pResp = tcore_at_tok_nth(network_token, 4))) { + if (strlen(pResp) > 0) { + AcT = atoi(pResp); + + if (0 == AcT) + resp.list[i].act = NETWORK_ACT_GSM; + else if (2 == AcT) + resp.list[i].act = NETWORK_ACT_UMTS; + } } - /* Send Notification - Network identity */ - dbg("Network name - Long name: [%s] Short name: [%s] " - "PLMN: [%s]", identity.long_name, - identity.short_name, identity.plmn); + 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); + resp.list_count++; - result = TEL_NETWORK_RESULT_SUCCESS; + tcore_at_tok_free(network_token); + g_free(alpha_name); + g_free(temp_plmn_info); } + } else { + dbg("RESPONSE NOK"); + resp.result = TCORE_RETURN_FAILURE; } - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, &identity, resp_cb_data->cb_data); +OUT: + custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH; - /* Free resource */ - tcore_free(identity.long_name); - tcore_free(identity.short_name); - tcore_free(identity.plmn); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, + TRESP_NETWORK_SEARCH, + sizeof(struct tresp_network_search), &resp); + } - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + /* Free tokens */ + tcore_at_tok_free(tokens); } -/* - * Operation - fetch_nw_name - * - * Request - - * AT-Command: AT+XCOPS= - * - * may be - * 0 numeric format of network MCC/MNC (three BCD - * digit country code and two/three BCD digit network code) - * 1 Short Name in ROM (NV-RAM) - * 2 Long Name in ROM (NV-RAM) - * 3 Short Network Operator Name (CPHS) - * 4 Long Network Operator Name (CPHS) - * 5 Short NITZ Name - * 6 Full NITZ Name - * 7 Service Provider Name - * 8 EONS short operator name from EF-PNN - * 9 EONS long operator name from EF-PNN - * 11 Short PLMN name (When PS or CS is registered) - * 12 Long PLMN name (When PS or CS is registered) - * 13 numeric format of network MCC/MNC even in limited service - * - * Response - Network name - * Success: (Multiple Single line) - * +XCOPS: [,[,]] - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn __imc_network_fetch_nw_name(CoreObject *co, - TcoreObjectResponseCallback cb, void *cb_data) +static void on_response_set_umts_band(TcorePending *p, int data_len, const void *data, void *user_data) { - ImcRespCbData *resp_cb_data = NULL; - TelReturn ret; + const TcoreATResponse *atResp = data; - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0); + dbg("On Response Set UMTS Band"); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - "AT+XCOPS=0;+XCOPS=5;+XCOPS=6", "+XCOPS", - TCORE_AT_COMMAND_TYPE_MULTILINE, - NULL, - __on_response_imc_network_fetch_nw_name, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Fetch Network name"); + if (atResp->success > 0) { + dbg("Response OK"); + } else { + dbg("Response NOK"); + } - return ret; + dbg("Wait for response of XRAT before sending final band setting response to AP"); + return; } -/* Hook functions */ -static TcoreHookReturn on_hook_imc_set_flight_mode(CoreObject *co, - TcoreCommand command, const void *request, const void *user_data, - TcoreObjectResponseCallback cb, const void *cb_data) -{ - gboolean *flight_mode = (gboolean *)request; - /* - * Hook Set Flight mode request. - * - * Disable Flight mode - Hook response (if success Register to Network) - * Enable Flight mode - return - */ - if (*flight_mode != TRUE) { - /* Add response hook */ - tcore_object_add_response_hook(co, command, request, - __on_response_imc_hook_set_flight_mode, NULL); +static void on_response_set_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data) +{ + const TcoreATResponse *atResp = data; - return TCORE_HOOK_RETURN_CONTINUE; + dbg("On Response Set GSM Band"); + if (atResp->success > 0) { + dbg("Response OK"); + } else { + dbg("Response NOK"); } - dbg("Flight mode - [Enabled]"); - return TCORE_HOOK_RETURN_CONTINUE; + dbg("Wait for response of XRAT before sending final band setting response to AP"); + return; } -static TcoreHookReturn on_hook_imc_sim_status(TcorePlugin *plugin, - TcoreNotification command, guint data_len, void *data, void *user_data) +static void on_response_get_umts_band(TcorePending *p, int data_len, const void *data, void *user_data) { - const TelSimCardStatus *sim_status = (TelSimCardStatus *)data; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + const char *line = NULL; + int total_umts_bands = 0; + int i = 0; + char *band_token = NULL; + char umts_band[20] = {0}; + char umts_band_1 = 0; + char umts_band_2 = 0; + char umts_band_5 = 0; + UserRequest *ur = NULL; + struct tresp_network_get_band resp = {0}; + + dbg("Entry on_response_get_umts_band"); + + resp.mode = NETWORK_BAND_MODE_PREFERRED; + resp.result = TCORE_RETURN_SUCCESS; + + if (atResp->success > 0) { + dbg("RESPONSE OK"); + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + total_umts_bands = g_slist_length(tokens); + dbg("Total UMTS bands enabled are : %d\n", total_umts_bands); + if (total_umts_bands < 1) { + goto OUT; + } + } + } else { + dbg("RESPONSE NOK"); + goto OUT; + } - tcore_check_return_value(sim_status != NULL, - TCORE_HOOK_RETURN_CONTINUE); + for (i = 0; i < total_umts_bands; i++) { + band_token = tcore_at_tok_nth(tokens, i); - /* - * Hook SIM initialization Notification - * - * SIM INIT complete - Attach to network (Register to network) - * SIM INIT not complete - return - */ - if (*sim_status == TEL_SIM_STATUS_SIM_INIT_COMPLETED) { - CoreObject *co = (CoreObject *)user_data; - dbg("SIM Initialized!!! Attach to Network"); + if (band_token == NULL) + continue; - tcore_check_return_value_assert(co != NULL, - TCORE_HOOK_RETURN_CONTINUE); + memset(umts_band, 0x00, sizeof(umts_band)); - /* - * TODO - Check for selection_mode - * Need to check if it is Manual or Automatic and based on - * that need to initiate Network Registratin accordingly. - */ - __imc_network_register_to_network(co); + if (atoi(band_token) == 0) { /* 0 means UMTS automatic */ + umts_band_1 = umts_band_2 = umts_band_5 = TRUE; + break; + } - return TCORE_HOOK_RETURN_CONTINUE; - } + /* Strip off starting quotes & ending quotes */ + strncpy(umts_band, band_token + 1, strlen(band_token) - 2); - dbg("SIM not yet initialized - SIM Status: [%d]", *sim_status); - return TCORE_HOOK_RETURN_CONTINUE; -} + if (!strcmp(umts_band, "UMTS_BAND_I")) { + umts_band_1 = TRUE; + } else if (!strcmp(umts_band, "UMTS_BAND_II")) { + umts_band_2 = TRUE; + } else if (!strcmp(umts_band, "UMTS_BAND_II")) { + umts_band_5 = TRUE; + } else { + /* Telephony is not interest */ + dbg("Telephony is not interested in %s band", umts_band); + } + } -/* Notification callbacks */ -/* - * Notification: +CREG: [,,[,]] - * - * Possible values of can be - * 0 Not registered, ME is not currently searching - * a new operator to register to - * 1 Registered, home network - * 2 Not registered, but ME is currently searching - * a new operator to register - * 3 Registration denied - * 4 Unknown - * 5 Registered, in roaming - * - * - * string type; two byte location area code in - * hexadecimal format (e.g. 00C3) - * - * - * string type; four byte cell ID in hexadecimal - * format (e.g. 0000A13F) - * - * - * 0 GSM - * 2 UTRAN - * 3 GSM w/EGPRS - * 4 UTRAN w/HSDPA - * 5 UTRAN w/HSUPA - * 6 UTRAN w/HSDPA and HSUPA - */ -static gboolean on_notification_imc_cs_network_info(CoreObject *co, - const void *event_info, void *user_data) -{ - GSList *lines = NULL; - gchar *line = NULL; +OUT: + if ((umts_band_1) && (umts_band_2) && (umts_band_5)) { + resp.band = NETWORK_BAND_TYPE_WCDMA; + } else if (umts_band_1) { + resp.band = NETWORK_BAND_TYPE_WCDMA2100; + } else if (umts_band_2) { + resp.band = NETWORK_BAND_TYPE_WCDMA1900; + } else if (umts_band_5) { + resp.band = NETWORK_BAND_TYPE_WCDMA850; + } else { + resp.result = TCORE_RETURN_FAILURE; + } - dbg("Network notification - CS network info: [+CREG]"); + dbg("Final resp.band sent to TS = %d", resp.band); - lines = (GSList *)event_info; - if (g_slist_length(lines) != 1) { - err("+CREG unsolicited message expected to be Single line " - "but received multiple lines"); - return TRUE; + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp); } - line = (gchar *) (lines->data); - if (line != NULL) { - TelNetworkRegStatusInfo registration_status = {0, }; - TelNetworkCellInfo cell_info = {0, }; - GSList *tokens = NULL; - gchar *token_str; - guint stat = 0, act = 0, lac = 0, ci = 0; - gboolean roam_state = FALSE; + if (tokens != NULL) + tcore_at_tok_free(tokens); - /* - * Tokenize - * - * +CREG: [,,[,]] - */ - tokens = tcore_at_tok_new(line); - if (g_slist_length(tokens) < 1) { - err("Invalid notification message"); - goto out; - } + dbg("Exit on_response_get_umts_band"); + return; +} - /* */ - if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) { - err("No in +CREG"); - goto out; +static void on_response_get_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data) +{ + struct tresp_network_get_band resp = {0}; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + int total_gsm_bands = 0; + const char *line = NULL; + int i = 0; + char *band_token = NULL; + UserRequest *ur = NULL; + int gsm_850 = 0; + int gsm_900 = 0; + int gsm_1800 = 0; + int gsm_1900 = 0; + + dbg("Entry on_response_get_gsm_band"); + + resp.mode = NETWORK_BAND_MODE_PREFERRED; + resp.result = TCORE_RETURN_SUCCESS; + + if (atResp->success > 0) { + dbg("RESPONSE OK"); + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + total_gsm_bands = g_slist_length(tokens); + dbg("Total GSM bands enabled are : %d\n", total_gsm_bands); + if (total_gsm_bands < 1) + goto OUT; } - stat = __imc_network_map_stat(atoi(token_str)); - (void)tcore_network_set_cs_reg_status(co, stat); - - /* */ - if ((token_str = g_slist_nth_data(tokens, 1))) { - token_str = tcore_at_tok_extract((const gchar *)token_str); + } - lac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16); + for (i = 0; i < total_gsm_bands; i++) { + band_token = tcore_at_tok_nth(tokens, i); - /* Update Location Area Code (lac) information */ - (void)tcore_network_set_lac(co, lac); + if (band_token == NULL) + continue; - tcore_free(token_str); - } else { - dbg("No in +CREG"); - (void)tcore_network_get_lac(co, &lac); + if (atoi(band_token) == 0) { /* 0 means GSM automatic */ + gsm_850 = gsm_900 = gsm_1800 = gsm_1900 = TRUE; + break; } - /* */ - if ((token_str = g_slist_nth_data(tokens, 2))) { - token_str = tcore_at_tok_extract((const gchar *)token_str); + switch (atoi(band_token)) { + case AT_GSM_XBANDSEL_850: + gsm_850 = TRUE; + break; - ci = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16); + case AT_GSM_XBANDSEL_900: + gsm_900 = TRUE; + break; - /* Update Cell ID (ci) information */ - (void)tcore_network_set_cell_id(co, ci); + case AT_GSM_XBANDSEL_1800: + gsm_1800 = TRUE; + break; - tcore_free(token_str); - } else { - dbg("No in +CREG"); - (void)tcore_network_get_cell_id(co, &ci); - } + case AT_GSM_XBANDSEL_1900: + gsm_1900 = TRUE; + break; - /* */ - if ((token_str = g_slist_nth_data(tokens, 3))) { - act = __imc_network_map_act(atoi(token_str)); - (void)tcore_network_set_access_technology(co, act); - } else { - dbg("No in +CREG"); - (void)tcore_network_get_access_technology(co, &act); - } - dbg(": %d : 0x%x : 0x%x : %d", stat, lac, ci, act); - - /* Send Notification - Network (CS) Registration status */ - registration_status.cs_status = stat; - registration_status.act = act; - (void)tcore_network_get_ps_reg_status(co, ®istration_status.ps_status); - - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS, - sizeof(TelNetworkRegStatusInfo), ®istration_status); - - switch (stat) { - case TEL_NETWORK_REG_STATUS_ROAMING: - roam_state = TRUE; // no break - case TEL_NETWORK_REG_STATUS_REGISTERED: - /* Fetch Network name - Internal request */ - (void)__imc_network_fetch_nw_name(co, - __on_response_imc_network_fetch_nw_name_internal, NULL); - break; default: - break; + break; } + } - /* Set Roaming state */ - tcore_network_set_roam_state(co, roam_state); +OUT: + + if (gsm_850 && gsm_900 && gsm_1800 && gsm_1900) { + resp.band = NETWORK_BAND_TYPE_GSM; + } else if (gsm_850 && gsm_1900) { + resp.band = NETWORK_BAND_TYPE_GSM_850_1900; + } else if (gsm_900 && gsm_1800) { + resp.band = NETWORK_BAND_TYPE_GSM_900_1800; + } else if (gsm_1900) { + resp.band = NETWORK_BAND_TYPE_GSM1900; + } else if (gsm_850) { + resp.band = NETWORK_BAND_TYPE_GSM850; + } else if (gsm_1800) { + resp.band = NETWORK_BAND_TYPE_GSM1800; + } else if (gsm_900) { + resp.band = NETWORK_BAND_TYPE_GSM900; + } else { + resp.result = TCORE_RETURN_FAILURE; + } - /* Send Notification - Cell info */ - cell_info.lac = (gint)lac; - cell_info.cell_id = (gint)ci; - (void)tcore_network_get_rac(co, &cell_info.rac); + dbg("Final resp.band sent to TS = %d", resp.band); - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO, - sizeof(TelNetworkCellInfo), &cell_info); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp); + } -out: - /* Free resource */ + if (tokens != NULL) tcore_at_tok_free(tokens); - } - return TRUE; + dbg("Exit on_response_get_gsm_band"); + return; } -/* - * Notification: +CGREG: [,,[,,]] - * - * Possible values of can be - * 0 Not registered, ME is not currently searching a - * new operator to register to - * 1 Registered, home network - * 2 Not registered, but ME is currently searching a - * new operator to register - * 3 Registration denied - * 4 Unknown - * 5 Registered, in roaming - * - * - * string type; two byte location area code in - * hexadecimal format (e.g. 00C3) - * - * - * string type; four byte cell ID in hexadecimal - * format (e.g. 0000A13F) - * - * - * 0 GSM - * 2 UTRAN - * 3 GSM w/EGPRS - * 4 UTRAN w/HSDPA - * 5 UTRAN w/HSUPA - * 6 UTRAN w/HSDPA and HSUPA - * - * : - * string type; one byte routing area code in hexadecimal format - */ -static gboolean on_notification_imc_ps_network_info(CoreObject *co, - const void *event_info, void *user_data) -{ - GSList *lines = NULL; - gchar *line = NULL; - dbg("Network notification - PS network info: [+CGREG]"); +static void on_response_get_xrat(TcorePending *p, int data_len, const void *data, void *user_data) +{ + TcoreHal *h = NULL; + UserRequest *ur = NULL; + + TcoreATRequest *atreq; + char *cmd_str = NULL; + UserRequest *dup_ur = NULL; + const TcoreATResponse *atResp = data; + const char *line = NULL; + char *pResp = NULL; + GSList *tokens = NULL; + TcorePending *pending = NULL; + CoreObject *o = NULL; + int cp_xrat = 0; + struct tresp_network_get_band resp = {0}; - lines = (GSList *)event_info; - if (g_slist_length(lines) != 1) { - err("+CGREG unsolicited message expected to be Single line " - "but received multiple lines"); - return TRUE; - } + dbg("Enter on_response_get_xrat !!"); - line = (gchar *) (lines->data); - if (line != NULL) { - TelNetworkRegStatusInfo registration_status = {0, }; - TelNetworkCellInfo cell_info = {0, }; - GSList *tokens = NULL; - gchar *token_str; - guint stat = 0, act = 0, lac = 0, ci = 0, rac = 0; - gboolean roam_state = FALSE; + resp.mode = NETWORK_BAND_MODE_PREFERRED; - /* - * Tokenize - * - * +CGREG: [,,[,,]] - */ - tokens = tcore_at_tok_new(line); - if (g_slist_length(tokens) < 1) { - err("Invalid notification message"); - goto out; - } + ur = tcore_pending_ref_user_request(p); + h = tcore_object_get_hal(tcore_pending_ref_core_object(p)); + o = tcore_pending_ref_core_object(p); - /* */ - if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) { - err("No in +CGREG"); - goto out; + if (atResp->success > 0) { + dbg("RESPONSE OK"); + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + msg("invalid message"); + goto OUT; + } } - stat = __imc_network_map_stat(atoi(token_str)); - (void)tcore_network_set_ps_reg_status(co, stat); - /* */ - if ((token_str = g_slist_nth_data(tokens, 1))) { - token_str = tcore_at_tok_extract((const gchar *)token_str); + if ((pResp = tcore_at_tok_nth(tokens, 0))) { + cp_xrat = atoi(pResp); - lac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16); + if ((cp_xrat == AT_XRAT_DUAL)) { /* mode is Dual, send reply to Telephony */ + resp.result = TCORE_RETURN_SUCCESS; + resp.band = NETWORK_BAND_TYPE_ANY; - /* Update Location Area Code (lac) information */ - (void)tcore_network_set_lac(co, lac); - - tcore_free(token_str); - } else { - dbg("No in +CGREG"); - (void)tcore_network_get_lac(co, &lac); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp); + } + goto OUT; + } else if ((cp_xrat == AT_XRAT_UMTS)) { + /* Get UMTS Band Information */ + dup_ur = tcore_user_request_ref(ur); /* duplicate user request for AT+XUBANDSEL */ + cmd_str = g_strdup_printf("AT+XUBANDSEL?"); + atreq = tcore_at_request_new(cmd_str, "+XUBANDSEL", TCORE_AT_SINGLELINE); + pending = tcore_pending_new(o, 0); + tcore_pending_set_request_data(pending, 0, atreq); + tcore_pending_set_response_callback(pending, on_response_get_umts_band, NULL); + tcore_pending_link_user_request(pending, ur); + tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL); + tcore_hal_send_request(h, pending); + g_free(cmd_str); + } else if ((cp_xrat == AT_XRAT_UMTS)) { + /* Get GSM Band Information */ + dup_ur = tcore_user_request_ref(ur); /* duplicate user request for AT+XBANDSEL */ + cmd_str = g_strdup_printf("AT+XBANDSEL?"); + atreq = tcore_at_request_new(cmd_str, "+XBANDSEL", TCORE_AT_SINGLELINE); + pending = tcore_pending_new(o, 0); + tcore_pending_set_request_data(pending, 0, atreq); + tcore_pending_set_response_callback(pending, on_response_get_gsm_band, NULL); + tcore_pending_link_user_request(pending, dup_ur); + tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL); + tcore_hal_send_request(h, pending); + g_free(cmd_str); + } } + } else { + dbg("RESPONSE NOK"); - /* */ - if ((token_str = g_slist_nth_data(tokens, 2))) { - token_str = tcore_at_tok_extract((const gchar *)token_str); + resp.result = TCORE_RETURN_FAILURE; + resp.band = NETWORK_BAND_TYPE_ANY; - ci = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp); + } + } +OUT: - /* Update Cell ID (ci) information */ - (void)tcore_network_set_cell_id(co, ci); + if (tokens != NULL) + tcore_at_tok_free(tokens); - tcore_free(token_str); - } else { - dbg("No in +CGREG"); - (void)tcore_network_get_cell_id(co, &ci); - } + dbg("Exit on_response_get_xrat !!"); - /* */ - if ((token_str = g_slist_nth_data(tokens, 3))) { - act = __imc_network_map_act(atoi(token_str)); - (void)tcore_network_set_access_technology(co, act); - } else { - dbg("No in +CGREG"); - (void)tcore_network_get_access_technology(co, &act); - } + return; +} - /* */ - if ((token_str = g_slist_nth_data(tokens, 4))) { - token_str = tcore_at_tok_extract((const gchar *)token_str); - rac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16); +static void on_response_set_xrat(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + struct tresp_network_set_band resp = {0}; + const TcoreATResponse *atResp = data; - /* Update Routing Area Code (rac) information */ - (void)tcore_network_set_rac(co, rac); + dbg("On Response Set XRAT"); - tcore_free(token_str); - } else { - err("No in +CGREG"); - (void)tcore_network_get_rac(co, &rac); - } - dbg(": %d : 0x%x : 0x%x : %d : 0x%x", stat, lac, ci, act, rac); + if (atResp->success > 0) { + dbg("Response OK"); + resp.result = TCORE_RETURN_SUCCESS; + } else { + dbg("Response NOK"); + resp.result = TCORE_RETURN_FAILURE; + } - /* Send Notification - Network (PS) Registration status */ - registration_status.ps_status = stat; - registration_status.act = act; - (void)tcore_network_get_cs_reg_status(co, ®istration_status.cs_status); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_SET_BAND, sizeof(struct tresp_network_set_band), &resp); + } - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS, - sizeof(TelNetworkRegStatusInfo), ®istration_status); + return; +} - /* Set Roaming state */ - if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING) - roam_state = TRUE; +static void on_response_set_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + struct tresp_network_set_preferred_plmn resp = {0}; + const TcoreATResponse *atResp = data; - tcore_network_set_roam_state(co, roam_state); + dbg("ENTER on_response_set_preferred_plmn"); - /* Send Notification - Cell info */ - cell_info.lac = lac; - cell_info.cell_id = ci; - cell_info.rac = rac; - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO, - sizeof(TelNetworkCellInfo), &cell_info); + if (atResp->success > 0) { + dbg("Response OK"); + resp.result = TCORE_RETURN_SUCCESS; + } else { + dbg("Response NOK"); + resp.result = TCORE_RETURN_FAILURE; + } -out: - /* Free resource */ - tcore_at_tok_free(tokens); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PREFERRED_PLMN, sizeof(struct tresp_network_set_preferred_plmn), &resp); } - return TRUE; + dbg("Exit on_response_set_preferred_plmn"); + return; } -/* - * Notification: +XNITZINFO: ,,,, - * - * - * string type; Network name in long alphanumeric format. - * - * - * string type; Network name in short alphanumeric format. - * - * - * Local Time Zone; represented as 1 unit = 15 minutes. - * - * - * string type value; Universal Time - * format is "yy/MM/dd,hh:mm:ss", - * wherein characters indicates year, month, day, hour, - * minutes, seconds. - * - * Daylight Saving Time; represented in hours. - */ -static gboolean on_notification_imc_network_time_info(CoreObject *co, - const void *event_info, void *user_data) +static void on_response_get_nitz_name(TcorePending *p, int data_len, const void *data, void *user_data) { - GSList *lines = NULL; - gchar *line = NULL; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + const char *line = NULL; + CoreObject *o = NULL; + struct tnoti_network_identity noti; + int nol = 0; + int count = 0; + int net_name_type = 0; + char *pResp = NULL; + char *net_name = NULL; + + dbg("Entry on_response_get_nitz_name (+XCOPS)"); + o = tcore_pending_ref_core_object(p); + if (atResp->success > 0) { + dbg("RESPONSE OK"); - dbg("Network notification - Time info: [+XNITZINFO]"); + if (atResp->lines) { + nol = g_slist_length(atResp->lines); + if (nol > 3) { + msg("invalid message"); + goto OUT; + } - lines = (GSList *)event_info; - if (g_slist_length(lines) != 1) { - err("+XNITZINFO unsolicited message expected to be Single line " - "but received multiple lines"); - return TRUE; - } - - line = (gchar *)lines->data; - if (line != NULL) { - GSList *tokens = NULL; - TelNetworkNitzInfoNoti nitz_info = {0, }; - gchar *fullname, *shortname; - gchar *ltz, *time; - gchar tmp_time[8] = {0}; - gchar *dstoff; + memset(¬i, 0, sizeof(struct tnoti_network_identity)); - /* - * Tokenize - * - * +XNITZINFO: ,,,, - */ - tokens = tcore_at_tok_new(line); + for (count = 0; count < nol; count++) { + // parse each line + line = g_slist_nth_data(atResp->lines, count); + tokens = tcore_at_tok_new(line); + dbg("line %d start---------------", count); + + if ((pResp = tcore_at_tok_nth(tokens, 0))) { + net_name_type = atoi(pResp); + dbg("Net name type : %d", net_name_type); + + switch (net_name_type) { + case 0: /* plmn_id (mcc, mnc) */ + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + if (strlen(pResp) > 0) { + net_name = tcore_at_tok_extract((const char *)pResp); + strncpy(noti.plmn, net_name, 6); + noti.plmn[6] = '\0'; + } + } + break; + + case 5: /* Short NITZ name*/ + case 3: /* Short Network Name (CPHS) */ + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + if (strlen(pResp) > 0) { + net_name = tcore_at_tok_extract((const char *)pResp); + strncpy(noti.short_name, net_name, 16); + noti.short_name[16] = '\0'; + } + } + break; + + case 6: /* Full NITZ name */ + case 4: /* Long Network Name (CPHS) */ + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + if (strlen(pResp) > 0) { + net_name = tcore_at_tok_extract((const char *)pResp); + strncpy(noti.full_name, net_name, 32); + noti.full_name[32] = '\0'; + } + } + break; - /* */ - if ((fullname = tcore_at_tok_nth(tokens, 1))) { - if (strlen(fullname) > 0) { - fullname = tcore_at_tok_extract((const char *)fullname); + default: + break; + } - /* Update Long name */ - tcore_network_set_long_name(co, fullname); + g_free(net_name); + net_name = NULL; + } - tcore_free(fullname); + tcore_at_tok_free(tokens); } - } - /* */ - if ((shortname = tcore_at_tok_nth(tokens, 1))) { - if (strlen(shortname) > 0) { - shortname = tcore_at_tok_extract((const char *)shortname); + dbg("plmn <%s> short NITZ name<%s> full NITZ name<%s>", + noti.plmn, noti.short_name, noti.full_name); + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_IDENTITY, + sizeof(struct tnoti_network_identity), ¬i); + } + } else { + dbg("RESPONSE NOK"); + } - /* Update Short name */ - tcore_network_set_short_name(co, shortname); +OUT: + dbg("Exit on_response_get_nitz_name"); +} - tcore_free(shortname); - } - } +static void on_response_get_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur; + int i = 0; + char *line = NULL; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + char *pResp = NULL; + int plmn_format = 0; - /* */ - if ((ltz = g_slist_nth_data(tokens, 2))) - nitz_info.gmtoff = atoi(ltz) * 15;/* gmtoff in minutes */ + struct tresp_network_get_preferred_plmn resp = {0}; + int total_lines = 0; + int GSM_AcT2 = 0, GSM_Compact_AcT2 = 0, UTRAN_AcT2 = 0; - if ((time = g_slist_nth_data(tokens, 3)) - && (strlen(time) > 18)) { - /* (time + 1) - Skip past initial quote (") */ - g_strlcpy(tmp_time, time + 1, 2+1); - nitz_info.year = atoi(tmp_time); + dbg("Entry"); - /* skip slash (/) after year param */ - g_strlcpy(tmp_time, time + 4, 2+1); - nitz_info.month = atoi(tmp_time); + if (atResp->success > 0) { + dbg("RESPONSE OK"); + if (atResp->lines) { + total_lines = g_slist_length(atResp->lines); + dbg("Total number of network present in Preferred PLMN list is %d\n", total_lines); - /* skip past slash (/) after month param */ - g_strlcpy(tmp_time, time + 7, 2+1); - nitz_info.day = atoi(tmp_time); + if (total_lines < 1) { + msg("invalid message"); + goto OUT; + } - /* skip past comma (,) after day param */ - g_strlcpy(tmp_time, time + 10, 2+1); - nitz_info.hour = atoi(tmp_time); + if (total_lines >= MAX_NETWORKS_PREF_PLMN_SUPPORT) + total_lines = MAX_NETWORKS_PREF_PLMN_SUPPORT; - /* skip past colon (:) after hour param */ - g_strlcpy(tmp_time, time + 13, 2+1); - nitz_info.minute = atoi(tmp_time); +/* ++CPOL: ,,[,,,,] [ ++CPOL: ,,[,,,,] +*/ + resp.result = TCORE_RETURN_SUCCESS; + + for (i = 0; i < total_lines; i++) { + /* Take each line response at a time & parse it */ + line = tcore_at_tok_nth(atResp->lines, i); + tokens = tcore_at_tok_new(line); - /* skip past colon (:) after minute param */ - g_strlcpy(tmp_time, time + 16, 2+1); - nitz_info.second = atoi(tmp_time); - } + /* ,,[,,,,] */ - /* */ - if ((dstoff = g_slist_nth_data(tokens, 4))) { - nitz_info.dstoff = atoi(dstoff); - nitz_info.isdst = TRUE; - } + /* EF Index */ + if ((pResp = tcore_at_tok_nth(tokens, 0))) { + dbg("Index : %s", pResp); + resp.list[i].ef_index = atoi(pResp); + } + /* Format */ + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + dbg("format : %s", pResp); + plmn_format = atoi(pResp); + } - /* Get PLMN */ - tcore_network_get_plmn(co, &nitz_info.plmn); + /* Operator PLMN ID */ + if ((pResp = tcore_at_tok_nth(tokens, 2))) { + dbg("plmn ID : %s", pResp); - /* Send Notification - Network time info */ - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_TIMEINFO, - sizeof(TelNetworkNitzInfoNoti), &nitz_info); + if (strlen(pResp) > 0) { + char *oper; - /* Free resource */ - tcore_free(nitz_info.plmn); - tcore_at_tok_free(tokens); - } + oper = tcore_at_tok_extract((const char *)pResp); + dbg("operator <%s>", oper); - return TRUE; -} + // Get only PLMN ID + if (plmn_format == 2) { + strncpy(resp.list[i].plmn, oper, 6); + resp.list[i].plmn[6] = '\0'; + } -/* - * Notification: - * +XCIEV: , - * or - * +XCIEV:, - * - * 'Radio Signal Strength' can have the values - * 0 -107 dBm or less or unknown - * 1 -99 dBm or less - * 2 -91 dBm or less - * 3 -83 dBm or less - * 4 -75 dBm or less - * 5 -67 dBm or less - * 6 -59 dBm or less - * 7 -51 dBm or less - * - * 'Battery Level' can have the values - * 0 0 % <= level < 5 % - * 1 5 % <= level < 15 % - * 2 15 % <= level < 25 % - * 3 25 % <= level < 40 % - * 4 40 % <= level < 55 % - * 5 55 % <= level < 70 % - * 6 70 % <= level < 85 % - * 7 85 % <= level <= 100 % - * - * NOTE: - * is not consider for - * TCORE_NOTIFICATION_NETWORK_RSSI notification - */ -static gboolean on_notification_imc_network_rssi(CoreObject *co, - const void *event_info, void *user_data) -{ - GSList *lines = NULL; - gchar *line = NULL; + g_free (oper); + } + } - dbg("Network notification - Icon (rssi) info: [+XCIEV]"); + if ((pResp = tcore_at_tok_nth(tokens, 3))) { + dbg("GSM_AcT2 : %s", pResp); + GSM_AcT2 = atoi(pResp); + } - lines = (GSList *)event_info; - if (g_slist_length(lines) != 1) { - err("+XCIEV unsolicited message expected to be Single line " - "but received multiple lines"); - return TRUE; - } + if ((pResp = tcore_at_tok_nth(tokens, 4))) { + dbg("GSM_Compact AcT2 : %s", pResp); + GSM_Compact_AcT2 = atoi(pResp); + } - line = (gchar *)lines->data; - if (line != NULL) { - GSList *tokens = NULL; - gchar *rssi_token; + if ((pResp = tcore_at_tok_nth(tokens, 5))) { + dbg("UTRAN_AcT2 : %s", pResp); + UTRAN_AcT2 = atoi(pResp); + } - /* - * Tokenize - * - * +XCIEV: , - */ - tokens = tcore_at_tok_new(line); + if (UTRAN_AcT2 && (GSM_AcT2 || GSM_Compact_AcT2)) + resp.list[i].act = NETWORK_ACT_GSM_UTRAN; + else if (UTRAN_AcT2) + resp.list[i].act = NETWORK_ACT_UMTS; + else if (GSM_AcT2 || GSM_Compact_AcT2) + resp.list[i].act = NETWORK_ACT_GPRS; - rssi_token = (gchar *)g_slist_nth_data(tokens, 0); - if (rssi_token && strlen(rssi_token)) { - guint rssi_bar = atoi(rssi_token); - dbg("RSSI Level: [%d]", rssi_bar); + (resp.list_count)++; - /* Send Notification - Network Rssi */ - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_RSSI, - sizeof(guint), &rssi_bar); + tcore_at_tok_free(tokens); + } } - - /* Free resource */ - tcore_at_tok_free(tokens); + } else { + dbg("RESPONSE NOT OK"); + // TODO: CMEE error mapping is required. + resp.result = TCORE_RETURN_FAILURE; } - return TRUE; +OUT: + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PREFERRED_PLMN, sizeof(struct tresp_network_get_preferred_plmn), &resp); + } + dbg("Exit"); + return; } -/* Network Responses */ - -static void on_response_imc_network_search(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_get_serving_network(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - CustomData *custom_data; - - ImcRespCbData *resp_cb_data = user_data; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - TelNetworkPlmnList plmn_list = {0, }; - guint num_network_avail = 0; - guint count; + const TcoreATResponse *resp = data; + UserRequest *ur; + struct tresp_network_get_serving_network Tresp = {0}; + char *long_plmn_name = NULL; + char *short_plmn_name = NULL; + char *plmn_id = NULL; + CoreObject *o; GSList *tokens = NULL; - - dbg("Enter"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); - - custom_data = tcore_object_ref_user_data(co); - tcore_check_return_assert(custom_data != NULL); - - if (at_resp && at_resp->success) { - const gchar *line; - GSList *net_token = NULL; - gchar *resp; - gint act; - - /* If Request is Cancelled then return back SUCCESS/SEARCH_CANCELLED */ - if (custom_data->search_state - == IMC_NETWORK_SEARCH_STATE_CANCELLED) { - dbg("Network Search has been Cancelled!!!"); - - /* - * TODO: - * - * Need to introduce new Result - - * TEL_NETWORK_RESULT_SEARCH_ABORTED/CANCELLED - * - * Presently sending TEL_NETWORK_RESULT_FAILURE - */ - result = TEL_NETWORK_RESULT_FAILURE; - - goto END; + const char *line; + int network_mode = -1; + int plmn_format = -1; + int AcT = -1; + struct tnoti_network_identity noti; + char *pResp = NULL; + int nol, count = 0; + + o = tcore_pending_ref_core_object(p); + + if (resp->success <= 0) { + dbg("RESPONSE NOK"); + + ur = tcore_pending_ref_user_request(p); + if (ur) { + Tresp.result = TCORE_RETURN_FAILURE; + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp); } - if (!at_resp->lines) { - err("invalid response received"); - goto END; - } - - line = (char *) at_resp->lines->data; - tokens = tcore_at_tok_new(line); - num_network_avail = g_slist_length(tokens); - if (num_network_avail < 1) { - err("invalid message"); - goto END; - } - - plmn_list.network_list = tcore_malloc0(sizeof(TelNetworkInfo) * num_network_avail); + return; + } else { dbg("RESPONSE OK"); - plmn_list.count = 0; - for (count = 0; count < num_network_avail; count++) { + nol = g_slist_length(resp->lines); + dbg("nol : %d", nol); - net_token = tcore_at_tok_new(g_slist_nth_data(tokens, count)); - if (NULL == net_token) - continue; - - resp = tcore_at_tok_nth(net_token, 0); - if (resp != NULL) { - plmn_list.network_list[count].plmn_status = atoi(resp); - dbg("status[%d]", plmn_list.network_list[count].plmn_status); + for (count = 0; count < nol; count++) { + // parse each line + line = g_slist_nth_data(resp->lines, count); + tokens = tcore_at_tok_new(line); + dbg("line %d start---------------", count); + // mode + if ((pResp = tcore_at_tok_nth(tokens, 0))) { + dbg("mode : %s", pResp); + network_mode = atoi(pResp); } - if ((resp = tcore_at_tok_nth(net_token, 1))) { - /* Long Alpha name */ - dbg("long alpha name[%s]", resp); - plmn_list.network_list[count].network_identity.long_name = - tcore_at_tok_extract(resp); + // format (optional) + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + dbg("format : %s", pResp); + if (strlen(pResp) > 0) + plmn_format = atoi(pResp); } - if ((resp = tcore_at_tok_nth(net_token, 2))) { - /* Short Alpha name */ - dbg("Short Alpha name[%s]", resp); - plmn_list.network_list[count].network_identity.short_name = - tcore_at_tok_extract(resp); - } + // plmn + switch (plmn_format) { + case AT_COPS_FORMAT_LONG_ALPHANUMERIC: + if ((pResp = tcore_at_tok_nth(tokens, 2))) { + dbg("long PLMN : %s", pResp); + if (strlen(pResp) > 0) { + long_plmn_name = tcore_at_tok_extract((const char *)pResp); - /* PLMN ID */ - if ((resp = tcore_at_tok_nth(net_token, 3))) { - dbg("PLMN ID[%s]", resp); - plmn_list.network_list[count].network_identity.plmn = - tcore_at_tok_extract(resp); - } + // set network name into po + tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_FULL, long_plmn_name); + } + } + break; - /* Parse Access Technology */ - if ((resp = tcore_at_tok_nth(tokens, 4))) { - act = atoi(resp); - if (0 == act) - plmn_list.network_list[count].act = TEL_NETWORK_ACT_GSM; - else if (2 == act) - plmn_list.network_list[count].act = TEL_NETWORK_ACT_UMTS; + case AT_COPS_FORMAT_SHORT_ALPHANUMERIC: + if ((pResp = tcore_at_tok_nth(tokens, 2))) { + dbg("short PLMN : %s", pResp); + if (strlen(pResp) > 0) { + short_plmn_name = tcore_at_tok_extract((const char *)pResp); + + // set network name into po + tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SHORT, short_plmn_name); + } } + break; - dbg("Operator [%d] :: status = %d, long_name = %s, short_name = %s plmn = %s, AcT=%d", - plmn_list.count, - plmn_list.network_list[count].plmn_status, - plmn_list.network_list[count].network_identity.long_name, - plmn_list.network_list[count].network_identity.short_name, - plmn_list.network_list[count].network_identity.plmn, - plmn_list.network_list[count].act); + case AT_COPS_FORMAT_NUMERIC: + if ((pResp = tcore_at_tok_nth(tokens, 2))) { + dbg("numeric : %s", pResp); + if (strlen(pResp) > 0) { + plmn_id = tcore_at_tok_extract((const char *)pResp); - plmn_list.count ++; - tcore_at_tok_free(net_token); - } - result = TEL_NETWORK_RESULT_SUCCESS; - } else { - err("RESPONSE NOK"); - result = __imc_network_convert_cme_error_tel_network_result(at_resp); - } + // set plmn id into po + tcore_network_set_plmn(o, plmn_id); + } + } + break; -END: - dbg("Network search : [%s]", - (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); + default: + break; + } - /* Update Search state */ - custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH; + // act + if ((pResp = tcore_at_tok_nth(tokens, 3))) { + dbg("AcT : %s", pResp); + if (strlen(pResp) > 0) { + AcT = atoi(pResp); + tcore_network_set_access_technology(o, lookup_tbl_access_technology[AcT]); + } + } - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, &plmn_list, resp_cb_data->cb_data); + tcore_at_tok_free(tokens); + } - imc_destroy_resp_cb_data(resp_cb_data); + if(plmn_id) + memcpy(Tresp.plmn, plmn_id, strlen(plmn_id)); + tcore_network_get_access_technology(o, &(Tresp.act)); + tcore_network_get_lac(o, &(Tresp.gsm.lac)); - /* Free resources*/ - for (count = 0; count < num_network_avail; count++) { - g_free(plmn_list.network_list[count].network_identity.long_name); - g_free(plmn_list.network_list[count].network_identity.short_name); - g_free(plmn_list.network_list[count].network_identity.plmn); - } + ur = tcore_pending_ref_user_request(p); + if (ur) { + Tresp.result = TCORE_RETURN_SUCCESS; + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp); + } else { + /* Network change noti */ + struct tnoti_network_change network_change; + + memset(&network_change, 0, sizeof(struct tnoti_network_change)); + if(plmn_id) + memcpy(network_change.plmn, plmn_id, strlen(plmn_id)); + tcore_network_get_access_technology(o, &(network_change.act)); + tcore_network_get_lac(o, &(network_change.gsm.lac)); + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(p)), tcore_pending_ref_core_object(p), + TNOTI_NETWORK_CHANGE, sizeof(struct tnoti_network_change), &network_change); + dbg("dbg.. network_change.plmn : %s", network_change.plmn); + dbg("dbg.. network_change.act : %d", network_change.act); + dbg("dbg.. network_change.gsm.lac : %d", network_change.gsm.lac); + + if ((AT_COPS_MODE_DEREGISTER != network_mode) && + (AT_COPS_MODE_SET_ONLY != network_mode)) { + /*Network identity noti*/ + memset(¬i, 0x0, sizeof(struct tnoti_network_identity)); + if (long_plmn_name) + memcpy(noti.full_name, long_plmn_name, MIN(32, strlen(long_plmn_name))); + if (short_plmn_name) + memcpy(noti.short_name, short_plmn_name, MIN(16, strlen(short_plmn_name))); + if (plmn_id) + memcpy(noti.plmn, plmn_id, strlen(plmn_id)); // plmn_id length is necessarily <= 6 + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), + o, TNOTI_NETWORK_IDENTITY, sizeof(struct tnoti_network_identity), ¬i); + dbg("dbg.. noti.short_name : %s", noti.short_name); + dbg("dbg.. noti.full_name : %s", noti.full_name); + dbg("dbg.. noti.plmn : %s", noti.plmn); + } + } - tcore_free(plmn_list.network_list); - tcore_at_tok_free(tokens); + g_free(long_plmn_name); + g_free(short_plmn_name); + g_free(plmn_id); + } + return; } -static gboolean on_response_imc_network_cancel_search(gpointer data) +static void on_response_network_set_mode(TcorePending *p, int data_len, const void *data, void *user_data) { - ImcRespCbData *resp_cb_data = data; - ImcNetworkCancelSearch *cancel_search = - (ImcNetworkCancelSearch *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data); + UserRequest *ur = NULL; + struct tresp_network_set_mode resp = {0}; + const TcoreATResponse *atResp = data; - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(cancel_search->co, (gint)cancel_search->result, - NULL, resp_cb_data->cb_data); + dbg("ENTER on_response_network_set_mode"); - imc_destroy_resp_cb_data(resp_cb_data); + if (atResp && atResp->success) { + dbg("RESPONSE OK"); + resp.result = TCORE_RETURN_SUCCESS; + } else { + err("RESPONSE NOK"); + resp.result = TCORE_RETURN_FAILURE; + } - /* To stop the cycle, need to return FALSE */ - return FALSE; + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, + TRESP_NETWORK_SET_MODE, + sizeof(struct tresp_network_set_mode), &resp); + } } -static void on_response_imc_network_get_selection_mode(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_network_get_mode(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkSelectionMode selection_mode = -1; + UserRequest *ur = NULL; + struct tresp_network_get_mode resp = {0}; + const TcoreATResponse *atResp = data; GSList *tokens = NULL; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - dbg("Enter"); + dbg("ENTER on_response_network_get_mode"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + resp.result = TCORE_RETURN_FAILURE; - if (at_resp && at_resp->success) { + if (atResp && atResp->success) { const gchar *line; - gint mode; + gint net_mode; - if (!at_resp->lines) { + if (!atResp->lines) { err("invalid response received"); goto END; } - line = (char *) at_resp->lines->data; + line = (char *) atResp->lines->data; tokens = tcore_at_tok_new(line); if (g_slist_length(tokens) < 1) { - msg("invalid message"); + err("invalid message"); goto END; } + dbg("RESPONSE OK"); - mode = atoi(tcore_at_tok_nth(tokens, 0)); - if (mode == 0) - selection_mode = TEL_NETWORK_SELECTION_MODE_AUTOMATIC; - else if (mode == 1) - selection_mode = TEL_NETWORK_SELECTION_MODE_MANUAL; + net_mode = atoi(tcore_at_tok_nth(tokens, 0)); + dbg("mode = %d", net_mode); - result = TEL_NETWORK_RESULT_SUCCESS; - dbg("selection mode[%d]", selection_mode); + switch (net_mode) { + case 0: + resp.mode = NETWORK_MODE_GSM; + break; + case 1: + resp.mode = NETWORK_MODE_AUTO; + break; + case 2: + resp.mode = NETWORK_MODE_WCDMA; + break; + default: + err("Unsupported mode [%d]", net_mode); + goto END; + } + resp.result = TCORE_RETURN_SUCCESS; } else { err("RESPONSE NOK"); - result = __imc_network_convert_cme_error_tel_network_result(at_resp); } END: - dbg("Get selection mode : [%s]", - (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, &selection_mode, resp_cb_data->cb_data); - - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, + TRESP_NETWORK_GET_MODE, + sizeof(struct tresp_network_get_mode), &resp); + } + /* Free resource*/ tcore_at_tok_free(tokens); } -static void on_response_imc_network_default(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_cancel_manual_search(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; + UserRequest *ur = NULL; + struct tresp_network_set_cancel_manual_search resp = {0}; + const TcoreATResponse *atResp = data; + CustomData *custom_data; - dbg("Enter"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + dbg("ENTER on_response_cancel_manual_search"); - if (at_resp && at_resp->success) { - dbg("RESPONSE OK"); - result = TEL_NETWORK_RESULT_SUCCESS; + if (atResp->success > 0) { + dbg("Response OK"); + resp.result = TCORE_RETURN_SUCCESS; } else { - err("RESPONSE NOK"); - result = __imc_network_convert_cme_error_tel_network_result(at_resp); + dbg("Response NOK"); + resp.result = TCORE_RETURN_FAILURE; } - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); + custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p)); + custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH; - imc_destroy_resp_cb_data(resp_cb_data); -} + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, + TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH, + sizeof(struct tresp_network_set_cancel_manual_search), &resp); + } + dbg("Exit on_response_cancel_manual_search"); +} -static void on_response_imc_network_get_mode(TcorePending *p, - guint data_len, const void *data, void *user_data) +static gboolean on_event_ps_network_regist(CoreObject *o, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - TelNetworkMode mode = -1; + struct tnoti_network_registration_status regist_status; + enum telephony_network_service_domain_status cs_status; + enum telephony_network_service_domain_status ps_status; + enum telephony_network_service_type service_type; + enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN; + struct tnoti_network_location_cellinfo net_lac_cell_info = {0}; + struct tnoti_ps_protocol_status noti = {0}; + unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_PS; + int stat = 0, AcT = 0; + unsigned int lac = 0xffff, ci = 0xffff; + unsigned int rac = 0xffff; GSList *tokens = NULL; + char *pResp; + char *line = NULL; + GSList *lines = NULL; - dbg("Enter"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + lines = (GSList *) data; + if (1 != g_slist_length(lines)) { + dbg("unsolicited msg but multiple line"); + goto OUT; + } + line = (char *) (lines->data); + dbg("+CGREG NOTI RECEIVED"); - if (at_resp && at_resp->success) { - const gchar *line; - gint net_mode; +/* ++CREG: [[,,[AcT]] + +Possible values of can be +0 Not registered, ME is not currently searching a new operator to register to +1 Registered, home network +2 Not registered, but ME is currently searching a new operator to register +3 Registration denied +4 Unknown +5 Registered, in roaming + + +string type; two byte location area code in hexadecimal format (e.g. 00C3) + + +string type; four byte cell ID in hexadecimal format (e.g. 0000A13F) + + +0 GSM +2 UTRAN +3 GSM w/EGPRS +4 UTRAN w/HSDPA +5 UTRAN w/HSUPA +6 UTRAN w/HSDPA and HSUPA +Note: is supporting from R7 and above Protocol Stack. + +: is R7 and above feature, string type; one byte routing area code in hexadecimal format. +*/ + if (line != NULL) { + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + msg("invalid message"); + goto OUT; + } - if (!at_resp->lines) { - err("invalid response received"); - goto END; + if (!(pResp = g_slist_nth_data(tokens, 0))) { + dbg("No STAT in +CGREG"); + goto OUT; + } else { + stat = atoi(pResp); + if ((pResp = g_slist_nth_data(tokens, 1))) { + pResp = util_removeQuotes(pResp); + lac = strtol(pResp, NULL, 16); + g_free(pResp); + } + + if ((pResp = g_slist_nth_data(tokens, 2))) { + pResp = util_removeQuotes(pResp); + ci = strtol(pResp, NULL, 16); + g_free(pResp); + } else { + dbg("No ci in +CGREG"); + } + + if ((pResp = g_slist_nth_data(tokens, 3))) + AcT = atoi(pResp); + else + dbg("No AcT in +CGREG"); + + if ((pResp = g_slist_nth_data(tokens, 4))) { + pResp = util_removeQuotes(pResp); + rac = strtol(pResp, NULL, 16); + g_free(pResp); + } else { + dbg("No rac in +CGREG"); + } + } + + + dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d, rac = 0x%x", stat, lac, ci, AcT, rac); + + ps_status = lookup_tbl_net_status[stat]; + + tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status); + _ps_set(tcore_object_ref_plugin(o), ps_status); + + tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status); + + act = lookup_tbl_access_technology[AcT]; + tcore_network_set_access_technology(o, act); + + tcore_network_get_service_type(o, &service_type); + dbg("prev_service_type = 0x%x", service_type); + service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status); + dbg("new_service_type = 0x%x", service_type); + tcore_network_set_service_type(o, service_type); + + tcore_network_set_lac(o, lac); + tcore_network_set_cell_id(o, ci); + tcore_network_set_rac(o, rac); + + net_lac_cell_info.lac = lac; + net_lac_cell_info.cell_id = ci; + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO, + sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info); + + regist_status.cs_domain_status = cs_status; + regist_status.ps_domain_status = ps_status; + regist_status.service_type = service_type; + regist_status.roaming_status = tcore_network_get_roaming_state(o); + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, + TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(regist_status), ®ist_status); +#if 0 + if (service_type == NETWORK_SERVICE_TYPE_HSDPA) + noti.status = TELEPHONY_HSDPA_ON; + else + noti.status = TELEPHONY_HSDPA_OFF; +#else + switch(AcT){ + case AT_COPS_ACT_GSM:/*Fall Through*/ + case AT_COPS_ACT_GSM_COMPACT:/*Fall Through*/ + case AT_COPS_ACT_UTRAN:/*Fall Through*/ + case AT_COPS_ACT_GSM_EGPRS:/*Fall Through*/ + case AT_COPS_ACT_E_UTRAN: + { + dbg("Not required for Protocol Status Notification"); + goto OUT; + } + case AT_COPS_ACT_UTRAN_HSDPA: + { + dbg("HSDPA"); + noti.status = TELEPHONY_HSDPA_ON; + break; + } + case AT_COPS_ACT_UTRAN_HSUPA: + { + dbg("HSUPA"); + noti.status = TELEPHONY_HSUPA_ON; + break; + } + case AT_COPS_ACT_UTRAN_HSDPA_HSUPA: + { + dbg("HSPA"); + noti.status = TELEPHONY_HSPA_ON; + break; + } + default: + { + dbg("Ignore"); + goto OUT; + } } +#endif + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_PS_PROTOCOL_STATUS, + sizeof(struct tnoti_ps_protocol_status), ¬i); + + /* Get PLMN ID needed to application */ + // get_serving_network(o, NULL); + } else { + dbg("Response NOK"); + } + +OUT: + if (NULL != tokens) + tcore_at_tok_free(tokens); + return TRUE; +} + +static gboolean on_event_cs_network_regist(CoreObject *o, const void *event_info, void *user_data) +{ + GSList *lines = NULL; + char *line = NULL; + struct tnoti_network_registration_status regist_status; + enum telephony_network_service_domain_status cs_status; + enum telephony_network_service_domain_status ps_status; + enum telephony_network_service_type service_type; + enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN; + struct tnoti_network_location_cellinfo net_lac_cell_info = {0}; + + + unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_CS; + int stat = 0, AcT = 0; + unsigned int lac = 0xffff, ci = 0xffff; + GSList *tokens = NULL; + char *pResp; - line = (char *) at_resp->lines->data; + lines = (GSList *) event_info; + if (1 != g_slist_length(lines)) { + dbg("unsolicited msg but multiple line"); + goto OUT; + } + line = (char *) (lines->data); + + dbg("+CREG NOTI RECEIVED"); + +/* ++CREG: [[,,[AcT]] + +Possible values of can be +0 Not registered, ME is not currently searching a new operator to register to +1 Registered, home network +2 Not registered, but ME is currently searching a new operator to register +3 Registration denied +4 Unknown +5 Registered, in roaming + + +string type; two byte location area code in hexadecimal format (e.g. 00C3) + + +string type; four byte cell ID in hexadecimal format (e.g. 0000A13F) + + +0 GSM +2 UTRAN +3 GSM w/EGPRS +4 UTRAN w/HSDPA +5 UTRAN w/HSUPA +6 UTRAN w/HSDPA and HSUPA +Note: is supporting from R7 and above Protocol Stack. +*/ + if (line != NULL) { tokens = tcore_at_tok_new(line); if (g_slist_length(tokens) < 1) { - err("invalid message"); - goto END; + msg("invalid message"); + goto OUT; } - dbg("RESPONSE OK"); - net_mode = atoi(tcore_at_tok_nth(tokens, 0)); - dbg("mode = %d", net_mode); + if (!(pResp = g_slist_nth_data(tokens, 0))) { + dbg("No STAT in +CREG"); + goto OUT; + } else { + stat = atoi(pResp); + if ((pResp = g_slist_nth_data(tokens, 1))) { + pResp = util_removeQuotes(pResp); + lac = strtol(pResp, NULL, 16); + g_free(pResp); + } - switch (net_mode) { - case 0: - mode = TEL_NETWORK_MODE_2G; - break; - case 1: - mode = TEL_NETWORK_MODE_AUTO; - break; - case 2: - mode = TEL_NETWORK_MODE_3G; - break; - default: - err("Unsupported mode [%d]", net_mode); - goto END; + if ((pResp = g_slist_nth_data(tokens, 2))) { + pResp = util_removeQuotes(pResp); + ci = strtol(pResp, NULL, 16); + g_free(pResp); + } else { + dbg("No ci in +CREG"); + } + + if ((pResp = g_slist_nth_data(tokens, 3))) + AcT = atoi(pResp); + else + dbg("No AcT in +CREG"); } - result = TEL_NETWORK_RESULT_SUCCESS; + + + dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d", stat, lac, ci, AcT); + + cs_status = lookup_tbl_net_status[stat]; + tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, cs_status); + + // tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status); + tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status); + + act = lookup_tbl_access_technology[AcT]; + tcore_network_set_access_technology(o, act); + + if (stat == AT_CREG_STAT_REG_ROAM) { + tcore_network_set_roaming_state(o, TRUE); + }else if ((stat == AT_CREG_STAT_REG_DENIED) && (TRUE == tcore_network_get_roaming_state(o))) { + dbg("Ignore roaming set with REG_DENIED when previous state is REG_ROAM"); + }else { + tcore_network_set_roaming_state(o, FALSE); + } + + tcore_network_get_service_type(o, &service_type); + dbg("prev_service_type = 0x%x", service_type); + service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status); + dbg("new_service_type = 0x%x", service_type); + tcore_network_set_service_type(o, service_type); + + tcore_network_set_lac(o, lac); + tcore_network_set_cell_id(o, ci); + + net_lac_cell_info.lac = lac; + net_lac_cell_info.cell_id = ci; + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO, + sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info); + + regist_status.cs_domain_status = cs_status; + regist_status.ps_domain_status = ps_status; + regist_status.service_type = service_type; + regist_status.roaming_status = tcore_network_get_roaming_state(o); + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, + TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), ®ist_status); + + /* Get PLMN ID needed to application */ + if ((NETWORK_SERVICE_DOMAIN_STATUS_FULL == cs_status) || + NETWORK_SERVICE_DOMAIN_STATUS_FULL == ps_status) + get_serving_network(o, NULL); } else { - err("RESPONSE NOK"); - result = __imc_network_convert_cme_error_tel_network_result(at_resp); + dbg("Response NOK"); } -END: - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, &mode, resp_cb_data->cb_data); - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); - /* Free resource*/ - tcore_at_tok_free(tokens); +OUT: + if (NULL != tokens) + tcore_at_tok_free(tokens); + return TRUE; } -static void on_response_imc_network_get_preferred_plmn(TcorePending *p, - guint data_len, const void *data, void *user_data) +static gboolean on_event_network_icon_info(CoreObject *o, const void *event_info, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkPreferredPlmnList plmn_list = {0,}; - guint count = 0, total_lines = 0; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - dbg("Enter"); + struct tnoti_network_icon_info net_icon_info = {0}; + char *line = NULL; + char *rssiToken = NULL; + char *batteryToken = NULL; + GSList *tokens = NULL; + GSList *lines = NULL; - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + lines = (GSList *) event_info; + if (1 != g_slist_length(lines)) { + dbg("unsolicited msg but multiple line"); + goto OUT; + } + line = (char *) (lines->data); + dbg("+XCIEV Network Icon Info Noti Recieve"); + memset(&net_icon_info, 0, sizeof(struct tnoti_network_icon_info)); - if (at_resp && at_resp->success) { - GSList *tokens; - gchar *resp; - gchar *line; - gboolean gsm_act2 = FALSE, gsm_compact_act2 = FALSE; - gboolean utran_act2 = FALSE; + if (line != NULL) { + dbg("Response OK"); - if (!at_resp->lines) { - err("invalid response received"); - goto END; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) != 2) { + msg("invalid message"); + goto OUT; } - total_lines = g_slist_length(at_resp->lines); - if (total_lines < 1) { - msg("invalid message"); - goto END; + rssiToken = (char *) g_slist_nth_data(tokens, 0); + + if (strlen(rssiToken) > 0) { + net_icon_info.type = NETWORK_ICON_INFO_RSSI; + net_icon_info.rssi = atoi(g_slist_nth_data(tokens, 0)); + dbg("rssi level : %d", net_icon_info.rssi); } - dbg("RESPONSE OK"); - result = TEL_NETWORK_RESULT_SUCCESS; + batteryToken = (char *) g_slist_nth_data(tokens, 1); + if (strlen(batteryToken) > 0) { + net_icon_info.type = NETWORK_ICON_INFO_BATTERY; + net_icon_info.battery = atoi(g_slist_nth_data(tokens, 1)); + dbg("battery level : %d", net_icon_info.battery); + } - plmn_list.list = tcore_malloc0(sizeof(TelNetworkPreferredPlmnInfo) * total_lines); - plmn_list.count = 0; + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_ICON_INFO, + sizeof(struct tnoti_network_icon_info), &net_icon_info); + } else { + dbg("Response NOK"); + } - for (count = 0; count < total_lines; count++) { - /* Take each line response at a time & parse it */ - line = tcore_at_tok_nth(at_resp->lines, count); - tokens = tcore_at_tok_new(line); - /*Index */ - if ((resp = tcore_at_tok_nth(tokens, 0))) { - plmn_list.list[count].index = atoi(resp); - } +OUT: + if (NULL != tokens) + tcore_at_tok_free(tokens); - /* PLMN ID */ - if ((resp = tcore_at_tok_nth(tokens, 2))) { - plmn_list.list[count].plmn = tcore_at_tok_extract(resp); - } + return TRUE; +} - /*GSM_AcT1 */ - if ((resp = tcore_at_tok_nth(tokens, 3))) { - gsm_act2 = atoi(resp); - } +static gboolean on_event_network_ctzv_time_info(CoreObject *o, const void *event_info, void *user_data) +{ + struct tnoti_network_timeinfo net_time_info = {0}; + char *line = NULL; + GSList *tokens = NULL; + char *time = NULL; + char *time_zone = NULL; + GSList *lines = NULL; + char ptime_param[20] = {0}; + UserRequest *ur = NULL; + dbg("Enter : on_event_network_ctzv_time_info"); + + lines = (GSList *) event_info; + if (1 != g_slist_length(lines)) { + dbg("unsolicited msg but multiple line"); + goto OUT; + } + line = (char *) (lines->data); - /*GSM_Compact_AcT2 */ - if ((resp = tcore_at_tok_nth(tokens, 4))) { - gsm_compact_act2 = atoi(resp); - } +/* ++CTZV: ,