cb81804498980c3b3df1f3899bdbea762fb24a9f
[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                 NULL,
1133                 on_response_imc_ss_set_barring, resp_cb_data,
1134                 on_send_imc_request, NULL);
1135         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Barring");
1136
1137         g_free(at_cmd);
1138
1139         return ret;
1140 }
1141
1142 static TelReturn imc_ss_get_barring_status(CoreObject *co, const TelSsBarringGetInfo *get_barring_info,
1143                 TcoreObjectResponseCallback cb, void *cb_data)
1144 {
1145         gchar *at_cmd = NULL;
1146         guint mode;
1147         guint classx;
1148         gchar *facility = NULL;
1149         ImcRespCbData *resp_cb_data = NULL;
1150         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1151
1152         mode = 2; /* query status - mode is fixed to 2 */
1153
1154         if (__imc_ss_convert_barring_type_to_facility(get_barring_info->type, &facility) == FALSE) {
1155                 err("Invalid arguments");
1156                 return ret;
1157         }
1158
1159         classx = __imc_ss_convert_class_to_imc_class(get_barring_info->class);
1160
1161         dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
1162
1163         /* AT-Command */
1164         at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,,%d", facility, mode, classx);
1165
1166         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, (void *)get_barring_info, sizeof(TelSsBarringGetInfo));
1167
1168         /* Send Request to modem */
1169         ret = tcore_at_prepare_and_send_request(co,
1170                 at_cmd, "+CLCK",
1171                 TCORE_AT_COMMAND_TYPE_MULTILINE,
1172                 NULL,
1173                 on_response_imc_ss_get_barring_status, resp_cb_data,
1174                 on_send_imc_request, NULL);
1175         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Barring Status");
1176
1177         g_free(at_cmd);
1178         return ret;
1179 }
1180
1181 /*
1182  * Operation - change_barring_password
1183  *
1184  * Request -
1185  * AT-Command: AT+CPWD= <fac>,<oldpwd>,<newpwd>
1186  * where,
1187  * <fac>
1188  * Barring facility type. Ref #TelSsBarringType
1189  * Eg: "AB" All Barring services
1190  *
1191  * <oldpwd>
1192  * Old Barring Password
1193  *
1194  * <newpwd>
1195  * New Barring Password
1196  *
1197  * Success:
1198  *      OK
1199  *
1200  * Failure:
1201  *      +CME ERROR: <error>
1202  */
1203 static TelReturn imc_ss_change_barring_password(CoreObject *co, const TelSsBarringPwdInfo *barring_pwd_info,
1204                 TcoreObjectResponseCallback cb, void *cb_data)
1205 {
1206         gchar *at_cmd = NULL;
1207         ImcRespCbData *resp_cb_data = NULL;
1208         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1209
1210         if (barring_pwd_info->old_pwd== NULL || barring_pwd_info->new_pwd == NULL) {
1211                 err("Invalid data");
1212                 return ret;
1213         }
1214
1215         dbg("Old password: [%s], New password: [%s]", barring_pwd_info->old_pwd, barring_pwd_info->new_pwd);
1216
1217         at_cmd = g_strdup_printf("AT+CPWD=\"%s\",\"%s\",\"%s\"", "AB", barring_pwd_info->old_pwd, barring_pwd_info->new_pwd);
1218
1219         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1220
1221         /* Send Request to modem */
1222         ret = tcore_at_prepare_and_send_request(co,
1223                 at_cmd, NULL,
1224                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1225                 NULL,
1226                 on_response_imc_ss_change_barring_password, resp_cb_data,
1227                 on_send_imc_request, NULL);
1228         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Change Barring Password");
1229
1230         g_free(at_cmd);
1231         return ret;
1232 }
1233
1234 /*
1235  * Operation - set_forwarding/get_forwarding_status
1236  *
1237  * Request -
1238  * AT-Command: AT+CCFC=<reason>,<mode>[,<number>[,<type>[,<class>[,<subaddr>[,<satype>[,<time>]]]]]]
1239  * where,
1240  * <reason>
1241  * Forwarding Condition. Ref #TelSsForwardCondition
1242  *
1243  * <mode>
1244  * Forwarding Mode. Ref #TelSsForwardMode
1245  * 0 disable
1246  * 1 enable
1247  * 2 query status
1248  * 3 registration
1249  * 4 erasure
1250  *
1251  *
1252  * <number>
1253  * Call Forwarding Number
1254  *
1255  * <type>
1256  * Default 145 when available string includes "+"
1257  * Otherwise 129
1258  *
1259  * <subaddr>
1260  * Parameter String type subaddress of format specified by <satype>
1261  *
1262  * <satype>
1263  * Parameter type of subaddress octet in integer format
1264  * Default 128
1265  *
1266  * <time>
1267  * Parameter time in seconds to wait before call is forwarded
1268  * Default 20, but only when <reason>=2 (no reply) is enabled
1269  *
1270  * <class>
1271  * SS class. Ref #TelSsClass
1272  *
1273  * <status>
1274  * 0 not active
1275  * 1 active
1276  *
1277  * Success: when <mode>=2:
1278  *      OK
1279  *      +CCFC: <status>,<class1>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][<CR><LF>
1280  *      +CCFC: <status>,<class2>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][...]]
1281  *
1282  * Failure:
1283  *      +CME ERROR: <error>
1284  */
1285 static TelReturn imc_ss_set_forwarding(CoreObject *co, const TelSsForwardInfo *forwarding_info,
1286                 TcoreObjectResponseCallback cb, void *cb_data)
1287 {
1288         gchar *at_cmd = NULL;
1289         gchar *tmp_cmd = NULL;
1290         guint classx;
1291         guint reason;
1292         guint mode;
1293         guint num_type;
1294         ImcRespCbData *resp_cb_data = NULL;
1295         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1296
1297         classx = __imc_ss_convert_class_to_imc_class(forwarding_info->class);
1298
1299         if (__imc_ss_convert_forwarding_mode_to_modem_mode(forwarding_info->mode, &mode) == FALSE) {
1300                 err("Invalid arguments");
1301                 return ret;
1302         }
1303
1304         if (__imc_ss_convert_forwarding_condition_to_modem_reason(forwarding_info->condition, &reason) == FALSE) {
1305                 err("Invalid arguments");
1306                 return ret;
1307         }
1308
1309         if (forwarding_info->number[0] == '+')
1310                 num_type = 145;
1311         else
1312                 num_type = 129;
1313
1314         dbg("classx: [%d], reason:[%d], mode: [%d]", classx, reason, mode);
1315
1316         if (mode == 3)  /* TEL_SS_CF_MODE_REGISTER */
1317                 tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,\"%s\",%d,%d", reason, mode, forwarding_info->number, num_type, classx);
1318         else
1319                 tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
1320
1321         if (reason == 2)        /* TEL_SS_CF_COND_CFNRY */
1322                 at_cmd = g_strdup_printf("%s,,,%d", tmp_cmd, forwarding_info->wait_time);
1323         else
1324                 at_cmd = g_strdup_printf("%s", tmp_cmd);
1325
1326         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1327
1328         /* Send Request to modem */
1329         ret = tcore_at_prepare_and_send_request(co,
1330                 at_cmd, NULL,
1331                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1332                 NULL,
1333                 on_response_imc_ss_set_forwarding, resp_cb_data,
1334                 on_send_imc_request, NULL);
1335         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Forwarding");
1336
1337         g_free(tmp_cmd);
1338         g_free(at_cmd);
1339
1340         return ret;
1341 }
1342
1343 static TelReturn imc_ss_get_forwarding_status(CoreObject *co, const TelSsForwardGetInfo *get_forwarding_info,
1344                 TcoreObjectResponseCallback cb, void *cb_data)
1345 {
1346         gchar *at_cmd = NULL;
1347         guint classx;
1348         guint reason;
1349         guint mode = 2; /* query status */
1350         ImcRespCbData *resp_cb_data = NULL;
1351         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1352
1353         classx = __imc_ss_convert_class_to_imc_class(get_forwarding_info->class);
1354
1355         if (__imc_ss_convert_forwarding_condition_to_modem_reason(get_forwarding_info->condition, &reason) == FALSE) {
1356                 err("Invalid arguments");
1357                 return ret;
1358         }
1359
1360         dbg("classx: [%d], reason: [%d], mode: [%d]", classx, reason, mode);
1361
1362         at_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
1363
1364         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, (void *)get_forwarding_info, sizeof(TelSsForwardGetInfo));
1365
1366         /* Send Request to modem */
1367         ret = tcore_at_prepare_and_send_request(co,
1368                 at_cmd, "+CCFC",
1369                 TCORE_AT_COMMAND_TYPE_MULTILINE,
1370                 NULL,
1371                 on_response_imc_ss_get_forwarding_status, resp_cb_data,
1372                 on_send_imc_request, NULL);
1373         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Forwarding Status");
1374
1375         g_free(at_cmd);
1376         return ret;
1377 }
1378
1379 /*
1380  * Operation - set_waiting/get_waiting_status
1381  *
1382  * Request -
1383  * AT-Command: AT+CCWA=[<n>[,<mode>[,<class>]]]
1384  * where,
1385  * <n>
1386  * Parameter Sets/shows the result code presentation status to the TE.
1387  * 0 presentation status is disabled to TE(default)
1388  * 1 presentation status is enabled to TE
1389  *
1390  * <mode>
1391  * 0 Disable call waiting
1392  * 1 Enable call waiting
1393  * 2 Query status
1394  *
1395  * <class>
1396  * SS class. Ref #TelSsClass
1397  *
1398  * <status>
1399  * 0 not active
1400  * 1 active
1401  *
1402  * Success: when <mode>=2:
1403  *      OK
1404  *      +CCWA: <status>,<class1>
1405  *      +CCWA: <status>,<class2>
1406  *
1407  * Failure:
1408  *      +CME ERROR: <error>
1409  */
1410 static TelReturn imc_ss_set_waiting(CoreObject *co, const TelSsWaitingInfo *waiting_info,
1411                 TcoreObjectResponseCallback cb, void *cb_data)
1412 {
1413         gchar *at_cmd = NULL;
1414         guint classx;
1415         guint mode;
1416         ImcRespCbData *resp_cb_data = NULL;
1417         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1418
1419         if (waiting_info->enable == TRUE)
1420                 mode = 1;
1421         else
1422                 mode = 0;
1423
1424         classx = __imc_ss_convert_class_to_imc_class(waiting_info->class);
1425
1426         dbg("mode: [%d], class: [%d]", mode, classx);
1427
1428         at_cmd = g_strdup_printf("AT+CCWA=1,%d,%d", mode, classx);
1429
1430         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1431
1432         /* Send Request to modem */
1433         ret = tcore_at_prepare_and_send_request(co,
1434                 at_cmd, NULL,
1435                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1436                 NULL,
1437                 on_response_imc_ss_set_waiting, resp_cb_data,
1438                 on_send_imc_request, NULL);
1439         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Waiting");
1440
1441         g_free(at_cmd);
1442         return ret;
1443 }
1444
1445 static TelReturn imc_ss_get_waiting_status(CoreObject *co, TelSsClass ss_class,
1446                 TcoreObjectResponseCallback cb, void *cb_data)
1447 {
1448         gchar *at_cmd = NULL;
1449         guint classx;
1450         ImcRespCbData *resp_cb_data = NULL;
1451         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1452
1453         classx = __imc_ss_convert_class_to_imc_class(ss_class);
1454
1455         dbg("class: [%d]", classx);
1456
1457         at_cmd = g_strdup_printf("AT+CCWA=1,2,%d", classx);
1458
1459         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &ss_class, sizeof(TelSsClass));
1460
1461         /* Send Request to modem */
1462         ret = tcore_at_prepare_and_send_request(co,
1463                 at_cmd, "+CCWA",
1464                 TCORE_AT_COMMAND_TYPE_MULTILINE,
1465                 NULL,
1466                 on_response_imc_ss_get_waiting_status, resp_cb_data,
1467                 on_send_imc_request, NULL);
1468         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Waiting Status");
1469
1470         g_free(at_cmd);
1471         return ret;
1472 }
1473
1474 /*
1475  * Operation - set_cli/get_cli_status
1476  *
1477  * Request -
1478  * AT-Command:
1479  * For CLIR: AT+CLIR= [<n>]
1480  * For CLIP: AT+CLIP= [<n>]
1481  * For COLP: AT+COLP= [<n>]
1482  * For COLR: AT+COLR= [<n>]
1483  * For CNAP: AT+CNAP= [<n>]
1484  *
1485  * where,
1486  * <n> All CLI except CLIR
1487  * 0 disable(default)
1488  * 1 enable
1489  *
1490  * <n> for CLIR
1491  * 0 default
1492  * 1 CLIR invocation
1493  * 2 CLIR suppression
1494  *
1495  * Success:
1496  *      OK
1497  *      +CLIR: <n>,<m>
1498  *
1499  * where,
1500  * <m> All CLI except CLIR
1501  * 0 Not provisioned
1502  * 1 Provisioned
1503  * 2 Unknown
1504  *
1505  *<m> For CLIR
1506  * 0 Not provisioned
1507  * 1 Provisioned in permanent mode
1508  * 2 Unknown (e.g. no network, etc.)
1509  * 3 Temporary mode presentation restricted
1510  * 4 Temporary mode presentation allowed
1511  *
1512  * Failure:
1513  *      +CME ERROR: <error>
1514  */
1515 static TelReturn imc_ss_set_cli(CoreObject *co, const TelSsCliInfo *cli_info,
1516                 TcoreObjectResponseCallback cb, void *cb_data)
1517 {
1518         gchar *at_cmd = NULL;
1519         gchar *cmd_prefix = NULL;
1520         gint status = 0;
1521         ImcRespCbData *resp_cb_data = NULL;
1522         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1523
1524         if (__imc_ss_convert_cli_info_modem_info(&cli_info, &status, &cmd_prefix) == FALSE)
1525                 return ret;
1526
1527         at_cmd = g_strdup_printf("AT%s=%d", cmd_prefix, status);
1528
1529         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1530
1531         /* Send Request to modem */
1532         ret = tcore_at_prepare_and_send_request(co,
1533                 at_cmd, NULL,
1534                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1535                 NULL,
1536                 on_response_imc_ss_set_cli, resp_cb_data,
1537                 on_send_imc_request, NULL);
1538         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Cli");
1539
1540         g_free(at_cmd);
1541         return ret;
1542 }
1543
1544 static TelReturn imc_ss_get_cli_status(CoreObject *co, TelSsCliType cli_type,
1545                 TcoreObjectResponseCallback cb, void *cb_data)
1546 {
1547         gchar *at_cmd = NULL;
1548         gchar *cmd_prefix = NULL;
1549         ImcRespCbData *resp_cb_data = NULL;
1550         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1551
1552         switch (cli_type) {
1553         case TEL_SS_CLI_CLIR:
1554                 cmd_prefix = "+CLIR";
1555                 break;
1556
1557         case TEL_SS_CLI_CLIP:
1558                 cmd_prefix = "+CLIP";
1559                 break;
1560
1561         case TEL_SS_CLI_COLP:
1562                 cmd_prefix = "+COLP";
1563                 break;
1564
1565         case TEL_SS_CLI_COLR:
1566                 cmd_prefix = "+COLR";
1567                 break;
1568
1569         case TEL_SS_CLI_CNAP:
1570                 cmd_prefix = "+CNAP";
1571                 break;
1572
1573         case TEL_SS_CLI_CDIP:
1574         default:
1575                 dbg("Unsupported CLI type: [%d]", cli_type);
1576                 return ret;
1577         }
1578
1579         at_cmd = g_strdup_printf("AT%s?", cmd_prefix);
1580
1581         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &cli_type, sizeof(TelSsCliType));
1582
1583         /* Send Request to modem */
1584         ret = tcore_at_prepare_and_send_request(co,
1585                 at_cmd, cmd_prefix,
1586                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1587                 NULL,
1588                 on_response_imc_ss_get_cli_status, resp_cb_data,
1589                 on_send_imc_request, NULL);
1590         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Cli Status");
1591
1592         g_free(at_cmd);
1593         return ret;
1594 }
1595
1596 /*
1597  * Operation - send_ussd_request
1598  *
1599  * Request -
1600  * AT-Command: AT+CUSD = [<n> [, <str> [, <dcs>]]]
1601  * where,
1602  * <n>
1603  * 0 Disable the result code presentation to the TE(default)
1604  * 1 Enable the result code presentation to the TE
1605  * 2 Cancel session (not applicable to read command response)
1606  *
1607  * <str>
1608  * USSD string
1609  *
1610  * <dcs>
1611  * Cell Broadcast Data Coding Scheme. Default value is 0.
1612  *
1613  * Success:
1614  *      OK
1615  *
1616  * Failure:
1617  *      +CME ERROR: <error>
1618  */
1619 static TelReturn imc_ss_send_ussd_request(CoreObject *co, const TelSsUssdInfo *ussd_request,
1620                 TcoreObjectResponseCallback cb, void *cb_data)
1621 {
1622         gchar *at_cmd = NULL;
1623         UssdSession *ussd_s = NULL;
1624         ImcRespCbData *resp_cb_data = NULL;
1625         TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
1626
1627         ussd_s = tcore_ss_ussd_get_session(co);
1628         if (!ussd_s) {
1629                 dbg("USSD session does not  exist");
1630                 tcore_ss_ussd_create_session(co, ussd_request->type, (void *)ussd_request->str, strlen((char *)ussd_request->str));
1631         } else {
1632                 if (ussd_request->type == TEL_SS_USSD_TYPE_USER_INIT) {
1633                         err("Ussd session is already exist");
1634                         return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1635                 }
1636                 tcore_ss_ussd_set_session_type(ussd_s, ussd_request->type);
1637         }
1638
1639         at_cmd = g_strdup_printf("AT+CUSD=1,\"%s\",%d", ussd_request->str, 0x0f);
1640
1641         resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1642
1643         /* Send Request to modem */
1644         ret = tcore_at_prepare_and_send_request(co,
1645                 at_cmd, NULL,
1646                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
1647                 NULL,
1648                 on_response_imc_ss_send_ussd_request, resp_cb_data,
1649                 on_send_imc_request, NULL);
1650         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Send Ussd Request");
1651
1652         g_free(at_cmd);
1653         return ret;
1654 }
1655
1656 /* SS Operations */
1657 static TcoreSsOps imc_ss_ops = {
1658         .set_barring = imc_ss_set_barring,
1659         .get_barring_status = imc_ss_get_barring_status,
1660         .change_barring_password = imc_ss_change_barring_password,
1661         .set_forwarding = imc_ss_set_forwarding,
1662         .get_forwarding_status = imc_ss_get_forwarding_status,
1663         .set_waiting = imc_ss_set_waiting,
1664         .get_waiting_status = imc_ss_get_waiting_status,
1665         .set_cli = imc_ss_set_cli,
1666         .get_cli_status = imc_ss_get_cli_status,
1667         .send_ussd_request = imc_ss_send_ussd_request
1668 };
1669
1670 gboolean imc_ss_init(TcorePlugin *p, CoreObject *co)
1671 {
1672         dbg("Entry");
1673
1674         /* Set operations */
1675         tcore_ss_set_ops(co, &imc_ss_ops);
1676
1677         /* Add Callbacks */
1678         tcore_object_add_callback(co, "+CUSD", on_notification_imc_ss_ussd, NULL);
1679
1680         dbg("Exit");
1681         return TRUE;
1682 }
1683
1684 void imc_ss_exit(TcorePlugin *p, CoreObject *co)
1685 {
1686         dbg("Exit");
1687 }