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>
37 #include "imc_common.h"
39 /* AT+CUSD = [<n> [, <str> [, <dcs>]]]
44 * 2 Cancel the session
52 static gboolean on_notification_imc_ss_ussd(CoreObject *co, const void *event_data,
56 gchar *resp_str = NULL;
57 guchar *dcs_str = NULL;
58 TelUtilAlphabetFormat dcs = TEL_UTIL_ALPHABET_FORMAT_SMS_DEFAULT;
60 GSList *tokens = NULL;
63 TelSsUssdNoti ussd_noti = {0,};
65 lines = (GSList *) event_data;
67 if (g_slist_length(lines) != 1) {
68 dbg("Unsolicited message but multiple lines");
72 cmd = (char *) (lines->data);
73 tokens = tcore_at_tok_new(cmd);
75 /* Parse USSD status */
76 resp_str = g_slist_nth_data(tokens, 0);
77 if (NULL == resp_str) {
78 err("status missing from +CUSD Notification");
79 tcore_at_tok_free(tokens);
82 ussd_status = atoi(resp_str);
83 dbg("USSD status[%d]", ussd_status);
85 if (ussd_status < TEL_SS_USSD_STATUS_NO_ACTION_REQUIRED ||
86 ussd_status > TEL_SS_USSD_STATUS_TIME_OUT) {
87 err("invalid USSD status");
88 tcore_at_tok_free(tokens);
93 * When network terminated the USSD session, no need to
94 * send notification to application
96 if (ussd_status == TEL_SS_USSD_STATUS_TERMINATED_BY_NETWORK) {
97 /* destroy USSD session if any */
98 UssdSession *ussd_session;
99 ussd_session = tcore_ss_ussd_get_session(co);
102 tcore_ss_ussd_destroy_session(ussd_session);
104 tcore_at_tok_free(tokens);
108 /* Parse USSD string */
109 resp_str = g_slist_nth_data(tokens, 1);
111 resp_str = tcore_at_tok_extract(resp_str);
113 len = strlen((gchar *)resp_str);
114 dbg("USSD String: [%s], len: [%d]", resp_str, len);
116 dbg("Ussd string missing from +CUSD Notification");
117 tcore_at_tok_free(tokens);
121 dcs_str = g_slist_nth_data(tokens, 2);
125 dcs = tcore_util_get_cbs_coding_scheme(atoi((gchar *)dcs_str));
127 warn("No dcs string. Using default dcs value");
130 ussd_noti.str = tcore_malloc0(len + 1);
132 if ((tcore_util_convert_str_to_utf8(ussd_noti.str, &len, dcs,
133 (const guchar *)resp_str, len + 1)) == FALSE) {
134 /* In case of unhandled dcs type(Reserved),
135 * copy ussd string to ussd_noti.str
137 memcpy(ussd_noti.str, resp_str, len);
140 dbg("ussd_noti.str[%s]", ussd_noti.str);
142 ussd_noti.status = ussd_status;
144 tcore_object_send_notification(co,
145 TCORE_NOTIFICATION_SS_USSD,
146 sizeof(TelSsUssdNoti), (void *)&ussd_noti);
148 tcore_at_tok_free(tokens);
149 tcore_free(resp_str);
150 tcore_free(ussd_noti.str);
155 static gboolean __imc_ss_convert_modem_class_to_class(gint classx, TelSsClass *class)
160 *class = TEL_SS_CLASS_ALL_TELE;
163 *class = TEL_SS_CLASS_VOICE;
166 *class = TEL_SS_CLASS_ALL_DATA_TELE;
169 *class = TEL_SS_CLASS_FAX;
172 *class = TEL_SS_CLASS_SMS;
175 *class = TEL_SS_CLASS_ALL_CS_SYNC;
178 *class = TEL_SS_CLASS_ALL_CS_ASYNC;
181 *class = TEL_SS_CLASS_ALL_DEDI_PS;
184 *class = TEL_SS_CLASS_ALL_DEDI_PAD;
187 err("Invalid modem class: [%d]", classx);
194 static guint __imc_ss_convert_class_to_imc_class(TelSsClass class)
198 case TEL_SS_CLASS_ALL_TELE:
201 case TEL_SS_CLASS_VOICE:
204 case TEL_SS_CLASS_ALL_DATA_TELE:
207 case TEL_SS_CLASS_FAX:
210 case TEL_SS_CLASS_SMS:
213 case TEL_SS_CLASS_ALL_CS_SYNC:
216 case TEL_SS_CLASS_ALL_CS_ASYNC:
219 case TEL_SS_CLASS_ALL_DEDI_PS:
222 case TEL_SS_CLASS_ALL_DEDI_PAD:
226 dbg("Unsupported class: [%d], returning default value 7", class);
231 static gboolean __imc_ss_convert_barring_type_to_facility(TelSsBarringType type,
236 case TEL_SS_CB_TYPE_BAOC:
239 case TEL_SS_CB_TYPE_BOIC:
242 case TEL_SS_CB_TYPE_BOIC_NOT_HC:
245 case TEL_SS_CB_TYPE_BAIC:
248 case TEL_SS_CB_TYPE_BIC_ROAM:
251 case TEL_SS_CB_TYPE_AB:
254 case TEL_SS_CB_TYPE_AOB:
257 case TEL_SS_CB_TYPE_AIB:
260 case TEL_SS_CB_TYPE_NS:
264 err("Unspported type: [%d]", type);
270 static gboolean __imc_ss_convert_forwarding_mode_to_modem_mode(TelSsForwardMode mode,
275 case TEL_SS_CF_MODE_DISABLE:
278 case TEL_SS_CF_MODE_ENABLE:
281 case TEL_SS_CF_MODE_REGISTER:
284 case TEL_SS_CF_MODE_DEREGISTER:
288 err("Unspported mode: [%d]", mode);
294 static gboolean __imc_ss_convert_forwarding_condition_to_modem_reason(TelSsForwardCondition condition,
298 case TEL_SS_CF_COND_CFU:
301 case TEL_SS_CF_COND_CFB:
304 case TEL_SS_CF_COND_CFNRY:
307 case TEL_SS_CF_COND_CFNRC:
310 case TEL_SS_CF_COND_ALL:
313 case TEL_SS_CF_COND_ALL_CFC:
317 dbg("Unsupported condition: [%d]", condition);
323 static gint __imc_ss_convert_cli_status_modem_status(gint cli_status)
325 if (cli_status == TEL_SS_CLI_DISABLE)
327 else if (cli_status == TEL_SS_CLI_ENABLE)
330 err("Invalid CLI status: [%d]", cli_status);
335 static gint __imc_ss_convert_clir_status_modem_status(gint clir_status)
337 if (clir_status == TEL_CLIR_STATUS_DEFAULT)
339 else if (clir_status == TEL_CLIR_STATUS_INVOCATION)
341 else if (clir_status == TEL_CLIR_STATUS_SUPPRESSION)
344 err("Invalid CLIR status: [%d]", clir_status);
349 static gboolean __imc_ss_convert_cli_info_modem_info(const TelSsCliInfo **cli_info,gint *status,
352 switch((*cli_info)->type)
354 case TEL_SS_CLI_CLIR:
355 if ((*status = __imc_ss_convert_clir_status_modem_status((*cli_info)->status.clir))
357 *cmd_prefix = "+CLIR";
359 err("invalid clir status");
363 case TEL_SS_CLI_CLIP:
364 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.clip)
366 *cmd_prefix = "+CLIP";
368 err("invalid clip status");
371 case TEL_SS_CLI_COLP:
372 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.colp)
374 *cmd_prefix = "+COLP";
376 err("invalid colp status");
379 case TEL_SS_CLI_COLR:
380 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.colr)
382 *cmd_prefix = "+COLR";
384 err("invalid colr status");
387 case TEL_SS_CLI_CNAP:
388 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.cnap)
390 *cmd_prefix = "+CNAP";
392 err("invalid cnap status");
396 case TEL_SS_CLI_CDIP:
398 err("Unsupported CLI type: [%d]", (*cli_info)->type);
402 if (*cmd_prefix == NULL)
408 static gboolean __imc_ss_convert_modem_cli_net_status_cli_status(TelSsCliType cli_type,
409 gint net_status, gint *status)
411 if (cli_type == TEL_SS_CLI_CLIR) {
412 switch (net_status) {
414 *status = TEL_CLIR_STATUS_NOT_PROVISIONED;
417 *status = TEL_CLIR_STATUS_PROVISIONED;
420 *status = TEL_CLIR_STATUS_UNKNOWN;
423 *status = TEL_CLIR_STATUS_TEMP_RESTRICTED;
426 *status = TEL_CLIR_STATUS_TEMP_ALLOWED;
429 err("Invalid clir net status: [%d]", net_status);
432 } else { //CLIP, COLP,COLR,CNAP.
433 switch (net_status) {
435 *status = TEL_SS_CLI_NOT_PROVISIONED;
438 *status = TEL_SS_CLI_PROVISIONED;
441 *status = TEL_SS_CLI_UNKNOWN;
444 err("Invalid status: [%d]", net_status);
451 static gboolean __imc_ss_convert_modem_cli_dev_status_cli_status(TelSsCliType cli_type,
452 gint dev_status, gint *status)
454 if (cli_type == TEL_SS_CLI_CLIR) {
455 switch (dev_status) {
457 *status = TEL_CLIR_STATUS_DEFAULT;
460 *status = TEL_CLIR_STATUS_INVOCATION;
463 *status = TEL_CLIR_STATUS_SUPPRESSION;
466 err("Invalid dev status: [%d]", dev_status);
469 } else { //CLIP, COLP,COLR,CNAP.
472 *status = TEL_SS_CLI_DISABLE;
475 *status = TEL_SS_CLI_ENABLE;
478 err("Invalid dev status: [%d]", dev_status);
486 static void on_response_imc_ss_set_barring(TcorePending *p,
487 guint data_len, const void *data, void *user_data)
489 const TcoreAtResponse *at_resp = data;
490 CoreObject *co = tcore_pending_ref_core_object(p);
491 ImcRespCbData *resp_cb_data = user_data;
493 /* TODO: CMEE error mapping is required */
494 TelSsResult result = TEL_SS_RESULT_FAILURE;
497 tcore_check_return_assert(co != NULL);
498 tcore_check_return_assert(resp_cb_data != NULL);
500 if (at_resp && at_resp->success)
501 result = TEL_SS_RESULT_SUCCESS;
503 dbg("Setting Barring status: [%s]",
504 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
506 /* Invoke callback */
507 if (resp_cb_data->cb)
508 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
510 imc_destroy_resp_cb_data(resp_cb_data);
513 static void on_response_imc_ss_get_barring_status(TcorePending *p,
514 guint data_len, const void *data, void *user_data)
516 const TcoreAtResponse *at_resp = data;
517 CoreObject *co = tcore_pending_ref_core_object(p);
518 ImcRespCbData *resp_cb_data = user_data;
519 TelSsBarringResp barring_resp = {0,};
520 TelSsBarringGetInfo *req_info;
521 gint valid_records = 0;
522 GSList *resp_data = NULL;
523 /* TODO: CMEE error mapping is required */
524 TelSsResult result = TEL_SS_RESULT_FAILURE;
527 tcore_check_return_assert(co != NULL);
528 tcore_check_return_assert(resp_cb_data != NULL);
530 req_info = (TelSsBarringGetInfo *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
533 if (at_resp->lines && at_resp->success) {
534 resp_data = (GSList *) at_resp->lines;
535 barring_resp.record_num= g_slist_length(resp_data);
536 dbg("Total records: [%d]", barring_resp.record_num);
539 err("RESPONSE - [NOK]");
542 err("No response data");
545 if (barring_resp.record_num > 0) {
546 barring_resp.records = tcore_malloc0((barring_resp.record_num) *
547 sizeof(TelSsBarringInfoRecord));
549 for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
551 GSList *tokens = NULL;
553 line = (const char *) resp_data->data;
554 tokens = tcore_at_tok_new(line);
555 if (g_slist_length(tokens) > 0) {
557 gchar *status = NULL;
559 status = g_slist_nth_data(tokens, 0);
561 dbg("Status is missing");
562 tcore_at_tok_free(tokens);
566 if (atoi(status) == 1) {
567 barring_resp.records[valid_records].enable = TRUE;
569 barring_resp.records[valid_records].enable = FALSE;
572 classx_str = g_slist_nth_data(tokens, 1);
574 dbg("Class error. Setting to the requested class: [%d]",
576 barring_resp.records[valid_records].class = req_info->class;
578 if (__imc_ss_convert_modem_class_to_class(atoi(classx_str),
579 &(barring_resp.records[valid_records].class))
581 tcore_at_tok_free(tokens);
586 barring_resp.records[valid_records].type= req_info->type;
587 result = TEL_SS_RESULT_SUCCESS;
590 err("Invalid response message");
592 tcore_at_tok_free(tokens);
596 dbg("Getting Barring status: [%s]",
597 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
598 barring_resp.record_num = valid_records;
600 /* Invoke callback */
601 if (resp_cb_data->cb)
602 resp_cb_data->cb(co, (gint)result, &barring_resp, resp_cb_data->cb_data);
604 imc_destroy_resp_cb_data(resp_cb_data);
606 if (barring_resp.records) {
607 tcore_free(barring_resp.records);
611 static void on_response_imc_ss_change_barring_password(TcorePending *p,
612 guint data_len, const void *data, void *user_data)
614 const TcoreAtResponse *at_resp = data;
615 CoreObject *co = tcore_pending_ref_core_object(p);
616 ImcRespCbData *resp_cb_data = user_data;
617 /* TODO: CMEE error mapping is required */
618 TelSsResult result = TEL_SS_RESULT_FAILURE;
621 tcore_check_return_assert(co != NULL);
622 tcore_check_return_assert(resp_cb_data != NULL);
624 if (at_resp && at_resp->success)
625 result = TEL_SS_RESULT_SUCCESS;
627 dbg("Change Barring Password: [%s]",
628 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
630 /* Invoke callback */
631 if (resp_cb_data->cb)
632 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
634 imc_destroy_resp_cb_data(resp_cb_data);
637 static void on_response_imc_ss_set_forwarding(TcorePending *p,
638 guint data_len, const void *data, void *user_data)
640 const TcoreAtResponse *at_resp = data;
641 CoreObject *co = tcore_pending_ref_core_object(p);
642 ImcRespCbData *resp_cb_data = user_data;
644 /* TODO: CMEE error mapping is required */
645 TelSsResult result = TEL_SS_RESULT_FAILURE;
648 tcore_check_return_assert(co != NULL);
649 tcore_check_return_assert(resp_cb_data != NULL);
651 if (at_resp && at_resp->success)
652 result = TEL_SS_RESULT_SUCCESS;
654 dbg("Set Forwarding Status: [%s]",
655 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
657 /* Invoke callback */
658 if (resp_cb_data->cb)
659 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
661 imc_destroy_resp_cb_data(resp_cb_data);
664 static void on_response_imc_ss_get_forwarding_status(TcorePending *p,
665 guint data_len, const void *data, void *user_data)
667 const TcoreAtResponse *at_resp = data;
668 CoreObject *co = tcore_pending_ref_core_object(p);
669 ImcRespCbData *resp_cb_data = user_data;
670 TelSsForwardingResp forwarding_resp = {0,};
671 TelSsForwardGetInfo *req_info;
672 gint valid_records = 0;
673 GSList *resp_data = NULL;
674 /* TODO: CMEE error mapping is required */
675 TelSsResult result = TEL_SS_RESULT_FAILURE;
678 tcore_check_return_assert(co != NULL);
679 tcore_check_return_assert(resp_cb_data != NULL);
681 req_info = (TelSsForwardGetInfo *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
684 if (at_resp->lines && at_resp->success) {
685 resp_data = (GSList *) at_resp->lines;
686 forwarding_resp.record_num= g_slist_length(resp_data);
687 dbg("Total records: [%d]", forwarding_resp.record_num);
689 err("RESPONSE - [NOK]");
692 err("No response data");
695 if (forwarding_resp.record_num > 0) {
696 forwarding_resp.records = tcore_malloc0((forwarding_resp.record_num) *
697 sizeof(TelSsForwardingInfoRecord));
698 for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
700 GSList *tokens = NULL;
702 line = (const char *) resp_data->data;
703 tokens = tcore_at_tok_new(line);
705 if (g_slist_length(tokens) > 0) {
707 gchar *status = NULL;
708 gchar *number = NULL;
709 gchar *time_str = NULL;
711 status = g_slist_nth_data(tokens, 0);
713 dbg("Status is missing");
714 tcore_at_tok_free(tokens);
718 if (atoi(status) == 1) {
719 forwarding_resp.records[valid_records].enable = TRUE;
721 forwarding_resp.records[valid_records].enable = FALSE;
724 classx_str = g_slist_nth_data(tokens, 1);
726 dbg("Class error. Setting to the requested class: [%d]",
728 forwarding_resp.records[valid_records].class =
731 if (__imc_ss_convert_modem_class_to_class(atoi(classx_str),
732 &(forwarding_resp.records[valid_records].class))
734 tcore_at_tok_free(tokens);
739 number = g_slist_nth_data(tokens, 2);
741 number = tcore_at_tok_extract(number);
742 memcpy((forwarding_resp.records[valid_records].number),
743 number, strlen(number));
747 time_str = g_slist_nth_data(tokens, 6);
749 forwarding_resp.records[valid_records].wait_time =
752 forwarding_resp.records[valid_records].condition =
755 result = TEL_SS_RESULT_SUCCESS;
758 err("Invalid response message");
760 tcore_at_tok_free(tokens);
764 dbg("Getting Forwarding Status: [%s]",
765 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
766 forwarding_resp.record_num = valid_records;
768 /* Invoke callback */
769 if (resp_cb_data->cb)
770 resp_cb_data->cb(co, (gint)result, &forwarding_resp, resp_cb_data->cb_data);
772 imc_destroy_resp_cb_data(resp_cb_data);
774 if (forwarding_resp.records) {
775 tcore_free(forwarding_resp.records);
779 static void on_response_imc_ss_set_waiting(TcorePending *p,
780 guint data_len, const void *data, void *user_data)
782 const TcoreAtResponse *at_resp = data;
783 CoreObject *co = tcore_pending_ref_core_object(p);
784 ImcRespCbData *resp_cb_data = user_data;
785 /* TODO: CMEE error mapping is required */
786 TelSsResult result = TEL_SS_RESULT_FAILURE;
789 tcore_check_return_assert(co != NULL);
790 tcore_check_return_assert(resp_cb_data != NULL);
792 if (at_resp && at_resp->success)
793 result = TEL_SS_RESULT_SUCCESS;
795 dbg("Set Waiting Status: [%s]",
796 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
798 /* Invoke callback */
799 if (resp_cb_data->cb)
800 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
802 imc_destroy_resp_cb_data(resp_cb_data);
805 static void on_response_imc_ss_get_waiting_status(TcorePending *p,
806 guint data_len, const void *data, void *user_data)
808 const TcoreAtResponse *at_resp = data;
809 CoreObject *co = tcore_pending_ref_core_object(p);
810 ImcRespCbData *resp_cb_data = user_data;
811 TelSsWaitingResp waiting_resp = {0,};
813 gint valid_records = 0;
814 GSList *resp_data = NULL;
815 /* TODO: CMEE error mapping is required */
816 TelSsResult result = TEL_SS_RESULT_FAILURE;
819 tcore_check_return_assert(co != NULL);
820 tcore_check_return_assert(resp_cb_data != NULL);
822 class = (TelSsClass *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
825 if (at_resp->lines && at_resp->success) {
826 resp_data = (GSList *) at_resp->lines;
827 waiting_resp.record_num= g_slist_length(resp_data);
828 dbg("Total records: [%d]", waiting_resp.record_num);
831 err("RESPONSE - [NOK]");
834 err("No response data");
837 if (waiting_resp.record_num > 0) {
838 waiting_resp.records = tcore_malloc0((waiting_resp.record_num) *
839 sizeof(TelSsWaitingInfo));
841 for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
843 GSList *tokens = NULL;
845 line = (const char *) resp_data->data;
846 tokens = tcore_at_tok_new(line);
848 if (g_slist_length(tokens) > 0) {
850 gchar *status = NULL;
852 status = g_slist_nth_data(tokens, 0);
854 dbg("Status is missing");
855 tcore_at_tok_free(tokens);
859 if (atoi(status) == 1) {
860 waiting_resp.records[valid_records].enable= TRUE;
862 waiting_resp.records[valid_records].enable = FALSE;
865 classx_str = g_slist_nth_data(tokens, 1);
867 dbg("Class error. Setting to the requested class: [%d]",
869 waiting_resp.records[valid_records].class = *class;
871 if (__imc_ss_convert_modem_class_to_class(atoi(classx_str),
872 &(waiting_resp.records[valid_records].class))
874 tcore_at_tok_free(tokens);
879 result = TEL_SS_RESULT_SUCCESS;
882 err("Invalid response message");
884 tcore_at_tok_free(tokens);
888 dbg("Getting Waiting Status: [%s]",
889 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
890 waiting_resp.record_num = valid_records;
892 /* Invoke callback */
893 if (resp_cb_data->cb)
894 resp_cb_data->cb(co, (gint)result, &waiting_resp, resp_cb_data->cb_data);
896 imc_destroy_resp_cb_data(resp_cb_data);
898 if (waiting_resp.records) {
899 tcore_free(waiting_resp.records);
903 static void on_response_imc_ss_set_cli(TcorePending *p,
904 guint data_len, const void *data, void *user_data)
906 const TcoreAtResponse *at_resp = data;
907 CoreObject *co = tcore_pending_ref_core_object(p);
908 ImcRespCbData *resp_cb_data = user_data;
909 /* TODO: CMEE error mapping is required */
910 TelSsResult result = TEL_SS_RESULT_FAILURE;
913 tcore_check_return_assert(co != NULL);
914 tcore_check_return_assert(resp_cb_data != NULL);
916 if (at_resp && at_resp->success)
917 result = TEL_SS_RESULT_SUCCESS;
919 dbg("Set Cli Status: [%s]",
920 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
922 /* Invoke callback */
923 if (resp_cb_data->cb)
924 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
926 imc_destroy_resp_cb_data(resp_cb_data);
929 static void on_response_imc_ss_get_cli_status(TcorePending *p,
930 guint data_len, const void *data, void *user_data)
932 const TcoreAtResponse *at_resp = data;
933 CoreObject *co = tcore_pending_ref_core_object(p);
934 ImcRespCbData *resp_cb_data = user_data;
935 TelSsCliResp cli_resp = {0,};
936 TelSsCliType *cli_type;
937 GSList *tokens = NULL;
938 /* TODO: CMEE error mapping is required */
939 TelSsResult result = TEL_SS_RESULT_FAILURE;
942 tcore_check_return_assert(co != NULL);
943 tcore_check_return_assert(resp_cb_data != NULL);
945 cli_type = (TelSsCliType *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
947 if (at_resp && at_resp->success) {
949 gchar *status = NULL;
953 if (!at_resp->lines) {
954 err("Invalid response message");
957 line = (const gchar *)at_resp->lines->data;
958 tokens = tcore_at_tok_new(line);
959 if (g_slist_length(tokens) < 1) {
960 err("Invalid response message");
964 status = g_slist_nth_data(tokens, 0);
966 err("dev_status is missing");
969 if (!__imc_ss_convert_modem_cli_dev_status_cli_status(*cli_type,
970 atoi(status), &dev_status))
973 status = g_slist_nth_data(tokens, 1);
975 err("net_status is missing");
978 if (!__imc_ss_convert_modem_cli_net_status_cli_status(*cli_type,
979 atoi(status), &net_status))
983 case TEL_SS_CLI_CLIR:
984 cli_resp.status.clir.net_status = net_status;
985 cli_resp.status.clir.dev_status = dev_status;
987 case TEL_SS_CLI_CLIP:
988 cli_resp.status.clip.net_status = net_status;
989 cli_resp.status.clip.dev_status = dev_status;
991 case TEL_SS_CLI_COLP:
992 cli_resp.status.colp.net_status = net_status;
993 cli_resp.status.colp.dev_status = dev_status;
995 case TEL_SS_CLI_COLR:
996 cli_resp.status.colr.net_status = net_status;
997 cli_resp.status.colr.dev_status = dev_status;
999 case TEL_SS_CLI_CNAP:
1000 cli_resp.status.cnap.net_status = net_status;
1001 cli_resp.status.cnap.dev_status = dev_status;
1004 err("Unsupported CLI type: [%d]", *cli_type);
1005 result = TEL_SS_RESULT_INVALID_PARAMETER;
1009 cli_resp.type = *cli_type;
1010 result = TEL_SS_RESULT_SUCCESS;
1012 err("RESPONSE NOK");
1016 tcore_at_tok_free(tokens);
1018 /* Invoke callback */
1019 if (resp_cb_data->cb)
1020 resp_cb_data->cb(co, (gint)result, &cli_resp, resp_cb_data->cb_data);
1022 imc_destroy_resp_cb_data(resp_cb_data);
1025 static void on_response_imc_ss_send_ussd_request(TcorePending *p,
1026 guint data_len, const void *data, void *user_data)
1028 const TcoreAtResponse *at_resp = data;
1029 CoreObject *co = tcore_pending_ref_core_object(p);
1030 ImcRespCbData *resp_cb_data = user_data;
1031 TelSsUssdResp ussd_resp = {0,};
1032 UssdSession *ussd_s = NULL;
1033 /* TODO: CMEE error mapping is required */
1034 TelSsResult result = TEL_SS_RESULT_FAILURE;
1037 tcore_check_return_assert(co != NULL);
1038 tcore_check_return_assert(resp_cb_data != NULL);
1040 ussd_s = tcore_ss_ussd_get_session(co);
1041 tcore_check_return(ussd_s != NULL);
1043 tcore_ss_ussd_get_session_type(ussd_s, &ussd_resp.type);
1045 if (at_resp && at_resp->success) {
1046 result = TEL_SS_RESULT_SUCCESS;
1047 /* Need to initialise ussd response string */
1048 ussd_resp.str = (unsigned char *)g_strdup("Operation success");
1050 ussd_resp.str = (unsigned char *)g_strdup("Operation failed");
1054 dbg("Send Ussd Request: [%s]",
1055 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1057 tcore_ss_ussd_destroy_session(ussd_s);
1060 /* Invoke callback */
1061 if (resp_cb_data->cb)
1062 resp_cb_data->cb(co, (gint)result, &ussd_resp, resp_cb_data->cb_data);
1064 imc_destroy_resp_cb_data(resp_cb_data);
1065 g_free(ussd_resp.str);
1070 * Operation - set_barring/get_barring_status
1073 * AT-Command: AT+CLCK=<fac>,<mode>[,<passwd>[,<class>]]
1076 * Barring facility type. Ref #TelSsBarringType
1087 * SS class. Ref #TelSsClass
1093 * Success: when <mode>=2:
1095 * +CLCK: <status>[,<class1> [<CR><LF>
1096 * +CLCK: <status>,<class2> [...]]
1099 * +CME ERROR: <error>
1101 static TelReturn imc_ss_set_barring(CoreObject *co, const TelSsBarringInfo *barring_info,
1102 TcoreObjectResponseCallback cb, void *cb_data)
1104 gchar *at_cmd = NULL;
1107 gchar *facility = NULL;
1108 ImcRespCbData *resp_cb_data = NULL;
1109 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1111 if (barring_info->enable == TRUE)
1116 if (__imc_ss_convert_barring_type_to_facility(barring_info->type,
1117 &facility) == FALSE) {
1118 err("Invalid arguments");
1122 classx = __imc_ss_convert_class_to_imc_class(barring_info->class);
1124 dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
1127 at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,\"%s\",%d", facility, mode,
1128 barring_info->pwd, classx);
1130 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1132 /* Send Request to modem */
1133 ret = tcore_at_prepare_and_send_request(co,
1135 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1137 on_response_imc_ss_set_barring, resp_cb_data,
1138 on_send_imc_request, NULL);
1139 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Barring");
1145 static TelReturn imc_ss_get_barring_status(CoreObject *co,
1146 const TelSsBarringGetInfo *get_barring_info,
1147 TcoreObjectResponseCallback cb, void *cb_data)
1149 gchar *at_cmd = NULL;
1152 gchar *facility = NULL;
1153 ImcRespCbData *resp_cb_data = NULL;
1154 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1156 mode = 2; /* query status - mode is fixed to 2 */
1158 if (__imc_ss_convert_barring_type_to_facility(get_barring_info->type,
1159 &facility) == FALSE) {
1160 err("Invalid arguments");
1164 classx = __imc_ss_convert_class_to_imc_class(get_barring_info->class);
1166 dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
1169 at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,,%d", facility, mode, classx);
1171 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, (void *)get_barring_info,
1172 sizeof(TelSsBarringGetInfo));
1174 /* Send Request to modem */
1175 ret = tcore_at_prepare_and_send_request(co,
1177 TCORE_AT_COMMAND_TYPE_MULTILINE,
1179 on_response_imc_ss_get_barring_status, resp_cb_data,
1180 on_send_imc_request, NULL);
1181 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Barring Status");
1188 * Operation - change_barring_password
1191 * AT-Command: AT+CPWD= <fac>,<oldpwd>,<newpwd>
1194 * Barring facility type. Ref #TelSsBarringType
1195 * Eg: "AB" All Barring services
1198 * Old Barring Password
1201 * New Barring Password
1207 * +CME ERROR: <error>
1209 static TelReturn imc_ss_change_barring_password(CoreObject *co,
1210 const TelSsBarringPwdInfo *barring_pwd_info,
1211 TcoreObjectResponseCallback cb, void *cb_data)
1213 gchar *at_cmd = NULL;
1214 ImcRespCbData *resp_cb_data = NULL;
1215 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1217 if (barring_pwd_info->old_pwd == NULL || barring_pwd_info->new_pwd == NULL) {
1218 err("Invalid data");
1222 dbg("Old password: [%s], New password: [%s]", barring_pwd_info->old_pwd,
1223 barring_pwd_info->new_pwd);
1225 at_cmd = g_strdup_printf("AT+CPWD=\"%s\",\"%s\",\"%s\"", "AB",
1226 barring_pwd_info->old_pwd, barring_pwd_info->new_pwd);
1228 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1230 /* Send Request to modem */
1231 ret = tcore_at_prepare_and_send_request(co,
1233 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1235 on_response_imc_ss_change_barring_password, resp_cb_data,
1236 on_send_imc_request, NULL);
1237 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Change Barring Password");
1244 * Operation - set_forwarding/get_forwarding_status
1247 * AT-Command: AT+CCFC=<reason>,<mode>[,<number>[,<type>
1248 * [,<class>[,<subaddr>[,<satype>[,<time>]]]]]]
1251 * Forwarding Condition. Ref #TelSsForwardCondition
1254 * Forwarding Mode. Ref #TelSsForwardMode
1263 * Call Forwarding Number
1266 * Default 145 when available string includes "+"
1270 * Parameter String type subaddress of format specified by <satype>
1273 * Parameter type of subaddress octet in integer format
1277 * Parameter time in seconds to wait before call is forwarded
1278 * Default 20, but only when <reason>=2 (no reply) is enabled
1281 * SS class. Ref #TelSsClass
1287 * Success: when <mode>=2:
1289 * +CCFC: <status>,<class1>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][<CR><LF>
1290 * +CCFC: <status>,<class2>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][...]]
1293 * +CME ERROR: <error>
1295 static TelReturn imc_ss_set_forwarding(CoreObject *co, const TelSsForwardInfo *forwarding_info,
1296 TcoreObjectResponseCallback cb, void *cb_data)
1298 gchar *at_cmd = NULL;
1299 gchar *tmp_cmd = NULL;
1304 ImcRespCbData *resp_cb_data = NULL;
1305 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1307 classx = __imc_ss_convert_class_to_imc_class(forwarding_info->class);
1309 if (__imc_ss_convert_forwarding_mode_to_modem_mode(forwarding_info->mode, &mode)
1311 err("Invalid arguments");
1315 if (__imc_ss_convert_forwarding_condition_to_modem_reason(forwarding_info->condition,
1316 &reason) == FALSE) {
1317 err("Invalid arguments");
1321 if (forwarding_info->number[0] == '+')
1326 dbg("classx: [%d], reason:[%d], mode: [%d]", classx, reason, mode);
1328 if (mode == 3) /* TEL_SS_CF_MODE_REGISTER */
1329 tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,\"%s\",%d,%d", reason, mode,
1330 forwarding_info->number, num_type, classx);
1332 tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
1334 if (reason == 2) /* TEL_SS_CF_COND_CFNRY */
1335 at_cmd = g_strdup_printf("%s,,,%d", tmp_cmd, forwarding_info->wait_time);
1337 at_cmd = g_strdup_printf("%s", tmp_cmd);
1339 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1341 /* Send Request to modem */
1342 ret = tcore_at_prepare_and_send_request(co,
1344 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1346 on_response_imc_ss_set_forwarding, resp_cb_data,
1347 on_send_imc_request, NULL);
1348 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Forwarding");
1356 static TelReturn imc_ss_get_forwarding_status(CoreObject *co, const TelSsForwardGetInfo *get_forwarding_info,
1357 TcoreObjectResponseCallback cb, void *cb_data)
1359 gchar *at_cmd = NULL;
1362 guint mode = 2; /* query status */
1363 ImcRespCbData *resp_cb_data = NULL;
1364 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1366 classx = __imc_ss_convert_class_to_imc_class(get_forwarding_info->class);
1368 if (__imc_ss_convert_forwarding_condition_to_modem_reason(get_forwarding_info->condition,
1369 &reason) == FALSE) {
1370 err("Invalid arguments");
1374 dbg("classx: [%d], reason: [%d], mode: [%d]", classx, reason, mode);
1376 at_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
1378 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, (void *)get_forwarding_info,
1379 sizeof(TelSsForwardGetInfo));
1381 /* Send Request to modem */
1382 ret = tcore_at_prepare_and_send_request(co,
1384 TCORE_AT_COMMAND_TYPE_MULTILINE,
1386 on_response_imc_ss_get_forwarding_status, resp_cb_data,
1387 on_send_imc_request, NULL);
1388 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Forwarding Status");
1395 * Operation - set_waiting/get_waiting_status
1398 * AT-Command: AT+CCWA=[<n>[,<mode>[,<class>]]]
1401 * Parameter Sets/shows the result code presentation status to the TE.
1402 * 0 presentation status is disabled to TE(default)
1403 * 1 presentation status is enabled to TE
1406 * 0 Disable call waiting
1407 * 1 Enable call waiting
1411 * SS class. Ref #TelSsClass
1417 * Success: when <mode>=2:
1419 * +CCWA: <status>,<class1>
1420 * +CCWA: <status>,<class2>
1423 * +CME ERROR: <error>
1425 static TelReturn imc_ss_set_waiting(CoreObject *co, const TelSsWaitingInfo *waiting_info,
1426 TcoreObjectResponseCallback cb, void *cb_data)
1428 gchar *at_cmd = NULL;
1431 ImcRespCbData *resp_cb_data = NULL;
1432 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1434 if (waiting_info->enable == TRUE)
1439 classx = __imc_ss_convert_class_to_imc_class(waiting_info->class);
1441 dbg("mode: [%d], class: [%d]", mode, classx);
1443 at_cmd = g_strdup_printf("AT+CCWA=1,%d,%d", mode, classx);
1445 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1447 /* Send Request to modem */
1448 ret = tcore_at_prepare_and_send_request(co,
1450 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1452 on_response_imc_ss_set_waiting, resp_cb_data,
1453 on_send_imc_request, NULL);
1454 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Waiting");
1460 static TelReturn imc_ss_get_waiting_status(CoreObject *co, TelSsClass ss_class,
1461 TcoreObjectResponseCallback cb, void *cb_data)
1463 gchar *at_cmd = NULL;
1465 ImcRespCbData *resp_cb_data = NULL;
1466 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1468 classx = __imc_ss_convert_class_to_imc_class(ss_class);
1470 dbg("class: [%d]", classx);
1472 at_cmd = g_strdup_printf("AT+CCWA=1,2,%d", classx);
1474 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &ss_class, sizeof(TelSsClass));
1476 /* Send Request to modem */
1477 ret = tcore_at_prepare_and_send_request(co,
1479 TCORE_AT_COMMAND_TYPE_MULTILINE,
1481 on_response_imc_ss_get_waiting_status, resp_cb_data,
1482 on_send_imc_request, NULL);
1483 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Waiting Status");
1490 * Operation - set_cli/get_cli_status
1494 * For CLIR: AT+CLIR= [<n>]
1495 * For CLIP: AT+CLIP= [<n>]
1496 * For COLP: AT+COLP= [<n>]
1497 * For COLR: AT+COLR= [<n>]
1498 * For CNAP: AT+CNAP= [<n>]
1501 * <n> All CLI except CLIR
1502 * 0 disable(default)
1508 * 2 CLIR suppression
1515 * <m> All CLI except CLIR
1522 * 1 Provisioned in permanent mode
1523 * 2 Unknown (e.g. no network, etc.)
1524 * 3 Temporary mode presentation restricted
1525 * 4 Temporary mode presentation allowed
1528 * +CME ERROR: <error>
1530 static TelReturn imc_ss_set_cli(CoreObject *co, const TelSsCliInfo *cli_info,
1531 TcoreObjectResponseCallback cb, void *cb_data)
1533 gchar *at_cmd = NULL;
1534 gchar *cmd_prefix = NULL;
1536 ImcRespCbData *resp_cb_data = NULL;
1537 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1539 if (__imc_ss_convert_cli_info_modem_info(&cli_info, &status, &cmd_prefix) == FALSE)
1542 at_cmd = g_strdup_printf("AT%s=%d", cmd_prefix, status);
1544 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1546 /* Send Request to modem */
1547 ret = tcore_at_prepare_and_send_request(co,
1549 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1551 on_response_imc_ss_set_cli, resp_cb_data,
1552 on_send_imc_request, NULL);
1553 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Cli");
1559 static TelReturn imc_ss_get_cli_status(CoreObject *co, TelSsCliType cli_type,
1560 TcoreObjectResponseCallback cb, void *cb_data)
1562 gchar *at_cmd = NULL;
1563 gchar *cmd_prefix = NULL;
1564 ImcRespCbData *resp_cb_data = NULL;
1565 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1568 case TEL_SS_CLI_CLIR:
1569 cmd_prefix = "+CLIR";
1571 case TEL_SS_CLI_CLIP:
1572 cmd_prefix = "+CLIP";
1574 case TEL_SS_CLI_COLP:
1575 cmd_prefix = "+COLP";
1577 case TEL_SS_CLI_COLR:
1578 cmd_prefix = "+COLR";
1580 case TEL_SS_CLI_CNAP:
1581 cmd_prefix = "+CNAP";
1583 case TEL_SS_CLI_CDIP:
1585 dbg("Unsupported CLI type: [%d]", cli_type);
1589 at_cmd = g_strdup_printf("AT%s?", cmd_prefix);
1591 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &cli_type, sizeof(TelSsCliType));
1593 /* Send Request to modem */
1594 ret = tcore_at_prepare_and_send_request(co,
1596 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1598 on_response_imc_ss_get_cli_status, resp_cb_data,
1599 on_send_imc_request, NULL);
1600 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Cli Status");
1607 * Operation - send_ussd_request
1610 * AT-Command: AT+CUSD = [<n> [, <str> [, <dcs>]]]
1613 * 0 Disable the result code presentation to the TE(default)
1614 * 1 Enable the result code presentation to the TE
1615 * 2 Cancel session (not applicable to read command response)
1621 * Cell Broadcast Data Coding Scheme. Default value is 0.
1627 * +CME ERROR: <error>
1629 static TelReturn imc_ss_send_ussd_request(CoreObject *co, const TelSsUssdInfo *ussd_request,
1630 TcoreObjectResponseCallback cb, void *cb_data)
1632 gchar *at_cmd = NULL;
1633 UssdSession *ussd_s = NULL;
1634 ImcRespCbData *resp_cb_data = NULL;
1635 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1637 ussd_s = tcore_ss_ussd_get_session(co);
1639 dbg("USSD session does not exist");
1640 tcore_ss_ussd_create_session(co, ussd_request->type, (void *)ussd_request->str,
1641 strlen((char *)ussd_request->str));
1643 if (ussd_request->type == TEL_SS_USSD_TYPE_USER_INIT) {
1644 err("Ussd session is already exist");
1645 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1647 tcore_ss_ussd_set_session_type(ussd_s, ussd_request->type);
1650 at_cmd = g_strdup_printf("AT+CUSD=1,\"%s\",%d", ussd_request->str, 0x0f);
1652 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1654 /* Send Request to modem */
1655 ret = tcore_at_prepare_and_send_request(co,
1657 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1659 on_response_imc_ss_send_ussd_request, resp_cb_data,
1660 on_send_imc_request, NULL);
1661 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Send Ussd Request");
1668 static TcoreSsOps imc_ss_ops = {
1669 .set_barring = imc_ss_set_barring,
1670 .get_barring_status = imc_ss_get_barring_status,
1671 .change_barring_password = imc_ss_change_barring_password,
1672 .set_forwarding = imc_ss_set_forwarding,
1673 .get_forwarding_status = imc_ss_get_forwarding_status,
1674 .set_waiting = imc_ss_set_waiting,
1675 .get_waiting_status = imc_ss_get_waiting_status,
1676 .set_cli = imc_ss_set_cli,
1677 .get_cli_status = imc_ss_get_cli_status,
1678 .send_ussd_request = imc_ss_send_ussd_request
1681 gboolean imc_ss_init(TcorePlugin *p, CoreObject *co)
1685 /* Set operations */
1686 tcore_ss_set_ops(co, &imc_ss_ops);
1689 tcore_object_add_callback(co, "+CUSD", on_notification_imc_ss_ussd, NULL);
1695 void imc_ss_exit(TcorePlugin *p, CoreObject *co)