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 gboolean 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 result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
129 (GDestroyNotify) g_hash_table_destroy);
131 tcore_storage_read_query_database(strg, handle, query, NULL, result, 4);
133 g_hash_table_iter_init(&iter, result);
134 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
136 noi = g_try_malloc0(sizeof(struct tcore_network_operator_info));
138 err("Memory allocation failed!!");
141 snprintf(noi->mcc, 4, "%s", (const char *)(g_hash_table_lookup(row, "1")));
142 snprintf(noi->mnc, 4, "%s", (const char *)(g_hash_table_lookup(row, "2")));
143 snprintf(noi->name, 41, "%s", (const char *)(g_hash_table_lookup(row, "3")));
144 snprintf(noi->country, 4, "%s", (const char *)(g_hash_table_lookup(row, "0")));
146 tcore_network_operator_info_add(co_network, noi);
153 dbg("count = %d", count);
155 g_hash_table_destroy(result);
157 tcore_storage_remove_handle(strg, handle);
160 static enum telephony_network_service_domain_status __atmodem_network_map_stat(guint stat)
164 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
166 return NETWORK_SERVICE_DOMAIN_STATUS_FULL;
168 return NETWORK_SERVICE_DOMAIN_STATUS_SEARCH;
170 return NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY;
172 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
174 return NETWORK_SERVICE_DOMAIN_STATUS_FULL;
176 return NETWORK_SERVICE_DOMAIN_STATUS_NO;
180 static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type,
181 int act, int cs_status, int ps_status)
183 enum telephony_network_service_type ret;
188 case NETWORK_ACT_NOT_SPECIFIED:
189 ret = NETWORK_SERVICE_TYPE_UNKNOWN;
192 case NETWORK_ACT_GSM:
193 if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE)
194 ret = NETWORK_SERVICE_TYPE_2_5G_EDGE;
196 ret = NETWORK_SERVICE_TYPE_2G;
199 case NETWORK_ACT_IS95A:
200 case NETWORK_ACT_IS95B:
201 ret = NETWORK_SERVICE_TYPE_2G;
204 case NETWORK_ACT_CDMA_1X:
205 case NETWORK_ACT_GPRS:
206 ret = NETWORK_SERVICE_TYPE_2_5G;
209 case NETWORK_ACT_EGPRS:
210 return NETWORK_SERVICE_TYPE_2_5G_EDGE;
212 case NETWORK_ACT_UMTS:
213 ret = NETWORK_SERVICE_TYPE_3G;
216 case NETWORK_ACT_EVDO_REV0:
217 case NETWORK_ACT_CDMA_1X_EVDO_REV0:
218 case NETWORK_ACT_EVDO_REVA:
219 case NETWORK_ACT_CDMA_1X_EVDO_REVA:
220 case NETWORK_ACT_EVDV:
221 ret = NETWORK_SERVICE_TYPE_3G;
226 dbg("Default Case executed.");
230 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO
231 && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) {
232 ret = NETWORK_SERVICE_TYPE_NO_SERVICE;
233 } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH
234 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) {
235 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL
236 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
239 ret = NETWORK_SERVICE_TYPE_SEARCH;
241 } else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY
242 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) {
243 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL
244 || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
247 ret = NETWORK_SERVICE_TYPE_EMERGENCY;
255 static gboolean on_notification_atmodem_cs_network_info(CoreObject *co_network,
256 const void *event_info, void *user_data)
258 GSList *lines = NULL;
261 dbg("Network notification - CS network info: [+CREG]");
263 lines = (GSList *)event_info;
264 if (g_slist_length(lines) != 1) {
265 err("+CREG unsolicited message expected to be Single line "
266 "but received multiple lines");
270 line = (char *) (lines->data);
272 struct tnoti_network_registration_status registration_status = {0, };
273 struct tnoti_network_location_cellinfo cell_info = {0, };
274 GSList *tokens = NULL;
276 guint stat = 0, act = 0, lac = 0, ci = 0;
281 * +CREG: <stat>[, <lac>, <ci>[, <AcT>]]
283 tokens = tcore_at_tok_new(line);
284 if (g_slist_length(tokens) < 1) {
285 err("Invalid notification message");
290 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
291 err("No <stat> in +CREG");
294 stat = __atmodem_network_map_stat(atoi(token_str)); /*TODO : Confirm*/
295 (void)tcore_network_set_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, stat);
298 if ((token_str = g_slist_nth_data(tokens, 1))) {
299 token_str = tcore_at_tok_extract((const char *)token_str);
300 if (token_str != NULL) {
301 lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
303 /* Update Location Area Code (lac) information */
304 (void)tcore_network_set_lac(co_network, lac);
310 dbg("No <lac> in +CREG");
311 (void)tcore_network_get_lac(co_network, &lac);
315 if ((token_str = g_slist_nth_data(tokens, 2))) {
316 token_str = tcore_at_tok_extract((const char *)token_str);
317 if (token_str != NULL) {
318 ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
319 /* Update Cell ID (ci) information */
320 (void)tcore_network_set_cell_id(co_network, ci);
326 dbg("No <ci> in +CREG");
327 (void)tcore_network_get_cell_id(co_network, &ci);
331 if ((token_str = g_slist_nth_data(tokens, 3))) {
332 gint idx = atoi(token_str);
333 if (idx >= 0 && idx < AT_COPS_ACT_MAX)
334 act = lookup_tbl_access_technology[idx];
336 act = NETWORK_ACT_UNKNOWN;
337 (void)tcore_network_set_access_technology(co_network, act);
339 dbg("No <AcT> in +CREG");
340 (void)tcore_network_get_access_technology(co_network, &act);
342 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d", stat, lac, ci, act);
344 /* Send Notification - Network (CS) Registration status */
345 registration_status.cs_domain_status = stat;
347 tcore_network_get_service_status(co_network,
348 TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ®istration_status.ps_domain_status);
350 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
352 TNOTI_NETWORK_REGISTRATION_STATUS,
353 sizeof(struct tnoti_network_registration_status), ®istration_status);
355 #if 0 /* TODO : Implement Roaming State */
357 case TEL_NETWORK_REG_STATUS_ROAMING:
358 roam_state = TRUE; /* no break */
359 case TEL_NETWORK_REG_STATUS_REGISTERED:
360 Fetch Network name - Internal request
361 (void)__atmodem_network_fetch_nw_name(co_network,
362 __on_response_atmodem_network_fetch_nw_name_internal, NULL);
369 tcore_network_set_roaming_state(co_network, roam_state);
372 /* Send Notification - Cell info */
373 cell_info.lac = (gint)lac;
374 cell_info.cell_id = (gint)ci;
376 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
378 TNOTI_NETWORK_LOCATION_CELLINFO,
379 sizeof(struct tnoti_network_location_cellinfo), &cell_info);
383 tcore_at_tok_free(tokens);
389 static gboolean on_notification_atmodem_ps_network_info(CoreObject *co_network,
390 const void *event_info, void *user_data)
392 GSList *lines = NULL;
395 dbg("Network notification - PS network info: [+CGREG]");
397 lines = (GSList *)event_info;
398 if (g_slist_length(lines) != 1) {
399 err("+CGREG unsolicited message expected to be Single line "
400 "but received multiple lines");
404 line = (char *) (lines->data);
406 struct tnoti_network_registration_status registration_status = {0, };
407 struct tnoti_network_location_cellinfo cell_info = {0, };
408 enum telephony_network_service_type service_type = 0;
409 GSList *tokens = NULL;
411 guint act = 0, lac = 0, ci = 0, rac = 0;
412 enum telephony_network_service_domain_status cs_status;
413 enum telephony_network_service_domain_status ps_status;
418 * +CGREG: <stat>[, <lac>, <ci>[, <AcT>, <rac>]]
420 tokens = tcore_at_tok_new(line);
421 if (g_slist_length(tokens) < 1) {
422 err("Invalid notification message");
427 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
428 err("No <stat> in +CGREG");
431 /* Emulator does not support ps doamin. so ps_status should be set no-service */
432 /* ps_status = __atmodem_network_map_stat(atoi(token_str)); */
433 ps_status = NETWORK_SERVICE_DOMAIN_STATUS_NO;
434 (void)tcore_network_set_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status);
437 if ((token_str = g_slist_nth_data(tokens, 1))) {
438 token_str = tcore_at_tok_extract((const char *)token_str);
439 if (token_str != NULL) {
440 lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
441 /* Update Location Area Code (lac) information */
442 (void)tcore_network_set_lac(co_network, lac);
448 dbg("No <lac> in +CGREG");
449 (void)tcore_network_get_lac(co_network, &lac);
453 if ((token_str = g_slist_nth_data(tokens, 2))) {
454 token_str = tcore_at_tok_extract((const char *)token_str);
455 if (token_str != NULL) {
456 ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
457 /* Update Cell ID (ci) information */
458 (void)tcore_network_set_cell_id(co_network, ci);
464 dbg("No <ci> in +CGREG");
465 (void)tcore_network_get_cell_id(co_network, &ci);
469 if ((token_str = g_slist_nth_data(tokens, 3))) {
470 gint idx = atoi(token_str);
471 if (idx >= 0 && idx < AT_COPS_ACT_MAX)
472 act = lookup_tbl_access_technology[idx];
474 act = NETWORK_ACT_UNKNOWN;
475 (void)tcore_network_set_access_technology(co_network, act);
477 dbg("No <AcT> in +CGREG");
478 (void)tcore_network_get_access_technology(co_network, &act);
482 if ((token_str = g_slist_nth_data(tokens, 4))) {
483 token_str = tcore_at_tok_extract((const char *)token_str);
484 if (token_str != NULL) {
485 rac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
486 /* Update Routing Area Code (rac) information */
487 (void)tcore_network_set_rac(co_network, rac);
493 err("No <rac> in +CGREG");
494 (void)tcore_network_get_rac(co_network, &rac);
496 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d <rac>: 0x%x", ps_status, lac, ci, act, rac);
498 /* Send Notification - Network (PS) Registration status */
499 registration_status.ps_domain_status = ps_status;
501 (void)tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
503 service_type = _get_service_type(service_type, act, cs_status, ps_status);
504 dbg("service_type = %d", service_type);
505 registration_status.service_type = service_type;
506 tcore_network_set_service_type(co_network, service_type);
508 (void)tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, ®istration_status.cs_domain_status);
510 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
512 TNOTI_NETWORK_REGISTRATION_STATUS,
513 sizeof(struct tnoti_network_registration_status), ®istration_status);
515 #if 0 /* TODO : Implement roaming state */
517 if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING)
520 tcore_network_set_roaming_state(co_network, roam_state);
523 /* Send Notification - Cell info */
525 cell_info.cell_id = ci;
527 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
529 TNOTI_NETWORK_LOCATION_CELLINFO,
530 sizeof(struct tnoti_network_location_cellinfo), &cell_info);
532 get_serving_network(co_network, NULL);
536 tcore_at_tok_free(tokens);
542 static gboolean on_notification_atmodem_network_rssi(CoreObject *co_network,
543 const void *event_info, void *user_data)
546 const gchar *line = NULL;
548 dbg("Network notification - Icon (rssi) info: [+CIEV]");
550 lines = (GSList *)event_info;
551 if (g_slist_length(lines) != 1) {
552 err("+CIEV unsolicited message expected to be "
553 "Single line but received multiple lines");
557 line = (const char *)lines->data;
562 static struct tnoti_network_icon_info net_icon_info = {0xff, 0, 0, 0};
564 tokens = tcore_at_tok_new(line);
567 descriptor = atoi(g_slist_nth_data(tokens, 0));
568 dbg("Descriptor: [%s]", (descriptor == 10 ? "RSSI"
569 : (descriptor == 15 ? "Battery" : "Unknown")));
572 value = atoi(g_slist_nth_data(tokens, 1));
574 switch (descriptor) {
576 dbg("RSSI Level: [%d]", value);
577 net_icon_info.type = NETWORK_ICON_INFO_RSSI;
578 net_icon_info.rssi = value;
580 /* Send Notification - Network Rssi */
581 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
583 TNOTI_NETWORK_ICON_INFO,
584 sizeof(struct tnoti_network_icon_info),
588 dbg("Battery Level: [%d]", value);
591 warn("Unknown descriptor: [%d]", descriptor);
596 tcore_at_tok_free(tokens);
602 static void __on_response_atmodem_network_registration(TcorePending *p,
603 int data_len, const void *data, void *user_data)
605 const struct tcore_at_response *at_resp = data;
608 if (at_resp && at_resp->success)
609 dbg("Network Registration - [OK]");
611 err("Network Registration - [NOK]");
614 static void __atmodem_network_register_to_network(CoreObject *co_network)
618 /* Send Request to modem */
619 ret = tcore_prepare_and_send_at_request(co_network,
623 __on_response_atmodem_network_registration, NULL,
624 on_send_at_request, NULL, 0, NULL, NULL);
625 dbg("Sending Network Registration request: [%s]",
626 (ret == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
629 static void on_sim_resp_hook_get_netname(UserRequest *ur, enum tcore_response_command command, unsigned int data_len,
630 const void *data, void *user_data)
632 const struct tresp_sim_read *resp = data;
633 CoreObject *o = user_data;
634 struct tnoti_network_registration_status regist_status;
635 struct tnoti_network_identity network_identity;
638 if (command == TRESP_SIM_GET_SPN) {
639 dbg("OK SPN GETTING!!");
640 dbg("resp->result = 0x%x", resp->result);
641 dbg("resp->data.spn.display_condition = 0x%x", resp->data.spn.display_condition);
642 dbg("resp->data.spn.spn = [%s]", resp->data.spn.spn);
644 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *)resp->data.spn.spn);
648 * 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
649 * 1 = display of registered PLMN name required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
650 * 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
651 * 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
653 if (resp->data.spn.display_condition & 0x01)
654 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
656 if ((resp->data.spn.display_condition & 0x02) == 0)
657 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
659 if ((resp->data.spn.display_condition & 0x03) == 0x01)
660 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
663 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, ®ist_status.cs_domain_status);
664 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ®ist_status.ps_domain_status);
665 tcore_network_get_service_type(o, ®ist_status.service_type);
666 regist_status.roaming_status = tcore_network_get_roaming_state(o);
668 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
669 TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), ®ist_status);
671 memset(&network_identity, 0x00, sizeof(struct tnoti_network_identity));
673 plmn = tcore_network_get_plmn(o);
675 dbg("plmn = %s", plmn);
676 g_strlcpy(network_identity.plmn, plmn, sizeof(network_identity.plmn));
679 g_strlcpy(network_identity.short_name, "SDK", sizeof(network_identity.short_name));
680 g_strlcpy(network_identity.full_name, "SDK", sizeof(network_identity.full_name));
682 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),
684 TNOTI_NETWORK_IDENTITY,
685 sizeof(struct tnoti_network_identity), &network_identity);
689 static enum tcore_hook_return on_hook_sim_init(Server *s, CoreObject *source,
690 enum tcore_notification_command command,
691 unsigned int data_len, void *data, void *user_data)
693 const struct tnoti_sim_status *sim = data;
694 UserRequest *ur = NULL;
696 if (sim->sim_status == SIM_STATUS_INIT_COMPLETED) {
697 CoreObject *co_network = (CoreObject *)user_data;
698 dbg("SIM Initialized!!! Attach to Network");
701 * TODO - Check for selection_mode
702 * Need to check if it is Manual or Automatic and based on
703 * that need to initiate Network Registration accordingly.
705 __atmodem_network_register_to_network(co_network);
707 /* Need to get SPN when sim initialization complete */
708 ur = tcore_user_request_new(NULL, NULL);
709 tcore_user_request_set_command(ur, TREQ_SIM_GET_SPN);
710 tcore_user_request_set_response_hook(ur, on_sim_resp_hook_get_netname, user_data);
711 tcore_object_dispatch_request(source, ur);
713 return TCORE_HOOK_RETURN_CONTINUE;
716 /* Network Responses */
717 static void on_response_network_search(TcorePending *p,
718 int data_len, const void *data, void *user_data)
720 const struct tcore_at_response *at_resp = data;
721 struct tresp_network_search nw_resp;
722 UserRequest *ur = NULL;
724 GSList *tokens = NULL;
728 memset(&nw_resp, 0x0, sizeof(struct tresp_network_search));
729 nw_resp.result = TCORE_RETURN_FAILURE;
731 if (at_resp && at_resp->success) {
733 GSList *net_token = NULL;
736 if (!at_resp->lines) {
737 err("invalid response received");
741 line = (char *) at_resp->lines->data;
742 tokens = tcore_at_tok_new(line);
743 nw_resp.list_count = g_slist_length(tokens);
744 if (nw_resp.list_count < 1) {
745 err("invalid message");
751 for (count = 0; count < nw_resp.list_count; count++) {
752 net_token = tcore_at_tok_new(g_slist_nth_data(tokens, count));
753 if (NULL == net_token)
757 resp = tcore_at_tok_nth(net_token, 0);
759 nw_resp.list[count].status = atoi(resp);
760 dbg("Status: [%d]", nw_resp.list[count].status);
764 if ((resp = tcore_at_tok_nth(net_token, 1))) {
767 name = tcore_at_tok_extract(resp);
768 dbg("name: [%s]", resp);
770 g_strlcpy(nw_resp.list[count].name, name, 41);
771 /* Emulator gives network name as # terminated string*/
772 if (nw_resp.list[count].name[5] == '#')
773 nw_resp.list[count].name[5] = '\0';
778 /* Short Alpha name */
779 if ((resp = tcore_at_tok_nth(net_token, 2))) {
781 dbg("Short Alpha name[%s]", resp);
782 plmn_list.network_list[count].network_identity.short_name =
783 tcore_at_tok_extract(resp); */
787 if ((resp = tcore_at_tok_nth(net_token, 3))) {
790 plmn = tcore_at_tok_extract(resp);
791 dbg("PLMN ID: [%s]", resp);
793 g_strlcpy(nw_resp.list[count].plmn, plmn, 6);
798 /* Parse Access Technology */
799 if ((resp = tcore_at_tok_nth(tokens, 4))) {
800 if (strlen(resp) > 0) {
801 gint act = atoi(resp);
802 dbg("AcT: [%d]", act);
803 if (act >= 0 && act < AT_COPS_ACT_MAX)
804 nw_resp.list[count].act = lookup_tbl_access_technology[act];
806 nw_resp.list[count].act = NETWORK_ACT_UNKNOWN;
809 nw_resp.list[count].act = NETWORK_ACT_UMTS;
812 dbg("[%d] Status: [%d] name: [%s] PLMN: [%s] AcT: [%d]",
814 nw_resp.list[count].status,
815 nw_resp.list[count].name,
816 nw_resp.list[count].plmn,
817 nw_resp.list[count].act);
819 tcore_at_tok_free(net_token);
822 nw_resp.result = TCORE_RETURN_SUCCESS;
826 err("CME Error[%s]", (char *)(at_resp->lines ? at_resp->lines->data : "Unknown"));
829 ur = tcore_pending_ref_user_request(p);
831 tcore_user_request_send_response(ur,
832 TRESP_NETWORK_SEARCH,
833 sizeof(struct tresp_network_search), &nw_resp);
839 dbg("Network search : [%s]",
840 (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
842 tcore_at_tok_free(tokens);
845 static void on_response_network_get_plmn_selection_mode(TcorePending *p,
846 int data_len, const void *data, void *user_data)
848 const struct tcore_at_response *at_resp = data;
849 struct tresp_network_get_plmn_selection_mode nw_resp = {0, };
850 UserRequest *ur = NULL;
851 GSList *tokens = NULL;
855 nw_resp.result = TCORE_RETURN_FAILURE; /* TODO - CME Error mapping required. */
857 if (at_resp && at_resp->success) {
861 if (!at_resp->lines) {
862 err("invalid response received");
866 line = (char *) at_resp->lines->data;
867 tokens = tcore_at_tok_new(line);
868 if (g_slist_length(tokens) < 1) {
869 msg("invalid message");
874 mode = atoi(tcore_at_tok_nth(tokens, 0));
876 nw_resp.mode = NETWORK_SELECT_MODE_AUTOMATIC;
878 nw_resp.mode = NETWORK_SELECT_MODE_MANUAL;
880 dbg("selection mode[%d]", nw_resp.mode);
881 nw_resp.result = TCORE_RETURN_SUCCESS;
886 ur = tcore_pending_ref_user_request(p);
888 tcore_user_request_send_response(ur,
889 TRESP_NETWORK_GET_PLMN_SELECTION_MODE,
890 sizeof(struct tresp_network_get_plmn_selection_mode), &nw_resp);
896 dbg("Get selection mode : [%s]",
897 (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
900 tcore_at_tok_free(tokens);
903 static void on_response_network_set_plmn_selection_mode(TcorePending *p,
904 int data_len, const void *data, void *user_data)
906 const struct tcore_at_response *at_resp = data;
907 struct tresp_network_set_plmn_selection_mode nw_resp;
908 UserRequest *ur = NULL;
913 if (at_resp->success) {
915 nw_resp.result = TCORE_RETURN_SUCCESS;
919 err("CME Error[%s]", (char *)at_resp->lines->data);
920 nw_resp.result = TCORE_RETURN_FAILURE;
923 err("Response: [NOK]");
926 ur = tcore_pending_ref_user_request(p);
928 tcore_user_request_send_response(ur,
929 TRESP_NETWORK_SET_PLMN_SELECTION_MODE,
930 sizeof(struct tresp_network_set_plmn_selection_mode), &nw_resp);
936 static void on_response_network_get_serving_network(TcorePending *p,
937 int data_len, const void *data, void *user_data)
939 const struct tcore_at_response *at_resp = data;
940 struct tresp_network_get_serving_network nw_resp = {0, };
941 enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
942 UserRequest *ur = NULL;
943 GSList *tokens = NULL;
945 CoreObject *co_network = tcore_pending_ref_core_object(p);
950 if (at_resp && at_resp->success) {
952 int num_lines, count;
953 char *local_data = NULL;
955 if (!at_resp->lines) {
956 err("invalid response received");
957 nw_resp.result = TCORE_RETURN_FAILURE;
962 nw_resp.result = TCORE_RETURN_SUCCESS;
964 num_lines = g_slist_length(at_resp->lines);
965 dbg("number of lines: %d", num_lines);
967 for (count = 0; count < num_lines; count++) {
968 line = g_slist_nth_data(at_resp->lines, count);
969 tokens = tcore_at_tok_new(line);
971 if ((local_data = tcore_at_tok_nth(tokens, 0)))
972 dbg("mode : %s", local_data);
975 if ((local_data = tcore_at_tok_nth(tokens, 1)))
976 dbg("format : %s", local_data);
979 if ((plmn = tcore_at_tok_nth(tokens, 2))) {
980 dbg("plmn : %s", plmn);
981 g_strlcpy(nw_resp.plmn, plmn, 6);
982 tcore_network_set_plmn(co_network, nw_resp.plmn);
983 if (!g_strcmp0(nw_resp.plmn, "11111")) {
984 /* In case of emulator, need to show "SDK" on indicator instead of "11111" */
985 tcore_network_set_network_name(co_network, TCORE_NETWORK_NAME_TYPE_FULL, "SDK");
990 if ((local_data = tcore_at_tok_nth(tokens, 3))) {
991 gint idx = atoi(local_data);
992 dbg("AcT : %s", local_data);
993 if (idx >= 0 && idx < AT_COPS_ACT_MAX)
994 act = lookup_tbl_access_technology[idx];
996 act = NETWORK_ACT_UNKNOWN;
1000 (void)tcore_network_get_lac(co_network, &lac);
1001 dbg("lac : %x", lac);
1003 nw_resp.gsm.lac = lac;
1005 tcore_at_tok_free(tokens);
1009 ur = tcore_pending_ref_user_request(p);
1011 tcore_user_request_send_response(ur,
1012 TRESP_NETWORK_GET_SERVING_NETWORK,
1013 sizeof(struct tresp_network_get_serving_network), &nw_resp);
1015 struct tnoti_network_change network_change;
1017 memset(&network_change, 0, sizeof(struct tnoti_network_change));
1018 memcpy(network_change.plmn, nw_resp.plmn, 6);
1019 network_change.act = act;
1020 network_change.gsm.lac = lac;
1022 tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(p)),
1023 tcore_pending_ref_core_object(p),
1024 TNOTI_NETWORK_CHANGE,
1025 sizeof(struct tnoti_network_change), &network_change);
1029 dbg("Get serving network : [%s]",
1030 (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
1034 static TReturn search_network(CoreObject *co_network, UserRequest *ur)
1036 TReturn ret = TCORE_RETURN_FAILURE;
1040 /* Send Request to modem */
1041 ret = tcore_prepare_and_send_at_request(co_network,
1042 "AT+COPS=?", "+COPS",
1043 TCORE_AT_SINGLELINE,
1045 on_response_network_search, NULL,
1046 on_send_at_request, NULL,
1048 dbg("ret: [0x%x]", ret);
1054 static TReturn set_plmn_selection_mode(CoreObject *co_network, UserRequest *ur)
1057 struct treq_network_set_plmn_selection_mode *mode_info = NULL;
1058 TReturn ret = TCORE_RETURN_FAILURE;
1062 mode_info = (struct treq_network_set_plmn_selection_mode *)tcore_user_request_ref_data(ur, 0);
1064 if (mode_info->mode == NETWORK_SELECT_MODE_AUTOMATIC) {
1065 at_cmd = g_strdup_printf("AT+COPS=0");
1066 dbg(" Mode - Automatic: -- %s", at_cmd);
1070 switch (mode_info->act) {
1071 case NETWORK_ACT_GSM:
1072 case NETWORK_ACT_GPRS:
1073 case NETWORK_ACT_EGPRS:
1077 case NETWORK_ACT_UMTS:
1078 case NETWORK_ACT_GSM_UTRAN:
1083 err("Unsupported AcT: [%d]", mode_info->act);
1086 at_cmd = g_strdup_printf("AT+COPS=1, 2, \"%s\", %d", mode_info->plmn, act);
1089 /* Send Request to modem */
1090 ret = tcore_prepare_and_send_at_request(co_network, at_cmd, NULL,
1093 on_response_network_set_plmn_selection_mode, NULL,
1094 on_send_at_request, NULL, 0, NULL, NULL);
1095 dbg("ret: [0x%x]", ret);
1097 /* Free resources */
1103 static TReturn get_plmn_selection_mode(CoreObject *co_network, UserRequest *ur)
1105 TReturn ret = TCORE_RETURN_FAILURE;
1109 /* Send Request to modem */
1110 ret = tcore_prepare_and_send_at_request(co_network,
1111 "AT+COPS?", "+COPS",
1112 TCORE_AT_SINGLELINE,
1114 on_response_network_get_plmn_selection_mode, NULL,
1115 on_send_at_request, NULL, 0, NULL, NULL);
1116 dbg("ret: [0x%x]", ret);
1121 static TReturn get_serving_network(CoreObject *co_network, UserRequest *ur)
1123 TReturn ret = TCORE_RETURN_FAILURE;
1127 /* Send Request to modem */
1128 ret = tcore_prepare_and_send_at_request(co_network,
1129 "AT+COPS?", "+COPS",
1130 TCORE_AT_SINGLELINE,
1132 on_response_network_get_serving_network, NULL,
1133 on_send_at_request, NULL, 0, NULL, NULL);
1134 dbg("ret: [0x%x]", ret);
1139 static TReturn get_default_subscription(CoreObject *co, UserRequest *ur)
1141 struct tresp_network_get_default_subs resp_data = {0, };
1142 TReturn ret = TCORE_RETURN_FAILURE;
1144 Storage *strg = NULL;
1145 TcorePlugin *plugin = tcore_object_ref_plugin(co);
1149 server = tcore_plugin_ref_server(plugin);
1150 strg = tcore_server_find_storage(server, "vconf");
1152 /* VCONFKEY is aligned to req_data->current_network type */
1153 resp_data.default_subs = tcore_storage_get_int(strg,
1154 STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_SERVICE_INT);
1156 resp_data.result = TCORE_RETURN_SUCCESS;
1159 ret = tcore_user_request_send_response(ur,
1160 TRESP_NETWORK_GET_DEFAULT_SUBSCRIPTION,
1161 sizeof(struct tresp_network_get_default_subs), &resp_data);
1163 dbg("ret: [0x%x]", ret);
1167 static TReturn get_default_data_subscription(CoreObject *co, UserRequest *ur)
1169 struct tresp_network_get_default_data_subs resp = {0, };
1171 Storage *strg = NULL;
1172 TcorePlugin *plugin = tcore_object_ref_plugin(co);
1177 server = tcore_plugin_ref_server(plugin);
1178 strg = tcore_server_find_storage(server, "vconf");
1180 resp.default_subs = tcore_storage_get_int(strg, STORAGE_KEY_TELEPHONY_DUALSIM_DEFAULT_DATA_SERVICE_INT);
1181 dbg("Defualt data Subscription: [%d]", resp.default_subs);
1183 resp.result = TCORE_RETURN_SUCCESS;
1185 ret = tcore_user_request_send_response(ur,
1186 TRESP_NETWORK_GET_DEFAULT_DATA_SUBSCRIPTION,
1187 sizeof(struct tresp_network_get_default_data_subs), &resp);
1188 if (TCORE_RETURN_SUCCESS == ret)
1189 tcore_user_request_unref(ur);
1194 /** Network operations */
1195 static struct tcore_network_operations network_ops = {
1196 .search = search_network,
1197 .set_plmn_selection_mode = set_plmn_selection_mode,
1198 .get_plmn_selection_mode = get_plmn_selection_mode,
1199 .set_service_domain = NULL,
1200 .get_service_domain = NULL,
1203 .set_preferred_plmn = NULL,
1204 .get_preferred_plmn = NULL,
1207 .set_power_on_attach = NULL,
1208 .get_power_on_attach = NULL,
1209 .set_cancel_manual_search = NULL,
1210 .get_serving_network = get_serving_network,
1211 .get_default_subscription = get_default_subscription,
1212 .get_default_data_subscription = get_default_data_subscription,
1215 gboolean s_network_init(TcorePlugin *p, TcoreHal *h)
1217 CoreObject *co_network;
1219 co_network = tcore_network_new(p, "umts_network", &network_ops, h);
1221 err("Core object is NULL");
1226 tcore_object_add_callback(co_network,
1228 on_notification_atmodem_cs_network_info, NULL);
1229 tcore_object_add_callback(co_network,
1231 on_notification_atmodem_ps_network_info, NULL);
1232 tcore_object_add_callback(co_network,
1234 on_notification_atmodem_network_rssi, NULL);
1236 /* Add notification hook */
1237 tcore_server_add_notification_hook(tcore_plugin_ref_server(p),
1239 on_hook_sim_init, co_network);
1241 _insert_mcc_mnc_oper_list(p, co_network);
1246 void s_network_exit(TcorePlugin *p)
1248 CoreObject *co_network;
1251 err("Plugin is NULL");
1255 co_network = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_NETWORK);
1257 tcore_network_free(co_network);