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