Code cleanup
[platform/core/telephony/tel-plugin-imc.git] / src / imc_ss.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <glib.h>
24
25 #include <tcore.h>
26 #include <server.h>
27 #include <plugin.h>
28 #include <core_object.h>
29 #include <hal.h>
30 #include <queue.h>
31 #include <storage.h>
32 #include <at.h>
33
34 #include <co_ss.h>
35
36 #include "imc_ss.h"
37 #include "imc_common.h"
38
39 /* AT+CUSD = [<n> [, <str> [, <dcs>]]]
40  * where,
41  * <n>
42  * 0 Disable
43  * 1 Enable
44  * 2 Cancel the session
45  *
46  * <str>
47  * Ussd string
48  *
49  * <dcs>
50  * Decoding format
51  */
52 static gboolean on_notification_imc_ss_ussd(CoreObject *co, const void *event_data,
53         void *user_data)
54 {
55         gchar *cmd = 0;
56         gchar *resp_str = NULL;
57         guchar *dcs_str = NULL;
58         TelUtilAlphabetFormat dcs = TEL_UTIL_ALPHABET_FORMAT_SMS_DEFAULT;
59         gushort len;
60         GSList *tokens = NULL;
61         GSList *lines = NULL;
62         int ussd_status = 0;
63         TelSsUssdNoti ussd_noti = {0,};
64
65         lines = (GSList *) event_data;
66
67         if (g_slist_length(lines) != 1) {
68                 dbg("Unsolicited message but multiple lines");
69                 return TRUE;
70         }
71
72         cmd = (char *) (lines->data);
73         tokens = tcore_at_tok_new(cmd);
74
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);
80                 return TRUE;
81         } else {
82                 ussd_status = atoi(resp_str);
83                 dbg("USSD status[%d]", ussd_status);
84
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);
89                         return TRUE;
90                 }
91
92                 /*
93                  * When network terminated the USSD session, no need to
94                  * send notification to application
95                  */
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);
100
101                         if (ussd_session)
102                                 tcore_ss_ussd_destroy_session(ussd_session);
103
104                         tcore_at_tok_free(tokens);
105                         return TRUE;
106                 }
107
108                 /* Parse USSD string */
109                 resp_str = g_slist_nth_data(tokens, 1);
110
111                 resp_str = tcore_at_tok_extract(resp_str);
112                 if (resp_str) {
113                         len = strlen((gchar *)resp_str);
114                         dbg("USSD String: [%s], len: [%d]", resp_str, len);
115                 } else {
116                         dbg("Ussd string  missing from +CUSD Notification");
117                         tcore_at_tok_free(tokens);
118                         return TRUE;
119                 }
120
121                 dcs_str = g_slist_nth_data(tokens, 2);
122         }
123
124         if (dcs_str) {
125                 dcs = tcore_util_get_cbs_coding_scheme(atoi((gchar *)dcs_str));
126         } else {
127                 warn("No dcs string. Using default dcs value");
128         }
129
130         ussd_noti.str = tcore_malloc0(len + 1);
131
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
136                  */
137                 memcpy(ussd_noti.str, resp_str, len);
138         }
139
140         dbg("ussd_noti.str[%s]", ussd_noti.str);
141
142         ussd_noti.status = ussd_status;
143
144         tcore_object_send_notification(co,
145                 TCORE_NOTIFICATION_SS_USSD,
146                 sizeof(TelSsUssdNoti), (void *)&ussd_noti);
147
148         tcore_at_tok_free(tokens);
149         tcore_free(resp_str);
150         tcore_free(ussd_noti.str);
151
152         return TRUE;
153 }
154
155 static gboolean __imc_ss_convert_modem_class_to_class(gint classx, TelSsClass *class)
156 {
157         switch(classx)
158         {
159         case 7:
160                 *class = TEL_SS_CLASS_ALL_TELE;
161         break;
162         case 1:
163                 *class = TEL_SS_CLASS_VOICE;
164         break;
165         case 2:
166                 *class = TEL_SS_CLASS_ALL_DATA_TELE;
167         break;
168         case 4:
169                 *class = TEL_SS_CLASS_FAX;
170         break;
171         case 8:
172                 *class = TEL_SS_CLASS_SMS;
173         break;
174         case 16:
175                 *class = TEL_SS_CLASS_ALL_CS_SYNC;
176         break;
177         case 32:
178                 *class = TEL_SS_CLASS_ALL_CS_ASYNC;
179         break;
180         case 64:
181                 *class = TEL_SS_CLASS_ALL_DEDI_PS;
182         break;
183         case 128:
184                 *class = TEL_SS_CLASS_ALL_DEDI_PAD;
185         break;
186         default:
187                 err("Invalid modem class: [%d]", classx);
188                 return FALSE;
189         }
190
191         return TRUE;
192 }
193
194 static guint __imc_ss_convert_class_to_imc_class(TelSsClass class)
195 {
196         switch(class)
197         {
198         case TEL_SS_CLASS_ALL_TELE:
199                 return 7;
200
201         case TEL_SS_CLASS_VOICE:
202                 return 1;
203
204         case TEL_SS_CLASS_ALL_DATA_TELE:
205                 return 2;
206
207         case TEL_SS_CLASS_FAX:
208                 return 4;
209
210         case TEL_SS_CLASS_SMS:
211                 return 8;
212
213         case TEL_SS_CLASS_ALL_CS_SYNC:
214                 return 16;
215
216         case TEL_SS_CLASS_ALL_CS_ASYNC:
217                 return 32;
218
219         case TEL_SS_CLASS_ALL_DEDI_PS:
220                 return 64;
221
222         case TEL_SS_CLASS_ALL_DEDI_PAD:
223                 return 128;
224
225         default:
226                 dbg("Unsupported class: [%d], returning default value 7", class);
227                 return 7;
228         }
229 }
230
231 static gboolean __imc_ss_convert_barring_type_to_facility(TelSsBarringType type,
232         gchar **facility)
233 {
234         switch(type)
235         {
236         case TEL_SS_CB_TYPE_BAOC:
237                 *facility = "AO";
238         break;
239         case TEL_SS_CB_TYPE_BOIC:
240                 *facility = "OI";
241         break;
242         case TEL_SS_CB_TYPE_BOIC_NOT_HC:
243                 *facility = "OX";
244         break;
245         case TEL_SS_CB_TYPE_BAIC:
246                 *facility = "AI";
247         break;
248         case TEL_SS_CB_TYPE_BIC_ROAM:
249                 *facility = "IR";
250         break;
251         case TEL_SS_CB_TYPE_AB:
252                 *facility = "AB";
253         break;
254         case TEL_SS_CB_TYPE_AOB:
255                 *facility = "AG";
256         break;
257         case TEL_SS_CB_TYPE_AIB:
258                 *facility = "AC";
259         break;
260         case TEL_SS_CB_TYPE_NS:
261                 *facility = "NS";
262         break;
263         default:
264                 err("Unspported type: [%d]", type);
265                 return FALSE;
266         }
267         return TRUE;
268 }
269
270 static gboolean __imc_ss_convert_forwarding_mode_to_modem_mode(TelSsForwardMode mode,
271         guint *modex)
272 {
273         switch(mode)
274         {
275         case TEL_SS_CF_MODE_DISABLE:
276                 *modex = 0;
277         break;
278         case TEL_SS_CF_MODE_ENABLE:
279                 *modex = 1;
280         break;
281         case TEL_SS_CF_MODE_REGISTER:
282                 *modex = 3;
283         break;
284         case TEL_SS_CF_MODE_DEREGISTER:
285                 *modex = 4;
286         break;
287         default:
288                 err("Unspported mode: [%d]", mode);
289                 return FALSE;
290         }
291         return TRUE;
292 }
293
294 static gboolean __imc_ss_convert_forwarding_condition_to_modem_reason(TelSsForwardCondition condition,
295         guint *reason)
296 {
297         switch (condition) {
298         case TEL_SS_CF_COND_CFU:
299                 *reason = 0;
300         break;
301         case TEL_SS_CF_COND_CFB:
302                 *reason = 1;
303         break;
304         case TEL_SS_CF_COND_CFNRY:
305                 *reason = 2;
306         break;
307         case TEL_SS_CF_COND_CFNRC:
308                 *reason = 3;
309         break;
310         case TEL_SS_CF_COND_ALL:
311                 *reason = 4;
312         break;
313         case TEL_SS_CF_COND_ALL_CFC:
314                 *reason = 5;
315         break;
316         default:
317                 dbg("Unsupported condition: [%d]", condition);
318                 return FALSE;
319         }
320         return TRUE;
321 }
322
323 static gint __imc_ss_convert_cli_status_modem_status(gint cli_status)
324 {
325         if (cli_status == TEL_SS_CLI_DISABLE)
326                 return 0;
327         else if (cli_status == TEL_SS_CLI_ENABLE)
328                 return 1;
329         else {
330                 err("Invalid CLI status: [%d]", cli_status);
331                 return -1;
332         }
333 }
334
335 static gint __imc_ss_convert_clir_status_modem_status(gint clir_status)
336 {
337         if (clir_status == TEL_CLIR_STATUS_DEFAULT)
338                  return 0;
339         else if (clir_status == TEL_CLIR_STATUS_INVOCATION)
340                  return 1;
341         else if (clir_status == TEL_CLIR_STATUS_SUPPRESSION)
342                  return 2;
343         else {
344                 err("Invalid CLIR status: [%d]", clir_status);
345                 return -1;
346         }
347 }
348
349 static gboolean __imc_ss_convert_cli_info_modem_info(const TelSsCliInfo **cli_info,gint *status,
350         gchar **cmd_prefix)
351 {
352         switch((*cli_info)->type)
353         {
354         case TEL_SS_CLI_CLIR:
355                 if ((*status = __imc_ss_convert_clir_status_modem_status((*cli_info)->status.clir))
356                         != -1) {
357                         *cmd_prefix = "+CLIR";
358                 } else {
359                         err("invalid clir status");
360                 }
361         break;
362
363         case TEL_SS_CLI_CLIP:
364                 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.clip)
365                         != -1)) {
366                         *cmd_prefix = "+CLIP";
367                 } else {
368                         err("invalid clip status");
369                 }
370         break;
371         case TEL_SS_CLI_COLP:
372                 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.colp)
373                         != -1)) {
374                         *cmd_prefix = "+COLP";
375                 } else {
376                         err("invalid colp status");
377                 }
378         break;
379         case TEL_SS_CLI_COLR:
380                 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.colr)
381                         != -1)) {
382                         *cmd_prefix = "+COLR";
383                 } else {
384                         err("invalid colr status");
385                 }
386         break;
387         case TEL_SS_CLI_CNAP:
388                 if ((*status =__imc_ss_convert_cli_status_modem_status((*cli_info)->status.cnap)
389                         != -1)) {
390                         *cmd_prefix = "+CNAP";
391                 } else {
392                         err("invalid cnap status");
393                 }
394
395         break;
396         case TEL_SS_CLI_CDIP:
397         default:
398                 err("Unsupported CLI type: [%d]", (*cli_info)->type);
399                 return FALSE;
400         }
401
402         if (*cmd_prefix == NULL)
403                 return FALSE;
404
405         return TRUE;
406 }
407
408 static gboolean __imc_ss_convert_modem_cli_net_status_cli_status(TelSsCliType cli_type,
409         gint net_status, gint *status)
410 {
411         if (cli_type == TEL_SS_CLI_CLIR) {
412                 switch (net_status) {
413                 case 0:
414                         *status = TEL_CLIR_STATUS_NOT_PROVISIONED;
415                 break;
416                 case 1:
417                         *status = TEL_CLIR_STATUS_PROVISIONED;
418                 break;
419                 case 2:
420                         *status = TEL_CLIR_STATUS_UNKNOWN;
421                 break;
422                 case 3:
423                         *status = TEL_CLIR_STATUS_TEMP_RESTRICTED;
424                 break;
425                 case 4:
426                         *status = TEL_CLIR_STATUS_TEMP_ALLOWED;
427                 break;
428                 default:
429                         err("Invalid clir net status: [%d]", net_status);
430                         return FALSE;
431                 }
432         } else { //CLIP, COLP,COLR,CNAP.
433                 switch (net_status) {
434                 case 0:
435                         *status = TEL_SS_CLI_NOT_PROVISIONED;
436                 break;
437                 case 1:
438                         *status = TEL_SS_CLI_PROVISIONED;
439                 break;
440                 case 2:
441                         *status = TEL_SS_CLI_UNKNOWN;
442                 break;
443                 default:
444                         err("Invalid status: [%d]", net_status);
445                         return FALSE;
446                 }
447         }
448         return TRUE;
449 }
450
451 static gboolean __imc_ss_convert_modem_cli_dev_status_cli_status(TelSsCliType cli_type,
452         gint dev_status, gint *status)
453 {
454         if (cli_type == TEL_SS_CLI_CLIR) {
455                 switch (dev_status) {
456                 case 0:
457                         *status = TEL_CLIR_STATUS_DEFAULT;
458                 break;
459                 case 1:
460                         *status = TEL_CLIR_STATUS_INVOCATION;
461                 break;
462                 case 2:
463                         *status = TEL_CLIR_STATUS_SUPPRESSION;
464                 break;
465                 default:
466                         err("Invalid dev status: [%d]", dev_status);
467                         return FALSE;
468                 }
469         } else { //CLIP, COLP,COLR,CNAP.
470                 switch(dev_status) {
471                 case 0:
472                         *status  = TEL_SS_CLI_DISABLE;
473                 break;
474                 case 1:
475                         *status  = TEL_SS_CLI_ENABLE;
476                 break;
477                 default:
478                         err("Invalid dev status: [%d]", dev_status);
479                         return FALSE;
480                 }
481         }
482         return TRUE;
483 }
484
485 /* SS Responses */
486 static void on_response_imc_ss_set_barring(TcorePending *p,
487         guint data_len, const void *data, void *user_data)
488 {
489         const TcoreAtResponse *at_resp = data;
490         CoreObject *co = tcore_pending_ref_core_object(p);
491         ImcRespCbData *resp_cb_data = user_data;
492
493         /* TODO: CMEE error mapping is required */
494         TelSsResult result = TEL_SS_RESULT_FAILURE;
495         dbg("Enter");
496
497         tcore_check_return_assert(co != NULL);
498         tcore_check_return_assert(resp_cb_data != NULL);
499
500         if (at_resp && at_resp->success)
501                 result = TEL_SS_RESULT_SUCCESS;
502
503         dbg("Setting Barring status: [%s]",
504                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
505
506         /* Invoke callback */
507         if (resp_cb_data->cb)
508                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
509
510         imc_destroy_resp_cb_data(resp_cb_data);
511 }
512
513 static void on_response_imc_ss_get_barring_status(TcorePending *p,
514         guint data_len, const void *data, void *user_data)
515 {
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;
525         dbg("Enter");
526
527         tcore_check_return_assert(co != NULL);
528         tcore_check_return_assert(resp_cb_data != NULL);
529
530         req_info = (TelSsBarringGetInfo *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
531
532         if (at_resp) {
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);
537                 }
538                 else {
539                         err("RESPONSE - [NOK]");
540                 }
541         } else {
542                 err("No response data");
543         }
544
545         if (barring_resp.record_num > 0) {
546                 barring_resp.records = tcore_malloc0((barring_resp.record_num) *
547                         sizeof(TelSsBarringInfoRecord));
548
549                 for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
550                         const gchar *line;
551                         GSList *tokens = NULL;
552
553                         line = (const char *) resp_data->data;
554                         tokens = tcore_at_tok_new(line);
555                         if (g_slist_length(tokens) > 0) {
556                                 gchar *classx_str;
557                                 gchar *status = NULL;
558
559                                 status = g_slist_nth_data(tokens, 0);
560                                 if (!status) {
561                                         dbg("Status is missing");
562                                         tcore_at_tok_free(tokens);
563                                         continue;
564                                 }
565
566                                 if (atoi(status) == 1) {
567                                         barring_resp.records[valid_records].enable = TRUE;
568                                 } else {
569                                         barring_resp.records[valid_records].enable = FALSE;
570                                 }
571
572                                 classx_str = g_slist_nth_data(tokens, 1);
573                                 if (!classx_str) {
574                                         dbg("Class error. Setting to the requested class: [%d]",
575                                                 req_info->class);
576                                         barring_resp.records[valid_records].class = req_info->class;
577                                 } else {
578                                         if (__imc_ss_convert_modem_class_to_class(atoi(classx_str),
579                                                 &(barring_resp.records[valid_records].class))
580                                                 == FALSE) {
581                                                 tcore_at_tok_free(tokens);
582                                                 continue;
583                                         }
584                                 }
585
586                                 barring_resp.records[valid_records].type= req_info->type;
587                                 result = TEL_SS_RESULT_SUCCESS;
588                                 valid_records++;
589                         } else {
590                                 err("Invalid response message");
591                         }
592                         tcore_at_tok_free(tokens);
593                 }
594         }
595
596         dbg("Getting Barring status: [%s]",
597                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
598         barring_resp.record_num = valid_records;
599
600         /* Invoke callback */
601         if (resp_cb_data->cb)
602                 resp_cb_data->cb(co, (gint)result, &barring_resp, resp_cb_data->cb_data);
603
604         imc_destroy_resp_cb_data(resp_cb_data);
605
606         if (barring_resp.records) {
607                 tcore_free(barring_resp.records);
608         }
609 }
610
611 static void on_response_imc_ss_change_barring_password(TcorePending *p,
612         guint data_len, const void *data, void *user_data)
613 {
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;
619         dbg("Enter");
620
621         tcore_check_return_assert(co != NULL);
622         tcore_check_return_assert(resp_cb_data != NULL);
623
624         if (at_resp && at_resp->success)
625                 result = TEL_SS_RESULT_SUCCESS;
626
627         dbg("Change Barring Password: [%s]",
628                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
629
630         /* Invoke callback */
631         if (resp_cb_data->cb)
632                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
633
634         imc_destroy_resp_cb_data(resp_cb_data);
635 }
636
637 static void on_response_imc_ss_set_forwarding(TcorePending *p,
638         guint data_len, const void *data, void *user_data)
639 {
640         const TcoreAtResponse *at_resp = data;
641         CoreObject *co = tcore_pending_ref_core_object(p);
642         ImcRespCbData *resp_cb_data = user_data;
643
644         /* TODO: CMEE error mapping is required */
645         TelSsResult result = TEL_SS_RESULT_FAILURE;
646         dbg("Enter");
647
648         tcore_check_return_assert(co != NULL);
649         tcore_check_return_assert(resp_cb_data != NULL);
650
651         if (at_resp && at_resp->success)
652                 result = TEL_SS_RESULT_SUCCESS;
653
654         dbg("Set Forwarding Status: [%s]",
655                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
656
657         /* Invoke callback */
658         if (resp_cb_data->cb)
659                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
660
661         imc_destroy_resp_cb_data(resp_cb_data);
662 }
663
664 static void on_response_imc_ss_get_forwarding_status(TcorePending *p,
665         guint data_len, const void *data, void *user_data)
666 {
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;
676         dbg("Enter");
677
678         tcore_check_return_assert(co != NULL);
679         tcore_check_return_assert(resp_cb_data != NULL);
680
681         req_info = (TelSsForwardGetInfo *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
682
683         if (at_resp) {
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);
688                 } else {
689                         err("RESPONSE - [NOK]");
690                 }
691         } else {
692                 err("No response data");
693         }
694
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) {
699                         const gchar *line;
700                         GSList *tokens = NULL;
701
702                         line = (const char *) resp_data->data;
703                         tokens = tcore_at_tok_new(line);
704
705                         if (g_slist_length(tokens) > 0) {
706                                 gchar *classx_str;
707                                 gchar *status = NULL;
708                                 gchar *number = NULL;
709                                 gchar *time_str = NULL;
710
711                                 status = g_slist_nth_data(tokens, 0);
712                                 if (!status) {
713                                         dbg("Status is missing");
714                                         tcore_at_tok_free(tokens);
715                                         continue;
716                                 }
717
718                                 if (atoi(status) == 1) {
719                                         forwarding_resp.records[valid_records].enable = TRUE;
720                                 } else {
721                                         forwarding_resp.records[valid_records].enable = FALSE;
722                                 }
723
724                                 classx_str = g_slist_nth_data(tokens, 1);
725                                 if (!classx_str) {
726                                         dbg("Class error. Setting to the requested class: [%d]",
727                                                 req_info->class);
728                                         forwarding_resp.records[valid_records].class =
729                                                 req_info->class;
730                                 } else {
731                                         if (__imc_ss_convert_modem_class_to_class(atoi(classx_str),
732                                                 &(forwarding_resp.records[valid_records].class))
733                                                 == FALSE) {
734                                                 tcore_at_tok_free(tokens);
735                                                 continue;
736                                         }
737                                 }
738
739                                 number = g_slist_nth_data(tokens, 2);
740                                 if (number) {
741                                         number =  tcore_at_tok_extract(number);
742                                         memcpy((forwarding_resp.records[valid_records].number),
743                                                 number, strlen(number));
744                                         g_free(number);
745                                 }
746
747                                 time_str = g_slist_nth_data(tokens, 6);
748                                 if (time_str)
749                                         forwarding_resp.records[valid_records].wait_time =
750                                         atoi(time_str);
751
752                                 forwarding_resp.records[valid_records].condition =
753                                         req_info->condition;
754
755                                 result = TEL_SS_RESULT_SUCCESS;
756                                 valid_records++;
757                         } else {
758                                 err("Invalid response message");
759                         }
760                         tcore_at_tok_free(tokens);
761                 }
762         }
763
764         dbg("Getting Forwarding Status: [%s]",
765                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
766         forwarding_resp.record_num = valid_records;
767
768         /* Invoke callback */
769         if (resp_cb_data->cb)
770                 resp_cb_data->cb(co, (gint)result, &forwarding_resp, resp_cb_data->cb_data);
771
772         imc_destroy_resp_cb_data(resp_cb_data);
773
774         if (forwarding_resp.records) {
775                 tcore_free(forwarding_resp.records);
776         }
777 }
778
779 static void on_response_imc_ss_set_waiting(TcorePending *p,
780         guint data_len, const void *data, void *user_data)
781 {
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;
787         dbg("Enter");
788
789         tcore_check_return_assert(co != NULL);
790         tcore_check_return_assert(resp_cb_data != NULL);
791
792         if (at_resp && at_resp->success)
793                 result = TEL_SS_RESULT_SUCCESS;
794
795         dbg("Set Waiting Status: [%s]",
796                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
797
798         /* Invoke callback */
799         if (resp_cb_data->cb)
800                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
801
802         imc_destroy_resp_cb_data(resp_cb_data);
803 }
804
805 static void on_response_imc_ss_get_waiting_status(TcorePending *p,
806         guint data_len, const void *data, void *user_data)
807 {
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,};
812         TelSsClass *class;
813         gint valid_records = 0;
814         GSList *resp_data = NULL;
815         /* TODO: CMEE error mapping is required */
816         TelSsResult result = TEL_SS_RESULT_FAILURE;
817         dbg("Enter");
818
819         tcore_check_return_assert(co != NULL);
820         tcore_check_return_assert(resp_cb_data != NULL);
821
822         class = (TelSsClass *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
823
824         if (at_resp) {
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);
829                 }
830                 else {
831                         err("RESPONSE - [NOK]");
832                 }
833         } else {
834                 err("No response data");
835         }
836
837         if (waiting_resp.record_num > 0) {
838                 waiting_resp.records = tcore_malloc0((waiting_resp.record_num) *
839                         sizeof(TelSsWaitingInfo));
840
841                 for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
842                         const gchar *line;
843                         GSList *tokens = NULL;
844
845                         line = (const char *) resp_data->data;
846                         tokens = tcore_at_tok_new(line);
847
848                         if (g_slist_length(tokens) > 0) {
849                                 gchar *classx_str;
850                                 gchar *status = NULL;
851
852                                 status = g_slist_nth_data(tokens, 0);
853                                 if (!status) {
854                                         dbg("Status is missing");
855                                         tcore_at_tok_free(tokens);
856                                         continue;
857                                 }
858
859                                 if (atoi(status) == 1) {
860                                         waiting_resp.records[valid_records].enable= TRUE;
861                                 } else {
862                                         waiting_resp.records[valid_records].enable = FALSE;
863                                 }
864
865                                 classx_str = g_slist_nth_data(tokens, 1);
866                                 if (!classx_str) {
867                                         dbg("Class error. Setting to the requested class: [%d]",
868                                                 *class);
869                                         waiting_resp.records[valid_records].class = *class;
870                                 } else {
871                                         if (__imc_ss_convert_modem_class_to_class(atoi(classx_str),
872                                                 &(waiting_resp.records[valid_records].class))
873                                                 == FALSE) {
874                                                 tcore_at_tok_free(tokens);
875                                                 continue;
876                                         }
877                                 }
878
879                                 result = TEL_SS_RESULT_SUCCESS;
880                                 valid_records++;
881                         } else {
882                                 err("Invalid response message");
883                         }
884                         tcore_at_tok_free(tokens);
885                 }
886         }
887
888         dbg("Getting Waiting Status: [%s]",
889                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
890         waiting_resp.record_num = valid_records;
891
892         /* Invoke callback */
893         if (resp_cb_data->cb)
894                 resp_cb_data->cb(co, (gint)result, &waiting_resp, resp_cb_data->cb_data);
895
896         imc_destroy_resp_cb_data(resp_cb_data);
897
898         if (waiting_resp.records) {
899                 tcore_free(waiting_resp.records);
900         }
901 }
902
903 static void on_response_imc_ss_set_cli(TcorePending *p,
904                 guint data_len, const void *data, void *user_data)
905 {
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;
911         dbg("Enter");
912
913         tcore_check_return_assert(co != NULL);
914         tcore_check_return_assert(resp_cb_data != NULL);
915
916         if (at_resp && at_resp->success)
917                 result = TEL_SS_RESULT_SUCCESS;
918
919         dbg("Set Cli Status: [%s]",
920                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
921
922         /* Invoke callback */
923         if (resp_cb_data->cb)
924                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
925
926         imc_destroy_resp_cb_data(resp_cb_data);
927 }
928
929 static void on_response_imc_ss_get_cli_status(TcorePending *p,
930         guint data_len, const void *data, void *user_data)
931 {
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;
940         dbg("Enter");
941
942         tcore_check_return_assert(co != NULL);
943         tcore_check_return_assert(resp_cb_data != NULL);
944
945         cli_type = (TelSsCliType *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
946
947         if (at_resp && at_resp->success) {
948                 const gchar *line;
949                 gchar  *status = NULL;
950                 gint net_status;
951                 gint dev_status;
952
953                 if (!at_resp->lines) {
954                         err("Invalid response message");
955                         goto END;
956                 }
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");
961                         goto END;
962                 }
963
964                 status = g_slist_nth_data(tokens, 0);
965                 if (!status) {
966                         err("dev_status is missing");
967                         goto END;
968                 }
969                 if (!__imc_ss_convert_modem_cli_dev_status_cli_status(*cli_type,
970                         atoi(status), &dev_status))
971                         goto END;
972
973                 status = g_slist_nth_data(tokens, 1);
974                 if (!status) {
975                         err("net_status is missing");
976                         goto END;
977                 }
978                 if (!__imc_ss_convert_modem_cli_net_status_cli_status(*cli_type,
979                         atoi(status), &net_status))
980                         goto END;
981
982                 switch(*cli_type){
983                 case TEL_SS_CLI_CLIR:
984                         cli_resp.status.clir.net_status = net_status;
985                         cli_resp.status.clir.dev_status = dev_status;
986                         break;
987                 case TEL_SS_CLI_CLIP:
988                         cli_resp.status.clip.net_status = net_status;
989                         cli_resp.status.clip.dev_status = dev_status;
990                         break;
991                 case TEL_SS_CLI_COLP:
992                         cli_resp.status.colp.net_status = net_status;
993                         cli_resp.status.colp.dev_status = dev_status;
994                         break;
995                 case TEL_SS_CLI_COLR:
996                         cli_resp.status.colr.net_status = net_status;
997                         cli_resp.status.colr.dev_status = dev_status;
998                         break;
999                 case TEL_SS_CLI_CNAP:
1000                         cli_resp.status.cnap.net_status = net_status;
1001                         cli_resp.status.cnap.dev_status = dev_status;
1002                         break;
1003                 default:
1004                         err("Unsupported CLI type: [%d]", *cli_type);
1005                         result = TEL_SS_RESULT_INVALID_PARAMETER;
1006                         goto END;
1007                 }
1008                 dbg("RESPONSE OK");
1009                 cli_resp.type = *cli_type;
1010                 result = TEL_SS_RESULT_SUCCESS;
1011         } else{
1012                 err("RESPONSE NOK");
1013         }
1014
1015 END:
1016         tcore_at_tok_free(tokens);
1017
1018         /* Invoke callback */
1019         if (resp_cb_data->cb)
1020                 resp_cb_data->cb(co, (gint)result, &cli_resp, resp_cb_data->cb_data);
1021
1022         imc_destroy_resp_cb_data(resp_cb_data);
1023 }
1024
1025 static void on_response_imc_ss_send_ussd_request(TcorePending *p,
1026         guint data_len, const void *data, void *user_data)
1027 {
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;
1035         dbg("Enter");
1036
1037         tcore_check_return_assert(co != NULL);
1038         tcore_check_return_assert(resp_cb_data != NULL);
1039
1040         ussd_s = tcore_ss_ussd_get_session(co);
1041         tcore_check_return(ussd_s != NULL);
1042
1043         tcore_ss_ussd_get_session_type(ussd_s, &ussd_resp.type);
1044
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");
1049         } else {
1050                 ussd_resp.str = (unsigned char *)g_strdup("Operation failed");
1051         }
1052
1053
1054         dbg("Send Ussd Request: [%s]",
1055                         (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1056
1057         tcore_ss_ussd_destroy_session(ussd_s);
1058
1059
1060         /* Invoke callback */
1061         if (resp_cb_data->cb)
1062                 resp_cb_data->cb(co, (gint)result, &ussd_resp, resp_cb_data->cb_data);
1063
1064         imc_destroy_resp_cb_data(resp_cb_data);
1065         g_free(ussd_resp.str);
1066 }
1067
1068 /* SS Operations */
1069 /*
1070  * Operation - set_barring/get_barring_status
1071  *
1072  * Request -
1073  * AT-Command: AT+CLCK=<fac>,<mode>[,<passwd>[,<class>]]
1074  * where,
1075  * <fac>
1076  * Barring facility type. Ref #TelSsBarringType
1077  *
1078  * <mode>
1079  * 0 unlock
1080  * 1 lock
1081  * 2 query status
1082  *
1083  * <passwd>
1084  * Barring Password
1085  *
1086  * <class>
1087  * SS class. Ref #TelSsClass
1088  *
1089  * <status>
1090  * 0 not active
1091  * 1 active
1092  *
1093  * Success: when <mode>=2:
1094  *      OK
1095  *      +CLCK: <status>[,<class1> [<CR><LF>
1096  *      +CLCK: <status>,<class2> [...]]
1097  *
1098  * Failure:
1099  *      +CME ERROR: <error>
1100  */
1101 static TelReturn imc_ss_set_barring(CoreObject *co, const TelSsBarringInfo *barring_info,
1102         TcoreObjectResponseCallback cb, void *cb_data)
1103 {
1104         gchar *at_cmd = NULL;
1105         guint mode;
1106         guint classx;
1107         gchar *facility = NULL;
1108         ImcRespCbData *resp_cb_data = NULL;
1109         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1110
1111         if (barring_info->enable == TRUE)
1112                 mode = 1;
1113         else
1114                 mode = 0;
1115
1116         if (__imc_ss_convert_barring_type_to_facility(barring_info->type,
1117                 &facility) == FALSE) {
1118                 err("Invalid arguments");
1119                 return ret;
1120         }
1121
1122         classx = __imc_ss_convert_class_to_imc_class(barring_info->class);
1123
1124         dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
1125
1126         /* AT-Command */
1127         at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,\"%s\",%d", facility, mode,
1128                         barring_info->pwd, classx);
1129
1130         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1131
1132         /* Send Request to modem */
1133         ret = tcore_at_prepare_and_send_request(co,
1134                 at_cmd, NULL,
1135                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1136                 NULL,
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");
1140
1141         g_free(at_cmd);
1142         return ret;
1143 }
1144
1145 static TelReturn imc_ss_get_barring_status(CoreObject *co,
1146         const TelSsBarringGetInfo *get_barring_info,
1147         TcoreObjectResponseCallback cb, void *cb_data)
1148 {
1149         gchar *at_cmd = NULL;
1150         guint mode;
1151         guint classx;
1152         gchar *facility = NULL;
1153         ImcRespCbData *resp_cb_data = NULL;
1154         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1155
1156         mode = 2; /* query status - mode is fixed to 2 */
1157
1158         if (__imc_ss_convert_barring_type_to_facility(get_barring_info->type,
1159                 &facility) == FALSE) {
1160                 err("Invalid arguments");
1161                 return ret;
1162         }
1163
1164         classx = __imc_ss_convert_class_to_imc_class(get_barring_info->class);
1165
1166         dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
1167
1168         /* AT-Command */
1169         at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,,%d", facility, mode, classx);
1170
1171         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, (void *)get_barring_info,
1172                 sizeof(TelSsBarringGetInfo));
1173
1174         /* Send Request to modem */
1175         ret = tcore_at_prepare_and_send_request(co,
1176                 at_cmd, "+CLCK",
1177                 TCORE_AT_COMMAND_TYPE_MULTILINE,
1178                 NULL,
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");
1182
1183         g_free(at_cmd);
1184         return ret;
1185 }
1186
1187 /*
1188  * Operation - change_barring_password
1189  *
1190  * Request -
1191  * AT-Command: AT+CPWD= <fac>,<oldpwd>,<newpwd>
1192  * where,
1193  * <fac>
1194  * Barring facility type. Ref #TelSsBarringType
1195  * Eg: "AB" All Barring services
1196  *
1197  * <oldpwd>
1198  * Old Barring Password
1199  *
1200  * <newpwd>
1201  * New Barring Password
1202  *
1203  * Success:
1204  *      OK
1205  *
1206  * Failure:
1207  *      +CME ERROR: <error>
1208  */
1209 static TelReturn imc_ss_change_barring_password(CoreObject *co,
1210         const TelSsBarringPwdInfo *barring_pwd_info,
1211         TcoreObjectResponseCallback cb, void *cb_data)
1212 {
1213         gchar *at_cmd = NULL;
1214         ImcRespCbData *resp_cb_data = NULL;
1215         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1216
1217         if (barring_pwd_info->old_pwd == NULL || barring_pwd_info->new_pwd == NULL) {
1218                 err("Invalid data");
1219                 return ret;
1220         }
1221
1222         dbg("Old password: [%s], New password: [%s]", barring_pwd_info->old_pwd,
1223                 barring_pwd_info->new_pwd);
1224
1225         at_cmd = g_strdup_printf("AT+CPWD=\"%s\",\"%s\",\"%s\"", "AB",
1226                         barring_pwd_info->old_pwd, barring_pwd_info->new_pwd);
1227
1228         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1229
1230         /* Send Request to modem */
1231         ret = tcore_at_prepare_and_send_request(co,
1232                 at_cmd, NULL,
1233                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1234                 NULL,
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");
1238
1239         g_free(at_cmd);
1240         return ret;
1241 }
1242
1243 /*
1244  * Operation - set_forwarding/get_forwarding_status
1245  *
1246  * Request -
1247  * AT-Command: AT+CCFC=<reason>,<mode>[,<number>[,<type>
1248  * [,<class>[,<subaddr>[,<satype>[,<time>]]]]]]
1249  * where,
1250  * <reason>
1251  * Forwarding Condition. Ref #TelSsForwardCondition
1252  *
1253  * <mode>
1254  * Forwarding Mode. Ref #TelSsForwardMode
1255  * 0 disable
1256  * 1 enable
1257  * 2 query status
1258  * 3 registration
1259  * 4 erasure
1260  *
1261  *
1262  * <number>
1263  * Call Forwarding Number
1264  *
1265  * <type>
1266  * Default 145 when available string includes "+"
1267  * Otherwise 129
1268  *
1269  * <subaddr>
1270  * Parameter String type subaddress of format specified by <satype>
1271  *
1272  * <satype>
1273  * Parameter type of subaddress octet in integer format
1274  * Default 128
1275  *
1276  * <time>
1277  * Parameter time in seconds to wait before call is forwarded
1278  * Default 20, but only when <reason>=2 (no reply) is enabled
1279  *
1280  * <class>
1281  * SS class. Ref #TelSsClass
1282  *
1283  * <status>
1284  * 0 not active
1285  * 1 active
1286  *
1287  * Success: when <mode>=2:
1288  *      OK
1289  *      +CCFC: <status>,<class1>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][<CR><LF>
1290  *      +CCFC: <status>,<class2>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][...]]
1291  *
1292  * Failure:
1293  *      +CME ERROR: <error>
1294  */
1295 static TelReturn imc_ss_set_forwarding(CoreObject *co, const TelSsForwardInfo *forwarding_info,
1296         TcoreObjectResponseCallback cb, void *cb_data)
1297 {
1298         gchar *at_cmd = NULL;
1299         gchar *tmp_cmd = NULL;
1300         guint classx;
1301         guint reason;
1302         guint mode;
1303         guint num_type;
1304         ImcRespCbData *resp_cb_data = NULL;
1305         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1306
1307         classx = __imc_ss_convert_class_to_imc_class(forwarding_info->class);
1308
1309         if (__imc_ss_convert_forwarding_mode_to_modem_mode(forwarding_info->mode, &mode)
1310                 == FALSE) {
1311                 err("Invalid arguments");
1312                 return ret;
1313         }
1314
1315         if (__imc_ss_convert_forwarding_condition_to_modem_reason(forwarding_info->condition,
1316                 &reason) == FALSE) {
1317                 err("Invalid arguments");
1318                 return ret;
1319         }
1320
1321         if (forwarding_info->number[0] == '+')
1322                 num_type = 145;
1323         else
1324                 num_type = 129;
1325
1326         dbg("classx: [%d], reason:[%d], mode: [%d]", classx, reason, mode);
1327
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);
1331         else
1332                 tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
1333
1334         if (reason == 2) /* TEL_SS_CF_COND_CFNRY */
1335                 at_cmd = g_strdup_printf("%s,,,%d", tmp_cmd, forwarding_info->wait_time);
1336         else
1337                 at_cmd = g_strdup_printf("%s", tmp_cmd);
1338
1339         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1340
1341         /* Send Request to modem */
1342         ret = tcore_at_prepare_and_send_request(co,
1343                 at_cmd, NULL,
1344                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1345                 NULL,
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");
1349
1350         g_free(tmp_cmd);
1351         g_free(at_cmd);
1352
1353         return ret;
1354 }
1355
1356 static TelReturn imc_ss_get_forwarding_status(CoreObject *co, const TelSsForwardGetInfo *get_forwarding_info,
1357         TcoreObjectResponseCallback cb, void *cb_data)
1358 {
1359         gchar *at_cmd = NULL;
1360         guint classx;
1361         guint reason;
1362         guint mode = 2; /* query status */
1363         ImcRespCbData *resp_cb_data = NULL;
1364         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1365
1366         classx = __imc_ss_convert_class_to_imc_class(get_forwarding_info->class);
1367
1368         if (__imc_ss_convert_forwarding_condition_to_modem_reason(get_forwarding_info->condition,
1369                 &reason) == FALSE) {
1370                 err("Invalid arguments");
1371                 return ret;
1372         }
1373
1374         dbg("classx: [%d], reason: [%d], mode: [%d]", classx, reason, mode);
1375
1376         at_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
1377
1378         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, (void *)get_forwarding_info,
1379                 sizeof(TelSsForwardGetInfo));
1380
1381         /* Send Request to modem */
1382         ret = tcore_at_prepare_and_send_request(co,
1383                 at_cmd, "+CCFC",
1384                 TCORE_AT_COMMAND_TYPE_MULTILINE,
1385                 NULL,
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");
1389
1390         g_free(at_cmd);
1391         return ret;
1392 }
1393
1394 /*
1395  * Operation - set_waiting/get_waiting_status
1396  *
1397  * Request -
1398  * AT-Command: AT+CCWA=[<n>[,<mode>[,<class>]]]
1399  * where,
1400  * <n>
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
1404  *
1405  * <mode>
1406  * 0 Disable call waiting
1407  * 1 Enable call waiting
1408  * 2 Query status
1409  *
1410  * <class>
1411  * SS class. Ref #TelSsClass
1412  *
1413  * <status>
1414  * 0 not active
1415  * 1 active
1416  *
1417  * Success: when <mode>=2:
1418  *      OK
1419  *      +CCWA: <status>,<class1>
1420  *      +CCWA: <status>,<class2>
1421  *
1422  * Failure:
1423  *      +CME ERROR: <error>
1424  */
1425 static TelReturn imc_ss_set_waiting(CoreObject *co, const TelSsWaitingInfo *waiting_info,
1426         TcoreObjectResponseCallback cb, void *cb_data)
1427 {
1428         gchar *at_cmd = NULL;
1429         guint classx;
1430         guint mode;
1431         ImcRespCbData *resp_cb_data = NULL;
1432         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1433
1434         if (waiting_info->enable == TRUE)
1435                 mode = 1;
1436         else
1437                 mode = 0;
1438
1439         classx = __imc_ss_convert_class_to_imc_class(waiting_info->class);
1440
1441         dbg("mode: [%d], class: [%d]", mode, classx);
1442
1443         at_cmd = g_strdup_printf("AT+CCWA=1,%d,%d", mode, classx);
1444
1445         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1446
1447         /* Send Request to modem */
1448         ret = tcore_at_prepare_and_send_request(co,
1449                 at_cmd, NULL,
1450                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1451                 NULL,
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");
1455
1456         g_free(at_cmd);
1457         return ret;
1458 }
1459
1460 static TelReturn imc_ss_get_waiting_status(CoreObject *co, TelSsClass ss_class,
1461         TcoreObjectResponseCallback cb, void *cb_data)
1462 {
1463         gchar *at_cmd = NULL;
1464         guint classx;
1465         ImcRespCbData *resp_cb_data = NULL;
1466         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1467
1468         classx = __imc_ss_convert_class_to_imc_class(ss_class);
1469
1470         dbg("class: [%d]", classx);
1471
1472         at_cmd = g_strdup_printf("AT+CCWA=1,2,%d", classx);
1473
1474         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &ss_class, sizeof(TelSsClass));
1475
1476         /* Send Request to modem */
1477         ret = tcore_at_prepare_and_send_request(co,
1478                 at_cmd, "+CCWA",
1479                 TCORE_AT_COMMAND_TYPE_MULTILINE,
1480                 NULL,
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");
1484
1485         g_free(at_cmd);
1486         return ret;
1487 }
1488
1489 /*
1490  * Operation - set_cli/get_cli_status
1491  *
1492  * Request -
1493  * AT-Command:
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>]
1499  *
1500  * where,
1501  * <n> All CLI except CLIR
1502  * 0 disable(default)
1503  * 1 enable
1504  *
1505  * <n> for CLIR
1506  * 0 default
1507  * 1 CLIR invocation
1508  * 2 CLIR suppression
1509  *
1510  * Success:
1511  *      OK
1512  *      +CLIR: <n>,<m>
1513  *
1514  * where,
1515  * <m> All CLI except CLIR
1516  * 0 Not provisioned
1517  * 1 Provisioned
1518  * 2 Unknown
1519  *
1520  *<m> For CLIR
1521  * 0 Not provisioned
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
1526  *
1527  * Failure:
1528  *      +CME ERROR: <error>
1529  */
1530 static TelReturn imc_ss_set_cli(CoreObject *co, const TelSsCliInfo *cli_info,
1531         TcoreObjectResponseCallback cb, void *cb_data)
1532 {
1533         gchar *at_cmd = NULL;
1534         gchar *cmd_prefix = NULL;
1535         gint status = 0;
1536         ImcRespCbData *resp_cb_data = NULL;
1537         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1538
1539         if (__imc_ss_convert_cli_info_modem_info(&cli_info, &status, &cmd_prefix) == FALSE)
1540                 return ret;
1541
1542         at_cmd = g_strdup_printf("AT%s=%d", cmd_prefix, status);
1543
1544         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1545
1546         /* Send Request to modem */
1547         ret = tcore_at_prepare_and_send_request(co,
1548                 at_cmd, NULL,
1549                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1550                 NULL,
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");
1554
1555         g_free(at_cmd);
1556         return ret;
1557 }
1558
1559 static TelReturn imc_ss_get_cli_status(CoreObject *co, TelSsCliType cli_type,
1560         TcoreObjectResponseCallback cb, void *cb_data)
1561 {
1562         gchar *at_cmd = NULL;
1563         gchar *cmd_prefix = NULL;
1564         ImcRespCbData *resp_cb_data = NULL;
1565         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1566
1567         switch (cli_type) {
1568         case TEL_SS_CLI_CLIR:
1569                 cmd_prefix = "+CLIR";
1570         break;
1571         case TEL_SS_CLI_CLIP:
1572                 cmd_prefix = "+CLIP";
1573         break;
1574         case TEL_SS_CLI_COLP:
1575                 cmd_prefix = "+COLP";
1576         break;
1577         case TEL_SS_CLI_COLR:
1578                 cmd_prefix = "+COLR";
1579         break;
1580         case TEL_SS_CLI_CNAP:
1581                 cmd_prefix = "+CNAP";
1582         break;
1583         case TEL_SS_CLI_CDIP:
1584         default:
1585                 dbg("Unsupported CLI type: [%d]", cli_type);
1586                 return ret;
1587         }
1588
1589         at_cmd = g_strdup_printf("AT%s?", cmd_prefix);
1590
1591         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &cli_type, sizeof(TelSsCliType));
1592
1593         /* Send Request to modem */
1594         ret = tcore_at_prepare_and_send_request(co,
1595                 at_cmd, cmd_prefix,
1596                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1597                 NULL,
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");
1601
1602         g_free(at_cmd);
1603         return ret;
1604 }
1605
1606 /*
1607  * Operation - send_ussd_request
1608  *
1609  * Request -
1610  * AT-Command: AT+CUSD = [<n> [, <str> [, <dcs>]]]
1611  * where,
1612  * <n>
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)
1616  *
1617  * <str>
1618  * USSD string
1619  *
1620  * <dcs>
1621  * Cell Broadcast Data Coding Scheme. Default value is 0.
1622  *
1623  * Success:
1624  *      OK
1625  *
1626  * Failure:
1627  *      +CME ERROR: <error>
1628  */
1629 static TelReturn imc_ss_send_ussd_request(CoreObject *co, const TelSsUssdInfo *ussd_request,
1630         TcoreObjectResponseCallback cb, void *cb_data)
1631 {
1632         gchar *at_cmd = NULL;
1633         UssdSession *ussd_s = NULL;
1634         ImcRespCbData *resp_cb_data = NULL;
1635         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1636
1637         ussd_s = tcore_ss_ussd_get_session(co);
1638         if (!ussd_s) {
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));
1642         } else {
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;
1646                 }
1647                 tcore_ss_ussd_set_session_type(ussd_s, ussd_request->type);
1648         }
1649
1650         at_cmd = g_strdup_printf("AT+CUSD=1,\"%s\",%d", ussd_request->str, 0x0f);
1651
1652         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1653
1654         /* Send Request to modem */
1655         ret = tcore_at_prepare_and_send_request(co,
1656                 at_cmd, NULL,
1657                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1658                 NULL,
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");
1662
1663         g_free(at_cmd);
1664         return ret;
1665 }
1666
1667 /* SS Operations */
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
1679 };
1680
1681 gboolean imc_ss_init(TcorePlugin *p, CoreObject *co)
1682 {
1683         dbg("Entry");
1684
1685         /* Set operations */
1686         tcore_ss_set_ops(co, &imc_ss_ops);
1687
1688         /* Add Callbacks */
1689         tcore_object_add_callback(co, "+CUSD", on_notification_imc_ss_ussd, NULL);
1690
1691         dbg("Exit");
1692         return TRUE;
1693 }
1694
1695 void imc_ss_exit(TcorePlugin *p, CoreObject *co)
1696 {
1697         dbg("Exit");
1698 }