4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hayoon Ko <hayoon.ko@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.
26 #include <tzplatform_config.h>
29 #include <core_object.h>
33 #include <co_network.h>
39 #include "s_network.h"
41 #define ATMODEM_NETWORK_BASE_16 16
42 #define MCC_MNC_OPER_LIST_DB tzplatform_mkpath(TZ_SYS_DB, ".mcc_mnc_oper_list.db")
45 ATMDOEM_NETWORK_ACT_GSM, /* GSM */
46 ATMDOEM_NETWORK_ACT_GSM_COMPACT, /* GSM Compact */
47 ATMDOEM_NETWORK_ACT_UTRAN, /* UTRAN */
48 ATMDOEM_NETWORK_ACT_GSM_EGPRS, /* GSM w/EGPRS */
49 ATMDOEM_NETWORK_ACT_UTRAN_HSDPA, /* UTRAN w/HSDPA */
50 ATMDOEM_NETWORK_ACT_UTRAN_HSUPA, /* UTRAN w/HSUPA */
51 ATMDOEM_NETWORK_ACT_UTRAN_HSDPA_HSUPA, /* UTRAN w/HSDPA and HSUPA */
52 ATMDOEM_NETWORK_ACT_E_UTRAN, /* E-UTRAN */
55 #define AT_CREG_STAT_NOT_REG 0 /* not registered, MT is not currently searching a new operator to register to */
56 #define AT_CREG_STAT_REG_HOME 1 /* registered, home network */
57 #define AT_CREG_STAT_SEARCHING 2 /* not registered, but MT is currently searching a new operator to register to */
58 #define AT_CREG_STAT_REG_DENIED 3 /* registration denied */
59 #define AT_CREG_STAT_UNKNOWN 4 /* unknown */
60 #define AT_CREG_STAT_REG_ROAM 5 /* registered, roaming */
63 static unsigned int lookup_tbl_net_status[] = {
64 [AT_CREG_STAT_NOT_REG] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
65 [AT_CREG_STAT_REG_HOME] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
66 [AT_CREG_STAT_SEARCHING] = NETWORK_SERVICE_DOMAIN_STATUS_SEARCH,
67 [AT_CREG_STAT_REG_DENIED] = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY,
68 [AT_CREG_STAT_UNKNOWN] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
69 [AT_CREG_STAT_REG_ROAM] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
73 #define AT_COPS_MODE_AUTOMATIC 0 /* automatic (<oper> field is ignored) */
74 #define AT_COPS_MODE_MANUAL 1 /* manual (<oper> field shall be present, and <AcT> optionally) */
75 #define AT_COPS_MODE_DEREGISTER 2 /* deregister from network */
76 #define AT_COPS_MODE_SET_ONLY 3 /* set only <format> */
78 #define AT_COPS_FORMAT_LONG_ALPHANUMERIC 0 /* long format alphanumeric <oper> */
79 #define AT_COPS_FORMAT_SHORT_ALPHANUMERIC 1 /* short format alphanumeric <oper> */
80 #define AT_COPS_FORMAT_NUMERIC 2 /* numeric <oper> */
82 #define AT_COPS_ACT_GSM 0 /* GSM */
83 #define AT_COPS_ACT_GSM_COMPACT 1 /* GSM Compact */
84 #define AT_COPS_ACT_UTRAN 2 /* UTRAN */
85 #define AT_COPS_ACT_GSM_EGPRS 3 /* GSM w/EGPRS */
86 #define AT_COPS_ACT_UTRAN_HSDPA 4 /* UTRAN w/HSDPA */
87 #define AT_COPS_ACT_UTRAN_HSUPA 5 /* UTRAN w/HSUPA */
88 #define AT_COPS_ACT_UTRAN_HSDPA_HSUPA 6 /* UTRAN w/HSDPA and HSUPA */
89 #define AT_COPS_ACT_E_UTRAN 7 /* E-UTRAN */
90 #define AT_COPS_ACT_MAX 8
92 static unsigned int lookup_tbl_access_technology[] = {
93 [AT_COPS_ACT_GSM] = NETWORK_ACT_GSM,
94 [AT_COPS_ACT_GSM_COMPACT] = NETWORK_ACT_GSM,
95 [AT_COPS_ACT_UTRAN] = NETWORK_ACT_UTRAN,
96 [AT_COPS_ACT_GSM_EGPRS] = NETWORK_ACT_EGPRS,
97 [AT_COPS_ACT_UTRAN_HSDPA] = NETWORK_ACT_UTRAN,
98 [AT_COPS_ACT_UTRAN_HSUPA] = NETWORK_ACT_UTRAN,
99 [AT_COPS_ACT_UTRAN_HSDPA_HSUPA] = NETWORK_ACT_UTRAN,
100 [AT_COPS_ACT_E_UTRAN] = NETWORK_ACT_GSM_UTRAN,
103 static TReturn get_serving_network(CoreObject *o, UserRequest *ur);
105 static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *co_network)
110 char query[255] = {0, };
113 GHashTable *result = NULL, *row = NULL;
114 struct tcore_network_operator_info *noi = NULL;
117 s = tcore_plugin_ref_server(p);
118 strg = tcore_server_find_storage(s, "database");
120 handle = tcore_storage_create_handle(strg, MCC_MNC_OPER_LIST_DB);
122 err("fail to create database handle");
126 snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list");
128 tcore_storage_read_query_database(strg, handle, query, NULL, &result, 4);
130 g_hash_table_iter_init(&iter, result);
131 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
133 noi = g_try_malloc0(sizeof(struct tcore_network_operator_info));
135 err("Memory allocation failed!!");
138 snprintf(noi->mcc, 4, "%s", (const char *)(g_hash_table_lookup(row, "1")));
139 snprintf(noi->mnc, 4, "%s", (const char *)(g_hash_table_lookup(row, "2")));
140 snprintf(noi->name, 41, "%s", (const char *)(g_hash_table_lookup(row, "3")));
141 snprintf(noi->country, 4, "%s", (const char *)(g_hash_table_lookup(row, "0")));
143 tcore_network_operator_info_add(co_network, noi);
150 dbg("count = %d", count);
152 g_hash_table_destroy(result);
154 tcore_storage_remove_handle(strg, handle);
157 static enum telephony_network_service_domain_status __atmodem_network_map_stat(guint stat)
161 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
163 return NETWORK_SERVICE_DOMAIN_STATUS_FULL;
165 return NETWORK_SERVICE_DOMAIN_STATUS_SEARCH;
167 return NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY;
169 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
171 return NETWORK_SERVICE_DOMAIN_STATUS_FULL;
173 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
177 static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type,
178 int act, int cs_status, int ps_status)
180 enum telephony_network_service_type ret;
185 case NETWORK_ACT_NOT_SPECIFIED:
186 ret = NETWORK_SERVICE_TYPE_UNKNOWN;
189 case NETWORK_ACT_GSM:
190 if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE)
191 ret = NETWORK_SERVICE_TYPE_2_5G_EDGE;
193 ret = NETWORK_SERVICE_TYPE_2G;
196 case NETWORK_ACT_IS95A:
197 case NETWORK_ACT_IS95B:
198 ret = NETWORK_SERVICE_TYPE_2G;
201 case NETWORK_ACT_CDMA_1X:
202 case NETWORK_ACT_GPRS:
203 ret = NETWORK_SERVICE_TYPE_2_5G;
206 case NETWORK_ACT_EGPRS:
207 return NETWORK_SERVICE_TYPE_2_5G_EDGE;
209 case NETWORK_ACT_UMTS:
210 ret = NETWORK_SERVICE_TYPE_3G;
213 case NETWORK_ACT_EVDO_REV0:
214 case NETWORK_ACT_CDMA_1X_EVDO_REV0:
215 case NETWORK_ACT_EVDO_REVA:
216 case NETWORK_ACT_CDMA_1X_EVDO_REVA:
217 case NETWORK_ACT_EVDV:
218 ret = NETWORK_SERVICE_TYPE_3G;
223 dbg("Default Case executed.");
227 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO
228 && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) {
229 ret = NETWORK_SERVICE_TYPE_NO_SERVICE;
230 } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH
231 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) {
232 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL
233 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
236 ret = NETWORK_SERVICE_TYPE_SEARCH;
238 } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY
239 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) {
240 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL
241 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
244 ret = NETWORK_SERVICE_TYPE_EMERGENCY;
252 static gboolean on_notification_atmodem_cs_network_info(CoreObject *co_network,
253 const void *event_info, void *user_data)
255 GSList *lines = NULL;
258 dbg("Network notification - CS network info: [+CREG]");
260 lines = (GSList *)event_info;
261 if (g_slist_length(lines) != 1) {
262 err("+CREG unsolicited message expected to be Single line "
263 "but received multiple lines");
267 line = (char *) (lines->data);
269 struct tnoti_network_registration_status registration_status = {0, };
270 struct tnoti_network_location_cellinfo cell_info = {0, };
271 GSList *tokens = NULL;
273 guint stat = 0, act = 0, lac = 0, ci = 0;
278 * +CREG: <stat>[, <lac>, <ci>[, <AcT>]]
280 tokens = tcore_at_tok_new(line);
281 if (g_slist_length(tokens) < 1) {
282 err("Invalid notification message");
287 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
288 err("No <stat> in +CREG");
291 stat = __atmodem_network_map_stat(atoi(token_str)); /*TODO : Confirm*/
292 (void)tcore_network_set_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, stat);
295 if ((token_str = g_slist_nth_data(tokens, 1))) {
296 token_str = tcore_at_tok_extract((const char *)token_str);
297 if (token_str != NULL) {
298 lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
300 /* Update Location Area Code (lac) information */
301 (void)tcore_network_set_lac(co_network, lac);
307 dbg("No <lac> in +CREG");
308 (void)tcore_network_get_lac(co_network, &lac);
312 if ((token_str = g_slist_nth_data(tokens, 2))) {
313 token_str = tcore_at_tok_extract((const char *)token_str);
314 if (token_str != NULL) {
315 ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
316 /* Update Cell ID (ci) information */
317 (void)tcore_network_set_cell_id(co_network, ci);
323 dbg("No <ci> in +CREG");
324 (void)tcore_network_get_cell_id(co_network, &ci);
328 if ((token_str = g_slist_nth_data(tokens, 3))) {
329 gint idx = atoi(token_str);
330 if (idx >= 0 && idx < AT_COPS_ACT_MAX)
331 act = lookup_tbl_access_technology[idx];
333 act = NETWORK_ACT_UNKNOWN;
334 (void)tcore_network_set_access_technology(co_network, act);
336 dbg("No <AcT> in +CREG");
337 (void)tcore_network_get_access_technology(co_network, &act);
339 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d", stat, lac, ci, act);
341 /* Send Notification - Network (CS) Registration status */
342 registration_status.cs_domain_status = stat;
344 tcore_network_get_service_status(co_network,
345 TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ®istration_status.ps_domain_status);
347 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
349 TNOTI_NETWORK_REGISTRATION_STATUS,
350 sizeof(struct tnoti_network_registration_status), ®istration_status);
352 #if 0 /* TODO : Implement Roaming State */
354 case TEL_NETWORK_REG_STATUS_ROAMING:
355 roam_state = TRUE; /* no break */
356 case TEL_NETWORK_REG_STATUS_REGISTERED:
357 Fetch Network name - Internal request
358 (void)__atmodem_network_fetch_nw_name(co_network,
359 __on_response_atmodem_network_fetch_nw_name_internal, NULL);
366 tcore_network_set_roaming_state(co_network, roam_state);
369 /* Send Notification - Cell info */
370 cell_info.lac = (gint)lac;
371 cell_info.cell_id = (gint)ci;
373 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
375 TNOTI_NETWORK_LOCATION_CELLINFO,
376 sizeof(struct tnoti_network_location_cellinfo), &cell_info);
380 tcore_at_tok_free(tokens);
386 static gboolean on_notification_atmodem_ps_network_info(CoreObject *co_network,
387 const void *event_info, void *user_data)
389 GSList *lines = NULL;
392 dbg("Network notification - PS network info: [+CGREG]");
394 lines = (GSList *)event_info;
395 if (g_slist_length(lines) != 1) {
396 err("+CGREG unsolicited message expected to be Single line "
397 "but received multiple lines");
401 line = (char *) (lines->data);
403 struct tnoti_network_registration_status registration_status = {0, };
404 struct tnoti_network_location_cellinfo cell_info = {0, };
405 enum telephony_network_service_type service_type = 0;
406 GSList *tokens = NULL;
408 guint act = 0, lac = 0, ci = 0, rac = 0;
409 enum telephony_network_service_domain_status cs_status;
410 enum telephony_network_service_domain_status ps_status;
415 * +CGREG: <stat>[, <lac>, <ci>[, <AcT>, <rac>]]
417 tokens = tcore_at_tok_new(line);
418 if (g_slist_length(tokens) < 1) {
419 err("Invalid notification message");
424 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
425 err("No <stat> in +CGREG");
428 /* Emulator does not support ps doamin. so ps_status should be set no-service */
429 /* ps_status = __atmodem_network_map_stat(atoi(token_str)); */
430 ps_status = NETWORK_SERVICE_DOMAIN_STATUS_NO;
431 (void)tcore_network_set_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status);
434 if ((token_str = g_slist_nth_data(tokens, 1))) {
435 token_str = tcore_at_tok_extract((const char *)token_str);
436 if (token_str != NULL) {
437 lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
438 /* Update Location Area Code (lac) information */
439 (void)tcore_network_set_lac(co_network, lac);
445 dbg("No <lac> in +CGREG");
446 (void)tcore_network_get_lac(co_network, &lac);
450 if ((token_str = g_slist_nth_data(tokens, 2))) {
451 token_str = tcore_at_tok_extract((const char *)token_str);
452 if (token_str != NULL) {
453 ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
454 /* Update Cell ID (ci) information */
455 (void)tcore_network_set_cell_id(co_network, ci);
461 dbg("No <ci> in +CGREG");
462 (void)tcore_network_get_cell_id(co_network, &ci);
466 if ((token_str = g_slist_nth_data(tokens, 3))) {
467 gint idx = atoi(token_str);
468 if (idx >= 0 && idx < AT_COPS_ACT_MAX)
469 act = lookup_tbl_access_technology[idx];
471 act = NETWORK_ACT_UNKNOWN;
472 (void)tcore_network_set_access_technology(co_network, act);
474 dbg("No <AcT> in +CGREG");
475 (void)tcore_network_get_access_technology(co_network, &act);
479 if ((token_str = g_slist_nth_data(tokens, 4))) {
480 token_str = tcore_at_tok_extract((const char *)token_str);
481 if (token_str != NULL) {
482 rac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
483 /* Update Routing Area Code (rac) information */
484 (void)tcore_network_set_rac(co_network, rac);
490 err("No <rac> in +CGREG");
491 (void)tcore_network_get_rac(co_network, &rac);
493 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d <rac>: 0x%x", ps_status, lac, ci, act, rac);
495 /* Send Notification - Network (PS) Registration status */
496 registration_status.ps_domain_status = ps_status;
498 (void)tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
500 service_type = _get_service_type(service_type, act, cs_status, ps_status);
501 dbg("service_type = %d", service_type);
502 registration_status.service_type = service_type;
503 tcore_network_set_service_type(co_network, service_type);
505 (void)tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, ®istration_status.cs_domain_status);
507 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
509 TNOTI_NETWORK_REGISTRATION_STATUS,
510 sizeof(struct tnoti_network_registration_status), ®istration_status);
512 #if 0 /* TODO : Implement roaming state */
514 if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING)
517 tcore_network_set_roaming_state(co_network, roam_state);
520 /* Send Notification - Cell info */
522 cell_info.cell_id = ci;
524 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
526 TNOTI_NETWORK_LOCATION_CELLINFO,
527 sizeof(struct tnoti_network_location_cellinfo), &cell_info);
529 get_serving_network(co_network, NULL);
533 tcore_at_tok_free(tokens);
539 static gboolean on_notification_atmodem_network_rssi(CoreObject *co_network,
540 const void *event_info, void *user_data)
543 const gchar *line = NULL;
545 dbg("Network notification - Icon (rssi) info: [+CIEV]");
547 lines = (GSList *)event_info;
548 if (g_slist_length(lines) != 1) {
549 err("+CIEV unsolicited message expected to be "
550 "Single line but received multiple lines");
554 line = (const char *)lines->data;
559 static struct tnoti_network_icon_info net_icon_info = {0xff, 0, 0, 0};
561 tokens = tcore_at_tok_new(line);
564 descriptor = atoi(g_slist_nth_data(tokens, 0));
565 dbg("Descriptor: [%s]", (descriptor == 10 ? "RSSI"
566 : (descriptor == 15 ? "Battery" : "Unknown")));
569 value = atoi(g_slist_nth_data(tokens, 1));
571 switch (descriptor) {
573 dbg("RSSI Level: [%d]", value);
574 net_icon_info.type = NETWORK_ICON_INFO_RSSI;
575 net_icon_info.rssi = value;
577 /* Send Notification - Network Rssi */
578 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
580 TNOTI_NETWORK_ICON_INFO,
581 sizeof(struct tnoti_network_icon_info),
585 dbg("Battery Level: [%d]", value);
588 warn("Unknown descriptor: [%d]", descriptor);
593 tcore_at_tok_free(tokens);
599 static void __on_response_atmodem_network_registration(TcorePending *p,
600 int data_len, const void *data, void *user_data)
602 const struct tcore_at_response *at_resp = data;
605 if (at_resp && at_resp->success)
606 dbg("Network Registration - [OK]");
608 err("Network Registration - [NOK]");
611 static void __atmodem_network_register_to_network(CoreObject *co_network)
615 /* Send Request to modem */
616 ret = tcore_prepare_and_send_at_request(co_network,
620 __on_response_atmodem_network_registration, NULL,
621 on_send_at_request, NULL, 0, NULL, NULL);
622 dbg("Sending Network Registration request: [%s]",
623 (ret == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
626 static void on_sim_resp_hook_get_netname(UserRequest *ur, enum tcore_response_command command, unsigned int data_len,
627 const void *data, void *user_data)
629 const struct tresp_sim_read *resp = data;
630 CoreObject *o = user_data;
631 struct tnoti_network_registration_status regist_status;
632 struct tnoti_network_identity network_identity;
635 if (command == TRESP_SIM_GET_SPN) {
636 dbg("OK SPN GETTING!!");
637 dbg("resp->result = 0x%x", resp->result);
638 dbg("resp->data.spn.display_condition = 0x%x", resp->data.spn.display_condition);
639 dbg("resp->data.spn.spn = [%s]", resp->data.spn.spn);
641 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *)resp->data.spn.spn);
645 * 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
646 * 1 = display of registered PLMN name required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
647 * 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
648 * 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
650 if (resp->data.spn.display_condition & 0x01)
651 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
653 if ((resp->data.spn.display_condition & 0x02) == 0)
654 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
656 if ((resp->data.spn.display_condition & 0x03) == 0x01)
657 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
660 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, ®ist_status.cs_domain_status);
661 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ®ist_status.ps_domain_status);
662 tcore_network_get_service_type(o, ®ist_status.service_type);
663 regist_status.roaming_status = tcore_network_get_roaming_state(o);
665 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
666 TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), ®ist_status);
668 memset(&network_identity, 0x00, sizeof(struct tnoti_network_identity));
670 plmn = tcore_network_get_plmn(o);
672 dbg("plmn = %s", plmn);
673 g_strlcpy(network_identity.plmn, plmn, sizeof(network_identity.plmn));
676 g_strlcpy(network_identity.short_name, "SDK", sizeof(network_identity.short_name));
677 g_strlcpy(network_identity.full_name, "SDK", sizeof(network_identity.full_name));
679 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),
681 TNOTI_NETWORK_IDENTITY,
682 sizeof(struct tnoti_network_identity), &network_identity);
686 static enum tcore_hook_return on_hook_sim_init(Server *s, CoreObject *source,
687 enum tcore_notification_command command,
688 unsigned int data_len, void *data, void *user_data)
690 const struct tnoti_sim_status *sim = data;
691 UserRequest *ur = NULL;
693 if (sim->sim_status == SIM_STATUS_INIT_COMPLETED) {
694 CoreObject *co_network = (CoreObject *)user_data;
695 dbg("SIM Initialized!!! Attach to Network");
698 * TODO - Check for selection_mode
699 * Need to check if it is Manual or Automatic and based on
700 * that need to initiate Network Registration accordingly.
702 __atmodem_network_register_to_network(co_network);
704 /* Need to get SPN when sim initialization complete */
705 ur = tcore_user_request_new(NULL, NULL);
706 tcore_user_request_set_command(ur, TREQ_SIM_GET_SPN);
707 tcore_user_request_set_response_hook(ur, on_sim_resp_hook_get_netname, user_data);
708 tcore_object_dispatch_request(source, ur);
710 return TCORE_HOOK_RETURN_CONTINUE;
713 /* Network Responses */
714 static void on_response_network_search(TcorePending *p,
715 int data_len, const void *data, void *user_data)
717 const struct tcore_at_response *at_resp = data;
718 struct tresp_network_search nw_resp;
719 UserRequest *ur = NULL;
721 GSList *tokens = NULL;
725 memset(&nw_resp, 0x0, sizeof(struct tresp_network_search));
726 nw_resp.result = TCORE_RETURN_FAILURE;
728 if (at_resp && at_resp->success) {
730 GSList *net_token = NULL;
733 if (!at_resp->lines) {
734 err("invalid response received");
738 line = (char *) at_resp->lines->data;
739 tokens = tcore_at_tok_new(line);
740 nw_resp.list_count = g_slist_length(tokens);
741 if (nw_resp.list_count < 1) {
742 err("invalid message");
748 for (count = 0; count < nw_resp.list_count; count++) {
749 net_token = tcore_at_tok_new(g_slist_nth_data(tokens, count));
750 if (NULL == net_token)
754 resp = tcore_at_tok_nth(net_token, 0);
756 nw_resp.list[count].status = atoi(resp);
757 dbg("Status: [%d]", nw_resp.list[count].status);
761 if ((resp = tcore_at_tok_nth(net_token, 1))) {
764 name = tcore_at_tok_extract(resp);
765 dbg("name: [%s]", resp);
767 g_strlcpy(nw_resp.list[count].name, name, 41);
768 /* Emulator gives network name as # terminated string*/
769 if (nw_resp.list[count].name[5] == '#')
770 nw_resp.list[count].name[5] = '\0';
775 /* Short Alpha name */
776 if ((resp = tcore_at_tok_nth(net_token, 2))) {
778 dbg("Short Alpha name[%s]", resp);
779 plmn_list.network_list[count].network_identity.short_name =
780 tcore_at_tok_extract(resp); */
784 if ((resp = tcore_at_tok_nth(net_token, 3))) {
787 plmn = tcore_at_tok_extract(resp);
788 dbg("PLMN ID: [%s]", resp);
790 g_strlcpy(nw_resp.list[count].plmn, plmn, 6);
795 /* Parse Access Technology */
796 if ((resp = tcore_at_tok_nth(tokens, 4))) {
797 if (strlen(resp) > 0) {
798 gint act = atoi(resp);
799 dbg("AcT: [%d]", act);
800 if (act >= 0 && act < AT_COPS_ACT_MAX)
801 nw_resp.list[count].act = lookup_tbl_access_technology[act];
803 nw_resp.list[count].act = NETWORK_ACT_UNKNOWN;
806 nw_resp.list[count].act = NETWORK_ACT_UMTS;
809 dbg("[%d] Status: [%d] name: [%s] PLMN: [%s] AcT: [%d]",
811 nw_resp.list[count].status,
812 nw_resp.list[count].name,
813 nw_resp.list[count].plmn,
814 nw_resp.list[count].act);
816 tcore_at_tok_free(net_token);
819 nw_resp.result = TCORE_RETURN_SUCCESS;
823 err("CME Error[%s]", (char *)(at_resp->lines ? at_resp->lines->data : "Unknown"));
826 ur = tcore_pending_ref_user_request(p);
828 tcore_user_request_send_response(ur,
829 TRESP_NETWORK_SEARCH,
830 sizeof(struct tresp_network_search), &nw_resp);
836 dbg("Network search : [%s]",
837 (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
839 tcore_at_tok_free(tokens);
842 static void on_response_network_get_plmn_selection_mode(TcorePending *p,
843 int data_len, const void *data, void *user_data)
845 const struct tcore_at_response *at_resp = data;
846 struct tresp_network_get_plmn_selection_mode nw_resp = {0, };
847 UserRequest *ur = NULL;
848 GSList *tokens = NULL;
852 nw_resp.result = TCORE_RETURN_FAILURE; /* TODO - CME Error mapping required. */
854 if (at_resp && at_resp->success) {
858 if (!at_resp->lines) {
859 err("invalid response received");
863 line = (char *) at_resp->lines->data;
864 tokens = tcore_at_tok_new(line);
865 if (g_slist_length(tokens) < 1) {
866 msg("invalid message");
871 mode = atoi(tcore_at_tok_nth(tokens, 0));
873 nw_resp.mode = NETWORK_SELECT_MODE_AUTOMATIC;
875 nw_resp.mode = NETWORK_SELECT_MODE_MANUAL;
877 dbg("selection mode[%d]", nw_resp.mode);
878 nw_resp.result = TCORE_RETURN_SUCCESS;
883 ur = tcore_pending_ref_user_request(p);
885 tcore_user_request_send_response(ur,
886 TRESP_NETWORK_GET_PLMN_SELECTION_MODE,
887 sizeof(struct tresp_network_get_plmn_selection_mode), &nw_resp);
893 dbg("Get selection mode : [%s]",
894 (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
897 tcore_at_tok_free(tokens);
900 static void on_response_network_set_plmn_selection_mode(TcorePending *p,
901 int data_len, const void *data, void *user_data)
903 const struct tcore_at_response *at_resp = data;
904 struct tresp_network_set_plmn_selection_mode nw_resp;
905 UserRequest *ur = NULL;
910 if (at_resp->success) {
912 nw_resp.result = TCORE_RETURN_SUCCESS;
915 if (at_resp->lines) {
916 err("CME Error[%s]", (char *)at_resp->lines->data);
917 nw_resp.result = TCORE_RETURN_FAILURE;
921 err("Response: [NOK]");
924 ur = tcore_pending_ref_user_request(p);
926 tcore_user_request_send_response(ur,
927 TRESP_NETWORK_SET_PLMN_SELECTION_MODE,
928 sizeof(struct tresp_network_set_plmn_selection_mode), &nw_resp);
934 static void on_response_network_get_serving_network(TcorePending *p,
935 int data_len, const void *data, void *user_data)
937 const struct tcore_at_response *at_resp = data;
938 struct tresp_network_get_serving_network nw_resp = {0, };
939 enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
940 UserRequest *ur = NULL;
941 GSList *tokens = NULL;
943 CoreObject *co_network = tcore_pending_ref_core_object(p);
948 if (at_resp && at_resp->success) {
950 int num_lines, count;
951 char *local_data = NULL;
953 if (!at_resp->lines) {
954 err("invalid response received");
955 nw_resp.result = TCORE_RETURN_FAILURE;
960 nw_resp.result = TCORE_RETURN_SUCCESS;
962 num_lines = g_slist_length(at_resp->lines);
963 dbg("number of lines: %d", num_lines);
965 for (count = 0; count < num_lines; count++) {
966 line = g_slist_nth_data(at_resp->lines, count);
967 tokens = tcore_at_tok_new(line);
969 if ((local_data = tcore_at_tok_nth(tokens, 0)))
970 dbg("mode : %s", local_data);
973 if ((local_data = tcore_at_tok_nth(tokens, 1)))
974 dbg("format : %s", local_data);
977 if ((plmn = tcore_at_tok_nth(tokens, 2))) {
978 dbg("plmn : %s", plmn);
979 g_strlcpy(nw_resp.plmn, plmn, 6);
980 tcore_network_set_plmn(co_network, nw_resp.plmn);
981 if (!g_strcmp0(nw_resp.plmn, "11111")) {
982 /* In case of emulator, need to show "SDK" on indicator instead of "11111" */
983 tcore_network_set_network_name(co_network, TCORE_NETWORK_NAME_TYPE_FULL, "SDK");
988 if ((local_data = tcore_at_tok_nth(tokens, 3))) {
989 gint idx = atoi(local_data);
990 dbg("AcT : %s", local_data);
991 if (idx >= 0 && idx < AT_COPS_ACT_MAX)
992 act = lookup_tbl_access_technology[idx];
994 act = NETWORK_ACT_UNKNOWN;
998 (void)tcore_network_get_lac(co_network, &lac);
999 dbg("lac : %x", lac);
1001 nw_resp.gsm.lac = lac;
1003 tcore_at_tok_free(tokens);
1007 ur = tcore_pending_ref_user_request(p);
1009 tcore_user_request_send_response(ur,
1010 TRESP_NETWORK_GET_SERVING_NETWORK,
1011 sizeof(struct tresp_network_get_serving_network), &nw_resp);
1013 struct tnoti_network_change network_change;
1015 memset(&network_change, 0, sizeof(struct tnoti_network_change));
1016 memcpy(network_change.plmn, nw_resp.plmn, 6);
1017 network_change.act = act;
1018 network_change.gsm.lac = lac;
1020 tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(p)),
1021 tcore_pending_ref_core_object(p),
1022 TNOTI_NETWORK_CHANGE,
1023 sizeof(struct tnoti_network_change), &network_change);
1027 dbg("Get serving network : [%s]",
1028 (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
1032 static TReturn search_network(CoreObject *co_network, UserRequest *ur)
1034 TReturn ret = TCORE_RETURN_FAILURE;
1038 /* Send Request to modem */
1039 ret = tcore_prepare_and_send_at_request(co_network,
1040 "AT+COPS=?", "+COPS",
1041 TCORE_AT_SINGLELINE,
1043 on_response_network_search, NULL,
1044 on_send_at_request, NULL,
1046 dbg("ret: [0x%x]", ret);
1052 static TReturn set_plmn_selection_mode(CoreObject *co_network, UserRequest *ur)
1055 struct treq_network_set_plmn_selection_mode *mode_info = NULL;
1056 TReturn ret = TCORE_RETURN_FAILURE;
1060 mode_info = (struct treq_network_set_plmn_selection_mode *)tcore_user_request_ref_data(ur, 0);
1062 if (mode_info->mode == NETWORK_SELECT_MODE_AUTOMATIC) {
1063 at_cmd = g_strdup_printf("AT+COPS=0");
1064 dbg(" Mode - Automatic: -- %s", at_cmd);
1068 switch (mode_info->act) {
1069 case NETWORK_ACT_GSM:
1070 case NETWORK_ACT_GPRS:
1071 case NETWORK_ACT_EGPRS:
1075 case NETWORK_ACT_UMTS:
1076 case NETWORK_ACT_GSM_UTRAN:
1081 err("Unsupported AcT: [%d]", mode_info->act);
1084 at_cmd = g_strdup_printf("AT+COPS=1, 2, \"%s\", %d", mode_info->plmn, act);
1087 /* Send Request to modem */
1088 ret = tcore_prepare_and_send_at_request(co_network, at_cmd, NULL,
1091 on_response_network_set_plmn_selection_mode, NULL,
1092 on_send_at_request, NULL, 0, NULL, NULL);
1093 dbg("ret: [0x%x]", ret);
1095 /* Free resources */
1101 static TReturn get_plmn_selection_mode(CoreObject *co_network, UserRequest *ur)
1103 TReturn ret = TCORE_RETURN_FAILURE;
1107 /* Send Request to modem */
1108 ret = tcore_prepare_and_send_at_request(co_network,
1109 "AT+COPS?", "+COPS",
1110 TCORE_AT_SINGLELINE,
1112 on_response_network_get_plmn_selection_mode, NULL,
1113 on_send_at_request, NULL, 0, NULL, NULL);
1114 dbg("ret: [0x%x]", ret);
1119 static TReturn get_serving_network(CoreObject *co_network, UserRequest *ur)
1121 TReturn ret = TCORE_RETURN_FAILURE;
1125 /* Send Request to modem */
1126 ret = tcore_prepare_and_send_at_request(co_network,
1127 "AT+COPS?", "+COPS",
1128 TCORE_AT_SINGLELINE,
1130 on_response_network_get_serving_network, NULL,
1131 on_send_at_request, NULL, 0, NULL, NULL);
1132 dbg("ret: [0x%x]", ret);
1137 static TReturn get_default_subscription(CoreObject *co, UserRequest *ur)
1139 struct tresp_network_get_default_subs resp_data = {0, };
1140 TReturn ret = TCORE_RETURN_FAILURE;
1142 Storage *strg = NULL;
1143 TcorePlugin *plugin = tcore_object_ref_plugin(co);
1147 server = tcore_plugin_ref_server(plugin);
1148 strg = tcore_server_find_storage(server, "vconf");
1150 /* VCONFKEY is aligned to req_data->current_network type */
1151 resp_data.default_subs = tcore_storage_get_int(strg,
1152 STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_SERVICE_INT);
1154 resp_data.result = TCORE_RETURN_SUCCESS;
1157 ret = tcore_user_request_send_response(ur,
1158 TRESP_NETWORK_GET_DEFAULT_SUBSCRIPTION,
1159 sizeof(struct tresp_network_get_default_subs), &resp_data);
1161 dbg("ret: [0x%x]", ret);
1165 static TReturn get_default_data_subscription(CoreObject *co, UserRequest *ur)
1167 struct tresp_network_get_default_data_subs resp = {0, };
1169 Storage *strg = NULL;
1170 TcorePlugin *plugin = tcore_object_ref_plugin(co);
1175 server = tcore_plugin_ref_server(plugin);
1176 strg = tcore_server_find_storage(server, "vconf");
1178 resp.default_subs = tcore_storage_get_int(strg, STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_DATA_SERVICE_INT);
1179 dbg("Defualt data Subscription: [%d]", resp.default_subs);
1181 resp.result = TCORE_RETURN_SUCCESS;
1183 ret = tcore_user_request_send_response(ur,
1184 TRESP_NETWORK_GET_DEFAULT_DATA_SUBSCRIPTION,
1185 sizeof(struct tresp_network_get_default_data_subs), &resp);
1186 if (TCORE_RETURN_SUCCESS == ret)
1187 tcore_user_request_unref(ur);
1192 /** Network operations */
1193 static struct tcore_network_operations network_ops = {
1194 .search = search_network,
1195 .set_plmn_selection_mode = set_plmn_selection_mode,
1196 .get_plmn_selection_mode = get_plmn_selection_mode,
1197 .set_service_domain = NULL,
1198 .get_service_domain = NULL,
1201 .set_preferred_plmn = NULL,
1202 .get_preferred_plmn = NULL,
1205 .set_power_on_attach = NULL,
1206 .get_power_on_attach = NULL,
1207 .set_cancel_manual_search = NULL,
1208 .get_serving_network = get_serving_network,
1209 .get_default_subscription = get_default_subscription,
1210 .get_default_data_subscription = get_default_data_subscription,
1213 gboolean s_network_init(TcorePlugin *p, TcoreHal *h)
1215 CoreObject *co_network;
1217 co_network = tcore_network_new(p, "umts_network", &network_ops, h);
1219 err("Core object is NULL");
1224 tcore_object_add_callback(co_network,
1226 on_notification_atmodem_cs_network_info, NULL);
1227 tcore_object_add_callback(co_network,
1229 on_notification_atmodem_ps_network_info, NULL);
1230 tcore_object_add_callback(co_network,
1232 on_notification_atmodem_network_rssi, NULL);
1234 /* Add notification hook */
1235 tcore_server_add_notification_hook(tcore_plugin_ref_server(p),
1237 on_hook_sim_init, co_network);
1239 _insert_mcc_mnc_oper_list(p, co_network);
1244 void s_network_exit(TcorePlugin *p)
1246 CoreObject *co_network;
1249 err("Plugin is NULL");
1253 co_network = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_NETWORK);
1255 tcore_network_free(co_network);