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, void *user_data)
55 gchar *resp_str = NULL;
56 guchar *dcs_str = NULL;
57 TelUtilAlphabetFormat dcs = TEL_UTIL_ALPHABET_FORMAT_SMS_DEFAULT;
59 GSList *tokens = NULL;
62 TelSsUssdNoti ussd_noti = {0,};
64 lines = (GSList *) event_data;
66 if (g_slist_length(lines) != 1) {
67 dbg("Unsolicited message but multiple lines");
71 cmd = (char *) (lines->data);
72 tokens = tcore_at_tok_new(cmd);
74 /* Parse USSD status */
75 resp_str = g_slist_nth_data(tokens, 0);
76 if (NULL == resp_str) {
77 err("status is missing from %CUSD Notification");
78 tcore_at_tok_free(tokens);
81 ussd_status = atoi(resp_str);
82 dbg("USSD status[%d]", ussd_status);
84 if (ussd_status < TEL_SS_USSD_STATUS_NO_ACTION_REQUIRED ||
85 ussd_status > TEL_SS_USSD_STATUS_TIME_OUT) {
86 err("invalid USSD status");
87 tcore_at_tok_free(tokens);
91 /* When network terminated the USSD session, no need to send notification to application */
92 if (ussd_status == TEL_SS_USSD_STATUS_TERMINATED_BY_NETWORK) {
93 /* destroy USSD session if any */
94 UssdSession *ussd_session;
95 ussd_session = tcore_ss_ussd_get_session(co);
98 tcore_ss_ussd_destroy_session(ussd_session);
100 tcore_at_tok_free(tokens);
104 /* Parse USSD string */
105 resp_str = g_slist_nth_data(tokens, 1);
107 resp_str = tcore_at_tok_extract(resp_str);
109 len = strlen((gchar *)resp_str);
110 dbg("USSD String: [%s], len: [%d]", resp_str, len);
112 dbg("Ussd strings is missing from %CUSD Notification");
113 tcore_at_tok_free(tokens);
117 dcs_str = g_slist_nth_data(tokens, 2);
121 dcs = tcore_util_get_cbs_coding_scheme(atoi((gchar *)dcs_str));
123 warn("No dcs string. Using default dcs value");
126 ussd_noti.str = tcore_malloc0(len+1);
128 if ((tcore_util_convert_str_to_utf8(ussd_noti.str, &len, dcs,
129 (const guchar *)resp_str, len+1)) == FALSE) {
130 /* In case of Unhandled dcs type(Reserved), ussd string to ussd_noti.str */
131 memcpy(ussd_noti.str, resp_str, len);
134 dbg("ussd_noti.str[%s]", ussd_noti.str);
136 ussd_noti.status = ussd_status;
138 tcore_object_send_notification(co,
139 TCORE_NOTIFICATION_SS_USSD,
140 sizeof(TelSsUssdNoti), (void *)&ussd_noti);
142 tcore_at_tok_free(tokens);
143 tcore_free(resp_str);
144 tcore_free(ussd_noti.str);
149 static gboolean __imc_ss_convert_modem_class_to_class(gint classx, TelSsClass *class)
154 *class = TEL_SS_CLASS_ALL_TELE;
158 *class = TEL_SS_CLASS_VOICE;
162 *class = TEL_SS_CLASS_ALL_DATA_TELE;
166 *class = TEL_SS_CLASS_FAX;
170 *class = TEL_SS_CLASS_SMS;
174 *class = TEL_SS_CLASS_ALL_CS_SYNC;
178 *class = TEL_SS_CLASS_ALL_CS_ASYNC;
182 *class = TEL_SS_CLASS_ALL_DEDI_PS;
186 *class = TEL_SS_CLASS_ALL_DEDI_PAD;
190 err("Invalid modem class: [%d]", classx);
197 static guint __imc_ss_convert_class_to_imc_class(TelSsClass class)
201 case TEL_SS_CLASS_ALL_TELE:
204 case TEL_SS_CLASS_VOICE:
207 case TEL_SS_CLASS_ALL_DATA_TELE:
210 case TEL_SS_CLASS_FAX:
213 case TEL_SS_CLASS_SMS:
216 case TEL_SS_CLASS_ALL_CS_SYNC:
219 case TEL_SS_CLASS_ALL_CS_ASYNC:
222 case TEL_SS_CLASS_ALL_DEDI_PS:
225 case TEL_SS_CLASS_ALL_DEDI_PAD:
229 dbg("Unsupported class: [%d], returning default value 7", class);
234 static gboolean __imc_ss_convert_barring_type_to_facility(TelSsBarringType type, gchar **facility)
238 case TEL_SS_CB_TYPE_BAOC:
242 case TEL_SS_CB_TYPE_BOIC:
246 case TEL_SS_CB_TYPE_BOIC_NOT_HC:
250 case TEL_SS_CB_TYPE_BAIC:
254 case TEL_SS_CB_TYPE_BIC_ROAM:
258 case TEL_SS_CB_TYPE_AB:
262 case TEL_SS_CB_TYPE_AOB:
266 case TEL_SS_CB_TYPE_AIB:
270 case TEL_SS_CB_TYPE_NS:
275 err("Unspported type: [%d]", type);
281 static gboolean __imc_ss_convert_forwarding_mode_to_modem_mode(TelSsForwardMode mode, guint *modex)
285 case TEL_SS_CF_MODE_DISABLE:
289 case TEL_SS_CF_MODE_ENABLE:
293 case TEL_SS_CF_MODE_REGISTER:
297 case TEL_SS_CF_MODE_DEREGISTER:
302 err("Unspported mode: [%d]", mode);
308 static gboolean __imc_ss_convert_forwarding_condition_to_modem_reason(TelSsForwardCondition condition, guint *reason)
311 case TEL_SS_CF_COND_CFU:
315 case TEL_SS_CF_COND_CFB:
319 case TEL_SS_CF_COND_CFNRY:
323 case TEL_SS_CF_COND_CFNRC:
327 case TEL_SS_CF_COND_ALL:
331 case TEL_SS_CF_COND_ALL_CFC:
336 dbg("Unsupported condition: [%d]", condition);
342 static gint __imc_ss_convert_cli_status_modem_status(gint cli_status)
344 if (cli_status == TEL_SS_CLI_DISABLE)
346 else if (cli_status == TEL_SS_CLI_ENABLE)
349 err("Invalid CLI status: [%d]", cli_status);
354 static gint __imc_ss_convert_clir_status_modem_status(gint clir_status)
356 if (clir_status == TEL_CLIR_STATUS_DEFAULT)
358 else if (clir_status == TEL_CLIR_STATUS_INVOCATION)
360 else if (clir_status == TEL_CLIR_STATUS_SUPPRESSION)
363 err("Invalid CLIR status: [%d]", clir_status);
368 static gboolean __imc_ss_convert_cli_info_modem_info(const TelSsCliInfo **cli_info, gint *status,
371 switch((*cli_info)->type)
373 case TEL_SS_CLI_CLIR:
374 if ((*status = __imc_ss_convert_clir_status_modem_status((*cli_info)->status.clir)) != -1)
375 *cmd_prefix = "+CLIR";
377 err("invalid clir status");
380 case TEL_SS_CLI_CLIP:
381 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.clip) != -1))
382 *cmd_prefix = "+CLIP";
384 err("invalid cli status");
386 case TEL_SS_CLI_COLP:
387 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.colp) != -1))
388 *cmd_prefix = "+COLP";
390 err("invalid cli status");
392 case TEL_SS_CLI_COLR:
393 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.colr) != -1))
394 *cmd_prefix = "+COLR";
396 err("invalid cli status");
399 case TEL_SS_CLI_CNAP:
400 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.cnap) != -1))
401 *cmd_prefix = "+CNAP";
403 err("invalid cli status");
406 case TEL_SS_CLI_CDIP:
408 err("Unsupported CLI type: [%d]", (*cli_info)->type);
412 if (*cmd_prefix == NULL)
418 static gboolean __imc_ss_convert_modem_cli_net_status_cli_status(TelSsCliType cli_type, gint net_status,
421 if (cli_type == TEL_SS_CLI_CLIR) {
422 switch (net_status) {
424 *status = TEL_CLIR_STATUS_NOT_PROVISIONED;
427 *status = TEL_CLIR_STATUS_PROVISIONED;
430 *status = TEL_CLIR_STATUS_UNKNOWN;
433 *status = TEL_CLIR_STATUS_TEMP_RESTRICTED;
436 *status = TEL_CLIR_STATUS_TEMP_ALLOWED;
439 err("Invalid clir net status: [%d]", net_status);
442 } else { //CLIP, COLP,COLR,CNAP.
443 switch (net_status) {
445 *status = TEL_SS_CLI_NOT_PROVISIONED;
448 *status = TEL_SS_CLI_PROVISIONED;
451 *status = TEL_SS_CLI_UNKNOWN;
454 err("Invalid status: [%d]", net_status);
461 static gboolean __imc_ss_convert_modem_cli_dev_status_cli_status(TelSsCliType cli_type,
462 gint dev_status, gint *status)
464 if (cli_type == TEL_SS_CLI_CLIR) {
465 switch (dev_status) {
467 *status = TEL_CLIR_STATUS_DEFAULT;
470 *status = TEL_CLIR_STATUS_INVOCATION;
473 *status = TEL_CLIR_STATUS_SUPPRESSION;
476 err("Invalid dev status: [%d]", dev_status);
479 } else { //CLIP, COLP,COLR,CNAP.
482 *status = TEL_SS_CLI_DISABLE;
485 *status = TEL_SS_CLI_ENABLE;
488 err("Invalid dev status: [%d]", dev_status);
496 static void on_response_imc_ss_set_barring(TcorePending *p,
497 guint data_len, const void *data, void *user_data)
499 const TcoreAtResponse *at_resp = data;
500 CoreObject *co = tcore_pending_ref_core_object(p);
501 ImcRespCbData *resp_cb_data = user_data;
503 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
506 tcore_check_return_assert(co != NULL);
507 tcore_check_return_assert(resp_cb_data != NULL);
509 if (at_resp && at_resp->success)
510 result = TEL_SS_RESULT_SUCCESS;
512 dbg("Setting Barring status: [%s]",
513 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
515 /* Invoke callback */
516 if (resp_cb_data->cb)
517 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
519 imc_destroy_resp_cb_data(resp_cb_data);
522 static void on_response_imc_ss_get_barring_status(TcorePending *p,
523 guint data_len, const void *data, void *user_data)
525 const TcoreAtResponse *at_resp = data;
526 CoreObject *co = tcore_pending_ref_core_object(p);
527 ImcRespCbData *resp_cb_data = user_data;
528 TelSsBarringResp barring_resp = {0,};
529 TelSsBarringGetInfo *req_info;
530 gint valid_records = 0;
531 GSList *resp_data = NULL;
533 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
536 tcore_check_return_assert(co != NULL);
537 tcore_check_return_assert(resp_cb_data != NULL);
539 req_info = (TelSsBarringGetInfo *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
542 if (at_resp->lines && at_resp->success) {
543 resp_data = (GSList *) at_resp->lines;
544 barring_resp.record_num= g_slist_length(resp_data);
545 dbg("Total records: [%d]", barring_resp.record_num);
548 err("RESPONSE - [NOK]");
551 err("No response data");
554 if (barring_resp.record_num > 0) {
555 barring_resp.records = tcore_malloc0((barring_resp.record_num) *
556 sizeof(TelSsBarringInfoRecord));
557 for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
559 GSList *tokens = NULL;
561 line = (const char *) resp_data->data;
562 tokens = tcore_at_tok_new(line);
563 if (g_slist_length(tokens) > 0) {
565 gchar *status = NULL;
567 status = g_slist_nth_data(tokens, 0);
569 dbg("Status is missing");
570 tcore_at_tok_free(tokens);
574 if (atoi(status) == 1) {
575 barring_resp.records[valid_records].enable = TRUE;
577 barring_resp.records[valid_records].enable = FALSE;
580 classx_str = g_slist_nth_data(tokens, 1);
582 dbg("Class error. Setting to the requested class: [%d]", req_info->class);
583 barring_resp.records[valid_records].class = req_info->class;
585 if (__imc_ss_convert_modem_class_to_class(atoi(classx_str),
586 &(barring_resp.records[valid_records].class)) == FALSE) {
587 tcore_at_tok_free(tokens);
592 barring_resp.records[valid_records].type= req_info->type;
593 result = TEL_SS_RESULT_SUCCESS;
596 err("Invalid response message");
598 tcore_at_tok_free(tokens);
602 dbg("Getting Barring status: [%s]",
603 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
604 barring_resp.record_num = valid_records;
606 /* Invoke callback */
607 if (resp_cb_data->cb)
608 resp_cb_data->cb(co, (gint)result, &barring_resp, resp_cb_data->cb_data);
610 imc_destroy_resp_cb_data(resp_cb_data);
612 if (barring_resp.records) {
613 tcore_free(barring_resp.records);
617 static void on_response_imc_ss_change_barring_password(TcorePending *p,
618 guint data_len, const void *data, void *user_data)
620 const TcoreAtResponse *at_resp = data;
621 CoreObject *co = tcore_pending_ref_core_object(p);
622 ImcRespCbData *resp_cb_data = user_data;
624 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
627 tcore_check_return_assert(co != NULL);
628 tcore_check_return_assert(resp_cb_data != NULL);
630 if (at_resp && at_resp->success)
631 result = TEL_SS_RESULT_SUCCESS;
633 dbg("Change Barring Password: [%s]",
634 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
636 /* Invoke callback */
637 if (resp_cb_data->cb)
638 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
640 imc_destroy_resp_cb_data(resp_cb_data);
643 static void on_response_imc_ss_set_forwarding(TcorePending *p,
644 guint data_len, const void *data, void *user_data)
646 const TcoreAtResponse *at_resp = data;
647 CoreObject *co = tcore_pending_ref_core_object(p);
648 ImcRespCbData *resp_cb_data = user_data;
650 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
653 tcore_check_return_assert(co != NULL);
654 tcore_check_return_assert(resp_cb_data != NULL);
656 if (at_resp && at_resp->success)
657 result = TEL_SS_RESULT_SUCCESS;
659 dbg("Set Forwarding Status: [%s]",
660 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
662 /* Invoke callback */
663 if (resp_cb_data->cb)
664 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
666 imc_destroy_resp_cb_data(resp_cb_data);
669 static void on_response_imc_ss_get_forwarding_status(TcorePending *p,
670 guint data_len, const void *data, void *user_data)
672 const TcoreAtResponse *at_resp = data;
673 CoreObject *co = tcore_pending_ref_core_object(p);
674 ImcRespCbData *resp_cb_data = user_data;
675 TelSsForwardingResp forwarding_resp = {0,};
676 TelSsForwardGetInfo *req_info;
677 gint valid_records = 0;
678 GSList *resp_data = NULL;
680 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
683 tcore_check_return_assert(co != NULL);
684 tcore_check_return_assert(resp_cb_data != NULL);
686 req_info = (TelSsForwardGetInfo *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
689 if (at_resp->lines && at_resp->success) {
690 resp_data = (GSList *) at_resp->lines;
691 forwarding_resp.record_num= g_slist_length(resp_data);
692 dbg("Total records: [%d]", forwarding_resp.record_num);
695 err("RESPONSE - [NOK]");
698 err("No response data");
701 if (forwarding_resp.record_num > 0) {
702 forwarding_resp.records = tcore_malloc0((forwarding_resp.record_num) *
703 sizeof(TelSsForwardingInfoRecord));
704 for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
706 GSList *tokens = NULL;
708 line = (const char *) resp_data->data;
709 tokens = tcore_at_tok_new(line);
710 if (g_slist_length(tokens) > 0) {
712 gchar *status = NULL;
713 gchar *number = NULL;
714 gchar *time_str = NULL;
716 status = g_slist_nth_data(tokens, 0);
718 dbg("Status is missing");
719 tcore_at_tok_free(tokens);
723 if (atoi(status) == 1) {
724 forwarding_resp.records[valid_records].enable = TRUE;
726 forwarding_resp.records[valid_records].enable = FALSE;
729 classx_str = g_slist_nth_data(tokens, 1);
731 dbg("Class error. Setting to the requested class: [%d]", req_info->class);
732 forwarding_resp.records[valid_records].class = req_info->class;
734 if (__imc_ss_convert_modem_class_to_class(atoi(classx_str),
735 &(forwarding_resp.records[valid_records].class)) == FALSE) {
736 tcore_at_tok_free(tokens);
741 number = g_slist_nth_data(tokens, 2);
743 number = tcore_at_tok_extract(number);
744 memcpy((forwarding_resp.records[valid_records].number), number, strlen(number));
748 time_str = g_slist_nth_data(tokens, 6);
750 forwarding_resp.records[valid_records].wait_time = atoi(time_str);
752 forwarding_resp.records[valid_records].condition = req_info->condition;
754 result = TEL_SS_RESULT_SUCCESS;
757 err("Invalid response message");
759 tcore_at_tok_free(tokens);
763 dbg("Getting Forwarding Status: [%s]",
764 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
765 forwarding_resp.record_num = valid_records;
767 /* Invoke callback */
768 if (resp_cb_data->cb)
769 resp_cb_data->cb(co, (gint)result, &forwarding_resp, resp_cb_data->cb_data);
771 imc_destroy_resp_cb_data(resp_cb_data);
773 if (forwarding_resp.records) {
774 tcore_free(forwarding_resp.records);
778 static void on_response_imc_ss_set_waiting(TcorePending *p,
779 guint data_len, const void *data, void *user_data)
781 const TcoreAtResponse *at_resp = data;
782 CoreObject *co = tcore_pending_ref_core_object(p);
783 ImcRespCbData *resp_cb_data = user_data;
785 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
788 tcore_check_return_assert(co != NULL);
789 tcore_check_return_assert(resp_cb_data != NULL);
791 if (at_resp && at_resp->success)
792 result = TEL_SS_RESULT_SUCCESS;
794 dbg("Set Waiting Status: [%s]",
795 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
797 /* Invoke callback */
798 if (resp_cb_data->cb)
799 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
801 imc_destroy_resp_cb_data(resp_cb_data);
804 static void on_response_imc_ss_get_waiting_status(TcorePending *p,
805 guint data_len, const void *data, void *user_data)
807 const TcoreAtResponse *at_resp = data;
808 CoreObject *co = tcore_pending_ref_core_object(p);
809 ImcRespCbData *resp_cb_data = user_data;
810 TelSsWaitingResp waiting_resp = {0,};
812 gint valid_records = 0;
813 GSList *resp_data = NULL;
815 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
818 tcore_check_return_assert(co != NULL);
819 tcore_check_return_assert(resp_cb_data != NULL);
821 class = (TelSsClass *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
824 if (at_resp->lines && at_resp->success) {
825 resp_data = (GSList *) at_resp->lines;
826 waiting_resp.record_num= g_slist_length(resp_data);
827 dbg("Total records: [%d]", waiting_resp.record_num);
830 err("RESPONSE - [NOK]");
833 err("No response data");
836 if (waiting_resp.record_num > 0) {
837 waiting_resp.records = tcore_malloc0((waiting_resp.record_num) * sizeof(TelSsWaitingInfo));
838 for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
840 GSList *tokens = NULL;
842 line = (const char *) resp_data->data;
843 tokens = tcore_at_tok_new(line);
844 if (g_slist_length(tokens) > 0) {
846 gchar *status = NULL;
848 status = g_slist_nth_data(tokens, 0);
850 dbg("Status is missing");
851 tcore_at_tok_free(tokens);
855 if (atoi(status) == 1) {
856 waiting_resp.records[valid_records].enable= TRUE;
858 waiting_resp.records[valid_records].enable = FALSE;
861 classx_str = g_slist_nth_data(tokens, 1);
863 dbg("Class error. Setting to the requested class: [%d]", *class);
864 waiting_resp.records[valid_records].class = *class;
866 if (__imc_ss_convert_modem_class_to_class(atoi(classx_str), &(waiting_resp.records[valid_records].class)) == FALSE) {
867 tcore_at_tok_free(tokens);
872 result = TEL_SS_RESULT_SUCCESS;
875 err("Invalid response message");
877 tcore_at_tok_free(tokens);
881 dbg("Getting Waiting Status: [%s]",
882 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
883 waiting_resp.record_num = valid_records;
885 /* Invoke callback */
886 if (resp_cb_data->cb)
887 resp_cb_data->cb(co, (gint)result, &waiting_resp, resp_cb_data->cb_data);
889 imc_destroy_resp_cb_data(resp_cb_data);
891 if (waiting_resp.records) {
892 tcore_free(waiting_resp.records);
896 static void on_response_imc_ss_set_cli(TcorePending *p,
897 guint data_len, const void *data, void *user_data)
899 const TcoreAtResponse *at_resp = data;
900 CoreObject *co = tcore_pending_ref_core_object(p);
901 ImcRespCbData *resp_cb_data = user_data;
903 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
906 tcore_check_return_assert(co != NULL);
907 tcore_check_return_assert(resp_cb_data != NULL);
909 if (at_resp && at_resp->success)
910 result = TEL_SS_RESULT_SUCCESS;
912 dbg("Set Cli Status: [%s]",
913 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
915 /* Invoke callback */
916 if (resp_cb_data->cb)
917 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
919 imc_destroy_resp_cb_data(resp_cb_data);
922 static void on_response_imc_ss_get_cli_status(TcorePending *p,
923 guint data_len, const void *data, void *user_data)
925 const TcoreAtResponse *at_resp = data;
926 CoreObject *co = tcore_pending_ref_core_object(p);
927 ImcRespCbData *resp_cb_data = user_data;
928 TelSsCliResp cli_resp = {0,};
929 TelSsCliType *cli_type;
930 GSList *tokens = NULL;
932 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
935 tcore_check_return_assert(co != NULL);
936 tcore_check_return_assert(resp_cb_data != NULL);
938 cli_type = (TelSsCliType *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
940 if (*cli_type == TEL_SS_CLI_CDIP) {
941 err("Unsupported CLI type: [%d]", *cli_type);
942 result = TEL_SS_RESULT_INVALID_PARAMETER;
946 if (at_resp && at_resp->success) {
948 gchar *status = NULL;
952 if (!at_resp->lines) {
953 err("Invalid response message");
956 line = (const gchar *)at_resp->lines->data;
957 tokens = tcore_at_tok_new(line);
958 if (g_slist_length(tokens) < 1) {
959 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, atoi(status), &dev_status))
972 status = g_slist_nth_data(tokens, 1);
974 err("net_status is missing");
977 if (!__imc_ss_convert_modem_cli_net_status_cli_status(*cli_type, atoi(status), &net_status))
981 case TEL_SS_CLI_CLIR:
982 cli_resp.status.clir.net_status = net_status;
983 cli_resp.status.clir.dev_status = dev_status;
985 case TEL_SS_CLI_CLIP:
986 cli_resp.status.clip.net_status = net_status;
987 cli_resp.status.clip.dev_status = dev_status;
989 case TEL_SS_CLI_COLP:
990 cli_resp.status.colp.net_status = net_status;
991 cli_resp.status.colp.dev_status = dev_status;
993 case TEL_SS_CLI_COLR:
994 cli_resp.status.colr.net_status = net_status;
995 cli_resp.status.colr.dev_status = dev_status;
997 case TEL_SS_CLI_CNAP:
998 cli_resp.status.cnap.net_status = net_status;
999 cli_resp.status.cnap.dev_status = dev_status;
1002 err("Unsupported CLI type: [%d]", *cli_type);
1003 result = TEL_SS_RESULT_INVALID_PARAMETER;
1007 cli_resp.type = *cli_type;
1008 result = TEL_SS_RESULT_SUCCESS;
1010 err("RESPONSE NOK");
1014 tcore_at_tok_free(tokens);
1016 /* Invoke callback */
1017 if (resp_cb_data->cb)
1018 resp_cb_data->cb(co, (gint)result, &cli_resp, resp_cb_data->cb_data);
1020 imc_destroy_resp_cb_data(resp_cb_data);
1023 static void on_response_imc_ss_send_ussd_request(TcorePending *p,
1024 guint data_len, const void *data, void *user_data)
1026 const TcoreAtResponse *at_resp = data;
1027 CoreObject *co = tcore_pending_ref_core_object(p);
1028 ImcRespCbData *resp_cb_data = user_data;
1029 TelSsUssdResp ussd_resp = {0,};
1030 UssdSession *ussd_s = NULL;
1032 TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
1035 tcore_check_return_assert(co != NULL);
1036 tcore_check_return_assert(resp_cb_data != NULL);
1038 ussd_s = tcore_ss_ussd_get_session(co);
1039 tcore_check_return(ussd_s != NULL);
1041 tcore_ss_ussd_get_session_type(ussd_s, &ussd_resp.type);
1043 if (at_resp && at_resp->success) {
1044 result = TEL_SS_RESULT_SUCCESS;
1045 /* Need to initialise ussd response string */
1046 ussd_resp.str = (unsigned char *)g_strdup("Operation success");
1048 ussd_resp.str = (unsigned char *)g_strdup("Operation failed");
1052 dbg("Send Ussd Request: [%s]",
1053 (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1055 tcore_ss_ussd_destroy_session(ussd_s);
1058 /* Invoke callback */
1059 if (resp_cb_data->cb)
1060 resp_cb_data->cb(co, (gint)result, &ussd_resp, resp_cb_data->cb_data);
1062 imc_destroy_resp_cb_data(resp_cb_data);
1063 g_free(ussd_resp.str);
1068 * Operation - set_barring/get_barring_status
1071 * AT-Command: AT+CLCK=<fac>,<mode>[,<passwd>[,<class>]]
1074 * Barring facility type. Ref #TelSsBarringType
1085 * SS class. Ref #TelSsClass
1091 * Success: when <mode>=2:
1093 * +CLCK: <status>[,<class1> [<CR><LF>
1094 * +CLCK: <status>,<class2> [...]]
1097 * +CME ERROR: <error>
1099 static TelReturn imc_ss_set_barring(CoreObject *co, const TelSsBarringInfo *barring_info,
1100 TcoreObjectResponseCallback cb, void *cb_data)
1102 gchar *at_cmd = NULL;
1105 gchar *facility = NULL;
1106 ImcRespCbData *resp_cb_data = NULL;
1107 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1109 if (barring_info->enable == TRUE)
1114 if (__imc_ss_convert_barring_type_to_facility(barring_info->type, &facility) == FALSE) {
1115 err("Invalid arguments");
1119 classx = __imc_ss_convert_class_to_imc_class(barring_info->class);
1121 dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
1124 at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,\"%s\",%d", facility, mode, barring_info->pwd, classx);
1126 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1128 /* Send Request to modem */
1129 ret = tcore_at_prepare_and_send_request(co,
1131 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1132 TCORE_PENDING_PRIORITY_DEFAULT,
1134 on_response_imc_ss_set_barring, resp_cb_data,
1135 on_send_imc_request, NULL,
1138 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Barring");
1145 static TelReturn imc_ss_get_barring_status(CoreObject *co, const TelSsBarringGetInfo *get_barring_info,
1146 TcoreObjectResponseCallback cb, void *cb_data)
1148 gchar *at_cmd = NULL;
1151 gchar *facility = NULL;
1152 ImcRespCbData *resp_cb_data = NULL;
1153 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1155 mode = 2; /* query status - mode is fixed to 2 */
1157 if (__imc_ss_convert_barring_type_to_facility(get_barring_info->type, &facility) == FALSE) {
1158 err("Invalid arguments");
1162 classx = __imc_ss_convert_class_to_imc_class(get_barring_info->class);
1164 dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
1167 at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,,%d", facility, mode, classx);
1169 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, (void *)get_barring_info, sizeof(TelSsBarringGetInfo));
1171 /* Send Request to modem */
1172 ret = tcore_at_prepare_and_send_request(co,
1174 TCORE_AT_COMMAND_TYPE_MULTILINE,
1175 TCORE_PENDING_PRIORITY_DEFAULT,
1177 on_response_imc_ss_get_barring_status, resp_cb_data,
1178 on_send_imc_request, NULL,
1181 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Barring Status");
1189 * Operation - change_barring_password
1192 * AT-Command: AT+CPWD= <fac>,<oldpwd>,<newpwd>
1195 * Barring facility type. Ref #TelSsBarringType
1196 * Eg: "AB" All Barring services
1199 * Old Barring Password
1202 * New Barring Password
1208 * +CME ERROR: <error>
1210 static TelReturn imc_ss_change_barring_password(CoreObject *co, 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, barring_pwd_info->new_pwd);
1224 at_cmd = g_strdup_printf("AT+CPWD=\"%s\",\"%s\",\"%s\"", "AB", barring_pwd_info->old_pwd, barring_pwd_info->new_pwd);
1226 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1228 /* Send Request to modem */
1229 ret = tcore_at_prepare_and_send_request(co,
1231 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1232 TCORE_PENDING_PRIORITY_DEFAULT,
1234 on_response_imc_ss_change_barring_password, resp_cb_data,
1235 on_send_imc_request, NULL,
1238 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Change Barring Password");
1246 * Operation - set_forwarding/get_forwarding_status
1249 * AT-Command: AT+CCFC=<reason>,<mode>[,<number>[,<type>[,<class>[,<subaddr>[,<satype>[,<time>]]]]]]
1252 * Forwarding Condition. Ref #TelSsForwardCondition
1255 * Forwarding Mode. Ref #TelSsForwardMode
1264 * Call Forwarding Number
1267 * Default 145 when available string includes "+"
1271 * Parameter String type subaddress of format specified by <satype>
1274 * Parameter type of subaddress octet in integer format
1278 * Parameter time in seconds to wait before call is forwarded
1279 * Default 20, but only when <reason>=2 (no reply) is enabled
1282 * SS class. Ref #TelSsClass
1288 * Success: when <mode>=2:
1290 * +CCFC: <status>,<class1>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][<CR><LF>
1291 * +CCFC: <status>,<class2>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][...]]
1294 * +CME ERROR: <error>
1296 static TelReturn imc_ss_set_forwarding(CoreObject *co, const TelSsForwardInfo *forwarding_info,
1297 TcoreObjectResponseCallback cb, void *cb_data)
1299 gchar *at_cmd = NULL;
1300 gchar *tmp_cmd = NULL;
1305 ImcRespCbData *resp_cb_data = NULL;
1306 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1308 classx = __imc_ss_convert_class_to_imc_class(forwarding_info->class);
1310 if (__imc_ss_convert_forwarding_mode_to_modem_mode(forwarding_info->mode, &mode) == FALSE) {
1311 err("Invalid arguments");
1315 if (__imc_ss_convert_forwarding_condition_to_modem_reason(forwarding_info->condition, &reason) == FALSE) {
1316 err("Invalid arguments");
1320 if (forwarding_info->number[0] == '+')
1325 dbg("classx: [%d], reason:[%d], mode: [%d]", classx, reason, mode);
1327 if (mode == 3) /* TEL_SS_CF_MODE_REGISTER */
1328 tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,\"%s\",%d,%d", reason, mode, forwarding_info->number, num_type, classx);
1330 tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
1332 if (reason == 2) /* TEL_SS_CF_COND_CFNRY */
1333 at_cmd = g_strdup_printf("%s,,,%d", tmp_cmd, forwarding_info->wait_time);
1335 at_cmd = g_strdup_printf("%s", tmp_cmd);
1337 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1339 /* Send Request to modem */
1340 ret = tcore_at_prepare_and_send_request(co,
1342 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1343 TCORE_PENDING_PRIORITY_DEFAULT,
1345 on_response_imc_ss_set_forwarding, resp_cb_data,
1346 on_send_imc_request, NULL,
1349 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Forwarding");
1357 static TelReturn imc_ss_get_forwarding_status(CoreObject *co, const TelSsForwardGetInfo *get_forwarding_info,
1358 TcoreObjectResponseCallback cb, void *cb_data)
1360 gchar *at_cmd = NULL;
1363 guint mode = 2; /* query status */
1364 ImcRespCbData *resp_cb_data = NULL;
1365 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1367 classx = __imc_ss_convert_class_to_imc_class(get_forwarding_info->class);
1369 if (__imc_ss_convert_forwarding_condition_to_modem_reason(get_forwarding_info->condition, &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, sizeof(TelSsForwardGetInfo));
1380 /* Send Request to modem */
1381 ret = tcore_at_prepare_and_send_request(co,
1383 TCORE_AT_COMMAND_TYPE_MULTILINE,
1384 TCORE_PENDING_PRIORITY_DEFAULT,
1386 on_response_imc_ss_get_forwarding_status, resp_cb_data,
1387 on_send_imc_request, NULL,
1390 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Forwarding Status");
1398 * Operation - set_waiting/get_waiting_status
1401 * AT-Command: AT+CCWA=[<n>[,<mode>[,<class>]]]
1404 * Parameter Sets/shows the result code presentation status to the TE.
1405 * 0 presentation status is disabled to TE(default)
1406 * 1 presentation status is enabled to TE
1409 * 0 Disable call waiting
1410 * 1 Enable call waiting
1414 * SS class. Ref #TelSsClass
1420 * Success: when <mode>=2:
1422 * +CCWA: <status>,<class1>
1423 * +CCWA: <status>,<class2>
1426 * +CME ERROR: <error>
1428 static TelReturn imc_ss_set_waiting(CoreObject *co, const TelSsWaitingInfo *waiting_info,
1429 TcoreObjectResponseCallback cb, void *cb_data)
1431 gchar *at_cmd = NULL;
1434 ImcRespCbData *resp_cb_data = NULL;
1435 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1437 if (waiting_info->enable == TRUE)
1442 classx = __imc_ss_convert_class_to_imc_class(waiting_info->class);
1444 dbg("mode: [%d], class: [%d]", mode, classx);
1446 at_cmd = g_strdup_printf("AT+CCWA=1,%d,%d", mode, classx);
1448 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1450 /* Send Request to modem */
1451 ret = tcore_at_prepare_and_send_request(co,
1453 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1454 TCORE_PENDING_PRIORITY_DEFAULT,
1456 on_response_imc_ss_set_waiting, resp_cb_data,
1457 on_send_imc_request, NULL,
1460 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Waiting");
1467 static TelReturn imc_ss_get_waiting_status(CoreObject *co, TelSsClass ss_class,
1468 TcoreObjectResponseCallback cb, void *cb_data)
1470 gchar *at_cmd = NULL;
1472 ImcRespCbData *resp_cb_data = NULL;
1473 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1475 classx = __imc_ss_convert_class_to_imc_class(ss_class);
1477 dbg("class: [%d]", classx);
1479 at_cmd = g_strdup_printf("AT+CCWA=1,2,%d", classx);
1481 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &ss_class, sizeof(TelSsClass));
1483 /* Send Request to modem */
1484 ret = tcore_at_prepare_and_send_request(co,
1486 TCORE_AT_COMMAND_TYPE_MULTILINE,
1487 TCORE_PENDING_PRIORITY_DEFAULT,
1489 on_response_imc_ss_get_waiting_status, resp_cb_data,
1490 on_send_imc_request, NULL,
1493 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Waiting Status");
1501 * Operation - set_cli/get_cli_status
1505 * For CLIR: AT+CLIR= [<n>]
1506 * For CLIP: AT+CLIP= [<n>]
1507 * For COLP: AT+COLP= [<n>]
1508 * For COLR: AT+COLR= [<n>]
1509 * For CNAP: AT+CNAP= [<n>]
1512 * <n> All CLI except CLIR
1513 * 0 disable(default)
1519 * 2 CLIR suppression
1526 * <m> All CLI except CLIR
1533 * 1 Provisioned in permanent mode
1534 * 2 Unknown (e.g. no network, etc.)
1535 * 3 Temporary mode presentation restricted
1536 * 4 Temporary mode presentation allowed
1539 * +CME ERROR: <error>
1541 static TelReturn imc_ss_set_cli(CoreObject *co, const TelSsCliInfo *cli_info,
1542 TcoreObjectResponseCallback cb, void *cb_data)
1544 gchar *at_cmd = NULL;
1545 gchar *cmd_prefix = NULL;
1547 ImcRespCbData *resp_cb_data = NULL;
1548 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1550 if (__imc_ss_convert_cli_info_modem_info(&cli_info, &status, &cmd_prefix) == FALSE)
1553 at_cmd = g_strdup_printf("AT%s=%d", cmd_prefix, status);
1555 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1557 /* Send Request to modem */
1558 ret = tcore_at_prepare_and_send_request(co,
1560 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1561 TCORE_PENDING_PRIORITY_DEFAULT,
1563 on_response_imc_ss_set_cli, resp_cb_data,
1564 on_send_imc_request, NULL,
1567 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Cli");
1574 static TelReturn imc_ss_get_cli_status(CoreObject *co, TelSsCliType cli_type,
1575 TcoreObjectResponseCallback cb, void *cb_data)
1577 gchar *at_cmd = NULL;
1578 gchar *cmd_prefix = NULL;
1579 ImcRespCbData *resp_cb_data = NULL;
1580 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1583 case TEL_SS_CLI_CLIR:
1584 cmd_prefix = "+CLIR";
1587 case TEL_SS_CLI_CLIP:
1588 cmd_prefix = "+CLIP";
1591 case TEL_SS_CLI_COLP:
1592 cmd_prefix = "+COLP";
1595 case TEL_SS_CLI_COLR:
1596 cmd_prefix = "+COLR";
1599 case TEL_SS_CLI_CNAP:
1600 cmd_prefix = "+CNAP";
1603 case TEL_SS_CLI_CDIP:
1605 dbg("Unsupported CLI type: [%d]", cli_type);
1609 at_cmd = g_strdup_printf("AT%s?", cmd_prefix);
1611 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &cli_type, sizeof(TelSsCliType));
1613 /* Send Request to modem */
1614 ret = tcore_at_prepare_and_send_request(co,
1616 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1617 TCORE_PENDING_PRIORITY_DEFAULT,
1619 on_response_imc_ss_get_cli_status, resp_cb_data,
1620 on_send_imc_request, NULL,
1623 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Cli Status");
1631 * Operation - send_ussd_request
1634 * AT-Command: AT+CUSD = [<n> [, <str> [, <dcs>]]]
1637 * 0 Disable the result code presentation to the TE(default)
1638 * 1 Enable the result code presentation to the TE
1639 * 2 Cancel session (not applicable to read command response)
1645 * Cell Broadcast Data Coding Scheme. Default value is 0.
1651 * +CME ERROR: <error>
1653 static TelReturn imc_ss_send_ussd_request(CoreObject *co, const TelSsUssdInfo *ussd_request,
1654 TcoreObjectResponseCallback cb, void *cb_data)
1656 gchar *at_cmd = NULL;
1657 UssdSession *ussd_s = NULL;
1658 ImcRespCbData *resp_cb_data = NULL;
1659 TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1661 ussd_s = tcore_ss_ussd_get_session(co);
1663 dbg("USSD session does not exist");
1664 tcore_ss_ussd_create_session(co, ussd_request->type, (void *)ussd_request->str, strlen((char *)ussd_request->str));
1666 if (ussd_request->type == TEL_SS_USSD_TYPE_USER_INIT) {
1667 err("Ussd session is already exist");
1668 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1670 tcore_ss_ussd_set_session_type(ussd_s, ussd_request->type);
1673 at_cmd = g_strdup_printf("AT+CUSD=1,\"%s\",%d", ussd_request->str, 0x0f);
1675 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1677 /* Send Request to modem */
1678 ret = tcore_at_prepare_and_send_request(co,
1680 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1681 TCORE_PENDING_PRIORITY_DEFAULT,
1683 on_response_imc_ss_send_ussd_request, resp_cb_data,
1684 on_send_imc_request, NULL,
1687 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Send Ussd Request");
1695 static TcoreSsOps imc_ss_ops = {
1696 .set_barring = imc_ss_set_barring,
1697 .get_barring_status = imc_ss_get_barring_status,
1698 .change_barring_password = imc_ss_change_barring_password,
1699 .set_forwarding = imc_ss_set_forwarding,
1700 .get_forwarding_status = imc_ss_get_forwarding_status,
1701 .set_waiting = imc_ss_set_waiting,
1702 .get_waiting_status = imc_ss_get_waiting_status,
1703 .set_cli = imc_ss_set_cli,
1704 .get_cli_status = imc_ss_get_cli_status,
1705 .send_ussd_request = imc_ss_send_ussd_request
1708 gboolean imc_ss_init(TcorePlugin *p, CoreObject *co)
1712 /* Set operations */
1713 tcore_ss_set_ops(co, &imc_ss_ops);
1716 tcore_object_add_callback(co, "+CUSD", on_notification_imc_ss_ussd, NULL);
1722 void imc_ss_exit(TcorePlugin *p, CoreObject *co)