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 TelNetworkResult
146 __imc_network_convert_cme_error_tel_network_result(const TcoreAtResponse *at_resp)
148 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
150 GSList *tokens = NULL;
154 if (!at_resp || !at_resp->lines) {
155 err("Invalid response data");
159 line = (const gchar *)at_resp->lines->data;
160 tokens = tcore_at_tok_new(line);
161 if (g_slist_length(tokens) > 0) {
165 resp_str = g_slist_nth_data(tokens, 0);
167 err("Invalid CME Error data");
168 tcore_at_tok_free(tokens);
171 cme_err = atoi(resp_str);
172 dbg("CME error[%d]", cme_err);
176 result = TEL_NETWORK_RESULT_OPERATION_NOT_PERMITTED;
180 result = TEL_NETWORK_RESULT_OPERATION_NOT_SUPPORTED;
184 result = TEL_NETWORK_RESULT_MEMORY_FAILURE;
189 result = TEL_NETWORK_RESULT_FAILURE;
193 result = TEL_NETWORK_RESULT_INVALID_PARAMETER;
197 result = TEL_NETWORK_RESULT_FAILURE;
200 tcore_at_tok_free(tokens);
205 static void __on_response_imc_network_fetch_nw_name_internal(CoreObject *co,
206 gint result, const void *response, void *user_data)
208 TelNetworkIdentityInfo *identity = (TelNetworkIdentityInfo *)response;
210 /* Send notification if result is SUCCESS */
211 if (result == TEL_NETWORK_RESULT_SUCCESS)
212 tcore_object_send_notification(co,
213 TCORE_NOTIFICATION_NETWORK_IDENTITY,
214 sizeof(TelNetworkIdentityInfo), identity);
217 static TcoreHookReturn __on_response_imc_hook_set_flight_mode(CoreObject *co,
218 gint result, TcoreCommand command, const void *response, const void *user_data)
221 tcore_check_return_value(result == TEL_MODEM_RESULT_SUCCESS,
222 TCORE_HOOK_RETURN_CONTINUE);
224 dbg("Flight mode 'disabled', register to Network");
227 * TODO - Check for selection_mode
228 * Need to check if it is Manual or Automatic and based on
229 * that need to initiate Network Registratin accordingly.
231 __imc_network_register_to_network(co);
233 return TCORE_HOOK_RETURN_CONTINUE;
236 static void __on_response_imc_network_fetch_nw_name(TcorePending *p,
237 guint data_len, const void *data, void *user_data)
239 const TcoreAtResponse *at_resp = data;
240 CoreObject *co = tcore_pending_ref_core_object(p);
241 ImcRespCbData *resp_cb_data = user_data;
242 TelNetworkIdentityInfo identity = {0, };
244 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
248 tcore_check_return_assert(co != NULL);
249 tcore_check_return_assert(resp_cb_data != NULL);
251 if (at_resp && at_resp->success) {
252 if (at_resp->lines) {
254 GSList *tokens = NULL;
258 /* Validate that only 3 lines of response is received */
259 nol = g_slist_length(at_resp->lines);
261 err("Invalid response message");
262 imc_destroy_resp_cb_data(resp_cb_data);
266 /* Process the Multi-line response */
267 for (i = 0; i < nol; i++) {
268 line = g_slist_nth_data(at_resp->lines, i);
273 * +XCOPS: <type>[,<name>[,<display_condition>]]
275 dbg("<line> : [%s]", line);
276 tokens = tcore_at_tok_new(line);
278 if ((token_str = tcore_at_tok_nth(tokens, 0))) {
279 guint type = atoi(token_str);
280 dbg("<type> : [%d]", type);
283 case 0: /* PLMN (mcc, mnc) */
284 if ((token_str = tcore_at_tok_nth(tokens, 1))) {
285 if (strlen(token_str) > 0) {
286 identity.plmn = tcore_at_tok_extract((const char *)token_str);
289 tcore_network_set_plmn( co, identity.plmn);
294 case 1: /* Short Name in ROM (NV-RAM) */
295 case 3: /* Short Network Operator Name (CPHS) */
296 case 5: /* Short NITZ Name */
297 if ((token_str = tcore_at_tok_nth(tokens, 1))) {
298 if (strlen(token_str) > 0) {
299 identity.short_name = tcore_at_tok_extract((const char *)token_str);
302 /* Update Short name */
303 tcore_network_set_short_name(co, identity.short_name);
308 case 2: /* Long Name in ROM (NV-RAM) */
309 case 4: /* Long Network Operator Name (CPHS) */
310 case 6: /* Full NITZ Name */
311 if ((token_str = tcore_at_tok_nth(tokens, 1))) {
312 if (strlen(token_str) > 0) {
313 identity.long_name = tcore_at_tok_extract((const char *)token_str);
315 /* Update Long name */
316 tcore_network_set_long_name(co, identity.long_name);
327 tcore_at_tok_free(tokens);
330 /* Send Notification - Network identity */
331 dbg("Network name - Long name: [%s] Short name: [%s] "
332 "PLMN: [%s]", identity.long_name,
333 identity.short_name, identity.plmn);
335 result = TEL_NETWORK_RESULT_SUCCESS;
339 /* Invoke callback */
340 if (resp_cb_data->cb)
341 resp_cb_data->cb(co, (gint)result, &identity, resp_cb_data->cb_data);
344 tcore_free(identity.long_name);
345 tcore_free(identity.short_name);
346 tcore_free(identity.plmn);
348 /* Free callback data */
349 imc_destroy_resp_cb_data(resp_cb_data);
353 * Operation - fetch_nw_name
356 * AT-Command: AT+XCOPS=<Type>
359 * 0 numeric format of network MCC/MNC (three BCD
360 * digit country code and two/three BCD digit network code)
361 * 1 Short Name in ROM (NV-RAM)
362 * 2 Long Name in ROM (NV-RAM)
363 * 3 Short Network Operator Name (CPHS)
364 * 4 Long Network Operator Name (CPHS)
367 * 7 Service Provider Name
368 * 8 EONS short operator name from EF-PNN
369 * 9 EONS long operator name from EF-PNN
370 * 11 Short PLMN name (When PS or CS is registered)
371 * 12 Long PLMN name (When PS or CS is registered)
372 * 13 numeric format of network MCC/MNC even in limited service
374 * Response - Network name
375 * Success: (Multiple Single line)
376 * +XCOPS: <type>[,<name>[,<display_condition>]]
379 * +CME ERROR: <error>
381 static TelReturn __imc_network_fetch_nw_name(CoreObject *co,
382 TcoreObjectResponseCallback cb, void *cb_data)
384 ImcRespCbData *resp_cb_data = NULL;
387 /* Response callback data */
388 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
390 /* Send Request to modem */
391 ret = tcore_at_prepare_and_send_request(co,
392 "AT+XCOPS=0;+XCOPS=5;+XCOPS=6", "+XCOPS",
393 TCORE_AT_COMMAND_TYPE_MULTILINE,
395 __on_response_imc_network_fetch_nw_name, resp_cb_data,
396 on_send_imc_request, NULL);
397 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Fetch Network name");
403 static TcoreHookReturn on_hook_imc_set_flight_mode(CoreObject *co,
404 TcoreCommand command, const void *request, const void *user_data,
405 TcoreObjectResponseCallback cb, const void *cb_data)
407 gboolean *flight_mode = (gboolean *)request;
410 * Hook Set Flight mode request.
412 * Disable Flight mode - Hook response (if success Register to Network)
413 * Enable Flight mode - return
415 if (*flight_mode != TRUE) {
416 /* Add response hook */
417 tcore_object_add_response_hook(co, command, request,
418 __on_response_imc_hook_set_flight_mode, NULL);
420 return TCORE_HOOK_RETURN_CONTINUE;
423 dbg("Flight mode - [Enabled]");
424 return TCORE_HOOK_RETURN_CONTINUE;
427 static TcoreHookReturn on_hook_imc_sim_status(TcorePlugin *plugin,
428 TcoreNotification command, guint data_len, void *data, void *user_data)
430 const TelSimCardStatus *sim_status = (TelSimCardStatus *)data;
432 tcore_check_return_value(sim_status != NULL,
433 TCORE_HOOK_RETURN_CONTINUE);
436 * Hook SIM initialization Notification
438 * SIM INIT complete - Attach to network (Register to network)
439 * SIM INIT not complete - return
441 if (*sim_status == TEL_SIM_STATUS_SIM_INIT_COMPLETED) {
442 CoreObject *co = (CoreObject *)user_data;
443 dbg("SIM Initialized!!! Attach to Network");
445 tcore_check_return_value_assert(co != NULL,
446 TCORE_HOOK_RETURN_CONTINUE);
449 * TODO - Check for selection_mode
450 * Need to check if it is Manual or Automatic and based on
451 * that need to initiate Network Registratin accordingly.
453 __imc_network_register_to_network(co);
455 return TCORE_HOOK_RETURN_CONTINUE;
458 dbg("SIM not yet initialized - SIM Status: [%d]", *sim_status);
459 return TCORE_HOOK_RETURN_CONTINUE;
462 /* Notification callbacks */
464 * Notification: +CREG: <stat>[,<lac>,<ci>[,<AcT>]]
466 * Possible values of <stat> can be
467 * 0 Not registered, ME is not currently searching
468 * a new operator to register to
469 * 1 Registered, home network
470 * 2 Not registered, but ME is currently searching
471 * a new operator to register
472 * 3 Registration denied
474 * 5 Registered, in roaming
477 * string type; two byte location area code in
478 * hexadecimal format (e.g. 00C3)
481 * string type; four byte cell ID in hexadecimal
482 * format (e.g. 0000A13F)
490 * 6 UTRAN w/HSDPA and HSUPA
492 static gboolean on_notification_imc_cs_network_info(CoreObject *co,
493 const void *event_info, void *user_data)
495 GSList *lines = NULL;
498 dbg("Network notification - CS network info: [+CREG]");
500 lines = (GSList *)event_info;
501 if (g_slist_length(lines) != 1) {
502 err("+CREG unsolicited message expected to be Single line "
503 "but received multiple lines");
507 line = (gchar *) (lines->data);
509 TelNetworkRegStatusInfo registration_status = {0, };
510 TelNetworkCellInfo cell_info = {0, };
511 GSList *tokens = NULL;
513 guint stat = 0, act = 0, lac = 0, ci = 0;
514 gboolean roam_state = FALSE;
519 * +CREG: <stat>[,<lac>,<ci>[,<AcT>]]
521 tokens = tcore_at_tok_new(line);
522 if (g_slist_length(tokens) < 1) {
523 err("Invalid notification message");
528 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
529 err("No <stat> in +CREG");
532 stat = __imc_network_map_stat(atoi(token_str));
533 (void)tcore_network_set_cs_reg_status(co, stat);
536 if ((token_str = g_slist_nth_data(tokens, 1))) {
537 token_str = tcore_at_tok_extract((const gchar *)token_str);
539 lac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
541 /* Update Location Area Code (lac) information */
542 (void)tcore_network_set_lac(co, lac);
544 tcore_free(token_str);
546 dbg("No <lac> in +CREG");
547 (void)tcore_network_get_lac(co, &lac);
551 if ((token_str = g_slist_nth_data(tokens, 2))) {
552 token_str = tcore_at_tok_extract((const gchar *)token_str);
554 ci = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
556 /* Update Cell ID (ci) information */
557 (void)tcore_network_set_cell_id(co, ci);
559 tcore_free(token_str);
561 dbg("No <ci> in +CREG");
562 (void)tcore_network_get_cell_id(co, &ci);
566 if ((token_str = g_slist_nth_data(tokens, 3))) {
567 act = __imc_network_map_act(atoi(token_str));
568 (void)tcore_network_set_access_technology(co, act);
570 dbg("No <AcT> in +CREG");
571 (void)tcore_network_get_access_technology(co, &act);
573 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d", stat, lac, ci, act);
575 /* Send Notification - Network (CS) Registration status */
576 registration_status.cs_status = stat;
577 registration_status.act = act;
578 (void)tcore_network_get_ps_reg_status(co, ®istration_status.ps_status);
580 tcore_object_send_notification(co,
581 TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS,
582 sizeof(TelNetworkRegStatusInfo), ®istration_status);
585 case TEL_NETWORK_REG_STATUS_ROAMING:
586 roam_state = TRUE; // no break
587 case TEL_NETWORK_REG_STATUS_REGISTERED:
588 /* Fetch Network name - Internal request */
589 (void)__imc_network_fetch_nw_name(co,
590 __on_response_imc_network_fetch_nw_name_internal, NULL);
596 /* Set Roaming state */
597 tcore_network_set_roam_state(co, roam_state);
599 /* Send Notification - Cell info */
600 cell_info.lac = (gint)lac;
601 cell_info.cell_id = (gint)ci;
602 (void)tcore_network_get_rac(co, &cell_info.rac);
604 tcore_object_send_notification(co,
605 TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO,
606 sizeof(TelNetworkCellInfo), &cell_info);
610 tcore_at_tok_free(tokens);
617 * Notification: +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]]
619 * Possible values of <stat> can be
620 * 0 Not registered, ME is not currently searching a
621 * new operator to register to
622 * 1 Registered, home network
623 * 2 Not registered, but ME is currently searching a
624 * new operator to register
625 * 3 Registration denied
627 * 5 Registered, in roaming
630 * string type; two byte location area code in
631 * hexadecimal format (e.g. 00C3)
634 * string type; four byte cell ID in hexadecimal
635 * format (e.g. 0000A13F)
643 * 6 UTRAN w/HSDPA and HSUPA
646 * string type; one byte routing area code in hexadecimal format
648 static gboolean on_notification_imc_ps_network_info(CoreObject *co,
649 const void *event_info, void *user_data)
651 GSList *lines = NULL;
654 dbg("Network notification - PS network info: [+CGREG]");
656 lines = (GSList *)event_info;
657 if (g_slist_length(lines) != 1) {
658 err("+CGREG unsolicited message expected to be Single line "
659 "but received multiple lines");
663 line = (gchar *) (lines->data);
665 TelNetworkRegStatusInfo registration_status = {0, };
666 TelNetworkCellInfo cell_info = {0, };
667 GSList *tokens = NULL;
669 guint stat = 0, act = 0, lac = 0, ci = 0, rac = 0;
670 gboolean roam_state = FALSE;
675 * +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]]
677 tokens = tcore_at_tok_new(line);
678 if (g_slist_length(tokens) < 1) {
679 err("Invalid notification message");
684 if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
685 err("No <stat> in +CGREG");
688 stat = __imc_network_map_stat(atoi(token_str));
689 (void)tcore_network_set_ps_reg_status(co, stat);
692 if ((token_str = g_slist_nth_data(tokens, 1))) {
693 token_str = tcore_at_tok_extract((const gchar *)token_str);
695 lac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
697 /* Update Location Area Code (lac) information */
698 (void)tcore_network_set_lac(co, lac);
700 tcore_free(token_str);
702 dbg("No <lac> in +CGREG");
703 (void)tcore_network_get_lac(co, &lac);
707 if ((token_str = g_slist_nth_data(tokens, 2))) {
708 token_str = tcore_at_tok_extract((const gchar *)token_str);
710 ci = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
712 /* Update Cell ID (ci) information */
713 (void)tcore_network_set_cell_id(co, ci);
715 tcore_free(token_str);
717 dbg("No <ci> in +CGREG");
718 (void)tcore_network_get_cell_id(co, &ci);
722 if ((token_str = g_slist_nth_data(tokens, 3))) {
723 act = __imc_network_map_act(atoi(token_str));
724 (void)tcore_network_set_access_technology(co, act);
726 dbg("No <AcT> in +CGREG");
727 (void)tcore_network_get_access_technology(co, &act);
731 if ((token_str = g_slist_nth_data(tokens, 4))) {
732 token_str = tcore_at_tok_extract((const gchar *)token_str);
734 rac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16);
736 /* Update Routing Area Code (rac) information */
737 (void)tcore_network_set_rac(co, rac);
739 tcore_free(token_str);
741 err("No <ci> in +CGREG");
742 (void)tcore_network_get_rac(co, &rac);
744 dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d <rac>: 0x%x", stat, lac, ci, act, rac);
746 /* Send Notification - Network (PS) Registration status */
747 registration_status.ps_status = stat;
748 registration_status.act = act;
749 (void)tcore_network_get_cs_reg_status(co, ®istration_status.cs_status);
751 tcore_object_send_notification(co,
752 TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS,
753 sizeof(TelNetworkRegStatusInfo), ®istration_status);
755 /* Set Roaming state */
756 if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING)
759 tcore_network_set_roam_state(co, roam_state);
761 /* Send Notification - Cell info */
763 cell_info.cell_id = ci;
765 tcore_object_send_notification(co,
766 TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO,
767 sizeof(TelNetworkCellInfo), &cell_info);
771 tcore_at_tok_free(tokens);
778 * Notification: +XNITZINFO: <fullname>,<shortname>,<LTZ>,<UT>,<DST>
781 * string type; Network name in long alphanumeric format.
784 * string type; Network name in short alphanumeric format.
787 * Local Time Zone; represented as 1 unit = 15 minutes.
790 * string type value; Universal Time
791 * format is "yy/MM/dd,hh:mm:ss",
792 * wherein characters indicates year, month, day, hour,
795 * Daylight Saving Time; represented in hours.
797 static gboolean on_notification_imc_network_time_info(CoreObject *co,
798 const void *event_info, void *user_data)
800 GSList *lines = NULL;
803 dbg("Network notification - Time info: [+XNITZINFO]");
805 lines = (GSList *)event_info;
806 if (g_slist_length(lines) != 1) {
807 err("+XNITZINFO unsolicited message expected to be Single line "
808 "but received multiple lines");
812 line = (gchar *)lines->data;
814 GSList *tokens = NULL;
815 TelNetworkNitzInfoNoti nitz_info = {0, };
816 gchar *fullname, *shortname;
818 gchar tmp_time[8] = {0};
824 * +XNITZINFO: <fullname>,<shortname>,<LTZ>,<UT>,<DST>
826 tokens = tcore_at_tok_new(line);
829 if ((fullname = tcore_at_tok_nth(tokens, 1))) {
830 if (strlen(fullname) > 0) {
831 fullname = tcore_at_tok_extract((const char *)fullname);
833 /* Update Long name */
834 tcore_network_set_long_name(co, fullname);
836 tcore_free(fullname);
841 if ((shortname = tcore_at_tok_nth(tokens, 1))) {
842 if (strlen(shortname) > 0) {
843 shortname = tcore_at_tok_extract((const char *)shortname);
845 /* Update Short name */
846 tcore_network_set_short_name(co, shortname);
848 tcore_free(shortname);
853 if ((ltz = g_slist_nth_data(tokens, 2)))
854 nitz_info.gmtoff = atoi(ltz) * 15;/* gmtoff in minutes */
856 if ((time = g_slist_nth_data(tokens, 3))
857 && (strlen(time) > 18)) {
858 /* (time + 1) - Skip past initial quote (") */
859 g_strlcpy(tmp_time, time + 1, 2+1);
860 nitz_info.year = atoi(tmp_time);
862 /* skip slash (/) after year param */
863 g_strlcpy(tmp_time, time + 4, 2+1);
864 nitz_info.month = atoi(tmp_time);
866 /* skip past slash (/) after month param */
867 g_strlcpy(tmp_time, time + 7, 2+1);
868 nitz_info.day = atoi(tmp_time);
870 /* skip past comma (,) after day param */
871 g_strlcpy(tmp_time, time + 10, 2+1);
872 nitz_info.hour = atoi(tmp_time);
874 /* skip past colon (:) after hour param */
875 g_strlcpy(tmp_time, time + 13, 2+1);
876 nitz_info.minute = atoi(tmp_time);
878 /* skip past colon (:) after minute param */
879 g_strlcpy(tmp_time, time + 16, 2+1);
880 nitz_info.second = atoi(tmp_time);
884 if ((dstoff = g_slist_nth_data(tokens, 4))) {
885 nitz_info.dstoff = atoi(dstoff);
886 nitz_info.isdst = TRUE;
890 tcore_network_get_plmn(co, &nitz_info.plmn);
892 /* Send Notification - Network time info */
893 tcore_object_send_notification(co,
894 TCORE_NOTIFICATION_NETWORK_TIMEINFO,
895 sizeof(TelNetworkNitzInfoNoti), &nitz_info);
898 tcore_free(nitz_info.plmn);
899 tcore_at_tok_free(tokens);
909 * +XCIEV:,<battery_level>
911 * 'Radio Signal Strength' <rssi> can have the values
912 * 0 -107 dBm or less or unknown
921 * 'Battery Level' <battery_level> can have the values
922 * 0 0 % <= level < 5 %
923 * 1 5 % <= level < 15 %
924 * 2 15 % <= level < 25 %
925 * 3 25 % <= level < 40 %
926 * 4 40 % <= level < 55 %
927 * 5 55 % <= level < 70 %
928 * 6 70 % <= level < 85 %
929 * 7 85 % <= level <= 100 %
932 * <battery_level> is not consider for
933 * TCORE_NOTIFICATION_NETWORK_RSSI notification
935 static gboolean on_notification_imc_network_rssi(CoreObject *co,
936 const void *event_info, void *user_data)
938 GSList *lines = NULL;
941 dbg("Network notification - Icon (rssi) info: [+XCIEV]");
943 lines = (GSList *)event_info;
944 if (g_slist_length(lines) != 1) {
945 err("+XCIEV unsolicited message expected to be Single line "
946 "but received multiple lines");
950 line = (gchar *)lines->data;
952 GSList *tokens = NULL;
960 tokens = tcore_at_tok_new(line);
962 rssi_token = (gchar *)g_slist_nth_data(tokens, 0);
963 if (rssi_token && strlen(rssi_token)) {
964 guint rssi_bar = atoi(rssi_token);
965 dbg("RSSI Level: [%d]", rssi_bar);
967 /* Send Notification - Network Rssi */
968 tcore_object_send_notification(co,
969 TCORE_NOTIFICATION_NETWORK_RSSI,
970 sizeof(guint), &rssi_bar);
974 tcore_at_tok_free(tokens);
980 /* Network Responses */
982 static void on_response_imc_network_search(TcorePending *p,
983 guint data_len, const void *data, void *user_data)
985 const TcoreAtResponse *at_resp = data;
986 CoreObject *co = tcore_pending_ref_core_object(p);
987 CustomData *custom_data;
989 ImcRespCbData *resp_cb_data = user_data;
990 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
991 TelNetworkPlmnList plmn_list = {0, };
992 guint num_network_avail = 0;
994 GSList *tokens = NULL;
997 tcore_check_return_assert(co != NULL);
998 tcore_check_return_assert(resp_cb_data != NULL);
1000 custom_data = tcore_object_ref_user_data(co);
1001 tcore_check_return_assert(custom_data != NULL);
1003 if (at_resp && at_resp->success) {
1005 GSList *net_token = NULL;
1009 /* If Request is Cancelled then return back SUCCESS/SEARCH_CANCELLED */
1010 if (custom_data->search_state
1011 == IMC_NETWORK_SEARCH_STATE_CANCELLED) {
1012 dbg("Network Search has been Cancelled!!!");
1017 * Need to introduce new Result -
1018 * TEL_NETWORK_RESULT_SEARCH_ABORTED/CANCELLED
1020 * Presently sending TEL_NETWORK_RESULT_FAILURE
1022 result = TEL_NETWORK_RESULT_FAILURE;
1027 if (!at_resp->lines) {
1028 err("invalid response received");
1032 line = (char *) at_resp->lines->data;
1033 tokens = tcore_at_tok_new(line);
1034 num_network_avail = g_slist_length(tokens);
1035 if (num_network_avail < 1) {
1036 err("invalid message");
1040 plmn_list.network_list = tcore_malloc0(sizeof(TelNetworkInfo) * num_network_avail);
1042 plmn_list.count = 0;
1043 for (count = 0; count < num_network_avail; count++) {
1045 net_token = tcore_at_tok_new(g_slist_nth_data(tokens, count));
1046 if (NULL == net_token)
1049 resp = tcore_at_tok_nth(net_token, 0);
1051 plmn_list.network_list[count].plmn_status = atoi(resp);
1052 dbg("status[%d]", plmn_list.network_list[count].plmn_status);
1055 if ((resp = tcore_at_tok_nth(net_token, 1))) {
1056 /* Long Alpha name */
1057 dbg("long alpha name[%s]", resp);
1058 plmn_list.network_list[count].network_identity.long_name =
1059 tcore_at_tok_extract(resp);
1062 if ((resp = tcore_at_tok_nth(net_token, 2))) {
1063 /* Short Alpha name */
1064 dbg("Short Alpha name[%s]", resp);
1065 plmn_list.network_list[count].network_identity.short_name =
1066 tcore_at_tok_extract(resp);
1070 if ((resp = tcore_at_tok_nth(net_token, 3))) {
1071 dbg("PLMN ID[%s]", resp);
1072 plmn_list.network_list[count].network_identity.plmn =
1073 tcore_at_tok_extract(resp);
1076 /* Parse Access Technology */
1077 if ((resp = tcore_at_tok_nth(tokens, 4))) {
1080 plmn_list.network_list[count].act = TEL_NETWORK_ACT_GSM;
1082 plmn_list.network_list[count].act = TEL_NETWORK_ACT_UMTS;
1085 dbg("Operator [%d] :: status = %d, long_name = %s, short_name = %s plmn = %s, AcT=%d",
1087 plmn_list.network_list[count].plmn_status,
1088 plmn_list.network_list[count].network_identity.long_name,
1089 plmn_list.network_list[count].network_identity.short_name,
1090 plmn_list.network_list[count].network_identity.plmn,
1091 plmn_list.network_list[count].act);
1094 tcore_at_tok_free(net_token);
1096 result = TEL_NETWORK_RESULT_SUCCESS;
1098 err("RESPONSE NOK");
1099 result = __imc_network_convert_cme_error_tel_network_result(at_resp);
1103 dbg("Network search : [%s]",
1104 (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1106 /* Update Search state */
1107 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
1109 /* Invoke callback */
1110 if (resp_cb_data->cb)
1111 resp_cb_data->cb(co, (gint)result, &plmn_list, resp_cb_data->cb_data);
1113 imc_destroy_resp_cb_data(resp_cb_data);
1116 for (count = 0; count < num_network_avail; count++) {
1117 g_free(plmn_list.network_list[count].network_identity.long_name);
1118 g_free(plmn_list.network_list[count].network_identity.short_name);
1119 g_free(plmn_list.network_list[count].network_identity.plmn);
1122 tcore_free(plmn_list.network_list);
1123 tcore_at_tok_free(tokens);
1126 static gboolean on_response_imc_network_cancel_search(gpointer data)
1128 ImcRespCbData *resp_cb_data = data;
1129 ImcNetworkCancelSearch *cancel_search =
1130 (ImcNetworkCancelSearch *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
1132 /* Invoke callback */
1133 if (resp_cb_data->cb)
1134 resp_cb_data->cb(cancel_search->co, (gint)cancel_search->result,
1135 NULL, resp_cb_data->cb_data);
1137 imc_destroy_resp_cb_data(resp_cb_data);
1139 /* To stop the cycle, need to return FALSE */
1143 static void on_response_imc_network_get_selection_mode(TcorePending *p,
1144 guint data_len, const void *data, void *user_data)
1146 const TcoreAtResponse *at_resp = data;
1147 CoreObject *co = tcore_pending_ref_core_object(p);
1148 ImcRespCbData *resp_cb_data = user_data;
1149 TelNetworkSelectionMode selection_mode = -1;
1150 GSList *tokens = NULL;
1152 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
1155 tcore_check_return_assert(co != NULL);
1156 tcore_check_return_assert(resp_cb_data != NULL);
1158 if (at_resp && at_resp->success) {
1162 if (!at_resp->lines) {
1163 err("invalid response received");
1167 line = (char *) at_resp->lines->data;
1168 tokens = tcore_at_tok_new(line);
1169 if (g_slist_length(tokens) < 1) {
1170 msg("invalid message");
1175 mode = atoi(tcore_at_tok_nth(tokens, 0));
1177 selection_mode = TEL_NETWORK_SELECTION_MODE_AUTOMATIC;
1179 selection_mode = TEL_NETWORK_SELECTION_MODE_MANUAL;
1181 result = TEL_NETWORK_RESULT_SUCCESS;
1182 dbg("selection mode[%d]", selection_mode);
1185 err("RESPONSE NOK");
1186 result = __imc_network_convert_cme_error_tel_network_result(at_resp);
1190 dbg("Get selection mode : [%s]",
1191 (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1192 /* Invoke callback */
1193 if (resp_cb_data->cb)
1194 resp_cb_data->cb(co, (gint)result, &selection_mode, resp_cb_data->cb_data);
1196 /* Free callback data */
1197 imc_destroy_resp_cb_data(resp_cb_data);
1199 tcore_at_tok_free(tokens);
1202 static void on_response_imc_network_default(TcorePending *p,
1203 guint data_len, const void *data, void *user_data)
1205 const TcoreAtResponse *at_resp = data;
1206 CoreObject *co = tcore_pending_ref_core_object(p);
1207 ImcRespCbData *resp_cb_data = user_data;
1208 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
1211 tcore_check_return_assert(co != NULL);
1212 tcore_check_return_assert(resp_cb_data != NULL);
1214 if (at_resp && at_resp->success) {
1216 result = TEL_NETWORK_RESULT_SUCCESS;
1218 err("RESPONSE NOK");
1219 result = __imc_network_convert_cme_error_tel_network_result(at_resp);
1222 /* Invoke callback */
1223 if (resp_cb_data->cb)
1224 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1226 imc_destroy_resp_cb_data(resp_cb_data);
1230 static void on_response_imc_network_get_mode(TcorePending *p,
1231 guint data_len, const void *data, void *user_data)
1233 const TcoreAtResponse *at_resp = data;
1234 CoreObject *co = tcore_pending_ref_core_object(p);
1235 ImcRespCbData *resp_cb_data = user_data;
1236 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
1237 TelNetworkMode mode = -1;
1238 GSList *tokens = NULL;
1241 tcore_check_return_assert(co != NULL);
1242 tcore_check_return_assert(resp_cb_data != NULL);
1244 if (at_resp && at_resp->success) {
1248 if (!at_resp->lines) {
1249 err("invalid response received");
1253 line = (char *) at_resp->lines->data;
1254 tokens = tcore_at_tok_new(line);
1255 if (g_slist_length(tokens) < 1) {
1256 err("invalid message");
1261 net_mode = atoi(tcore_at_tok_nth(tokens, 0));
1262 dbg("mode = %d", net_mode);
1266 mode = TEL_NETWORK_MODE_2G;
1269 mode = TEL_NETWORK_MODE_AUTO;
1272 mode = TEL_NETWORK_MODE_3G;
1275 err("Unsupported mode [%d]", net_mode);
1278 result = TEL_NETWORK_RESULT_SUCCESS;
1280 err("RESPONSE NOK");
1281 result = __imc_network_convert_cme_error_tel_network_result(at_resp);
1284 /* Invoke callback */
1285 if (resp_cb_data->cb)
1286 resp_cb_data->cb(co, (gint)result, &mode, resp_cb_data->cb_data);
1288 /* Free callback data */
1289 imc_destroy_resp_cb_data(resp_cb_data);
1291 tcore_at_tok_free(tokens);
1294 static void on_response_imc_network_get_preferred_plmn(TcorePending *p,
1295 guint data_len, const void *data, void *user_data)
1297 const TcoreAtResponse *at_resp = data;
1298 CoreObject *co = tcore_pending_ref_core_object(p);
1299 ImcRespCbData *resp_cb_data = user_data;
1300 TelNetworkPreferredPlmnList plmn_list = {0,};
1301 guint count = 0, total_lines = 0;
1302 TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
1305 tcore_check_return_assert(co != NULL);
1306 tcore_check_return_assert(resp_cb_data != NULL);
1308 if (at_resp && at_resp->success) {
1312 gboolean gsm_act2 = FALSE, gsm_compact_act2 = FALSE;
1313 gboolean utran_act2 = FALSE;
1315 if (!at_resp->lines) {
1316 err("invalid response received");
1320 total_lines = g_slist_length(at_resp->lines);
1321 if (total_lines < 1) {
1322 msg("invalid message");
1327 result = TEL_NETWORK_RESULT_SUCCESS;
1329 plmn_list.list = tcore_malloc0(sizeof(TelNetworkPreferredPlmnInfo) * total_lines);
1330 plmn_list.count = 0;
1332 for (count = 0; count < total_lines; count++) {
1333 /* Take each line response at a time & parse it */
1334 line = tcore_at_tok_nth(at_resp->lines, count);
1335 tokens = tcore_at_tok_new(line);
1338 if ((resp = tcore_at_tok_nth(tokens, 0))) {
1339 plmn_list.list[count].index = atoi(resp);
1343 if ((resp = tcore_at_tok_nth(tokens, 2))) {
1344 plmn_list.list[count].plmn = tcore_at_tok_extract(resp);
1348 if ((resp = tcore_at_tok_nth(tokens, 3))) {
1349 gsm_act2 = atoi(resp);
1352 /*GSM_Compact_AcT2 */
1353 if ((resp = tcore_at_tok_nth(tokens, 4))) {
1354 gsm_compact_act2 = atoi(resp);
1358 if ((resp = tcore_at_tok_nth(tokens, 5))) {
1359 utran_act2 = atoi(resp);
1363 plmn_list.list[count].act = TEL_NETWORK_ACT_UMTS;
1364 else if (utran_act2 || gsm_compact_act2)
1365 plmn_list.list[count].act = TEL_NETWORK_ACT_GSM;
1368 tcore_at_tok_free(tokens);
1370 dbg("index[%d], plmn[%s], act[%d]",
1371 plmn_list.list[count].index,
1372 plmn_list.list[count].plmn,
1373 plmn_list.list[count].act);
1376 plmn_list.count = count;
1378 err("RESPONSE NOK");
1379 result = __imc_network_convert_cme_error_tel_network_result(at_resp);
1383 dbg("get preferred plmn : [%s]",
1384 (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1386 /* Invoke callback */
1387 if (resp_cb_data->cb)
1388 resp_cb_data->cb(co, (gint)result, &plmn_list, resp_cb_data->cb_data);
1390 /* Free callback data */
1391 imc_destroy_resp_cb_data(resp_cb_data);
1393 for(count = 0; count < total_lines; count++) {
1394 g_free(plmn_list.list[count].plmn);
1396 tcore_free(plmn_list.list);
1400 /* Network Operations */
1402 * Operation - set_power_status
1405 * AT-Command: AT+XCOPS=<Type>
1408 * 0 numeric format of network MCC/MNC (three BCD
1409 * digit country code and two/three BCD digit network code)
1410 * 1 Short Name in ROM (NV-RAM)
1411 * 2 Long Name in ROM (NV-RAM)
1412 * 3 Short Network Operator Name (CPHS)
1413 * 4 Long Network Operator Name (CPHS)
1416 * 7 Service Provider Name
1417 * 8 EONS short operator name from EF-PNN
1418 * 9 EONS long operator name from EF-PNN
1419 * 11 Short PLMN name (When PS or CS is registered)
1420 * 12 Long PLMN name (When PS or CS is registered)
1421 * 13 numeric format of network MCC/MNC even in limited service
1423 * Response - Network name
1424 * Success: (Multiple Single line)
1425 * +XCOPS: <type>[,<name>[,<display_condition>]]
1428 * +CME ERROR: <error>
1430 static TelReturn imc_network_get_identity_info(CoreObject *co,
1431 TcoreObjectResponseCallback cb, void *cb_data)
1433 return __imc_network_fetch_nw_name(co, cb, cb_data);
1437 * Operation - network search
1439 * AT-Command: AT+COPS=?
1442 * Success: (Single line)
1443 * +COPS: [list of supported (<stat>,long alphanumeric <oper>
1444 * ,short alphanumeric <oper>,numeric <oper>[,< AcT>]
1445 * [,,(list of supported <mode>s),(list of supported <format>s)]
1448 * describes the format in which operator name is to be displayed. Different values of <format> can be:
1449 * 0 <oper> format presentations are set to long alphanumeric. If Network name not available it displays
1450 * combination of Mcc and MNC in string format.
1451 * 1 <oper> format presentation is set to short alphanumeric.
1452 * 2 <oper> format presentations set to numeric.
1454 * string type given in format <format>; this field may be up to 16 character long for long alphanumeric format, up
1455 * to 8 characters for short alphanumeric format and 5 Characters long for numeric format (MCC/MNC codes)
1457 * describes the status of the network. It is one of the response parameter for test command.
1458 * 0 Unknown Networks
1459 * 1 Network Available
1461 * 3 Forbidden Network
1463 * indicates the radio access technology and values can be:
1468 * +CME ERROR: <error>
1471 static TelReturn imc_network_search(CoreObject *co,
1472 TcoreObjectResponseCallback cb, void *cb_data)
1474 ImcRespCbData *resp_cb_data;
1475 CustomData *custom_data;
1476 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1478 custom_data = tcore_object_ref_user_data(co);
1479 if (custom_data->search_state
1480 == IMC_NETWORK_SEARCH_STATE_IN_PROGRESS) {
1481 warn("Network Search: [ALREADY IN PROGRESS]");
1482 return TEL_RETURN_FAILURE;
1485 /* Response callback data */
1486 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1488 /* Send Request to modem */
1489 ret = tcore_at_prepare_and_send_request_ex(co,
1490 "AT+COPS=?", "+COPS",
1491 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1492 TCORE_PENDING_PRIORITY_DEFAULT,
1494 on_response_imc_network_search, resp_cb_data,
1495 on_send_imc_request, NULL,
1498 if (ret != TEL_RETURN_SUCCESS) {
1499 err("Failed to process request - [%s]", "Network Search");
1500 imc_destroy_resp_cb_data(resp_cb_data);
1503 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_IN_PROGRESS;
1504 dbg("Search State: [IN PROGRESS]");
1510 static TelReturn imc_network_cancel_search(CoreObject *co,
1511 TcoreObjectResponseCallback cb, void *cb_data)
1513 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1514 ImcRespCbData *resp_cb_data;
1515 CustomData *custom_data;
1516 ImcNetworkCancelSearch cancel_search = {0, };
1518 custom_data = tcore_object_ref_user_data(co);
1519 if (custom_data->search_state
1520 == IMC_NETWORK_SEARCH_STATE_IN_PROGRESS) {
1521 dbg("Search in Progress...");
1523 /* Send Request to modem */
1524 ret = tcore_at_prepare_and_send_request_ex(co,
1526 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1527 TCORE_PENDING_PRIORITY_IMMEDIATELY,
1530 on_send_imc_request, NULL,
1533 if (ret != TEL_RETURN_SUCCESS) {
1534 err("Failed to process request - [%s]", "Cancel network search");
1538 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_CANCELLED;
1539 dbg("Search State: [CANCELLED]");
1543 dbg("No Search in Progress...");
1544 ret = TEL_RETURN_SUCCESS;
1547 cancel_search.co = co;
1548 cancel_search.result = TEL_NETWORK_RESULT_SUCCESS;
1550 /* Response callback data */
1551 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
1552 &cancel_search, sizeof(ImcNetworkCancelSearch));
1555 g_idle_add(on_response_imc_network_cancel_search, (gpointer)resp_cb_data);
1562 * Operation - automatic network selection
1564 * AT-Command: AT+COPS= [<mode> [, <format> [, <oper>> [, <AcT>]]]]
1567 * is used to select, whether the selection is done automatically by the ME or is forced by this command to
1568 * operator <oper> given in the format <format>.
1569 * The values of <mode> can be:
1570 * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
1571 * 1 Manual. Other parameters like format and operator need to be passed
1572 * 2 Deregister from network
1573 * 3 It sets <format> value. In this case <format> becomes a mandatory input
1574 * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered
1577 * Success:(No result)
1581 static TelReturn imc_network_select_automatic(CoreObject *co,
1582 TcoreObjectResponseCallback cb, void *cb_data)
1584 ImcRespCbData *resp_cb_data;
1585 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1588 /* Response callback data */
1589 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1591 /* Send Request to modem */
1592 ret = tcore_at_prepare_and_send_request(co,
1594 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1596 on_response_imc_network_default, resp_cb_data,
1597 on_send_imc_request, NULL);
1598 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Automatic network selection");
1604 * Operation - manual network selection
1606 * AT-Command: AT+COPS= [<mode> [, <format> [, <oper>> [, <AcT>]]]]
1609 * is used to select, whether the selection is done automatically by the ME or is forced by this command to
1610 * operator <oper> given in the format <format>.
1611 * The values of <mode> can be:
1612 * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
1613 * 1 Manual. Other parameters like format and operator need to be passed
1614 * 2 Deregister from network
1615 * 3 It sets <format> value. In this case <format> becomes a mandatory input
1616 * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered.
1618 * string type given in format <format>; this field may be up to 16 character long for long alphanumeric format, up
1619 * to 8 characters for short alphanumeric format and 5 Characters long for numeric format (MCC/MNC codes)
1621 * indicates the radio access technology and values can be:
1626 * Success:(No result)
1630 static TelReturn imc_network_select_manual(CoreObject *co,
1631 const TelNetworkSelectManualInfo *sel_manual,
1632 TcoreObjectResponseCallback cb, void *cb_data)
1634 ImcRespCbData *resp_cb_data;
1635 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1640 switch (sel_manual->act) {
1641 case TEL_NETWORK_ACT_GSM:
1642 case TEL_NETWORK_ACT_GPRS:
1643 case TEL_NETWORK_ACT_EGPRS:
1646 case TEL_NETWORK_ACT_UMTS:
1647 case TEL_NETWORK_ACT_GSM_AND_UMTS:
1648 case TEL_NETWORK_ACT_HSDPA:
1649 case TEL_NETWORK_ACT_HSPA:
1653 err("unsupported AcT");
1658 at_cmd = g_strdup_printf("AT+COPS=1,2,\"%s\",%d", sel_manual->plmn, act);
1660 /* Response callback data */
1661 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1663 /* Send Request to modem */
1664 ret = tcore_at_prepare_and_send_request(co,
1666 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1668 on_response_imc_network_default, resp_cb_data,
1669 on_send_imc_request, NULL);
1670 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Manual network selection");
1678 * Operation - get network selection mode
1680 * AT-Command: AT+COPS?
1683 * Success: (Single line)
1684 * +COPS: <mode>[,<format>,<oper>[,< AcT>]]
1686 * is used to select, whether the selection is done automatically by the ME or is forced by this command to
1687 * operator <oper> given in the format <format>.
1688 * The values of <mode> can be:
1689 * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
1690 * 1 Manual. Other parameters like format and operator need to be passed
1691 * 2 Deregister from network
1692 * 3 It sets <format> value. In this case <format> becomes a mandatory input
1693 * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered
1696 * +CME ERROR: <error>
1698 static TelReturn imc_network_get_selection_mode(CoreObject *co,
1699 TcoreObjectResponseCallback cb, void *cb_data)
1701 ImcRespCbData *resp_cb_data;
1702 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1704 /* Response callback data */
1705 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1707 /* Send Request to modem */
1708 ret = tcore_at_prepare_and_send_request(co,
1709 "AT+COPS?", "+COPS",
1710 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1712 on_response_imc_network_get_selection_mode, resp_cb_data,
1713 on_send_imc_request, NULL);
1714 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get selection mode");
1720 * Operation - set preferred plmn
1722 * AT-Command: AT+CPOL=<index>][,<format>[,<oper>[,<GSM_AcT>,<GSM_Compact_AcT>,<UTRAN_AcT>]]]
1724 * <indexn> integer type; the order number of operator in the SIM/USIM preferred operator list
1726 * 0 long format alphanumeric <oper>
1727 * 1 short format alphanumeric <oper>
1729 * <opern> string type; <format> indicates if the format is alphanumeric or numeric (see +COPS)
1730 * <GSM_AcTn>: GSM access technology
1731 * 0 access technology not selected
1732 * 1 access technology selected
1733 * <GSM_Compact_AcTn>: GSM compact access technology
1734 * 0 access technology not selected
1735 * 1 access technology selected
1736 * <UTRA_AcTn>: UTRA access technology
1737 * 0 access technology not selected
1738 * 1 access technology selected
1741 * Success:(No Result)
1744 * +CME ERROR: <error>
1746 static TelReturn imc_network_set_preferred_plmn(CoreObject *co,
1747 const TelNetworkPreferredPlmnInfo *pref_plmn,
1748 TcoreObjectResponseCallback cb, void *cb_data)
1750 ImcRespCbData *resp_cb_data;
1752 gboolean gsm_act = FALSE;
1753 gboolean gsm_compact_act = FALSE;
1754 gboolean utran_act = FALSE;
1755 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1758 switch (pref_plmn->act) {
1759 case TEL_NETWORK_ACT_GSM:
1760 case TEL_NETWORK_ACT_GPRS:
1761 case TEL_NETWORK_ACT_EGPRS:
1764 case TEL_NETWORK_ACT_UMTS:
1765 case TEL_NETWORK_ACT_HSDPA:
1766 case TEL_NETWORK_ACT_HSPA:
1769 case TEL_NETWORK_ACT_GSM_AND_UMTS:
1770 gsm_act = utran_act = TRUE;
1773 warn("unsupported AcT");
1777 at_cmd = g_strdup_printf("AT+CPOL=%d,%d,\"%s\",%d,%d,%d",
1778 pref_plmn->index, 2, pref_plmn->plmn, gsm_act, gsm_compact_act, utran_act);
1780 /* Response callback data */
1781 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1783 /* Send Request to modem */
1784 ret = tcore_at_prepare_and_send_request(co,
1786 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1788 on_response_imc_network_default, resp_cb_data,
1789 on_send_imc_request, NULL);
1790 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set preferred plmn");
1797 * Operation - get preferred plmn
1799 * AT-Command: AT+CPOL?
1801 * Success: (multiline)
1802 * +CPOL: <index1>,<format>,<oper1>
1803 * [,<GSM_AcT1>,<GSM_Compact_AcT1>,<UTRAN_AcT1>][<CR><LF>
1804 * +CPOL: <index2>,<format>,<oper2>[,<GSM_AcT2>,<GSM_Compact_AcT2>,<UTRAN_AcT2>] [
\85]]
1809 static TelReturn imc_network_get_preferred_plmn(CoreObject *co,
1810 TcoreObjectResponseCallback cb, void *cb_data)
1812 ImcRespCbData *resp_cb_data;
1813 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1816 /* Response callback data */
1817 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1819 /* Send Request to modem */
1820 ret = tcore_at_prepare_and_send_request(co,
1821 "AT+CPOL=,2;+CPOL?", "+CPOL", //to make sure <oper> is numeric type in reponse.
1822 TCORE_AT_COMMAND_TYPE_MULTILINE,
1824 on_response_imc_network_get_preferred_plmn, resp_cb_data,
1825 on_send_imc_request, NULL);
1826 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get preferred plmn");
1832 * Operation - set network mode
1834 * AT-Command: AT+XRAT=<AcT> [, <PreferredAct>]
1836 * <AcT> indicates the radio access technology and may be
1838 * 1 GSM / UMTS Dual mode
1840 * 3-7 Reserved for future use.
1841 * 8 This option is to swap the RAT mode between the two stacks. Example: If Stack1 is in GSM mode and
1842 * Stack2 is in UMTS mode, this will configure Stack1 in UMTS mode and Stack2 in GSM mode.
1843 * Note : <Act> = 8 is used only for dual sim configuration. In this case < PreferredAct > is ignored
1845 * This parameter is used for network registration in case of <AcT>=1.
1849 * Success: (No result)
1852 * +CME ERROR: <error>
1854 static TelReturn imc_network_set_mode(CoreObject *co, TelNetworkMode mode,
1855 TcoreObjectResponseCallback cb, void *cb_data)
1857 ImcRespCbData *resp_cb_data;
1858 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1863 case TEL_NETWORK_MODE_AUTO:
1866 case TEL_NETWORK_MODE_2G:
1869 case TEL_NETWORK_MODE_3G:
1872 case TEL_NETWORK_MODE_LTE:
1874 err("Unsupported mode");
1880 at_cmd = g_strdup_printf("AT+XRAT=%d,2", act); //PreferredAct is UMTS
1883 at_cmd = g_strdup_printf("AT+XRAT=%d", act);
1885 /* Response callback data */
1886 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1888 /* Send Request to modem */
1889 ret = tcore_at_prepare_and_send_request(co,
1891 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1893 on_response_imc_network_default, resp_cb_data,
1894 on_send_imc_request, NULL);
1895 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set network mode");
1902 * Operation - get network mode
1904 * AT-Command: AT+XRAT?
1907 * Success: (Single line)
1908 * +XRAT : <Act>,<PreferredAct>
1909 * <AcT> indicates the radio access technology and may be
1911 * 1 GSM / UMTS Dual mode
1913 * 3-7 Reserved for future use.
1914 * 8 This option is to swap the RAT mode between the two stacks. Example: If Stack1 is in GSM mode and
1915 * Stack2 is in UMTS mode, this will configure Stack1 in UMTS mode and Stack2 in GSM mode.
1916 * Note : <Act> = 8 is used only for dual sim configuration. In this case < PreferredAct > is ignored
1918 * This parameter is used for network registration in case of <AcT>=1.
1923 * +CME ERROR: <error>
1926 static TelReturn imc_network_get_mode(CoreObject *co,
1927 TcoreObjectResponseCallback cb, void *cb_data)
1929 ImcRespCbData *resp_cb_data;
1933 /* Response callback data */
1934 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1936 /* Send Request to modem */
1937 ret = tcore_at_prepare_and_send_request(co,
1938 "AT+XRAT?", "+XRAT",
1939 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1941 on_response_imc_network_get_mode, resp_cb_data,
1942 on_send_imc_request, NULL);
1943 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get network mode");
1948 static TelReturn imc_network_get_neighboring_cell_info(CoreObject *co,
1949 TcoreObjectResponseCallback cb, void *cb_data)
1953 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1956 /* Network Operations */
1957 static TcoreNetworkOps imc_network_ops = {
1958 .get_identity_info = imc_network_get_identity_info,
1959 .search = imc_network_search,
1960 .cancel_search = imc_network_cancel_search,
1961 .select_automatic = imc_network_select_automatic,
1962 .select_manual = imc_network_select_manual,
1963 .get_selection_mode = imc_network_get_selection_mode,
1964 .set_preferred_plmn = imc_network_set_preferred_plmn,
1965 .get_preferred_plmn = imc_network_get_preferred_plmn,
1966 .set_mode = imc_network_set_mode,
1967 .get_mode = imc_network_get_mode,
1968 .get_neighboring_cell_info = imc_network_get_neighboring_cell_info
1971 gboolean imc_network_init(TcorePlugin *p, CoreObject *co)
1973 CustomData *custom_data;
1976 /* Set operations */
1977 tcore_network_set_ops(co, &imc_network_ops);
1980 custom_data = tcore_malloc0(sizeof(CustomData));
1981 custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH;
1983 /* Link Custom data */
1984 tcore_object_link_user_data(co, custom_data);
1987 tcore_object_add_callback(co, "+CREG", on_notification_imc_cs_network_info, NULL);
1988 tcore_object_add_callback(co, "+CGREG", on_notification_imc_ps_network_info, NULL);
1989 tcore_object_add_callback(co, "+XNITZINFO", on_notification_imc_network_time_info, NULL);
1990 tcore_object_add_callback(co, "+XCIEV", on_notification_imc_network_rssi, NULL);
1993 * Add Hooks - Request and Notification
1995 tcore_plugin_add_request_hook(p,
1996 TCORE_COMMAND_MODEM_SET_FLIGHTMODE,
1997 on_hook_imc_set_flight_mode, NULL);
1998 tcore_plugin_add_notification_hook(p,
1999 TCORE_NOTIFICATION_SIM_STATUS,
2000 on_hook_imc_sim_status, co);
2002 //_insert_mcc_mnc_oper_list(cp, co_network);
2008 void imc_network_exit(TcorePlugin *p, CoreObject *co)
2010 CustomData *custom_data;
2012 custom_data = tcore_object_ref_user_data(co);
2013 if (custom_data != NULL)
2014 tcore_free(custom_data);