4 * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
28 #include <core_object.h>
33 #include <tzplatform_config.h>
35 #include <co_network.h>
37 #include "imc_network.h"
38 #include "imc_common.h"
40 #define IMC_NETWORK_BASE_16 16
43 IMC_NETWORK_SEARCH_STATE_NO_SEARCH,
44 IMC_NETWORK_SEARCH_STATE_IN_PROGRESS,
45 IMC_NETWORK_SEARCH_STATE_CANCELLED
46 } ImcNetworkSearchState;
49 ImcNetworkSearchState search_state;
54 TelNetworkResult result;
55 } ImcNetworkCancelSearch;
57 static TelNetworkAct __imc_network_map_act(guint act)
66 * 6 UTRAN w/HSDPA and HSUPA
70 return TEL_NETWORK_ACT_GSM;
72 return TEL_NETWORK_ACT_UMTS;
74 return TEL_NETWORK_ACT_EGPRS;
76 return TEL_NETWORK_ACT_HSDPA;
78 return TEL_NETWORK_ACT_HSUPA;
80 return TEL_NETWORK_ACT_HSPA;
82 return TEL_NETWORK_ACT_UNKNOWN;
86 static TelNetworkRegStatus __imc_network_map_stat(guint stat)
90 * 0 Not registered, ME is not currently searching a
91 * new operator to register to
92 * 1 Registered, home network
93 * 2 Not registered, but ME is currently searching a
94 * new operator to register
95 * 3 Registration denied
97 * 5 Registered, in roaming
101 return TEL_NETWORK_REG_STATUS_UNREGISTERED;
103 return TEL_NETWORK_REG_STATUS_REGISTERED;
105 return TEL_NETWORK_REG_STATUS_SEARCHING;
107 return TEL_NETWORK_REG_STATUS_DENIED;
109 return TEL_NETWORK_REG_STATUS_UNKNOWN;
111 return TEL_NETWORK_REG_STATUS_ROAMING;
113 return TEL_NETWORK_REG_STATUS_UNKNOWN;
117 static void __on_response_imc_network_registration(TcorePending *p,
118 guint data_len, const void *data, void *user_data)
120 const TcoreAtResponse *at_resp = data;
123 if (at_resp && at_resp->success) {
124 dbg("Network Registration - [OK]");
126 err("Network Registration - [NOK]");
130 static void __imc_network_register_to_network(CoreObject *co)
134 /* Send Request to modem */
135 ret = tcore_at_prepare_and_send_request(co,
137 TCORE_AT_COMMAND_TYPE_NO_RESULT,
139 __on_response_imc_network_registration, NULL,
140 on_send_imc_request, NULL);
141 dbg("Sending Network Registration request: [%s]",
142 (ret == TEL_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
145 static void __on_response_imc_network_fetch_nw_name_internal(CoreObject *co,
146 gint result, const void *response, void *user_data)
148 TelNetworkIdentityInfo *identity = (TelNetworkIdentityInfo *)response;
150 /* Send notification if result is SUCCESS */
151 if (result == TEL_NETWORK_RESULT_SUCCESS)
152 tcore_object_send_notification(co,
153 TCORE_NOTIFICATION_NETWORK_IDENTITY,
154 sizeof(TelNetworkIdentityInfo), identity);
157 static TcoreHookReturn __on_response_imc_hook_set_flight_mode(CoreObject *co,
158 gint result, TcoreCommand command, const void *response, const void *user_data)
161 tcore_check_return_value(result == TEL_MODEM_RESULT_SUCCESS,
162 TCORE_HOOK_RETURN_CONTINUE);
164 dbg("Flight mode 'disabled', register to Network");
167 * TODO - Check for selection_mode
168 * Need to check if it is Manual or Automatic and based on
169 * that need to initiate Network Registratin accordingly.
171 __imc_network_register_to_network(co);
173 return TCORE_HOOK_RETURN_CONTINUE;
176 static void __on_response_imc_network_fetch_nw_name(TcorePending *p,
177 guint data_len, const void *data, void *user_data)
179 const TcoreAtResponse *at_resp = data;
180 CoreObject *co = tcore_pending_ref_core_object(p);
181 ImcRespCbData *resp_cb_data = user_data;
182 TelNetworkIdentityInfo identity = {0, };
184 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
188 tcore_check_return_assert(co != NULL);
189 tcore_check_return_assert(resp_cb_data != NULL);
191 if (at_resp && at_resp->success) {
192 if (at_resp->lines) {
194 GSList *tokens = NULL;
198 /* Validate that only 3 lines of response is received */
199 nol = g_slist_length(at_resp->lines);
201 err("Invalid response message");
205 /* Process the Multi-line response */
206 for (i = 0; i < nol; i++) {
207 line = g_slist_nth_data(at_resp->lines, i);
212 * +XCOPS: <type>[,<name>[,<display_condition>]]
214 dbg("<line> : [%s]", line);
215 tokens = tcore_at_tok_new(line);
217 if ((token_str = tcore_at_tok_nth(tokens, 0))) {
218 guint type = atoi(token_str);
219 dbg("<type> : [%d]", type);
222 case 0: /* PLMN (mcc, mnc) */
223 if ((token_str = tcore_at_tok_nth(tokens, 1))) {
224 if (strlen(token_str) > 0) {
225 identity.plmn = tcore_at_tok_extract((const char *)token_str);
228 tcore_network_set_plmn( co, identity.plmn);
233 case 1: /* Short Name in ROM (NV-RAM) */
234 case 3: /* Short Network Operator Name (CPHS) */
235 case 5: /* Short NITZ Name */
236 if ((token_str = tcore_at_tok_nth(tokens, 1))) {
237 if (strlen(token_str) > 0) {
238 identity.short_name = tcore_at_tok_extract((const char *)token_str);
241 /* Update Short name */
242 tcore_network_set_short_name(co, identity.short_name);
247 case 2: /* Long Name in ROM (NV-RAM) */
248 case 4: /* Long Network Operator Name (CPHS) */
249 case 6: /* Full NITZ Name */
250 if ((token_str = tcore_at_tok_nth(tokens, 1))) {
251 if (strlen(token_str) > 0) {
252 identity.long_name = tcore_at_tok_extract((const char *)token_str);
254 /* Update Long name */
255 tcore_network_set_long_name(co, identity.long_name);
266 tcore_at_tok_free(tokens);
269 /* Send Notification - Network identity */
270 dbg("Network name - Long name: [%s] Short name: [%s] "
271 "PLMN: [%s]", identity.long_name,
272 identity.short_name, identity.plmn);
274 result = TEL_NETWORK_RESULT_SUCCESS;
278 /* Invoke callback */
279 if (resp_cb_data->cb)
280 resp_cb_data->cb(co, (gint)result, &identity, resp_cb_data->cb_data);
283 tcore_free(identity.long_name);
284 tcore_free(identity.short_name);
285 tcore_free(identity.plmn);
287 /* Free callback data */
288 imc_destroy_resp_cb_data(resp_cb_data);
292 * Operation - fetch_nw_name
295 * AT-Command: AT+XCOPS=<Type>
298 * 0 numeric format of network MCC/MNC (three BCD
299 * digit country code and two/three BCD digit network code)
300 * 1 Short Name in ROM (NV-RAM)
301 * 2 Long Name in ROM (NV-RAM)
302 * 3 Short Network Operator Name (CPHS)
303 * 4 Long Network Operator Name (CPHS)
306 * 7 Service Provider Name
307 * 8 EONS short operator name from EF-PNN
308 * 9 EONS long operator name from EF-PNN
309 * 11 Short PLMN name (When PS or CS is registered)
310 * 12 Long PLMN name (When PS or CS is registered)
311 * 13 numeric format of network MCC/MNC even in limited service
313 * Response - Network name
314 * Success: (Multiple Single line)
315 * +XCOPS: <type>[,<name>[,<display_condition>]]
318 * +CME ERROR: <error>
320 static TelReturn __imc_network_fetch_nw_name(CoreObject *co,
321 TcoreObjectResponseCallback cb, void *cb_data)
323 ImcRespCbData *resp_cb_data = NULL;
326 /* Response callback data */
327 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
329 /* Send Request to modem */
330 ret = tcore_at_prepare_and_send_request(co,
331 "AT+XCOPS=0;+XCOPS=5;+XCOPS=6", "+XCOPS",
332 TCORE_AT_COMMAND_TYPE_MULTILINE,
334 __on_response_imc_network_fetch_nw_name, resp_cb_data,
335 on_send_imc_request, NULL);
336 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Fetch Network name");
342 static TcoreHookReturn on_hook_imc_set_flight_mode(CoreObject *co,
343 TcoreCommand command, const void *request, const void *user_data,
344 TcoreObjectResponseCallback cb, const void *cb_data)
346 gboolean *flight_mode = (gboolean *)request;
349 * Hook Set Flight mode request.
351 * Disable Flight mode - Hook response (if success Register to Network)
352 * Enable Flight mode - return
354 if (*flight_mode != TRUE) {
355 /* Add response hook */
356 tcore_object_add_response_hook(co, command, request,
357 __on_response_imc_hook_set_flight_mode, NULL);
359 return TCORE_HOOK_RETURN_CONTINUE;
362 dbg("Flight mode - [Enabled]");
363 return TCORE_HOOK_RETURN_CONTINUE;
366 static TcoreHookReturn on_hook_imc_sim_status(TcorePlugin *plugin,
367 TcoreNotification command, guint data_len, void *data, void *user_data)
369 const TelSimCardStatus *sim_status = (TelSimCardStatus *)data;
371 tcore_check_return_value(sim_status != NULL,
372 TCORE_HOOK_RETURN_CONTINUE);
375 * Hook SIM initialization Notification
377 * SIM INIT complete - Attach to network (Register to network)
378 * SIM INIT not complete - return
380 if (*sim_status == TEL_SIM_STATUS_SIM_INIT_COMPLETED) {
381 CoreObject *co = (CoreObject *)user_data;
382 dbg("SIM Initialized!!! Attach to Network");
384 tcore_check_return_value_assert(co != NULL,
385 TCORE_HOOK_RETURN_CONTINUE);
388 * TODO - Check for selection_mode
389 * Need to check if it is Manual or Automatic and based on
390 * that need to initiate Network Registratin accordingly.
392 __imc_network_register_to_network(co);
394 return TCORE_HOOK_RETURN_CONTINUE;
397 dbg("SIM not yet initialized - SIM Status: [%d]", *sim_status);
398 return TCORE_HOOK_RETURN_CONTINUE;
401 /* Notification callbacks */
403 * Notification: +CREG: <stat>[,<lac>,<ci>[,<AcT>]]
405 * Possible values of <stat> can be
406 * 0 Not registered, ME is not currently searching
407 * a new operator to register to
408 * 1 Registered, home network
409 * 2 Not registered, but ME is currently searching
410 * a new operator to register
411 * 3 Registration denied
413 * 5 Registered, in roaming
416 * string type; two byte location area code in
417 * hexadecimal format (e.g. 00C3)
420 * string type; four byte cell ID in hexadecimal
421 * format (e.g. 0000A13F)
429 * 6 UTRAN w/HSDPA and HSUPA
431 static gboolean on_notification_imc_cs_network_info(CoreObject *co,
432 const void *event_info, void *user_data)
434 GSList *lines = NULL;
437 dbg("Network notification - CS network info: [+CREG]");
439 lines = (GSList *)event_info;
440 if (g_slist_length(lines) != 1) {
441 err("+CREG unsolicited message expected to be Single line "
442 "but received multiple lines");
446 line = (gchar *) (lines->data);
448 TelNetworkRegStatusInfo registration_status = {0, };
449 TelNetworkCellInfo cell_info = {0, };
450 GSList *tokens = NULL;
452 guint stat = 0, act = 0, lac = 0, ci = 0;
453 gboolean roam_state = FALSE;
458 * +CREG: <stat>[,<lac>,<ci>[,<AcT>]]
460 tokens = tcore_at_tok_new(line);
461 if (g_slist_length(tokens) < 1) {
462 err("Invalid notification message");
467 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
468 err("No <stat> in +CREG");
471 stat = __imc_network_map_stat(atoi(token_str));
472 (void)tcore_network_set_cs_reg_status(co, stat);
475 if ((token_str = g_slist_nth_data(tokens, 1))) {
476 token_str = tcore_at_tok_extract((const gchar *)token_str);
478 lac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
480 /* Update Location Area Code (lac) information */
481 (void)tcore_network_set_lac(co, lac);
483 tcore_free(token_str);
485 dbg("No <lac> in +CREG");
486 (void)tcore_network_get_lac(co, &lac);
490 if ((token_str = g_slist_nth_data(tokens, 2))) {
491 token_str = tcore_at_tok_extract((const gchar *)token_str);
493 ci = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
495 /* Update Cell ID (ci) information */
496 (void)tcore_network_set_cell_id(co, ci);
498 tcore_free(token_str);
500 dbg("No <ci> in +CREG");
501 (void)tcore_network_get_cell_id(co, &ci);
505 if ((token_str = g_slist_nth_data(tokens, 3))) {
506 act = __imc_network_map_act(atoi(token_str));
507 (void)tcore_network_set_access_technology(co, act);
509 dbg("No <AcT> in +CREG");
510 (void)tcore_network_get_access_technology(co, &act);
512 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d", stat, lac, ci, act);
514 /* Send Notification - Network (CS) Registration status */
515 registration_status.cs_status = stat;
516 registration_status.act = act;
517 (void)tcore_network_get_ps_reg_status(co, ®istration_status.ps_status);
519 tcore_object_send_notification(co,
520 TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS,
521 sizeof(TelNetworkRegStatusInfo), ®istration_status);
524 case TEL_NETWORK_REG_STATUS_ROAMING:
525 roam_state = TRUE; // no break
526 case TEL_NETWORK_REG_STATUS_REGISTERED:
527 /* Fetch Network name - Internal request */
528 (void)__imc_network_fetch_nw_name(co,
529 __on_response_imc_network_fetch_nw_name_internal, NULL);
535 /* Set Roaming state */
536 tcore_network_set_roam_state(co, roam_state);
538 /* Send Notification - Cell info */
539 cell_info.lac = (gint)lac;
540 cell_info.cell_id = (gint)ci;
541 (void)tcore_network_get_rac(co, &cell_info.rac);
543 tcore_object_send_notification(co,
544 TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO,
545 sizeof(TelNetworkCellInfo), &cell_info);
549 tcore_at_tok_free(tokens);
556 * Notification: +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]]
558 * Possible values of <stat> can be
559 * 0 Not registered, ME is not currently searching a
560 * new operator to register to
561 * 1 Registered, home network
562 * 2 Not registered, but ME is currently searching a
563 * new operator to register
564 * 3 Registration denied
566 * 5 Registered, in roaming
569 * string type; two byte location area code in
570 * hexadecimal format (e.g. 00C3)
573 * string type; four byte cell ID in hexadecimal
574 * format (e.g. 0000A13F)
582 * 6 UTRAN w/HSDPA and HSUPA
585 * string type; one byte routing area code in hexadecimal format
587 static gboolean on_notification_imc_ps_network_info(CoreObject *co,
588 const void *event_info, void *user_data)
590 GSList *lines = NULL;
593 dbg("Network notification - PS network info: [+CGREG]");
595 lines = (GSList *)event_info;
596 if (g_slist_length(lines) != 1) {
597 err("+CGREG unsolicited message expected to be Single line "
598 "but received multiple lines");
602 line = (gchar *) (lines->data);
604 TelNetworkRegStatusInfo registration_status = {0, };
605 TelNetworkCellInfo cell_info = {0, };
606 GSList *tokens = NULL;
608 guint stat = 0, act = 0, lac = 0, ci = 0, rac = 0;
609 gboolean roam_state = FALSE;
614 * +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]]
616 tokens = tcore_at_tok_new(line);
617 if (g_slist_length(tokens) < 1) {
618 err("Invalid notification message");
623 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
624 err("No <stat> in +CGREG");
627 stat = __imc_network_map_stat(atoi(token_str));
628 (void)tcore_network_set_ps_reg_status(co, stat);
631 if ((token_str = g_slist_nth_data(tokens, 1))) {
632 token_str = tcore_at_tok_extract((const gchar *)token_str);
634 lac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
636 /* Update Location Area Code (lac) information */
637 (void)tcore_network_set_lac(co, lac);
639 tcore_free(token_str);
641 dbg("No <lac> in +CGREG");
642 (void)tcore_network_get_lac(co, &lac);
646 if ((token_str = g_slist_nth_data(tokens, 2))) {
647 token_str = tcore_at_tok_extract((const gchar *)token_str);
649 ci = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
651 /* Update Cell ID (ci) information */
652 (void)tcore_network_set_cell_id(co, ci);
654 tcore_free(token_str);
656 dbg("No <ci> in +CGREG");
657 (void)tcore_network_get_cell_id(co, &ci);
661 if ((token_str = g_slist_nth_data(tokens, 3))) {
662 act = __imc_network_map_act(atoi(token_str));
663 (void)tcore_network_set_access_technology(co, act);
665 dbg("No <AcT> in +CGREG");
666 (void)tcore_network_get_access_technology(co, &act);
670 if ((token_str = g_slist_nth_data(tokens, 4))) {
671 token_str = tcore_at_tok_extract((const gchar *)token_str);
673 rac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
675 /* Update Routing Area Code (rac) information */
676 (void)tcore_network_set_rac(co, rac);
678 tcore_free(token_str);
680 err("No <ci> in +CGREG");
681 (void)tcore_network_get_rac(co, &rac);
683 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d <rac>: 0x%x", stat, lac, ci, act, rac);
685 /* Send Notification - Network (PS) Registration status */
686 registration_status.ps_status = stat;
687 registration_status.act = act;
688 (void)tcore_network_get_cs_reg_status(co, ®istration_status.cs_status);
690 tcore_object_send_notification(co,
691 TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS,
692 sizeof(TelNetworkRegStatusInfo), ®istration_status);
694 /* Set Roaming state */
695 if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING)
698 tcore_network_set_roam_state(co, roam_state);
700 /* Send Notification - Cell info */
702 cell_info.cell_id = ci;
704 tcore_object_send_notification(co,
705 TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO,
706 sizeof(TelNetworkCellInfo), &cell_info);
710 tcore_at_tok_free(tokens);
717 * Notification: +XNITZINFO: <fullname>,<shortname>,<LTZ>,<UT>,<DST>
720 * string type; Network name in long alphanumeric format.
723 * string type; Network name in short alphanumeric format.
726 * Local Time Zone; represented as 1 unit = 15 minutes.
729 * string type value; Universal Time
730 * format is "yy/MM/dd,hh:mm:ss",
731 * wherein characters indicates year, month, day, hour,
734 * Daylight Saving Time; represented in hours.
736 static gboolean on_notification_imc_network_time_info(CoreObject *co,
737 const void *event_info, void *user_data)
739 GSList *lines = NULL;
742 dbg("Network notification - Time info: [+XNITZINFO]");
744 lines = (GSList *)event_info;
745 if (g_slist_length(lines) != 1) {
746 err("+XNITZINFO unsolicited message expected to be Single line "
747 "but received multiple lines");
751 line = (gchar *)lines->data;
753 GSList *tokens = NULL;
754 TelNetworkNitzInfoNoti nitz_info = {0, };
755 gchar *fullname, *shortname;
757 gchar tmp_time[8] = {0};
763 * +XNITZINFO: <fullname>,<shortname>,<LTZ>,<UT>,<DST>
765 tokens = tcore_at_tok_new(line);
768 if ((fullname = tcore_at_tok_nth(tokens, 1))) {
769 if (strlen(fullname) > 0) {
770 fullname = tcore_at_tok_extract((const char *)fullname);
772 /* Update Long name */
773 tcore_network_set_long_name(co, fullname);
775 tcore_free(fullname);
780 if ((shortname = tcore_at_tok_nth(tokens, 1))) {
781 if (strlen(shortname) > 0) {
782 shortname = tcore_at_tok_extract((const char *)shortname);
784 /* Update Short name */
785 tcore_network_set_short_name(co, shortname);
787 tcore_free(shortname);
792 if ((ltz = g_slist_nth_data(tokens, 2)))
793 nitz_info.gmtoff = atoi(ltz) * 15;/* gmtoff in minutes */
795 if ((time = g_slist_nth_data(tokens, 3))
796 && (strlen(time) > 18)) {
797 /* (time + 1) - Skip past initial quote (") */
798 g_strlcpy(tmp_time, time + 1, 2+1);
799 nitz_info.year = atoi(tmp_time);
801 /* skip slash (/) after year param */
802 g_strlcpy(tmp_time, time + 4, 2+1);
803 nitz_info.month = atoi(tmp_time);
805 /* skip past slash (/) after month param */
806 g_strlcpy(tmp_time, time + 7, 2+1);
807 nitz_info.day = atoi(tmp_time);
809 /* skip past comma (,) after day param */
810 g_strlcpy(tmp_time, time + 10, 2+1);
811 nitz_info.hour = atoi(tmp_time);
813 /* skip past colon (:) after hour param */
814 g_strlcpy(tmp_time, time + 13, 2+1);
815 nitz_info.minute = atoi(tmp_time);
817 /* skip past colon (:) after minute param */
818 g_strlcpy(tmp_time, time + 16, 2+1);
819 nitz_info.second = atoi(tmp_time);
823 if ((dstoff = g_slist_nth_data(tokens, 4))) {
824 nitz_info.dstoff = atoi(dstoff);
825 nitz_info.isdst = TRUE;
829 tcore_network_get_plmn(co, &nitz_info.plmn);
831 /* Send Notification - Network time info */
832 tcore_object_send_notification(co,
833 TCORE_NOTIFICATION_NETWORK_TIMEINFO,
834 sizeof(TelNetworkNitzInfoNoti), &nitz_info);
837 tcore_free(nitz_info.plmn);
838 tcore_at_tok_free(tokens);
848 * +XCIEV:,<battery_level>
850 * 'Radio Signal Strength' <rssi> can have the values
851 * 0 -107 dBm or less or unknown
860 * 'Battery Level' <battery_level> can have the values
861 * 0 0 % <= level < 5 %
862 * 1 5 % <= level < 15 %
863 * 2 15 % <= level < 25 %
864 * 3 25 % <= level < 40 %
865 * 4 40 % <= level < 55 %
866 * 5 55 % <= level < 70 %
867 * 6 70 % <= level < 85 %
868 * 7 85 % <= level <= 100 %
871 * <battery_level> is not consider for
872 * TCORE_NOTIFICATION_NETWORK_RSSI notification
874 static gboolean on_notification_imc_network_rssi(CoreObject *co,
875 const void *event_info, void *user_data)
877 GSList *lines = NULL;
880 dbg("Network notification - Icon (rssi) info: [+XCIEV]");
882 lines = (GSList *)event_info;
883 if (g_slist_length(lines) != 1) {
884 err("+XCIEV unsolicited message expected to be Single line "
885 "but received multiple lines");
889 line = (gchar *)lines->data;
891 GSList *tokens = NULL;
899 tokens = tcore_at_tok_new(line);
901 rssi_token = (gchar *)g_slist_nth_data(tokens, 0);
902 if (rssi_token && strlen(rssi_token)) {
903 guint rssi_bar = atoi(rssi_token);
904 dbg("RSSI Level: [%d]", rssi_bar);
906 /* Send Notification - Network Rssi */
907 tcore_object_send_notification(co,
908 TCORE_NOTIFICATION_NETWORK_RSSI,
909 sizeof(guint), &rssi_bar);
913 tcore_at_tok_free(tokens);
919 /* Network Responses */
921 static void on_response_imc_network_search(TcorePending *p,
922 guint data_len, const void *data, void *user_data)
924 const TcoreAtResponse *at_resp = data;
925 CoreObject *co = tcore_pending_ref_core_object(p);
926 CustomData *custom_data;
928 ImcRespCbData *resp_cb_data = user_data;
929 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; //TODO - CME Error mapping required.
930 TelNetworkPlmnList plmn_list = {0, };
931 guint num_network_avail = 0;
933 GSList *tokens = NULL;
936 tcore_check_return_assert(co != NULL);
937 tcore_check_return_assert(resp_cb_data != NULL);
939 custom_data = tcore_object_ref_user_data(co);
940 tcore_check_return_assert(custom_data != NULL);
942 if (at_resp && at_resp->success) {
944 GSList *net_token = NULL;
948 /* If Request is Cancelled then return back SUCCESS/SEARCH_CANCELLED */
949 if (custom_data->search_state
950 == IMC_NETWORK_SEARCH_STATE_CANCELLED) {
951 dbg("Network Search has been Cancelled!!!");
956 * Need to introduce new Result -
957 * TEL_NETWORK_RESULT_SEARCH_ABORTED/CANCELLED
959 * Presently sending TEL_NETWORK_RESULT_FAILURE
961 result = TEL_NETWORK_RESULT_FAILURE;
966 if (!at_resp->lines) {
967 err("invalid response received");
971 line = (char *) at_resp->lines->data;
972 tokens = tcore_at_tok_new(line);
973 num_network_avail = g_slist_length(tokens);
974 if (num_network_avail < 1) {
975 err("invalid message");
979 plmn_list.network_list = tcore_malloc0(sizeof(TelNetworkInfo) * num_network_avail);
982 for (count = 0; count < num_network_avail; count++) {
984 net_token = tcore_at_tok_new(g_slist_nth_data(tokens, count));
985 if (NULL == net_token)
988 resp = tcore_at_tok_nth(net_token, 0);
990 plmn_list.network_list[count].plmn_status = atoi(resp);
991 dbg("status[%d]", plmn_list.network_list[count].plmn_status);
994 if ((resp = tcore_at_tok_nth(net_token, 1))) {
995 /* Long Alpha name */
996 dbg("long alpha name[%s]", resp);
997 plmn_list.network_list[count].network_identity.long_name =
998 tcore_at_tok_extract(resp);
1001 if ((resp = tcore_at_tok_nth(net_token, 2))) {
1002 /* Short Alpha name */
1003 dbg("Short Alpha name[%s]", resp);
1004 plmn_list.network_list[count].network_identity.short_name =
1005 tcore_at_tok_extract(resp);
1009 if ((resp = tcore_at_tok_nth(net_token, 3))) {
1010 dbg("PLMN ID[%s]", resp);
1011 plmn_list.network_list[count].network_identity.plmn =
1012 tcore_at_tok_extract(resp);
1015 /* Parse Access Technology */
1016 if ((resp = tcore_at_tok_nth(tokens, 4))) {
1019 plmn_list.network_list[count].act = TEL_NETWORK_ACT_GSM;
1021 plmn_list.network_list[count].act = TEL_NETWORK_ACT_UMTS;
1024 dbg("Operator [%d] :: status = %d, long_name = %s, short_name = %s plmn = %s, AcT=%d",
1026 plmn_list.network_list[count].plmn_status,
1027 plmn_list.network_list[count].network_identity.long_name,
1028 plmn_list.network_list[count].network_identity.short_name,
1029 plmn_list.network_list[count].network_identity.plmn,
1030 plmn_list.network_list[count].act);
1033 tcore_at_tok_free(net_token);
1035 result = TEL_NETWORK_RESULT_SUCCESS;
1037 err("RESPONSE NOK");
1039 err("CME Error[%s]",(char *)at_resp->lines->data);
1043 dbg("Network search : [%s]",
1044 (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1046 /* Update Search state */
1047 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
1049 /* Invoke callback */
1050 if (resp_cb_data->cb)
1051 resp_cb_data->cb(co, (gint)result, &plmn_list, resp_cb_data->cb_data);
1053 imc_destroy_resp_cb_data(resp_cb_data);
1056 for (count = 0; count < num_network_avail; count++) {
1057 g_free(plmn_list.network_list[count].network_identity.long_name);
1058 g_free(plmn_list.network_list[count].network_identity.short_name);
1059 g_free(plmn_list.network_list[count].network_identity.plmn);
1062 tcore_free(plmn_list.network_list);
1063 tcore_at_tok_free(tokens);
1066 static gboolean on_response_imc_network_cancel_search(gpointer data)
1068 ImcRespCbData *resp_cb_data = data;
1069 ImcNetworkCancelSearch *cancel_search =
1070 (ImcNetworkCancelSearch *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
1072 /* Invoke callback */
1073 if (resp_cb_data->cb)
1074 resp_cb_data->cb(cancel_search->co, (gint)cancel_search->result,
1075 NULL, resp_cb_data->cb_data);
1077 imc_destroy_resp_cb_data(resp_cb_data);
1079 /* To stop the cycle, need to return FALSE */
1083 static void on_response_imc_network_get_selection_mode(TcorePending *p,
1084 guint data_len, const void *data, void *user_data)
1086 const TcoreAtResponse *at_resp = data;
1087 CoreObject *co = tcore_pending_ref_core_object(p);
1088 ImcRespCbData *resp_cb_data = user_data;
1089 TelNetworkSelectionMode selection_mode = -1;
1090 GSList *tokens = NULL;
1092 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; //TODO - CME Error mapping required.
1095 tcore_check_return_assert(co != NULL);
1096 tcore_check_return_assert(resp_cb_data != NULL);
1098 if (at_resp && at_resp->success) {
1102 if (!at_resp->lines) {
1103 err("invalid response received");
1107 line = (char *) at_resp->lines->data;
1108 tokens = tcore_at_tok_new(line);
1109 if (g_slist_length(tokens) < 1) {
1110 msg("invalid message");
1115 mode = atoi(tcore_at_tok_nth(tokens, 0));
1117 selection_mode = TEL_NETWORK_SELECTION_MODE_AUTOMATIC;
1119 selection_mode = TEL_NETWORK_SELECTION_MODE_MANUAL;
1121 result = TEL_NETWORK_RESULT_SUCCESS;
1122 dbg("selection mode[%d]", selection_mode);
1125 err("RESPONSE NOK");
1129 dbg("Get selection mode : [%s]",
1130 (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1131 /* Invoke callback */
1132 if (resp_cb_data->cb)
1133 resp_cb_data->cb(co, (gint)result, &selection_mode, resp_cb_data->cb_data);
1135 /* Free callback data */
1136 imc_destroy_resp_cb_data(resp_cb_data);
1138 tcore_at_tok_free(tokens);
1141 static void on_response_imc_network_default(TcorePending *p,
1142 guint data_len, const void *data, void *user_data)
1144 const TcoreAtResponse *at_resp = data;
1145 CoreObject *co = tcore_pending_ref_core_object(p);
1146 ImcRespCbData *resp_cb_data = user_data;
1147 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; //TODO - CME Error mapping required.
1150 tcore_check_return_assert(co != NULL);
1151 tcore_check_return_assert(resp_cb_data != NULL);
1153 if (at_resp && at_resp->success) {
1155 result = TEL_NETWORK_RESULT_SUCCESS;
1157 err("RESPONSE NOK");
1159 err("CME Error[%s]",(char *)at_resp->lines->data);
1162 /* Invoke callback */
1163 if (resp_cb_data->cb)
1164 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1166 imc_destroy_resp_cb_data(resp_cb_data);
1170 static void on_response_imc_network_get_mode(TcorePending *p,
1171 guint data_len, const void *data, void *user_data)
1173 const TcoreAtResponse *at_resp = data;
1174 CoreObject *co = tcore_pending_ref_core_object(p);
1175 ImcRespCbData *resp_cb_data = user_data;
1176 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; //TODO - CME Error mapping required.
1177 TelNetworkMode mode = -1;
1178 GSList *tokens = NULL;
1181 tcore_check_return_assert(co != NULL);
1182 tcore_check_return_assert(resp_cb_data != NULL);
1184 if (at_resp && at_resp->success) {
1188 if (!at_resp->lines) {
1189 err("invalid response received");
1193 line = (char *) at_resp->lines->data;
1194 tokens = tcore_at_tok_new(line);
1195 if (g_slist_length(tokens) < 1) {
1196 err("invalid message");
1201 net_mode = atoi(tcore_at_tok_nth(tokens, 0));
1202 dbg("mode = %d", net_mode);
1206 mode = TEL_NETWORK_MODE_2G;
1209 mode = TEL_NETWORK_MODE_AUTO;
1212 mode = TEL_NETWORK_MODE_3G;
1215 err("Unsupported mode [%d]", net_mode);
1218 result = TEL_NETWORK_RESULT_SUCCESS;
1220 err("RESPONSE NOK");
1223 /* Invoke callback */
1224 if (resp_cb_data->cb)
1225 resp_cb_data->cb(co, (gint)result, &mode, resp_cb_data->cb_data);
1227 /* Free callback data */
1228 imc_destroy_resp_cb_data(resp_cb_data);
1230 tcore_at_tok_free(tokens);
1233 static void on_response_imc_network_get_preferred_plmn(TcorePending *p,
1234 guint data_len, const void *data, void *user_data)
1236 const TcoreAtResponse *at_resp = data;
1237 CoreObject *co = tcore_pending_ref_core_object(p);
1238 ImcRespCbData *resp_cb_data = user_data;
1239 TelNetworkPreferredPlmnList plmn_list = {0,};
1240 guint count = 0, total_lines = 0;
1241 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; //TODO - CME Error mapping required.
1244 tcore_check_return_assert(co != NULL);
1245 tcore_check_return_assert(resp_cb_data != NULL);
1247 if (at_resp && at_resp->success) {
1251 gboolean gsm_act2 = FALSE, gsm_compact_act2 = FALSE;
1252 gboolean utran_act2 = FALSE;
1254 if (!at_resp->lines) {
1255 err("invalid response received");
1259 total_lines = g_slist_length(at_resp->lines);
1260 if (total_lines < 1) {
1261 msg("invalid message");
1266 result = TEL_NETWORK_RESULT_SUCCESS;
1268 plmn_list.list = tcore_malloc0(sizeof(TelNetworkPreferredPlmnInfo) * total_lines);
1269 plmn_list.count = 0;
1271 for (count = 0; count < total_lines; count++) {
1272 /* Take each line response at a time & parse it */
1273 line = tcore_at_tok_nth(at_resp->lines, count);
1274 tokens = tcore_at_tok_new(line);
1277 if ((resp = tcore_at_tok_nth(tokens, 0))) {
1278 plmn_list.list[count].index = atoi(resp);
1282 if ((resp = tcore_at_tok_nth(tokens, 2))) {
1283 plmn_list.list[count].plmn = tcore_at_tok_extract(resp);
1287 if ((resp = tcore_at_tok_nth(tokens, 3))) {
1288 gsm_act2 = atoi(resp);
1291 /*GSM_Compact_AcT2 */
1292 if ((resp = tcore_at_tok_nth(tokens, 4))) {
1293 gsm_compact_act2 = atoi(resp);
1297 if ((resp = tcore_at_tok_nth(tokens, 5))) {
1298 utran_act2 = atoi(resp);
1302 plmn_list.list[count].act = TEL_NETWORK_ACT_UMTS;
1303 else if (utran_act2 || gsm_compact_act2)
1304 plmn_list.list[count].act = TEL_NETWORK_ACT_GSM;
1307 tcore_at_tok_free(tokens);
1309 dbg("index[%d], plmn[%s], act[%d]",
1310 plmn_list.list[count].index,
1311 plmn_list.list[count].plmn,
1312 plmn_list.list[count].act);
1315 plmn_list.count = count;
1317 err("RESPONSE NOK");
1319 err("CME Error[%s]",(char *)at_resp->lines->data);
1323 dbg("get preferred plmn : [%s]",
1324 (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1326 /* Invoke callback */
1327 if (resp_cb_data->cb)
1328 resp_cb_data->cb(co, (gint)result, &plmn_list, resp_cb_data->cb_data);
1330 /* Free callback data */
1331 imc_destroy_resp_cb_data(resp_cb_data);
1333 for(count = 0; count < total_lines; count++) {
1334 g_free(plmn_list.list[count].plmn);
1336 tcore_free(plmn_list.list);
1340 /* Network Operations */
1342 * Operation - set_power_status
1345 * AT-Command: AT+XCOPS=<Type>
1348 * 0 numeric format of network MCC/MNC (three BCD
1349 * digit country code and two/three BCD digit network code)
1350 * 1 Short Name in ROM (NV-RAM)
1351 * 2 Long Name in ROM (NV-RAM)
1352 * 3 Short Network Operator Name (CPHS)
1353 * 4 Long Network Operator Name (CPHS)
1356 * 7 Service Provider Name
1357 * 8 EONS short operator name from EF-PNN
1358 * 9 EONS long operator name from EF-PNN
1359 * 11 Short PLMN name (When PS or CS is registered)
1360 * 12 Long PLMN name (When PS or CS is registered)
1361 * 13 numeric format of network MCC/MNC even in limited service
1363 * Response - Network name
1364 * Success: (Multiple Single line)
1365 * +XCOPS: <type>[,<name>[,<display_condition>]]
1368 * +CME ERROR: <error>
1370 static TelReturn imc_network_get_identity_info(CoreObject *co,
1371 TcoreObjectResponseCallback cb, void *cb_data)
1373 return __imc_network_fetch_nw_name(co, cb, cb_data);
1377 * Operation - network search
1379 * AT-Command: AT+COPS=?
1382 * Success: (Single line)
1383 * +COPS: [list of supported (<stat>,long alphanumeric <oper>
1384 * ,short alphanumeric <oper>,numeric <oper>[,< AcT>]
1385 * [,,(list of supported <mode>s),(list of supported <format>s)]
1388 * describes the format in which operator name is to be displayed. Different values of <format> can be:
1389 * 0 <oper> format presentations are set to long alphanumeric. If Network name not available it displays
1390 * combination of Mcc and MNC in string format.
1391 * 1 <oper> format presentation is set to short alphanumeric.
1392 * 2 <oper> format presentations set to numeric.
1394 * string type given in format <format>; this field may be up to 16 character long for long alphanumeric format, up
1395 * to 8 characters for short alphanumeric format and 5 Characters long for numeric format (MCC/MNC codes)
1397 * describes the status of the network. It is one of the response parameter for test command.
1398 * 0 Unknown Networks
1399 * 1 Network Available
1401 * 3 Forbidden Network
1403 * indicates the radio access technology and values can be:
1408 * +CME ERROR: <error>
1411 static TelReturn imc_network_search(CoreObject *co,
1412 TcoreObjectResponseCallback cb, void *cb_data)
1414 ImcRespCbData *resp_cb_data;
1415 CustomData *custom_data;
1416 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1418 custom_data = tcore_object_ref_user_data(co);
1419 if (custom_data->search_state
1420 == IMC_NETWORK_SEARCH_STATE_IN_PROGRESS) {
1421 warn("Network Search: [ALREADY IN PROGRESS]");
1422 return TEL_RETURN_FAILURE;
1425 /* Response callback data */
1426 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1428 /* Send Request to modem */
1429 ret = tcore_at_prepare_and_send_request_ex(co,
1430 "AT+COPS=?", "+COPS",
1431 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1432 TCORE_PENDING_PRIORITY_DEFAULT,
1434 on_response_imc_network_search, resp_cb_data,
1435 on_send_imc_request, NULL,
1438 if (ret != TEL_RETURN_SUCCESS) {
1439 err("Failed to process request - [%s]", "Network Search");
1440 imc_destroy_resp_cb_data(resp_cb_data);
1443 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_IN_PROGRESS;
1444 dbg("Search State: [IN PROGRESS]");
1450 static TelReturn imc_network_cancel_search(CoreObject *co,
1451 TcoreObjectResponseCallback cb, void *cb_data)
1453 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1454 ImcRespCbData *resp_cb_data;
1455 CustomData *custom_data;
1456 ImcNetworkCancelSearch cancel_search = {0, };
1458 custom_data = tcore_object_ref_user_data(co);
1459 if (custom_data->search_state
1460 == IMC_NETWORK_SEARCH_STATE_IN_PROGRESS) {
1461 dbg("Search in Progress...");
1463 /* Send Request to modem */
1464 ret = tcore_at_prepare_and_send_request_ex(co,
1466 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1467 TCORE_PENDING_PRIORITY_IMMEDIATELY,
1470 on_send_imc_request, NULL,
1473 if (ret != TEL_RETURN_SUCCESS) {
1474 err("Failed to process request - [%s]", "Cancel network search");
1478 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_CANCELLED;
1479 dbg("Search State: [CANCELLED]");
1483 dbg("No Search in Progress...");
1484 ret = TEL_RETURN_SUCCESS;
1487 cancel_search.co = co;
1488 cancel_search.result = TEL_NETWORK_RESULT_SUCCESS;
1490 /* Response callback data */
1491 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
1492 &cancel_search, sizeof(ImcNetworkCancelSearch));
1495 g_idle_add(on_response_imc_network_cancel_search, (gpointer)resp_cb_data);
1502 * Operation - automatic network selection
1504 * AT-Command: AT+COPS= [<mode> [, <format> [, <oper>> [, <AcT>]]]]
1507 * is used to select, whether the selection is done automatically by the ME or is forced by this command to
1508 * operator <oper> given in the format <format>.
1509 * The values of <mode> can be:
1510 * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
1511 * 1 Manual. Other parameters like format and operator need to be passed
1512 * 2 Deregister from network
1513 * 3 It sets <format> value. In this case <format> becomes a mandatory input
1514 * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered
1517 * Success:(No result)
1521 static TelReturn imc_network_select_automatic(CoreObject *co,
1522 TcoreObjectResponseCallback cb, void *cb_data)
1524 ImcRespCbData *resp_cb_data;
1525 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1528 /* Response callback data */
1529 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1531 /* Send Request to modem */
1532 ret = tcore_at_prepare_and_send_request(co,
1534 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1536 on_response_imc_network_default, resp_cb_data,
1537 on_send_imc_request, NULL);
1538 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Automatic network selection");
1544 * Operation - manual network selection
1546 * AT-Command: AT+COPS= [<mode> [, <format> [, <oper>> [, <AcT>]]]]
1549 * is used to select, whether the selection is done automatically by the ME or is forced by this command to
1550 * operator <oper> given in the format <format>.
1551 * The values of <mode> can be:
1552 * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
1553 * 1 Manual. Other parameters like format and operator need to be passed
1554 * 2 Deregister from network
1555 * 3 It sets <format> value. In this case <format> becomes a mandatory input
1556 * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered.
1558 * string type given in format <format>; this field may be up to 16 character long for long alphanumeric format, up
1559 * to 8 characters for short alphanumeric format and 5 Characters long for numeric format (MCC/MNC codes)
1561 * indicates the radio access technology and values can be:
1566 * Success:(No result)
1570 static TelReturn imc_network_select_manual(CoreObject *co,
1571 const TelNetworkSelectManualInfo *sel_manual,
1572 TcoreObjectResponseCallback cb, void *cb_data)
1574 ImcRespCbData *resp_cb_data;
1575 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1580 switch(sel_manual->act) {
1581 case TEL_NETWORK_ACT_GSM:
1582 case TEL_NETWORK_ACT_GPRS:
1583 case TEL_NETWORK_ACT_EGPRS:
1586 case TEL_NETWORK_ACT_UMTS:
1587 case TEL_NETWORK_ACT_GSM_AND_UMTS:
1588 case TEL_NETWORK_ACT_HSDPA:
1589 case TEL_NETWORK_ACT_HSPA:
1593 err("unsupported AcT");
1598 at_cmd = g_strdup_printf("AT+COPS=1,2,\"%s\",%d", sel_manual->plmn, act);
1600 /* Response callback data */
1601 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1603 /* Send Request to modem */
1604 ret = tcore_at_prepare_and_send_request(co,
1606 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1608 on_response_imc_network_default, resp_cb_data,
1609 on_send_imc_request, NULL);
1610 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Manual network selection");
1618 * Operation - get network selection mode
1620 * AT-Command: AT+COPS?
1623 * Success: (Single line)
1624 * +COPS: <mode>[,<format>,<oper>[,< AcT>]]
1626 * is used to select, whether the selection is done automatically by the ME or is forced by this command to
1627 * operator <oper> given in the format <format>.
1628 * The values of <mode> can be:
1629 * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
1630 * 1 Manual. Other parameters like format and operator need to be passed
1631 * 2 Deregister from network
1632 * 3 It sets <format> value. In this case <format> becomes a mandatory input
1633 * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered
1636 * +CME ERROR: <error>
1638 static TelReturn imc_network_get_selection_mode(CoreObject *co,
1639 TcoreObjectResponseCallback cb, void *cb_data)
1641 ImcRespCbData *resp_cb_data;
1642 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1644 /* Response callback data */
1645 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1647 /* Send Request to modem */
1648 ret = tcore_at_prepare_and_send_request(co,
1649 "AT+COPS?", "+COPS",
1650 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1652 on_response_imc_network_get_selection_mode, resp_cb_data,
1653 on_send_imc_request, NULL);
1654 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get selection mode");
1660 * Operation - set preferred plmn
1662 * AT-Command: AT+CPOL=<index>][,<format>[,<oper>[,<GSM_AcT>,<GSM_Compact_AcT>,<UTRAN_AcT>]]]
1664 * <indexn> integer type; the order number of operator in the SIM/USIM preferred operator list
1666 * 0 long format alphanumeric <oper>
1667 * 1 short format alphanumeric <oper>
1669 * <opern> string type; <format> indicates if the format is alphanumeric or numeric (see +COPS)
1670 * <GSM_AcTn>: GSM access technology
1671 * 0 access technology not selected
1672 * 1 access technology selected
1673 * <GSM_Compact_AcTn>: GSM compact access technology
1674 * 0 access technology not selected
1675 * 1 access technology selected
1676 * <UTRA_AcTn>: UTRA access technology
1677 * 0 access technology not selected
1678 * 1 access technology selected
1681 * Success:(No Result)
1684 * +CME ERROR: <error>
1686 static TelReturn imc_network_set_preferred_plmn(CoreObject *co,
1687 const TelNetworkPreferredPlmnInfo *pref_plmn,
1688 TcoreObjectResponseCallback cb, void *cb_data)
1690 ImcRespCbData *resp_cb_data;
1692 gboolean gsm_act = FALSE;
1693 gboolean gsm_compact_act = FALSE;
1694 gboolean utran_act = FALSE;
1695 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1698 switch(pref_plmn->act) {
1699 case TEL_NETWORK_ACT_GSM:
1700 case TEL_NETWORK_ACT_GPRS:
1701 case TEL_NETWORK_ACT_EGPRS:
1704 case TEL_NETWORK_ACT_UMTS:
1705 case TEL_NETWORK_ACT_HSDPA:
1706 case TEL_NETWORK_ACT_HSPA:
1709 case TEL_NETWORK_ACT_GSM_AND_UMTS:
1710 gsm_act = utran_act = TRUE;
1713 warn("unsupported AcT");
1717 at_cmd = g_strdup_printf("AT+CPOL=%d,%d,\"%s\",%d,%d,%d",
1718 pref_plmn->index, 2, pref_plmn->plmn, gsm_act, gsm_compact_act, utran_act);
1720 /* Response callback data */
1721 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1723 /* Send Request to modem */
1724 ret = tcore_at_prepare_and_send_request(co,
1726 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1728 on_response_imc_network_default, resp_cb_data,
1729 on_send_imc_request, NULL);
1730 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set preferred plmn");
1737 * Operation - get preferred plmn
1739 * AT-Command: AT+CPOL?
1741 * Success: (multiline)
1742 * +CPOL: <index1>,<format>,<oper1>
1743 * [,<GSM_AcT1>,<GSM_Compact_AcT1>,<UTRAN_AcT1>][<CR><LF>
1744 * +CPOL: <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>] [
\85]]
1749 static TelReturn imc_network_get_preferred_plmn(CoreObject *co,
1750 TcoreObjectResponseCallback cb, void *cb_data)
1752 ImcRespCbData *resp_cb_data;
1753 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1756 /* Response callback data */
1757 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1759 /* Send Request to modem */
1760 ret = tcore_at_prepare_and_send_request(co,
1761 "AT+CPOL=,2;+CPOL?", "+CPOL", //to make sure <oper> is numeric type in reponse.
1762 TCORE_AT_COMMAND_TYPE_MULTILINE,
1764 on_response_imc_network_get_preferred_plmn, resp_cb_data,
1765 on_send_imc_request, NULL);
1766 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get preferred plmn");
1772 * Operation - set network mode
1774 * AT-Command: AT+XRAT=<AcT> [, <PreferredAct>]
1776 * <AcT> indicates the radio access technology and may be
1778 * 1 GSM / UMTS Dual mode
1780 * 3-7 Reserved for future use.
1781 * 8 This option is to swap the RAT mode between the two stacks. Example: If Stack1 is in GSM mode and
1782 * Stack2 is in UMTS mode, this will configure Stack1 in UMTS mode and Stack2 in GSM mode.
1783 * Note : <Act> = 8 is used only for dual sim configuration. In this case < PreferredAct > is ignored
1785 * This parameter is used for network registration in case of <AcT>=1.
1789 * Success: (No result)
1792 * +CME ERROR: <error>
1794 static TelReturn imc_network_set_mode(CoreObject *co, TelNetworkMode mode,
1795 TcoreObjectResponseCallback cb, void *cb_data)
1797 ImcRespCbData *resp_cb_data;
1798 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1803 case TEL_NETWORK_MODE_AUTO:
1806 case TEL_NETWORK_MODE_2G:
1809 case TEL_NETWORK_MODE_3G:
1812 case TEL_NETWORK_MODE_LTE:
1814 err("Unsupported mode");
1820 at_cmd = g_strdup_printf("AT+XRAT=%d,2", act); //PreferredAct is UMTS
1823 at_cmd = g_strdup_printf("AT+XRAT=%d", act);
1825 /* Response callback data */
1826 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1828 /* Send Request to modem */
1829 ret = tcore_at_prepare_and_send_request(co,
1831 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1833 on_response_imc_network_default, resp_cb_data,
1834 on_send_imc_request, NULL);
1835 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set network mode");
1842 * Operation - get network mode
1844 * AT-Command: AT+XRAT?
1847 * Success: (Single line)
1848 * +XRAT : <Act>,<PreferredAct>
1849 * <AcT> indicates the radio access technology and may be
1851 * 1 GSM / UMTS Dual mode
1853 * 3-7 Reserved for future use.
1854 * 8 This option is to swap the RAT mode between the two stacks. Example: If Stack1 is in GSM mode and
1855 * Stack2 is in UMTS mode, this will configure Stack1 in UMTS mode and Stack2 in GSM mode.
1856 * Note : <Act> = 8 is used only for dual sim configuration. In this case < PreferredAct > is ignored
1858 * This parameter is used for network registration in case of <AcT>=1.
1863 * +CME ERROR: <error>
1866 static TelReturn imc_network_get_mode(CoreObject *co,
1867 TcoreObjectResponseCallback cb, void *cb_data)
1869 ImcRespCbData *resp_cb_data;
1873 /* Response callback data */
1874 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1876 /* Send Request to modem */
1877 ret = tcore_at_prepare_and_send_request(co,
1878 "AT+XRAT?", "+XRAT",
1879 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1881 on_response_imc_network_get_mode, resp_cb_data,
1882 on_send_imc_request, NULL);
1883 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get network mode");
1888 static TelReturn imc_network_get_neighboring_cell_info(CoreObject *co,
1889 TcoreObjectResponseCallback cb, void *cb_data)
1893 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1896 /* Network Operations */
1897 static TcoreNetworkOps imc_network_ops = {
1898 .get_identity_info = imc_network_get_identity_info,
1899 .search = imc_network_search,
1900 .cancel_search = imc_network_cancel_search,
1901 .select_automatic = imc_network_select_automatic,
1902 .select_manual = imc_network_select_manual,
1903 .get_selection_mode = imc_network_get_selection_mode,
1904 .set_preferred_plmn = imc_network_set_preferred_plmn,
1905 .get_preferred_plmn = imc_network_get_preferred_plmn,
1906 .set_mode = imc_network_set_mode,
1907 .get_mode = imc_network_get_mode,
1908 .get_neighboring_cell_info = imc_network_get_neighboring_cell_info
1911 gboolean imc_network_init(TcorePlugin *p, CoreObject *co)
1913 CustomData *custom_data;
1916 /* Set operations */
1917 tcore_network_set_ops(co, &imc_network_ops);
1920 custom_data = tcore_malloc0(sizeof(CustomData));
1921 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
1923 /* Link Custom data */
1924 tcore_object_link_user_data(co, custom_data);
1927 tcore_object_add_callback(co, "+CREG", on_notification_imc_cs_network_info, NULL);
1928 tcore_object_add_callback(co, "+CGREG", on_notification_imc_ps_network_info, NULL);
1929 tcore_object_add_callback(co, "+XNITZINFO", on_notification_imc_network_time_info, NULL);
1930 tcore_object_add_callback(co, "+XCIEV", on_notification_imc_network_rssi, NULL);
1933 * Add Hooks - Request and Notification
1935 tcore_plugin_add_request_hook(p,
1936 TCORE_COMMAND_MODEM_SET_FLIGHTMODE,
1937 on_hook_imc_set_flight_mode, NULL);
1938 tcore_plugin_add_notification_hook(p,
1939 TCORE_NOTIFICATION_SIM_STATUS,
1940 on_hook_imc_sim_status, co);
1942 //_insert_mcc_mnc_oper_list(cp, co_network);
1948 void imc_network_exit(TcorePlugin *p, CoreObject *co)
1950 CustomData *custom_data;
1952 custom_data = tcore_object_ref_user_data(co);
1953 if (custom_data != NULL)
1954 tcore_free(custom_data);