Fix for 64-bit build compatibility
[platform/core/telephony/tel-plugin-imc.git] / src / imc_ss.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: sharanayya mathapati <sharan.m@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <glib.h>
26
27 #include <tcore.h>
28 #include <hal.h>
29 #include <core_object.h>
30 #include <plugin.h>
31 #include <queue.h>
32 #include <co_call.h>
33 #include <co_ss.h>
34 #include <user_request.h>
35 #include <util.h>
36 #include <server.h>
37 #include <at.h>
38
39 #include "imc_common.h"
40 #include "imc_ss.h"
41
42 #define NUM_TYPE_INTERNATIONAL      0x01
43 #define NUM_PLAN_ISDN                   0x01
44
45 // To avoid sending multiple response to application
46 static gboolean UssdResp = FALSE;
47
48 enum  telephony_ss_opcode {
49         SS_OPCO_REG = 0x01,       /* 0x01 : Registration */
50         SS_OPCO_DEREG,            /* 0x02 : De-registration(erase) */
51         SS_OPCO_ACTIVATE,         /* 0x03 : Activation */
52         SS_OPCO_DEACTIVATE,       /* 0x04 : De-activation */
53         SS_OPCO_MAX
54 };
55
56 struct ss_confirm_info {
57         enum telephony_ss_class class;
58         int flavor_type;
59         enum tcore_response_command resp;
60         void *data;
61         int data_len;
62 };
63
64 static gboolean _ss_request_message(TcorePending *pending, CoreObject *o, UserRequest *ur, void *on_resp, void *user_data);
65
66 static TReturn _ss_barring_get(CoreObject *o, UserRequest *ur, enum telephony_ss_class class, enum telephony_ss_barring_mode type, enum tcore_response_command resp);
67
68 static TReturn _ss_forwarding_get(CoreObject *o, UserRequest *ur, enum telephony_ss_class class, enum telephony_ss_forwarding_mode type, enum tcore_response_command resp);
69
70 static TReturn _ss_waiting_get(CoreObject *o, UserRequest *ur, enum telephony_ss_class class, enum tcore_response_command resp);
71
72 static TReturn imc_ss_barring_activate(CoreObject *o, UserRequest *ur);
73 static TReturn imc_ss_barring_deactivate(CoreObject *o, UserRequest *ur);
74 static TReturn imc_ss_barring_change_password(CoreObject *o, UserRequest *ur);
75 static TReturn imc_ss_barring_get_status(CoreObject *o, UserRequest *ur);
76
77 static TReturn imc_ss_forwarding_activate(CoreObject *o, UserRequest *ur);
78 static TReturn imc_ss_forwarding_deactivate(CoreObject *o, UserRequest *ur);
79 static TReturn imc_ss_forwarding_register(CoreObject *o, UserRequest *ur);
80 static TReturn imc_ss_forwarding_deregister(CoreObject *o, UserRequest *ur);
81 static TReturn imc_ss_forwarding_get_status(CoreObject *o, UserRequest *ur);
82
83 static TReturn imc_ss_waiting_activate(CoreObject *o, UserRequest *ur);
84 static TReturn imc_ss_waiting_deactivate(CoreObject *o, UserRequest *ur);
85 static TReturn imc_ss_waiting_get_status(CoreObject *o, UserRequest *ur);
86
87 static TReturn imc_ss_cli_activate(CoreObject *o, UserRequest *ur);
88 static TReturn imc_ss_cli_deactivate(CoreObject *o, UserRequest *ur);
89 static TReturn imc_ss_cli_get_status(CoreObject *o, UserRequest *ur);
90
91 static TReturn imc_ss_send_ussd(CoreObject *o, UserRequest *ur);
92
93 static TReturn imc_ss_set_aoc(CoreObject *o, UserRequest *ur);
94 static TReturn imc_ss_get_aoc(CoreObject *o, UserRequest *ur);
95
96 static TReturn imc_ss_manage_call_0_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data);
97 static TReturn imc_ss_manage_call_1_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data);
98 static TReturn imc_ss_manage_call_1x_send(CoreObject *o, UserRequest *ur, const int id, ConfirmCallback cb, void *user_data);
99 static TReturn imc_ss_manage_call_2_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data);
100 static TReturn imc_ss_manage_call_2x_send(CoreObject *o, UserRequest *ur, const int id, ConfirmCallback cb, void *user_data);
101 static TReturn imc_ss_manage_call_3_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data);
102 static TReturn imc_ss_manage_call_4_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data);
103 static TReturn imc_ss_manage_call_4dn_send(CoreObject *o, UserRequest *ur, const char *number, ConfirmCallback cb, void *user_data);
104
105 static void on_confirmation_ss_message_send(TcorePending *p, gboolean result, void *user_data);
106
107 static void _ss_ussd_response(UserRequest *ur, const char *ussd_str, enum telephony_ss_ussd_type type, enum telephony_ss_ussd_status status);
108 static void _ss_ussd_notification(TcorePlugin *p, const char *ussd_str, enum telephony_ss_ussd_status status);
109
110 static gboolean on_notification_ss_info(CoreObject *o, const void *data, void *user_data);
111 static gboolean on_notification_ss_ussd(CoreObject *o, const void *data, void *user_data);
112
113
114 static gboolean _ss_request_message(TcorePending *pending,
115                                                                         CoreObject *o,
116                                                                         UserRequest *ur,
117                                                                         void *on_resp,
118                                                                         void *user_data)
119 {
120         TcoreHal *hal = NULL;
121         TReturn ret;
122         dbg("Entry");
123
124         if (on_resp) {
125                 tcore_pending_set_response_callback(pending, on_resp, user_data);
126         }
127         tcore_pending_set_send_callback(pending, on_confirmation_ss_message_send, NULL);
128         if (ur) {
129                 tcore_pending_link_user_request(pending, ur);
130         } else {
131                 err("User Request is NULL, is this internal request??");
132         }
133
134         hal = tcore_object_get_hal(o);
135
136         // Send request to HAL
137         ret = tcore_hal_send_request(hal, pending);
138         if (TCORE_RETURN_SUCCESS != ret) {
139                 err("Request send failed");
140                 return FALSE;
141         }
142
143         dbg("Exit");
144         return TRUE;
145 }
146
147 static void _ss_ussd_response(UserRequest *ur, const char *ussd_str, enum telephony_ss_ussd_type type, enum telephony_ss_ussd_status status)
148 {
149         struct tresp_ss_ussd resp;
150         dbg("Entry");
151
152         if (ur) {
153                 memset(&resp, 0x0, sizeof(struct tresp_ss_ussd));
154                 resp.type = type;
155                 resp.status = status;
156                 resp.err = SS_ERROR_NONE;
157                 dbg("ussd_str = %s resp.type - %d resp.status - %d", ussd_str, resp.type, resp.status);
158
159                 if (ussd_str) {
160                         int len = strlen(ussd_str);
161                         if (len < MAX_SS_USSD_LEN) {
162                                 memcpy(resp.str, ussd_str, len);
163                                 resp.str[len] = '\0';
164                         } else {
165                                 memcpy(resp.str, ussd_str, MAX_SS_USSD_LEN);
166                                 resp.str[MAX_SS_USSD_LEN - 1] = '\0';
167                         }
168                         dbg("Response string: %s", resp.str);
169                 } else {
170                         dbg("USSD string is not present");
171                         memset(resp.str, '\0', MAX_SS_USSD_LEN);
172                 }
173                 UssdResp = TRUE;
174                 // Send response to TAPI
175                 tcore_user_request_send_response(ur, TRESP_SS_SEND_USSD, sizeof(struct tresp_ss_ussd), &resp);
176         } else {
177                 err("User request is NULL");
178         }
179
180         dbg("Exit");
181         return;
182 }
183
184 static void _ss_ussd_notification(TcorePlugin *p, const char *ussd_str, enum telephony_ss_ussd_status status)
185 {
186         CoreObject *core_obj = 0;
187         struct tnoti_ss_ussd noti;
188
189         dbg("function enter");
190         if (!p) {
191                 dbg("[ error ] p : (NULL)");
192                 return;
193         }
194         noti.status = status;
195         if (ussd_str) {
196                 int len = strlen(ussd_str);
197                 if (len < MAX_SS_USSD_LEN) {
198                         memcpy(noti.str, ussd_str, len);
199                         noti.str[len] = '\0';
200                 } else {
201                         memcpy(noti.str, ussd_str, MAX_SS_USSD_LEN);
202                         noti.str[MAX_SS_USSD_LEN - 1] = '\0';
203                 }
204         } else {
205                 memset(noti.str, '\0', MAX_SS_USSD_LEN);
206         }
207         dbg("noti.str - %s", noti.str);
208
209         core_obj = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SS);
210         tcore_server_send_notification(tcore_plugin_ref_server(p),
211                                                                    core_obj,
212                                                                    TNOTI_SS_USSD,
213                                                                    sizeof(struct tnoti_ss_ussd),
214                                                                    (void *) &noti);
215 }
216
217 static gboolean on_notification_ss_ussd(CoreObject *o, const void *data, void *user_data)
218 {
219         enum telephony_ss_ussd_status status;
220         UssdSession *ussd_session = 0;
221         char *ussd_str = 0, *cmd = 0;
222         TcorePlugin *plugin = 0;
223         int m = -1, dcs = 0;
224         char *ussdnoti = NULL, *str = NULL, *dcs_str = NULL;
225         GSList *tokens = NULL;
226         GSList *lines = NULL;
227         char *ussd_string = NULL;
228         unsigned int len;
229
230         plugin = tcore_object_ref_plugin(o);
231         ussd_session = tcore_ss_ussd_get_session(o);
232
233         dbg("function enter");
234         lines = (GSList *) data;
235         if (1 != g_slist_length(lines)) {
236                 dbg("unsolicited msg but multiple line");
237                 return TRUE;
238         }
239         cmd = (char *) (lines->data);
240         // parse ussd status
241         tokens = tcore_at_tok_new(cmd);
242
243         // parse <m>
244         ussdnoti = g_slist_nth_data(tokens, 0);
245         if (!ussdnoti) {
246                 dbg("+CUSD<m> is missing from %CUSD Notification");
247         } else {
248                 m = atoi(ussdnoti);
249                 dbg("USSD status  %d", m);
250                 // parse [ <str>, <dcs>]
251                 ussd_string = g_slist_nth_data(tokens, 1);
252                 if (ussd_string) {
253                         /* Strike off starting & ending quotes. 1 extra character for NULL termination */
254                         str = malloc(strlen(ussd_string) - 1);
255                         dbg("length of Ussd Stirng - %d", strlen(ussd_string));
256                         if (str) {
257                                 memset(str, 0x00, strlen(ussd_string) - 1);
258                         } else {
259                                 dbg("malloc failed");
260                                 if (NULL != tokens) {
261                                         tcore_at_tok_free(tokens);
262                                 }
263                                 return FALSE;
264                         }
265                         len = strlen(ussd_string) - 1;
266                         ++ussd_string;
267                         strncpy(str, ussd_string, len);
268
269                         dbg("USSD String - %s len = %d", str, strlen(str));
270                 }
271                 if ((dcs_str = g_slist_nth_data(tokens, 2))) {
272                         dcs = atoi(dcs_str);
273                         dbg("USSD dcs %d", dcs);
274                 }
275         }
276
277         switch (m) {
278         case 0:
279                 status = SS_USSD_NO_ACTION_REQUIRE;
280                 break;
281
282         case 1:
283                 status = SS_USSD_ACTION_REQUIRE;
284                 break;
285
286         case 2:
287                 status = SS_USSD_TERMINATED_BY_NET;
288                 break;
289
290         case 3:
291                 status = SS_USSD_OTHER_CLIENT;
292                 break;
293
294         case 4:
295                 status = SS_USSD_NOT_SUPPORT;
296                 break;
297
298         case 5:
299                 status = SS_USSD_TIME_OUT;
300                 break;
301
302         default:
303                 dbg("unsupported m : %d", m);
304                 status = SS_USSD_MAX;
305                 break;
306         }
307
308         switch (tcore_util_get_cbs_coding_scheme(dcs)) {
309         case TCORE_DCS_TYPE_7_BIT:
310         case TCORE_DCS_TYPE_UNSPECIFIED:
311         // ussd_str = tcore_util_unpack_gsm7bit(str, strlen(str));
312         // break;
313
314         case TCORE_DCS_TYPE_UCS2:
315         case TCORE_DCS_TYPE_8_BIT:
316                 if ((str != NULL) && (strlen(str) > 0)) {
317                         ussd_str = g_new0(char, strlen(str) + 1);
318                         if (ussd_str != NULL) {
319                                 memcpy(ussd_str, str, strlen(str));
320                                 ussd_str[strlen(str)] = '\0';
321                         }
322                 }
323                 break;
324
325         default:
326                 dbg("[ error ] unknown dcs type. ussd_session : %x", ussd_session);
327                 if (ussd_session) {
328                         UserRequest *ur = 0;
329                         enum telephony_ss_ussd_type type;
330
331                         tcore_ss_ussd_get_session_data(ussd_session, (void **) &ur);
332                         if (!ur) {
333                                 dbg("[ error ] ur : (0)");
334                                 goto CATCH;
335                         }
336
337                         type = (enum telephony_ss_ussd_type) tcore_ss_ussd_get_session_type(ussd_session);
338                         dbg("ussd type  - %d", type);
339
340                         _ss_ussd_response(ur, ussd_str, type, status);
341                 }
342
343 CATCH:
344                 if (NULL != tokens) {
345                         tcore_at_tok_free(tokens);
346                 }
347
348                 if (NULL != str) {
349                         free(str);
350                 }
351                 return FALSE;
352         }
353
354         switch (status) {
355         case SS_USSD_NO_ACTION_REQUIRE:
356         case SS_USSD_ACTION_REQUIRE:
357         case SS_USSD_OTHER_CLIENT:
358         case SS_USSD_NOT_SUPPORT:
359         case SS_USSD_TIME_OUT:
360         {
361                 if (ussd_session) {
362                         UserRequest *ur = 0;
363                         enum telephony_ss_ussd_type type;
364
365                         tcore_ss_ussd_get_session_data(ussd_session, (void **) &ur);
366                         if (!ur) {
367                                 dbg("[ error ] ur : (0)");
368                                 if (NULL != tokens) {
369                                         tcore_at_tok_free(tokens);
370                                 }
371
372                                 if (NULL != str) {
373                                         free(str);
374                                 }
375
376                                 if (ussd_str) {
377                                         g_free(ussd_str);
378                                 }
379                                 return FALSE;
380                         }
381                         type = (enum telephony_ss_ussd_type) tcore_ss_ussd_get_session_type(ussd_session);
382                         dbg("ussd type  - %d", type);
383                         _ss_ussd_response(ur, (const char *) ussd_str, type, status);
384                         if (ussd_str)
385                                 g_free(ussd_str);
386                 } else {
387                         tcore_ss_ussd_create_session(o, TCORE_SS_USSD_TYPE_NETWORK_INITIATED, 0, 0);
388                         _ss_ussd_notification(plugin, (const char *) ussd_str, status);
389
390                         if (ussd_str)
391                                 g_free(ussd_str);
392                 }
393         }
394         break;
395
396         case SS_USSD_TERMINATED_BY_NET:
397         {
398                 if (ussd_session) {
399                         UserRequest *ur = 0;
400                         tcore_ss_ussd_get_session_data(ussd_session, (void **) &ur);
401                         if (ur) {
402                                 tcore_user_request_unref(ur);
403                         }
404                         tcore_ss_ussd_destroy_session(ussd_session);
405                 }
406         }
407         break;
408
409         default:
410                 break;
411         }
412
413         if (NULL != tokens) {
414                 tcore_at_tok_free(tokens);
415         }
416
417         if (NULL != str) {
418                 free(str);
419         }
420
421         dbg("Exit");
422         return TRUE;
423 }
424
425 static gboolean on_notification_ss_info(CoreObject *o, const void *data, void *user_data)
426 {
427         TcorePlugin *plugin = 0;
428         CoreObject *co = 0;
429         char *cmd = 0, *number = 0, *pos;
430         int code1 = -1, code2 = -1, index = 0, ton = 0;
431         char *str_code1, *str_code2, *str_ton, *str_index;
432         GSList *tokens = NULL;
433         char *buf;
434         gboolean cssu = FALSE, cssi = FALSE;
435         GSList *lines = NULL;
436         char *resp = NULL;
437         dbg("function enter");
438
439         plugin = tcore_object_ref_plugin(o);
440         co = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL);
441         if (!co) {
442                 dbg("[ error ] plugin_ref_core_object : call");
443                 return FALSE;
444         }
445
446         lines = (GSList *) data;
447         if (1 != g_slist_length(lines)) {
448                 dbg("unsolicited msg but multiple line");
449                 goto OUT;
450         }
451
452         cmd = (char *) (lines->data);
453         pos = strchr(cmd, ':');
454         if (!pos) {
455                 dbg("[ error ] not valid SS- notification ");
456                 return TRUE;
457         }
458         buf = calloc(pos - cmd + 2, 1);
459         memcpy(buf, cmd, pos - cmd);
460         dbg("buf is %s", buf);
461
462         if (!strcmp(buf, "+CSSU")) {
463                 dbg("SS - +CSSU indication");
464                 cssu = TRUE;
465         } else if (!strcmp(buf, "+CSSI")) {
466                 dbg("SS - +CSSI indication");
467                 cssi = TRUE;
468         }
469         free(buf);
470
471         // handle %CSSU notification
472         if (cssu) {
473                 tokens = tcore_at_tok_new(cmd);
474                 // parse <code2>
475                 str_code2 = g_slist_nth_data(tokens, 0);
476                 if (!str_code2) {
477                         dbg("Code2 is missing from %CSSU indiaction");
478                 } else {
479                         code2 = atoi(str_code2);
480                         // parse [ <index>, <number> <type>]
481                         if ((str_index = g_slist_nth_data(tokens, 1))) {
482                                 index = atoi(str_index);
483                         }
484
485                         if ((resp = g_slist_nth_data(tokens, 2))) {
486                                 // Strike off double quotes
487                                 number = util_removeQuotes(resp);
488                                 str_ton = g_slist_nth_data(tokens, 3);
489
490                                 if (str_ton) {
491                                         ton = atoi(str_ton);
492                                 }
493                         }
494                 }
495
496                 dbg("CSSU - code2 = %d index = %d number = %s type = %d", code2, index, number, ton);
497                 switch (code2) {
498                 case 0:      // this is a forwarded call (MT call setup)
499                         tcore_call_information_mt_forwarded_call(co, number);
500                         break;
501
502                 case 2:     // call has been put on hold (during a voice call)
503                         tcore_call_information_held(co, number);
504                         break;
505
506                 case 3:     // call has been retrieved (during a voice call)
507                         tcore_call_information_active(co, number);
508                         break;
509
510                 case 4:     // multiparty call entered (during a voice call)
511                         tcore_call_information_joined(co, number);
512                         break;
513
514                 case 5:     // call on hold has been released
515                         tcore_call_information_released_on_hold(co, number);
516                         break;
517
518                 case 6:     // forward check SS message received (can be received whenever)
519                         tcore_call_information_cf_check_ss_message(co, number);
520                         break;
521
522                 case 7:     // call is being connected (alerting) with the remote party in alerting state in explicit call transfer operation (during a voice call)
523                         tcore_call_information_transfer_alert(co, number);
524                         break;
525
526                 case 8:     // call has been connected with the other remote party in explicit call transfer operation (also number and subaddress parameters may be present) (during a voice call or MT call setup)
527                         tcore_call_information_transfered(co, number);
528                         break;
529
530                 case 9:     // this is a deflected call (MT call setup):
531                         tcore_call_information_mt_deflected_call(co, number);
532                         break;
533
534                 default:
535                         dbg("CSSU - unsupported code2 : %d", code2);
536                         break;
537                 }
538         }
539         // handle %CSSI notification
540
541         if (cssi) {
542                 tokens = tcore_at_tok_new(cmd);
543                 // parse <code1>
544                 str_code1 = g_slist_nth_data(tokens, 0);
545                 if (!str_code1) {
546                         dbg("Code1 is missing from %CSSI indiaction");
547                 } else {
548                         code1 = atoi(str_code1);
549                         // parse [ <index> ]
550                         if ((str_index = g_slist_nth_data(tokens, 1))) {
551                                 index = atoi(str_index);
552                         }
553                 }
554
555                 dbg("CSSI - code1 - %d index - %d ", code1, index);
556
557                 switch (code1) {
558                 case 0:      // Unconditional CF is active
559                         tcore_call_information_mo_cfu(co);
560                         break;
561
562                 case 1:         // some of the conditional call forwarding are active
563                         tcore_call_information_mo_cfc(co);
564                         break;
565
566                 case 2:        // outgoing call is forwarded
567                         tcore_call_information_mo_forwarded(co);
568                         break;
569
570                 case 3:         // this call is waiting
571                         tcore_call_information_mo_waiting(co);
572                         break;
573
574                 case 5:         // outgoing call is barred
575                         tcore_call_information_mo_barred_outgoing(co);
576                         break;
577
578                 case 6:         // incoming call is barred
579                         tcore_call_information_mo_barred_incoming(co);
580                         break;
581
582                 case 7:         // CLIR suppression rejected
583                         tcore_call_information_mo_clir_suppression_reject(co);
584                         break;
585
586                 case 8:         // outgoing call is deflected
587                         tcore_call_information_mo_deflected(co);
588                         break;
589
590                 default:
591                         dbg("unsupported cmd : %d", code1);
592                         break;
593                 }
594         }
595 OUT:
596         if (NULL != tokens) {
597                 tcore_at_tok_free(tokens);
598         }
599
600         g_free(number);
601         return TRUE;
602 }
603
604 static void on_confirmation_ss_message_send(TcorePending *p, gboolean result, void *user_data)
605 {
606         dbg("");
607
608         if (result == FALSE) {
609                 // Fail
610                 dbg("FAIL");
611         } else {
612                 dbg("SEND OK");
613         }
614 }
615
616 static void on_response_ss_barring_set(TcorePending *p, int data_len, const void *data, void *user_data)
617 {
618         struct ss_confirm_info *info = 0;
619         enum telephony_ss_class class;
620         CoreObject *o = 0;
621         UserRequest *ur;
622         struct tresp_ss_barring resp = {0, };
623         UserRequest *ur_dup = 0;
624         GSList *tokens = NULL;
625         const char *line;
626         int error;
627         const TcoreATResponse *response;
628
629         dbg("function enter");
630         response = data;
631         o = tcore_pending_ref_core_object(p);
632         ur = tcore_pending_ref_user_request(p);
633
634         info = (struct ss_confirm_info *)user_data;
635         class = info->class;
636
637         if (response->success > 0) {
638                 dbg("RESPONSE OK");
639                 resp.err = SS_ERROR_NONE;
640         } else {
641                 dbg("RESPONSE NOT OK");
642                 line = (const char *)response->final_response;
643                 tokens = tcore_at_tok_new(line);
644
645                 if (g_slist_length(tokens) < 1) {
646                         dbg("err cause not specified or string corrupted");
647                         resp.err = SS_ERROR_SYSTEMFAILURE;
648                 } else {
649                         error = atoi(g_slist_nth_data(tokens, 0));
650                         err("Error: [%d]", error);
651                         /* TODO: CMEE error mapping is required. */
652                         resp.err = SS_ERROR_SYSTEMFAILURE;
653                 }
654                 tcore_at_tok_free(tokens);
655         }
656
657         dbg("on_response_ss_barring_set - rsp.err : %d, ur : %x flavor_type = %d", resp.err, ur, info->flavor_type);
658         dbg("[ check ] class : 0x%x", info->class);
659
660         if (response->success > 0) {
661                 if (info->class == SS_CLASS_VOICE) {
662                         class = SS_CLASS_ALL_TELE_BEARER;
663                 }
664
665                 ur_dup = tcore_user_request_ref(ur);
666
667                 if (info->flavor_type == SS_BARR_MODE_AB || info->flavor_type == SS_BARR_MODE_AOB) {
668                         _ss_barring_get(o, ur_dup, class, SS_BARR_MODE_BAOC, info->resp);
669                 } else if (info->flavor_type == SS_BARR_MODE_AIB) {
670                         _ss_barring_get(o, ur_dup, class, SS_BARR_MODE_BAIC, info->resp);
671                 } else {
672                         _ss_barring_get(o, ur_dup, class, info->flavor_type, info->resp);
673                 }
674         } else {
675                 if (ur) {
676                         tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_barring), &resp);
677                 } else {
678                         dbg("[ error ] ur is 0");
679                 }
680         }
681         g_free(user_data);
682 }
683
684 static void on_response_ss_barring_change_pwd(TcorePending *p, int data_len, const void *data, void *user_data)
685 {
686         const TcoreATResponse *response = data;
687         struct ss_confirm_info *info = 0;
688         UserRequest *ur;
689         struct tresp_ss_general resp;
690         int error;
691         GSList *tokens = NULL;
692         const char *line;
693
694         dbg("function enter");
695         ur = tcore_pending_ref_user_request(p);
696         info = (struct ss_confirm_info *) user_data;
697
698         if (response->success > 0) {
699                 dbg("RESPONSE OK");
700                 resp.err = SS_ERROR_NONE;
701         } else {
702                 dbg("RESPONSE NOT OK");
703
704                 line = (const char *) response->final_response;
705                 tokens = tcore_at_tok_new(line);
706
707                 if (g_slist_length(tokens) < 1) {
708                         dbg("err cause not specified or string corrupted");
709                         resp.err = SS_ERROR_SYSTEMFAILURE;
710                 } else {
711                         error = atoi(g_slist_nth_data(tokens, 0));
712                         err("Error: [%d]", error);
713                         // TODO: CMEE error mapping is required.
714                         resp.err = SS_ERROR_SYSTEMFAILURE;
715                 }
716                 tcore_at_tok_free(tokens);
717         }
718
719         dbg("on_response_ss_barring_change_pwd: rsp.err : %d, usr : %x", resp.err, ur);
720         if (ur) {
721                 tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_general), &resp);
722         } else {
723                 dbg("[ error ] ur is 0");
724         }
725
726         g_free(user_data);
727 }
728
729 static void on_response_ss_forwarding_set(TcorePending *p, int data_len, const void *data, void *user_data)
730 {
731         CoreObject *o = 0;
732         UserRequest *ur = 0, *dup_ur = 0;
733         struct ss_confirm_info *info = 0;
734         struct tresp_ss_forwarding resp = {0,};
735         GSList *tokens = NULL;
736         const char *line;
737         int error;
738         const TcoreATResponse *response;
739
740         dbg("function enter");
741
742         response = data;
743         o = tcore_pending_ref_core_object(p);
744         ur = tcore_pending_ref_user_request(p);
745
746         info = (struct ss_confirm_info *) user_data;
747
748         if (response->success > 0) {
749                 dbg("RESPONSE OK");
750                 resp.err = SS_ERROR_NONE;
751         } else {
752                 dbg("RESPONSE NOT OK");
753
754                 /* Extract Error */
755                 line = (const char *) response->final_response;
756                 tokens = tcore_at_tok_new(line);
757
758                 if (g_slist_length(tokens) < 1) {
759                         dbg("Error cause not specified or string corrupted");
760                         resp.err = SS_ERROR_SYSTEMFAILURE;
761                 } else {
762                         error = atoi(g_slist_nth_data(tokens, 0));
763                         err("Error: [%d]", error);
764                         // / TODO: CMEE error mapping is required.
765                         resp.err = SS_ERROR_SYSTEMFAILURE;
766                 }
767
768                 tcore_at_tok_free(tokens);
769         }
770
771         dbg("[ check ] class : 0x%x", info->class);
772         dbg("[ check ] flavor_type : 0x%x", info->flavor_type);
773
774         dbg("on_response_ss_forwarding_set - rsp.err : %d, ur : %x", resp.err, ur);
775
776         if (response->success > 0) {
777                 if (info->flavor_type == SS_CF_MODE_CF_ALL ||
778                         info->flavor_type == SS_CF_MODE_CFC) {
779                         if (ur) {
780                                 tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_forwarding), &resp);
781                         } else {
782                                 dbg("[ error ] ur is 0");
783                         }
784                 } else {
785                         dup_ur = tcore_user_request_ref(ur);
786                         _ss_forwarding_get(o, dup_ur, info->class, info->flavor_type, info->resp);
787                 }
788         } else {
789                 if (ur) {
790                         tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_forwarding), &resp);
791                 } else {
792                         dbg("[ error ] ur is 0");
793                 }
794         }
795         g_free(user_data);
796 }
797
798 static void on_response_ss_waiting_set(TcorePending *p, int data_len, const void *data, void *user_data)
799 {
800         CoreObject *core_obj = 0;
801         UserRequest *ur = 0;
802         UserRequest *ur_dup = 0;
803         struct ss_confirm_info *info = 0;
804         struct tresp_ss_waiting resp = {0,};
805         GSList *tokens = NULL;
806         const char *line;
807         int error;
808         const TcoreATResponse *response;
809
810         dbg("function enter");
811         response = data;
812         core_obj = tcore_pending_ref_core_object(p);
813         ur = tcore_pending_ref_user_request(p);
814
815         info = (struct ss_confirm_info *)user_data;
816
817         if (response->success > 0) {
818                 dbg("RESPONSE OK");
819                 resp.err = SS_ERROR_NONE;
820         } else {
821                 dbg("RESPONSE NOT OK");
822
823                 /* Extract Error */
824                 line = (const char *) response->final_response;
825                 tokens = tcore_at_tok_new(line);
826
827                 if (g_slist_length(tokens) < 1) {
828                         dbg("Error cause not specified or string corrupted");
829                         resp.err = SS_ERROR_SYSTEMFAILURE;
830                 } else {
831                         error = atoi(g_slist_nth_data(tokens, 0));
832                         err("Error: [%d]", error);
833                         /* TODO: CMEE error mapping is required. */
834                         resp.err = SS_ERROR_SYSTEMFAILURE;
835                 }
836
837                 /* Free tokens */
838                 tcore_at_tok_free(tokens);
839         }
840
841         dbg("Call Waiting - Error: [%d], UR: [0x%x] class: [0x%2x]", resp.err, ur, info->class);
842         if (resp.err == SS_ERROR_NONE) {
843                 ur_dup = tcore_user_request_ref(ur);
844
845                 dbg("Get Call Waiting status");
846                 _ss_waiting_get(core_obj, ur_dup, info->class, info->resp);
847         } else {
848                 if (ur) {
849                         tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_waiting), &resp);
850                 } else {
851                         err("User request is NULL");
852                 }
853         }
854         g_free(user_data);
855 }
856
857
858 static void on_confirmation_ss_ussd(TcorePending *p, int data_len, const void *data, void *user_data)
859 {
860         CoreObject *core_obj = 0;
861         struct ss_confirm_info *info = 0;
862         struct tresp_ss_ussd resp;
863         UserRequest *ur = NULL, *ussd_ur = NULL;
864         GSList *tokens = NULL;
865         const char *line;
866         int error;
867         UssdSession *ussd_s = NULL;
868         enum tcore_ss_ussd_type type = TCORE_SS_USSD_TYPE_MAX;
869         const TcoreATResponse *response;
870
871         dbg("function enter");
872         response = data;
873         ur = tcore_pending_ref_user_request(p);
874         info = (struct ss_confirm_info *) user_data;
875
876         memset(resp.str, 0x00, MAX_SS_USSD_LEN);
877
878         core_obj = tcore_pending_ref_core_object(p);
879         ussd_s = tcore_ss_ussd_get_session(core_obj);
880
881         if (ussd_s)
882                 type = tcore_ss_ussd_get_session_type(ussd_s);
883         else
884                 dbg("[ error ] ussd_s : (0)");
885
886         resp.type = (enum telephony_ss_ussd_type) type;
887         resp.status = SS_USSD_MAX; // hardcoded value.
888
889         if (response->success > 0) {
890                 dbg("RESPONSE OK");
891                 resp.err = SS_ERROR_NONE;
892         } else {
893                 dbg("RESPONSE NOT OK");
894
895                 line = (const char *) response->final_response;
896                 tokens = tcore_at_tok_new(line);
897
898                 if (g_slist_length(tokens) < 1) {
899                         dbg("err cause not specified or string corrupted");
900                         resp.err = SS_ERROR_SYSTEMFAILURE;
901                 } else {
902                         error = atoi(g_slist_nth_data(tokens, 0));
903                         err("Error: [%d]", error);
904                         // TODO: CMEE error mapping is required.
905                         resp.err = SS_ERROR_SYSTEMFAILURE;
906                 }
907                 tcore_at_tok_free(tokens);
908         }
909
910         dbg("on_confirmation_ss_ussd - rsp.err : %d, ur : %x", resp.err, ur);
911
912         if (response->success > 0) {
913                 if (type == TCORE_SS_USSD_TYPE_USER_INITIATED) {
914                         dbg("ussd type %d", resp.type);
915
916                         if (ussd_s) {
917                                 tcore_ss_ussd_get_session_data(ussd_s, (void **) &ussd_ur);
918                                 if (ussd_ur)
919                                         tcore_user_request_free(ussd_ur);
920                         }
921                 }
922         }
923
924         if (ussd_s)
925                 tcore_ss_ussd_destroy_session(ussd_s);
926
927         if (ur) {
928                 if (UssdResp == FALSE) { // to avoid sending multiple response to application.
929                         tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_ussd), &resp);
930                 }
931                 UssdResp = FALSE;
932         } else
933                 dbg("[ error ] ur : (0)");
934
935         g_free(user_data);
936 }
937
938 static void on_response_ss_barring_get(TcorePending *p, int data_len, const void *data, void *user_data)
939 {
940         UserRequest *ur = 0;
941         int status = 0, classx = 0, ss_err = 0;
942         GSList *respdata;
943         struct ss_confirm_info *info = 0;
944         struct tresp_ss_barring resp;
945         int countRecords = 0, countValidRecords = 0;
946         GSList *tokens = NULL;
947         const char *line;
948         char *classx_str;
949         char *stat = NULL;
950         const TcoreATResponse *response;
951
952         dbg("function enter");
953
954         response = data;
955         ur = tcore_pending_ref_user_request(p);
956         info = (struct ss_confirm_info *) user_data;
957
958         if (response->lines) {
959                 respdata = (GSList *) response->lines;
960                 countRecords = g_slist_length(respdata);
961                 dbg("total records : %d", countRecords);
962         } else {
963                 countRecords = 0;
964                 dbg("no active status - return to user");
965         }
966         resp.record_num = countRecords;
967         resp.record = 0;
968         if (resp.record_num > 0) {
969                 resp.record = g_new0(struct barring_info, resp.record_num);
970                 for (countValidRecords = 0; respdata != NULL; respdata = respdata->next) {
971                         line = (const char *) (respdata->data);
972                         tokens = tcore_at_tok_new(line);
973
974                         // parse <status>
975                         stat = g_slist_nth_data(tokens, 0);
976                         if (!stat) {
977                                 dbg("Stat is missing");
978                                 goto error;
979                         }
980
981                         status = atoi(stat);
982                         if (status == 1) {
983                                 resp.record[countValidRecords].status = SS_STATUS_ACTIVATE;
984                         } else {
985                                 resp.record[countValidRecords].status = SS_STATUS_DEACTIVATE;
986                         }
987                         dbg("call barring status - %d", status);
988
989                         // Parse <class>
990                         classx_str = g_slist_nth_data(tokens, 1);
991
992                         if (!classx_str) {
993                                 dbg("class error. classx not exist - set to requested one : %d", info->class);
994                                 switch (info->class) {
995                                 case SS_CLASS_ALL_TELE:
996                                         classx = 7;
997                                         break;
998
999                                 case SS_CLASS_VOICE:
1000                                         classx = 1;
1001                                         break;
1002
1003                                 case SS_CLASS_ALL_DATA_TELE:
1004                                         classx = 2;
1005                                         break;
1006
1007                                 case SS_CLASS_FAX:
1008                                         classx = 4;
1009                                         break;
1010
1011                                 case SS_CLASS_SMS:
1012                                         classx = 8;
1013                                         break;
1014
1015                                 case SS_CLASS_ALL_CS_SYNC:
1016                                         classx = 16;
1017                                         break;
1018
1019                                 default:
1020                                         classx = 7;
1021                                         dbg("unsupported class %d. set to default : 7", info->class);
1022                                         break;
1023                                 }
1024                         } else {
1025                                 classx = atoi(classx_str);
1026                                 dbg("call barring classx - %d", classx);
1027                         }
1028
1029                         switch (classx) {
1030                         case 1:
1031                                 resp.record[countValidRecords].class = SS_CLASS_VOICE;
1032                                 break;
1033
1034                         case 2:
1035                                 resp.record[countValidRecords].class = SS_CLASS_ALL_DATA_TELE;
1036                                 break;
1037
1038                         case 4:
1039                                 resp.record[countValidRecords].class = SS_CLASS_FAX;
1040                                 break;
1041
1042                         case 7:
1043                                 resp.record[countValidRecords].class = SS_CLASS_ALL_TELE;
1044                                 break;
1045
1046                         case 8:
1047                                 resp.record[countValidRecords].class = SS_CLASS_SMS;
1048                                 break;
1049
1050                         case 16:
1051                                 resp.record[countValidRecords].class = SS_CLASS_ALL_CS_SYNC;
1052                                 break;
1053
1054                         case 32:
1055                                 resp.record[countValidRecords].class = SS_CLASS_ALL_CS_ASYNC;
1056                                 break;
1057
1058                         default:
1059                                 dbg("unspoorted class : [%d]\n", classx);
1060                                 goto error;
1061                                 break;
1062                         }
1063                         resp.record[countValidRecords].mode = (enum telephony_ss_barring_mode) (info->flavor_type);
1064                         countValidRecords++;
1065                         tcore_at_tok_free(tokens);
1066                         continue;
1067
1068 error:
1069                         dbg("invalid field found. coutinue");
1070                         tcore_at_tok_free(tokens);
1071                         continue;
1072                 }
1073
1074                 dbg("valid count :%d", countValidRecords);
1075                 resp.record_num = countValidRecords;
1076                 resp.err = SS_ERROR_NONE;
1077         } else {
1078                 dbg("no active status - return to user");
1079         }
1080
1081         if (response->success > 0) {
1082                 dbg("RESPONSE OK");
1083                 resp.err = SS_ERROR_NONE;
1084         } else {
1085                 dbg("RESPONSE NOT OK");
1086                 resp.err = TCORE_RETURN_FAILURE;
1087                 resp.record = 0;
1088                 resp.record_num = 0;
1089
1090                 line = (const char *) response->final_response;
1091                 tokens = tcore_at_tok_new(line);
1092
1093                 if (g_slist_length(tokens) < 1) {
1094                         dbg("err cause not specified or string corrupted");
1095                         resp.err = SS_ERROR_SYSTEMFAILURE;
1096                 } else {
1097                         ss_err = atoi(g_slist_nth_data(tokens, 0));
1098                         err("Error: [%d]", ss_err);
1099                         // TODO: CMEE error mapping is required.
1100                         resp.err = SS_ERROR_SYSTEMFAILURE;
1101                 }
1102                 tcore_at_tok_free(tokens);
1103         }
1104
1105         dbg("on_response_ss_barring_get- rsp.err : %d, ur : %x", resp.err, ur);
1106
1107         if (ur)
1108                 tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_barring), &resp);
1109         else
1110                 dbg("[ error ] ur is 0");
1111
1112         if (resp.record) {
1113                 g_free(resp.record);
1114                 resp.record = NULL;
1115         }
1116
1117         g_free(user_data);
1118 }
1119
1120 static void on_response_ss_forwarding_get(TcorePending *p, int data_len, const void *data, void *user_data)
1121 {
1122         UserRequest *ur = 0;
1123         int classx = 0, ss_err = 0, time = 0;
1124         char *num;
1125         struct ss_confirm_info *info = 0;
1126         struct tresp_ss_forwarding resp;
1127         int countRecords = 0, countValidRecords = 0;
1128
1129         GSList *respdata = NULL, *tokens = NULL;
1130         const char *line;
1131         char *classx_str, *status, *ton, *time_str;
1132         const TcoreATResponse *response;
1133
1134         dbg("function enter");
1135         response = data;
1136
1137         ur = tcore_pending_ref_user_request(p);
1138         info = (struct ss_confirm_info *) user_data;
1139         if (response->lines) {
1140                 respdata = (GSList *) response->lines;
1141                 countRecords = g_slist_length(respdata);
1142                 dbg("total records : %d", countRecords);
1143         } else {
1144                 countRecords = 0;
1145                 dbg("no active status - return to user");
1146         }
1147         resp.record_num = countRecords;
1148         resp.record = 0;
1149         if (resp.record_num > 0) {
1150                 resp.record = g_new0(struct forwarding_info, resp.record_num);
1151
1152                 for (countValidRecords = 0; respdata != NULL; respdata = respdata->next) {
1153                         line = (const char *) (respdata->data);
1154                         tokens = tcore_at_tok_new(line);
1155
1156                         // parse <status>
1157                         status = g_slist_nth_data(tokens, 0);
1158                         if (!status) {
1159                                 dbg("start line error. skip this line");
1160                                 goto error;
1161                         } else {
1162                                 if (atoi(status) == 1) {
1163                                         resp.record[countValidRecords].status = SS_STATUS_ACTIVATE;
1164                                 } else {
1165                                         resp.record[countValidRecords].status = SS_STATUS_DEACTIVATE;
1166                                 }
1167                         }
1168
1169                         // Parse <class>
1170                         classx_str = g_slist_nth_data(tokens, 1);
1171                         if (!classx_str) {
1172                                 dbg("class error. skip this line");
1173                                 goto error;
1174                         } else {
1175                                 switch (atoi(classx_str)) {
1176                                 case 1:
1177                                         resp.record[countValidRecords].class = SS_CLASS_VOICE;
1178                                         break;
1179
1180                                 case 2:
1181                                         resp.record[countValidRecords].class = SS_CLASS_ALL_DATA_TELE;
1182                                         break;
1183
1184                                 case 4:
1185                                         resp.record[countValidRecords].class = SS_CLASS_FAX;
1186                                         break;
1187
1188                                 case 7:
1189                                         resp.record[countValidRecords].class = SS_CLASS_ALL_TELE;
1190                                         break;
1191
1192                                 case 8:
1193                                         resp.record[countValidRecords].class = SS_CLASS_SMS;
1194                                         break;
1195
1196                                 case 16:
1197                                         resp.record[countValidRecords].class = SS_CLASS_ALL_CS_SYNC;
1198                                         break;
1199
1200                                 case 32:
1201                                         resp.record[countValidRecords].class = SS_CLASS_ALL_CS_ASYNC;
1202                                         break;
1203
1204                                 default:
1205                                         dbg("unspoorted class : [%d]\n", classx);
1206                                         goto error;
1207                                         break;
1208                                 }
1209                         }
1210
1211                         // parse  <numer> <type>
1212                         num = g_slist_nth_data(tokens, 2);
1213                         if (num) {
1214                                 dbg("number  - %s", num);
1215                                 memcpy((resp.record[countValidRecords].number), num, strlen(num));
1216                                 resp.record[countValidRecords].number_present = TRUE;
1217
1218                                 ton = g_slist_nth_data(tokens, 3);
1219                                 if (ton) {
1220                                         resp.record[countValidRecords].ton = atoi(ton);
1221                                         dbg("number  type - %d", resp.record[countValidRecords].ton);
1222                                 }
1223                         }
1224
1225                         // skip  <subaddr> <satype>
1226                         // parse  <time>
1227                         time_str = g_slist_nth_data(tokens, 6);
1228                         if (time_str) {
1229                                 time = atoi(time_str);
1230                                 resp.record[countValidRecords].time = (enum telephony_ss_forwarding_no_reply_time) time;
1231                                 dbg("time  - %d", time);
1232                         }
1233
1234                         resp.record[countValidRecords].mode = (enum telephony_ss_forwarding_mode) (info->flavor_type);
1235                         dbg("flavor_type  - %d", (enum telephony_ss_forwarding_mode) (info->flavor_type));
1236
1237                         countValidRecords++;
1238                         tcore_at_tok_free(tokens);
1239                         continue;
1240 error:
1241                         dbg("invalid field found. coutinue");
1242                         tcore_at_tok_free(tokens);
1243                         continue;
1244                 }
1245                 dbg("valid count :%d", countValidRecords);
1246                 resp.record_num = countValidRecords;
1247                 resp.err = SS_ERROR_NONE;
1248         } else {
1249                 dbg("no active status - return to user");
1250         }
1251
1252         if (response->success > 0) {
1253                 dbg("RESPONSE OK");
1254                 resp.err = SS_ERROR_NONE;
1255         } else {
1256                 dbg("RESPONSE NOT OK");
1257                 resp.record = 0;
1258                 resp.record_num = 0;
1259                 line = (const char *) response->final_response;
1260                 tokens = tcore_at_tok_new(line);
1261
1262                 if (g_slist_length(tokens) < 1) {
1263                         dbg("err cause not specified or string corrupted");
1264                         resp.err = SS_ERROR_SYSTEMFAILURE;
1265                 } else {
1266                         ss_err = atoi(g_slist_nth_data(tokens, 0));
1267                         err("Error: [%d]", ss_err);
1268                         /* TODO: CMEE error mapping is required. */
1269                         resp.err = SS_ERROR_SYSTEMFAILURE;
1270                 }
1271                 tcore_at_tok_free(tokens);
1272         }
1273
1274         dbg("on_response_ss_forwarding_get- rsp.err : %d, ur : %x", resp.err, ur);
1275         if (ur)
1276                 tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_forwarding), &resp);
1277         else
1278                 dbg("[ error ] ur is 0");
1279
1280         if (resp.record) {
1281                 g_free(resp.record);
1282                 resp.record = NULL;
1283         }
1284         g_free(user_data);
1285 }
1286
1287 static void on_response_ss_waiting_get(TcorePending *p, int data_len, const void *data, void *user_data)
1288 {
1289         UserRequest *ur = 0;
1290         GSList *respdata, *tokens = NULL;
1291         int classx = 0, ss_err = 0;
1292         struct ss_confirm_info *info = 0;
1293         struct tresp_ss_waiting resp;
1294         int countRecords = 0, countValidRecords = 0;
1295         const char *line;
1296         char *classx_str, *status;
1297         const TcoreATResponse *response;
1298
1299         dbg("function enter");
1300         response = data;
1301         ur = tcore_pending_ref_user_request(p);
1302         info = (struct ss_confirm_info *) user_data;
1303
1304         if (response->lines) {
1305                 respdata = (GSList *) response->lines;
1306                 countRecords = g_slist_length(respdata);
1307                 dbg("total records : %d", countRecords);
1308         } else {
1309                 countRecords = 0;
1310                 dbg("no active status - return to user");
1311         }
1312         resp.record_num = countRecords;
1313         resp.record = 0;
1314
1315         if (resp.record_num > 0) {
1316                 resp.record = g_new0(struct waiting_info, resp.record_num);
1317
1318                 for (countValidRecords = 0; respdata != NULL; respdata = respdata->next) {
1319                         line = (const char *) (respdata->data);
1320                         tokens = tcore_at_tok_new(line);
1321
1322                         // parse <status>
1323                         status = g_slist_nth_data(tokens, 0);
1324                         if (!status) {
1325                                 dbg("Missing stat  in responce ");
1326                                 goto error;
1327                         } else {
1328                                 if (atoi(status) == 1) {
1329                                         resp.record[countValidRecords].status = SS_STATUS_ACTIVATE;
1330                                 } else {
1331                                         resp.record[countValidRecords].status = SS_STATUS_DEACTIVATE;
1332                                 }
1333                         }
1334                         dbg("status = %d", resp.record[countValidRecords].status);
1335
1336                         // Parse <class>
1337                         classx_str = g_slist_nth_data(tokens, 1);
1338                         if (!classx_str) {
1339                                 dbg("error - class is missing");
1340                                 goto error;
1341                         } else {
1342                                 switch (atoi(classx_str)) {
1343                                 case 1:
1344                                         resp.record[countValidRecords].class = SS_CLASS_VOICE;
1345                                         break;
1346
1347                                 case 2:
1348                                         resp.record[countValidRecords].class = SS_CLASS_ALL_DATA_TELE;
1349                                         break;
1350
1351                                 case 4:
1352                                         resp.record[countValidRecords].class = SS_CLASS_FAX;
1353                                         break;
1354
1355                                 case 7:
1356                                         resp.record[countValidRecords].class = SS_CLASS_ALL_TELE;
1357                                         break;
1358
1359                                 case 8:
1360                                         resp.record[countValidRecords].class = SS_CLASS_SMS;
1361                                         break;
1362
1363                                 case 16:
1364                                         resp.record[countValidRecords].class = SS_CLASS_ALL_CS_SYNC;
1365                                         break;
1366
1367                                 case 32:
1368                                         resp.record[countValidRecords].class = SS_CLASS_ALL_CS_ASYNC;
1369                                         break;
1370
1371                                 default:
1372                                         dbg("unspoorted class : [%d]\n", classx);
1373                                         goto error;
1374                                         break;
1375                                 }
1376                                 dbg("class info %d", resp.record[countValidRecords].class);
1377                         }
1378
1379                         countValidRecords++;
1380                         tcore_at_tok_free(tokens);
1381                         continue;
1382 error:
1383                         dbg("invalid field found. coutinue");
1384                         tcore_at_tok_free(tokens);
1385                         continue;
1386                 }
1387
1388                 dbg("valid count :%d", countValidRecords);
1389                 resp.record_num = countValidRecords;
1390                 resp.err = SS_ERROR_NONE;
1391         } else {
1392                 dbg("no active status - return to user");
1393         }
1394
1395         if (response->success > 0) {
1396                 dbg("RESPONSE OK");
1397                 resp.err = SS_ERROR_NONE;
1398         } else {
1399                 dbg("RESPONSE NOT OK");
1400                 resp.record = 0;
1401                 resp.record_num = 0;
1402                 line = (const char *) response->final_response;
1403                 tokens = tcore_at_tok_new(line);
1404
1405                 if (g_slist_length(tokens) < 1) {
1406                         dbg("err cause not specified or string corrupted");
1407                         resp.err = SS_ERROR_SYSTEMFAILURE;
1408                 } else {
1409                         ss_err = atoi(g_slist_nth_data(tokens, 0));
1410                         err("Error: [%d]", ss_err);
1411                         // TODO: CMEE error mapping is required.
1412                         resp.err = SS_ERROR_SYSTEMFAILURE;
1413                 }
1414                 tcore_at_tok_free(tokens);
1415         }
1416
1417         dbg("on_response_ss_waiting_get - rsp.err : %d, ur : %x", resp.err, ur);
1418         if (ur)
1419                 tcore_user_request_send_response(ur, info->resp, sizeof(struct tresp_ss_waiting), &resp);
1420         else
1421                 dbg("[ error ] ur is 0");
1422
1423         if (resp.record) {
1424                 g_free(resp.record);
1425                 resp.record = NULL;
1426         }
1427         g_free(user_data);
1428 }
1429
1430
1431 static void on_response_ss_cli_get(TcorePending *p, int data_len, const void *data, void *user_data)
1432 {
1433         UserRequest *ur = 0;
1434         struct tresp_ss_cli resp;
1435         enum telephony_ss_cli_type *p_type = NULL;
1436         char *line = NULL, *status;
1437         int error = FALSE;
1438         int cli_adj, stat;
1439         GSList *tokens = NULL;
1440         const TcoreATResponse *response;
1441
1442         dbg("function enter");
1443         response = data;
1444         ur = tcore_pending_ref_user_request(p);
1445         p_type = (enum telephony_ss_cli_type *) (user_data);
1446
1447         if (response->success > 0) {
1448                 line = (char *) (((GSList *) response->lines)->data);
1449                 tokens = tcore_at_tok_new(line);
1450
1451                 if (*p_type == SS_CLI_TYPE_CLIR) {
1452                         // +CLIR: <n> <m>
1453                         dbg("CLI type is CLIR");
1454                         // parse <n>
1455                         status = g_slist_nth_data(tokens, 0);
1456
1457                         if (!status) {
1458                                 dbg("Call line identification adjustment missing <n>");
1459                         } else {
1460                                 cli_adj = atoi(status);
1461                                 dbg("CLIR response value of <n> - %d", cli_adj);
1462
1463                                 if (cli_adj == 0) {
1464                                         // parse <m>
1465                                         status = g_slist_nth_data(tokens, 1);
1466                                         if (!status) {
1467                                                 dbg("status is missing<m>");
1468                                         }
1469                                         stat = atoi(status);
1470                                         dbg("CLIR response value of <m> - %d", stat);
1471
1472                                         if (stat == 1 || stat == 3) {
1473                                                 resp.status = TRUE;
1474                                         } else {
1475                                                 resp.status = FALSE;
1476                                         }
1477                                 } else if (cli_adj == 1) {
1478                                         resp.status = TRUE;
1479                                 } else {
1480                                         resp.status = FALSE;
1481                                 }
1482                                 dbg("resp.status -  %d", resp.status);
1483                         }
1484                         tcore_at_tok_free(tokens);
1485                 } else {
1486                         // parse <n>
1487                         status = g_slist_nth_data(tokens, 0);
1488                         if (!status) {
1489                                 dbg("Stat is missing");
1490                         } else {
1491                                 stat = atoi(status);
1492                                 if (stat == 1)
1493                                         resp.status = TRUE;
1494                                 else
1495                                         resp.status = FALSE;
1496
1497                                 dbg("resp.status -  %d", resp.status);
1498                         }
1499                         tcore_at_tok_free(tokens);
1500                 }
1501         }
1502
1503         if (response->success > 0) {
1504                 dbg("RESPONSE OK");
1505                 resp.err = SS_ERROR_NONE;
1506         } else {
1507                 dbg("RESPONSE NOT OK");
1508
1509                 line = (char *) response->final_response;
1510                 tokens = tcore_at_tok_new(line);
1511
1512                 if (g_slist_length(tokens) < 1) {
1513                         dbg("err cause not specified or string corrupted");
1514                         resp.err = SS_ERROR_SYSTEMFAILURE;
1515                 } else {
1516                         error = atoi(g_slist_nth_data(tokens, 0));
1517                         err("Error: [%d]", error);
1518                         // TODO: CMEE error mapping is required.
1519                         resp.err = SS_ERROR_SYSTEMFAILURE;
1520                 }
1521                 tcore_at_tok_free(tokens);
1522         }
1523
1524         resp.type = *p_type;
1525         dbg("check - resp.type = %d ", resp.type);
1526         if (ur)
1527                 tcore_user_request_send_response(ur, TRESP_SS_CLI_GET_STATUS, sizeof(struct tresp_ss_cli), &resp);
1528         else
1529                 dbg("[ error ] ur : (0)");
1530
1531         g_free(user_data);
1532 }
1533
1534 static struct tcore_ss_operations ss_ops = {
1535         .barring_activate = imc_ss_barring_activate,
1536         .barring_deactivate = imc_ss_barring_deactivate,
1537         .barring_change_password = imc_ss_barring_change_password,
1538         .barring_get_status = imc_ss_barring_get_status,
1539         .forwarding_activate = imc_ss_forwarding_activate,
1540         .forwarding_deactivate = imc_ss_forwarding_deactivate,
1541         .forwarding_register = imc_ss_forwarding_register,
1542         .forwarding_deregister = imc_ss_forwarding_deregister,
1543         .forwarding_get_status = imc_ss_forwarding_get_status,
1544         .waiting_activate = imc_ss_waiting_activate,
1545         .waiting_deactivate = imc_ss_waiting_deactivate,
1546         .waiting_get_status = imc_ss_waiting_get_status,
1547         .cli_activate = imc_ss_cli_activate,
1548         .cli_deactivate = imc_ss_cli_deactivate,
1549         .cli_get_status = imc_ss_cli_get_status,
1550         .send_ussd = imc_ss_send_ussd,
1551         .set_aoc = imc_ss_set_aoc,
1552         .get_aoc = imc_ss_get_aoc,
1553 };
1554
1555
1556 static TReturn _ss_barring_set(CoreObject *o, UserRequest *ur, enum telephony_ss_opcode op)
1557 {
1558         struct treq_ss_barring *barring = 0;
1559         struct ss_confirm_info *user_data = 0;
1560         char *cmd_str = NULL;
1561         TcorePending *pending = NULL;
1562         TcoreATRequest *req;
1563         char passwd[MAX_SS_BARRING_PASSWORD_LEN + 1];
1564         int opco;
1565         int classx;
1566         char *facility = NULL;
1567         gboolean ret = FALSE;
1568
1569         dbg("function enter");
1570         barring = (struct treq_ss_barring *) tcore_user_request_ref_data(ur, 0);
1571
1572         switch (op) {
1573         case SS_OPCO_ACTIVATE:
1574                 opco = 1;
1575                 break;
1576
1577         case SS_OPCO_DEACTIVATE:
1578                 opco = 0;
1579                 break;
1580
1581         default:
1582                 dbg("unsupported opco : %d", op);
1583                 return TCORE_RETURN_FAILURE;
1584         }
1585         dbg("opco - %d", opco);
1586
1587         switch (barring->mode) {
1588         case SS_BARR_MODE_BAOC:
1589                 facility = "AO";
1590                 break;
1591
1592         case SS_BARR_MODE_BOIC:
1593                 facility = "OI";
1594                 break;
1595
1596         case SS_BARR_MODE_BOIC_NOT_HC:
1597                 facility = "OX";
1598                 break;
1599
1600         case SS_BARR_MODE_BAIC:
1601                 facility = "AI";
1602                 break;
1603
1604         case SS_BARR_MODE_BIC_ROAM:
1605                 facility = "IR";
1606                 break;
1607
1608         case SS_BARR_MODE_AB:
1609                 facility = "AB";
1610                 break;
1611
1612         case SS_BARR_MODE_AOB:
1613                 facility = "AG";
1614                 break;
1615
1616         case SS_BARR_MODE_AIB:
1617                 facility = "AC";
1618                 break;
1619
1620         case SS_BARR_MODE_BIC_NOT_SIM:
1621         // facility = "NS";
1622         default:
1623                 dbg("unspported mode %d", barring->mode);
1624                 return TCORE_RETURN_FAILURE;
1625         }
1626
1627         dbg("facility - %s", facility);
1628
1629         switch (barring->class) {
1630         case SS_CLASS_ALL_TELE:
1631                 classx = 7;
1632                 break;
1633
1634         case SS_CLASS_VOICE:
1635                 classx = 1;
1636                 break;
1637
1638         case SS_CLASS_ALL_DATA_TELE:
1639                 classx = 2;
1640                 break;
1641
1642         case SS_CLASS_FAX:
1643                 classx = 4;
1644                 break;
1645
1646         case SS_CLASS_SMS:
1647                 classx = 8;
1648                 break;
1649
1650         case SS_CLASS_ALL_CS_SYNC:
1651                 classx = 16;
1652                 break;
1653
1654         default:
1655                 classx = 7;
1656                 dbg("unsupported class %d. set to default : 7", barring->class);
1657                 break;
1658         }
1659
1660         dbg("classx - %d", classx);
1661
1662         user_data = g_new0(struct ss_confirm_info, 1);
1663         if (!user_data) {
1664                 dbg("[ error ] failed to allocate memory");
1665                 return TCORE_RETURN_ENOMEM;
1666         }
1667
1668         // null-ended pwd handling added - unexpected  0x11 value observed in req string
1669         memcpy(passwd, barring->password, MAX_SS_BARRING_PASSWORD_LEN);
1670         passwd[MAX_SS_BARRING_PASSWORD_LEN] = '\0';
1671         dbg("passwd - %s", passwd);
1672
1673         pending = tcore_pending_new(o, 0);
1674
1675         cmd_str = g_strdup_printf("AT+CLCK=\"%s\",%d,\"%s\",%d", facility, opco, passwd, classx);
1676         dbg("request command : %s", cmd_str);
1677
1678         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
1679         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
1680
1681         tcore_pending_set_request_data(pending, 0, req);
1682
1683         if (op == SS_OPCO_ACTIVATE) {
1684                 user_data->resp = TRESP_SS_BARRING_ACTIVATE;
1685         } else if (op == SS_OPCO_DEACTIVATE) {
1686                 user_data->resp = TRESP_SS_BARRING_DEACTIVATE;
1687         } else {
1688                 dbg("[ error ] wrong ss opco (0x%x)", op);
1689                 if (user_data != NULL) {
1690                         g_free(user_data);
1691                 }
1692                 g_free(cmd_str);
1693                 tcore_pending_free(pending);
1694                 tcore_at_request_free(req);
1695                 return TCORE_RETURN_FAILURE;
1696         }
1697         user_data->flavor_type = (int) (barring->mode);
1698         user_data->class = barring->class;
1699
1700         ret = _ss_request_message(pending, o, ur, on_response_ss_barring_set, user_data);
1701         g_free(cmd_str);
1702
1703         if (!ret) {
1704                 dbg("AT request sent failed ");
1705                 if (user_data != NULL) {
1706                         g_free(user_data);
1707                         tcore_pending_free(pending);
1708                         tcore_at_request_free(req);
1709                 }
1710                 return TCORE_RETURN_FAILURE;
1711         }
1712         return TCORE_RETURN_SUCCESS;
1713 }
1714
1715 static TReturn _ss_barring_get(CoreObject *o,
1716                                                            UserRequest *ur,
1717                                                            enum telephony_ss_class class,
1718                                                            enum telephony_ss_barring_mode mode,
1719                                                            enum tcore_response_command resp)
1720 {
1721         struct ss_confirm_info *user_data = 0;
1722         gboolean ret = FALSE;
1723         char *cmd_str = NULL;
1724         int opco, classx;
1725         char *facility = NULL;
1726         TcorePending *pending = NULL;
1727         TcoreATRequest *req;
1728
1729         dbg("function enter");
1730
1731         // query status - opco is fixed to 2
1732         opco = 2;
1733         // barring mode
1734         switch (mode) {
1735         case SS_BARR_MODE_BAOC:
1736                 facility = "AO";
1737                 break;
1738
1739         case SS_BARR_MODE_BOIC:
1740                 facility = "OI";
1741                 break;
1742
1743         case SS_BARR_MODE_BOIC_NOT_HC:
1744                 facility = "OX";
1745                 break;
1746
1747         case SS_BARR_MODE_BAIC:
1748                 facility = "AI";
1749                 break;
1750
1751         case SS_BARR_MODE_BIC_ROAM:
1752                 facility = "IR";
1753                 break;
1754
1755         case SS_BARR_MODE_AB:
1756         case SS_BARR_MODE_AOB:
1757         case SS_BARR_MODE_AIB:
1758         case SS_BARR_MODE_BIC_NOT_SIM:
1759         default:
1760                 dbg("unsupported mode %d", mode);
1761                 return TCORE_RETURN_FAILURE;
1762         }
1763
1764         dbg("facility - %s", facility);
1765
1766         switch (class) {
1767         case SS_CLASS_ALL_TELE:
1768                 classx = 7;
1769                 break;
1770
1771         case SS_CLASS_VOICE:
1772                 classx = 1;
1773                 break;
1774
1775         case SS_CLASS_ALL_DATA_TELE:
1776                 classx = 2;
1777                 break;
1778
1779         case SS_CLASS_FAX:
1780                 classx = 4;
1781                 break;
1782
1783         case SS_CLASS_SMS:
1784                 classx = 8;
1785                 break;
1786
1787         case SS_CLASS_ALL_CS_SYNC:
1788                 classx = 16;
1789                 break;
1790
1791         default:
1792                 classx = 7;
1793                 dbg("unsupported class %d. set to default : 7", class);
1794                 break;
1795         }
1796
1797         user_data = g_new0(struct ss_confirm_info, 1);
1798         if (!user_data) {
1799                 dbg("[ error ] failed to allocate memory");
1800                 return TCORE_RETURN_ENOMEM;
1801         }
1802
1803         dbg("class - %d", classx);
1804         if (classx == 7)
1805                 cmd_str = g_strdup_printf("AT+CLCK=\"%s\",%d", facility, opco);
1806         else
1807                 cmd_str = g_strdup_printf("AT+CLCK=\"%s\",%d,,%d", facility, opco, classx);
1808
1809         dbg("request command : %s", cmd_str);
1810
1811         pending = tcore_pending_new(o, 0);
1812         req = tcore_at_request_new(cmd_str, "+CLCK", TCORE_AT_MULTILINE);
1813         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
1814
1815         tcore_pending_set_request_data(pending, 0, req);
1816
1817         user_data->resp = resp;
1818         user_data->flavor_type = (int) (mode);
1819         user_data->class = class;
1820
1821         ret = _ss_request_message(pending, o, ur, on_response_ss_barring_get, user_data);
1822         g_free(cmd_str);
1823
1824         if (!ret) {
1825                 dbg("AT request sent failed ");
1826                 if (user_data != NULL) {
1827                         g_free(user_data);
1828                         tcore_pending_free(pending);
1829                         tcore_at_request_free(req);
1830                 }
1831                 return TCORE_RETURN_FAILURE;
1832         }
1833
1834         return TCORE_RETURN_SUCCESS;
1835 }
1836
1837 static TReturn imc_ss_barring_activate(CoreObject *o, UserRequest *ur)
1838 {
1839         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
1840                 dbg("cp not ready/n");
1841                 return TCORE_RETURN_ENOSYS;
1842         }
1843         return _ss_barring_set(o, ur, SS_OPCO_ACTIVATE);
1844 }
1845
1846 static TReturn imc_ss_barring_deactivate(CoreObject *o, UserRequest *ur)
1847 {
1848         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
1849                 dbg("cp not ready/n");
1850                 return TCORE_RETURN_ENOSYS;
1851         }
1852         return _ss_barring_set(o, ur, SS_OPCO_DEACTIVATE);
1853 }
1854
1855 static TReturn imc_ss_barring_change_password(CoreObject *o, UserRequest *ur)
1856 {
1857         TcorePending *pending = NULL;
1858         TcoreATRequest *req;
1859         struct treq_ss_barring_change_password *barring = 0;
1860         struct ss_confirm_info *user_data = 0;
1861         char *cmd_str = NULL;
1862         gboolean ret = FALSE;
1863         char old_password[MAX_SS_BARRING_PASSWORD_LEN + 1];
1864         char new_password[MAX_SS_BARRING_PASSWORD_LEN + 1];
1865
1866         dbg("function enter");
1867
1868         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
1869                 dbg("cp not ready/n");
1870                 return TCORE_RETURN_ENOSYS;
1871         }
1872
1873         barring = (struct treq_ss_barring_change_password *) tcore_user_request_ref_data(ur, 0);
1874
1875         if (barring->password_old == NULL || barring->password_new == NULL) {
1876                 dbg("[error]password is null");
1877                 return TCORE_RETURN_FAILURE;
1878         }
1879         memcpy(old_password, barring->password_old, MAX_SS_BARRING_PASSWORD_LEN);
1880         old_password[MAX_SS_BARRING_PASSWORD_LEN] = '\0';
1881         memcpy(new_password, barring->password_new, MAX_SS_BARRING_PASSWORD_LEN);
1882         new_password[MAX_SS_BARRING_PASSWORD_LEN] = '\0';
1883
1884         user_data = g_new0(struct ss_confirm_info, 1);
1885         if (!user_data) {
1886                 dbg("[ error ] failed to allocate memory");
1887                 return TCORE_RETURN_ENOMEM;
1888         }
1889         user_data->resp = TRESP_SS_BARRING_CHANGE_PASSWORD;
1890
1891         dbg("old passwd - %s new passwd- %s", old_password, new_password);
1892         cmd_str = g_strdup_printf("AT+CPWD=\"%s\",\"%s\",\"%s\"", "AB", old_password, new_password);
1893         dbg("request command : %s", cmd_str);
1894
1895         pending = tcore_pending_new(o, 0);
1896         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
1897         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
1898
1899         tcore_pending_set_request_data(pending, 0, req);
1900
1901         ret = _ss_request_message(pending, o, ur, on_response_ss_barring_change_pwd, user_data);
1902         g_free(cmd_str);
1903         if (!ret) {
1904                 dbg("AT request sent failed ");
1905                 if (user_data != NULL) {
1906                         g_free(user_data);
1907                 }
1908                 tcore_pending_free(pending);
1909                 tcore_at_request_free(req);
1910                 return TCORE_RETURN_FAILURE;
1911         }
1912         return TCORE_RETURN_SUCCESS;
1913 }
1914
1915 static TReturn imc_ss_barring_get_status(CoreObject *o, UserRequest *ur)
1916 {
1917         struct treq_ss_barring *barring = 0;
1918
1919         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
1920                 dbg("cp not ready/n");
1921                 return TCORE_RETURN_ENOSYS;
1922         }
1923         barring = (struct treq_ss_barring *) tcore_user_request_ref_data(ur, 0);
1924
1925         return _ss_barring_get(o, ur, barring->class, barring->mode, TRESP_SS_BARRING_GET_STATUS);
1926 }
1927
1928 static TReturn _ss_forwarding_set(CoreObject *o, UserRequest *ur, enum telephony_ss_opcode op)
1929 {
1930         struct treq_ss_forwarding *forwarding = 0;
1931         struct ss_confirm_info *user_data = 0;
1932         gboolean ret = FALSE;
1933         int len = 0;
1934         char *cmd_str = NULL;
1935         char *tmp_str = NULL;
1936         int reason = 0, mode = 0, num_type = 0, classx = 0, time = 0;
1937         TcorePending *pending = NULL;
1938         TcoreATRequest *req;
1939
1940         dbg("_ss_forwarding_set with opco %d ", op);
1941
1942         forwarding = (struct treq_ss_forwarding *) tcore_user_request_ref_data(ur, 0);
1943         switch (forwarding->mode) {
1944         case SS_CF_MODE_CFU:
1945                 reason = 0;
1946                 break;
1947
1948         case SS_CF_MODE_CFB:
1949                 reason = 1;
1950                 break;
1951
1952         case SS_CF_MODE_CFNRy:
1953                 reason = 2;
1954                 break;
1955
1956         case SS_CF_MODE_CFNRc:
1957                 reason = 3;
1958                 break;
1959
1960         case SS_CF_MODE_CF_ALL:
1961                 reason = 4;
1962                 break;
1963
1964         case SS_CF_MODE_CFC:
1965                 reason = 5;
1966                 break;
1967
1968         default:
1969                 dbg("unsupported reason : %d");
1970                 return TCORE_RETURN_FAILURE;
1971                 break;
1972         }
1973
1974         dbg("reason = %d", reason);
1975         switch (op) {
1976         case SS_OPCO_DEACTIVATE:
1977                 mode = 0;
1978                 break;
1979
1980         case SS_OPCO_ACTIVATE:
1981                 mode = 1;
1982                 break;
1983
1984         case SS_OPCO_REG:
1985                 mode = 3;
1986                 break;
1987
1988         case SS_OPCO_DEREG:
1989                 mode = 4;
1990                 break;
1991
1992         default:
1993                 dbg("unsupported opco : %d", op);
1994                 return TCORE_RETURN_FAILURE;
1995         }
1996
1997         dbg("mode = %d", mode);
1998
1999         // class
2000         switch (forwarding->class) {
2001         case SS_CLASS_ALL_TELE:
2002                 classx = 7;
2003                 break;
2004
2005         case SS_CLASS_VOICE:
2006                 classx = 1;
2007                 break;
2008
2009         case SS_CLASS_ALL_DATA_TELE:
2010                 classx = 2;
2011                 break;
2012
2013         case SS_CLASS_FAX:
2014                 classx = 4;
2015                 break;
2016
2017         case SS_CLASS_SMS:
2018                 classx = 8;
2019                 break;
2020
2021         case SS_CLASS_ALL_CS_SYNC:
2022                 classx = 16;
2023                 break;
2024
2025         default:
2026                 classx = 7;
2027                 dbg("unsupported class %d. set to default : 7", forwarding->class);
2028                 break;
2029         }
2030         dbg("classx = %d", classx);
2031
2032         // number
2033         len = strlen(forwarding->number);
2034         if (len > 0) {
2035                 if (forwarding->number[0] == '+')
2036                         num_type = ((NUM_TYPE_INTERNATIONAL << 4) | NUM_PLAN_ISDN);
2037                 else
2038                         num_type = 0;
2039         }
2040         dbg("number = %s", forwarding->number);
2041
2042         user_data = g_new0(struct ss_confirm_info, 1);
2043         if (!user_data) {
2044                 dbg("[ error ] failed to allocate memory");
2045                 return TCORE_RETURN_ENOMEM;
2046         }
2047
2048         switch (op) {
2049         case SS_OPCO_REG:
2050                 user_data->resp = TRESP_SS_FORWARDING_REGISTER;
2051                 break;
2052
2053         case SS_OPCO_DEREG:
2054                 user_data->resp = TRESP_SS_FORWARDING_DEREGISTER;
2055                 break;
2056
2057         case SS_OPCO_ACTIVATE:
2058                 user_data->resp = TRESP_SS_FORWARDING_ACTIVATE;
2059                 break;
2060
2061         case SS_OPCO_DEACTIVATE:
2062                 user_data->resp = TRESP_SS_FORWARDING_DEACTIVATE;
2063                 break;
2064
2065         default:
2066                 dbg("[ error ] unknown op (0x%x)", op);
2067                 break;
2068         }
2069
2070         if (forwarding->number[0] == '+')
2071                 num_type = 145;
2072         else
2073                 num_type = 129;
2074
2075         if (op == SS_OPCO_REG)
2076                 tmp_str = g_strdup_printf("AT+CCFC=%d,%d,\"%s\",%d,%d", reason, mode, forwarding->number, num_type, classx);
2077         else // other opcode does not need num field
2078                 tmp_str = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
2079
2080         if (forwarding->mode == SS_CF_MODE_CFNRy) {
2081                 // add time info to 'no reply' case
2082                 time = (int) (forwarding->time);
2083                 cmd_str = g_strdup_printf("%s,,,%d", tmp_str, time);
2084         } else {
2085                 cmd_str = g_strdup_printf("%s", tmp_str);
2086         }
2087
2088         dbg("request command : %s", cmd_str);
2089         pending = tcore_pending_new(o, 0);
2090         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2091         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2092
2093         tcore_pending_set_request_data(pending, 0, req);
2094
2095         user_data->flavor_type = forwarding->mode;
2096         user_data->class = forwarding->class;
2097
2098         ret = _ss_request_message(pending, o, ur, on_response_ss_forwarding_set, user_data);
2099
2100         g_free(tmp_str);
2101         g_free(cmd_str);
2102
2103         if (!ret) {
2104                 dbg("AT request sent failed ");
2105                 if (user_data != NULL) {
2106                         g_free(user_data);
2107                 }
2108                 return TCORE_RETURN_FAILURE;
2109         }
2110
2111         return TCORE_RETURN_SUCCESS;
2112 }
2113
2114 static TReturn _ss_forwarding_get(CoreObject *o,
2115                                                                   UserRequest *ur,
2116                                                                   enum telephony_ss_class class,
2117                                                                   enum telephony_ss_forwarding_mode type,
2118                                                                   enum tcore_response_command resp)
2119 {
2120         struct ss_confirm_info *user_data = 0;
2121         gboolean ret = FALSE;
2122         char *cmd_str = NULL;
2123         int reason = 0, mode = 0, classx = 0;
2124         TcorePending *pending = NULL;
2125         TcoreATRequest *req;
2126
2127         dbg("function enter");
2128
2129         switch (type) {
2130         case SS_CF_MODE_CFU:
2131                 reason = 0;
2132                 break;
2133
2134         case SS_CF_MODE_CFB:
2135                 reason = 1;
2136                 break;
2137
2138         case SS_CF_MODE_CFNRy:
2139                 reason = 2;
2140                 break;
2141
2142         case SS_CF_MODE_CFNRc:
2143                 reason = 3;
2144                 break;
2145
2146         case SS_CF_MODE_CF_ALL:
2147                 reason = 4;
2148                 break;
2149
2150         case SS_CF_MODE_CFC:
2151                 reason = 5;
2152                 break;
2153
2154         default:
2155                 dbg("unsupported reason : %d");
2156                 break;
2157         }
2158         dbg("reason  = %d", reason);
2159
2160         switch (class) {
2161         case SS_CLASS_ALL_TELE:
2162                 classx = 7;
2163                 break;
2164
2165         case SS_CLASS_VOICE:
2166                 classx = 1;
2167                 break;
2168
2169         case SS_CLASS_ALL_DATA_TELE:
2170                 classx = 2;
2171                 break;
2172
2173         case SS_CLASS_FAX:
2174                 classx = 4;
2175                 break;
2176
2177         case SS_CLASS_SMS:
2178                 classx = 8;
2179                 break;
2180
2181         case SS_CLASS_ALL_CS_SYNC:
2182                 classx = 16;
2183                 break;
2184
2185         default:
2186                 classx = 7;
2187                 dbg("unsupported class %d. set to default : 7", class);
2188                 break;
2189         }
2190
2191         dbg("classx  = %d", classx);
2192
2193         // query status - mode set to 2
2194         mode = 2;
2195         user_data = g_new0(struct ss_confirm_info, 1);
2196         if (!user_data) {
2197                 dbg("[ error ] failed to allocate memory");
2198                 return TCORE_RETURN_ENOMEM;
2199         }
2200         user_data->resp = resp;
2201         user_data->class = class;
2202         user_data->flavor_type = type;
2203
2204         if (classx == 7)
2205                 cmd_str = g_strdup_printf("AT+CCFC=%d,%d", reason, mode);
2206         else
2207                 cmd_str = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
2208
2209         dbg("request command : %s", cmd_str);
2210
2211         pending = tcore_pending_new(o, 0);
2212         req = tcore_at_request_new(cmd_str, "+CCFC", TCORE_AT_MULTILINE);
2213         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2214
2215         tcore_pending_set_request_data(pending, 0, req);
2216
2217         ret = _ss_request_message(pending, o, ur, on_response_ss_forwarding_get, user_data);
2218         g_free(cmd_str);
2219
2220         if (!ret) {
2221                 dbg("AT request sent failed ");
2222                 if (user_data != NULL) {
2223                         g_free(user_data);
2224                         tcore_pending_free(pending);
2225                         tcore_at_request_free(req);
2226                 }
2227                 return TCORE_RETURN_FAILURE;
2228         }
2229
2230         return TCORE_RETURN_SUCCESS;
2231 }
2232
2233 static TReturn imc_ss_forwarding_activate(CoreObject *o, UserRequest *ur)
2234 {
2235         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2236                 dbg("cp not ready/n");
2237                 return TCORE_RETURN_ENOSYS;
2238         }
2239         return _ss_forwarding_set(o, ur, SS_OPCO_ACTIVATE);
2240 }
2241
2242 static TReturn imc_ss_forwarding_deactivate(CoreObject *o, UserRequest *ur)
2243 {
2244         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2245                 dbg("cp not ready/n");
2246                 return TCORE_RETURN_ENOSYS;
2247         }
2248         return _ss_forwarding_set(o, ur, SS_OPCO_DEACTIVATE);
2249 }
2250
2251 static TReturn imc_ss_forwarding_register(CoreObject *o, UserRequest *ur)
2252 {
2253         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2254                 dbg("cp not ready/n");
2255                 return TCORE_RETURN_ENOSYS;
2256         }
2257         return _ss_forwarding_set(o, ur, SS_OPCO_REG);
2258 }
2259
2260 static TReturn imc_ss_forwarding_deregister(CoreObject *o, UserRequest *ur)
2261 {
2262         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2263                 dbg("cp not ready/n");
2264                 return TCORE_RETURN_ENOSYS;
2265         }
2266         return _ss_forwarding_set(o, ur, SS_OPCO_DEREG);
2267 }
2268
2269 static TReturn imc_ss_forwarding_get_status(CoreObject *o, UserRequest *ur)
2270 {
2271         struct treq_ss_forwarding *forwarding = 0;
2272
2273         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2274                 dbg("cp not ready/n");
2275                 return TCORE_RETURN_ENOSYS;
2276         }
2277
2278         forwarding = (struct treq_ss_forwarding *) tcore_user_request_ref_data(ur, 0);
2279
2280         return _ss_forwarding_get(o, ur, forwarding->class, forwarding->mode, TRESP_SS_FORWARDING_GET_STATUS);
2281 }
2282
2283
2284 static TReturn _ss_waiting_set(CoreObject *o, UserRequest *ur, enum telephony_ss_opcode opco)
2285 {
2286         struct treq_ss_waiting *waiting = 0;
2287         struct ss_confirm_info *user_data = 0;
2288         gboolean ret = FALSE;
2289         int mode = 0, classx = 0;
2290         char *cmd_str;
2291         TcorePending *pending = NULL;
2292         TcoreATRequest *req;
2293
2294         dbg("function enter ");
2295         waiting = (struct treq_ss_waiting *) tcore_user_request_ref_data(ur, 0);
2296         user_data = g_new0(struct ss_confirm_info, 1);
2297         if (!user_data) {
2298                 dbg("[ error ] failed to allocate memory");
2299                 return TCORE_RETURN_ENOMEM;
2300         }
2301
2302         if (opco == SS_OPCO_ACTIVATE) {
2303                 user_data->resp = TRESP_SS_WAITING_ACTIVATE;
2304                 mode = 1; // enable
2305         } else if (opco == SS_OPCO_DEACTIVATE) {
2306                 user_data->resp = TRESP_SS_WAITING_DEACTIVATE;
2307                 mode = 0; // disable
2308         } else
2309                 dbg("[ error ] unknown ss mode (0x%x)", opco);
2310
2311         switch (waiting->class) {
2312         case SS_CLASS_ALL_TELE:
2313                 classx = 7;
2314                 break;
2315
2316         case SS_CLASS_VOICE:
2317                 classx = 1;
2318                 break;
2319
2320         case SS_CLASS_ALL_DATA_TELE:
2321                 classx = 2;
2322                 break;
2323
2324         case SS_CLASS_FAX:
2325                 classx = 4;
2326                 break;
2327
2328         case SS_CLASS_SMS:
2329                 classx = 8;
2330                 break;
2331
2332         default:
2333                 classx = 1;
2334                 dbg("unsupported class %d. set to default : 1", waiting->class);
2335                 break;
2336         }
2337         dbg("mode = %d classxx- %d", mode, classx);
2338
2339         user_data->class = waiting->class;
2340         user_data->flavor_type = (int) opco;
2341
2342         cmd_str = g_strdup_printf("AT+CCWA=1,%d,%d", mode, classx); // always enable +CCWA: unsolicited cmd
2343         dbg("request command : %s", cmd_str);
2344
2345         pending = tcore_pending_new(o, 0);
2346         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2347         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2348
2349         tcore_pending_set_request_data(pending, 0, req);
2350
2351         ret = _ss_request_message(pending, o, ur, on_response_ss_waiting_set, user_data);
2352         g_free(cmd_str);
2353         if (!ret) {
2354                 dbg("AT request sent failed ");
2355                 if (user_data != NULL) {
2356                         g_free(user_data);
2357                         tcore_pending_free(pending);
2358                         tcore_at_request_free(req);
2359                 }
2360                 return TCORE_RETURN_FAILURE;
2361         }
2362         return TCORE_RETURN_SUCCESS;
2363 }
2364
2365 static TReturn _ss_waiting_get(CoreObject *o,
2366                                                            UserRequest *ur,
2367                                                            enum telephony_ss_class class,
2368                                                            enum tcore_response_command resp)
2369 {
2370         struct ss_confirm_info *user_data = 0;
2371         gboolean ret = FALSE;
2372         int classx; // mode,
2373         char *cmd_str;
2374         TcorePending *pending = NULL;
2375         TcoreATRequest *req;
2376
2377         dbg("function  enter");
2378         switch (class) {
2379         case SS_CLASS_ALL_TELE:
2380                 classx = 7;
2381                 break;
2382
2383         case SS_CLASS_VOICE:
2384                 classx = 1;
2385                 break;
2386
2387         case SS_CLASS_ALL_DATA_TELE:
2388                 classx = 2;
2389                 break;
2390
2391         case SS_CLASS_FAX:
2392                 classx = 4;
2393                 break;
2394
2395         case SS_CLASS_SMS:
2396                 classx = 8;
2397                 break;
2398
2399         default:
2400                 classx = 7;
2401                 dbg("unsupported class %d. set to default : 7", class);
2402                 break;
2403         }
2404         dbg("classx - %d", classx);
2405
2406         dbg("allocating user data");
2407         user_data = g_new0(struct ss_confirm_info, 1);
2408         if (!user_data) {
2409                 dbg("[ error ] failed to allocate memory");
2410                 return TCORE_RETURN_ENOMEM;
2411         }
2412         user_data->resp = resp;
2413         user_data->class = class;
2414
2415         cmd_str = g_strdup_printf("AT+CCWA=1,2,%d", classx); // always enable +CCWA: unsolicited cmd , mode is fixed to 2(query status)
2416         dbg("request cmd : %s", cmd_str);
2417
2418         pending = tcore_pending_new(o, 0);
2419         req = tcore_at_request_new(cmd_str, "+CCWA", TCORE_AT_MULTILINE);
2420         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2421
2422         tcore_pending_set_request_data(pending, 0, req);
2423
2424         ret = _ss_request_message(pending, o, ur, on_response_ss_waiting_get, user_data);
2425         g_free(cmd_str);
2426         if (!ret) {
2427                 dbg("AT request sent failed ");
2428                 if (user_data != NULL) {
2429                         g_free(user_data);
2430                         tcore_pending_free(pending);
2431                         tcore_at_request_free(req);
2432                 }
2433                 return TCORE_RETURN_FAILURE;
2434         }
2435         return TCORE_RETURN_SUCCESS;
2436 }
2437
2438 static TReturn imc_ss_waiting_activate(CoreObject *o, UserRequest *ur)
2439 {
2440         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2441                 dbg("cp not ready/n");
2442                 return TCORE_RETURN_ENOSYS;
2443         }
2444         return _ss_waiting_set(o, ur, SS_OPCO_ACTIVATE);
2445 }
2446
2447 static TReturn imc_ss_waiting_deactivate(CoreObject *o, UserRequest *ur)
2448 {
2449         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2450                 dbg("cp not ready/n");
2451                 return TCORE_RETURN_ENOSYS;
2452         }
2453         return _ss_waiting_set(o, ur, SS_OPCO_DEACTIVATE);
2454 }
2455
2456 static TReturn imc_ss_waiting_get_status(CoreObject *o, UserRequest *ur)
2457 {
2458         struct treq_ss_waiting *waiting = 0;
2459
2460         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2461                 dbg("cp not ready/n");
2462                 return TCORE_RETURN_ENOSYS;
2463         }
2464         waiting = (struct treq_ss_waiting *) tcore_user_request_ref_data(ur, 0);
2465
2466         return _ss_waiting_get(o, ur, waiting->class, TRESP_SS_WAITING_GET_STATUS);
2467 }
2468
2469 static TReturn imc_ss_cli_activate(CoreObject *o, UserRequest *ur)
2470 {
2471         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2472                 dbg("cp not ready/n");
2473                 return TCORE_RETURN_ENOSYS;
2474         }
2475         return TCORE_RETURN_SUCCESS;
2476 }
2477
2478 static TReturn imc_ss_cli_deactivate(CoreObject *o, UserRequest *ur)
2479 {
2480         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2481                 dbg("cp not ready/n");
2482                 return TCORE_RETURN_ENOSYS;
2483         }
2484         return TCORE_RETURN_SUCCESS;
2485 }
2486
2487 static TReturn imc_ss_cli_get_status(CoreObject *o, UserRequest *ur)
2488 {
2489         struct treq_ss_cli *cli = 0;
2490         gboolean ret = FALSE;
2491         char *cmd_prefix = NULL, *rsp_prefix = NULL, *cmd_str = NULL;
2492         enum  telephony_ss_cli_type *user_data = 0;
2493         TcorePending *pending = NULL;
2494         TcoreATRequest *req;
2495
2496         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2497                 dbg("cp not ready/n");
2498                 return TCORE_RETURN_ENOSYS;
2499         }
2500
2501         cli = (struct treq_ss_cli *) tcore_user_request_ref_data(ur, 0);
2502         switch (cli->type) {
2503         case SS_CLI_TYPE_CLIP:
2504                 cmd_prefix = "+CLIP";
2505                 rsp_prefix = "+CLIP";
2506                 break;
2507
2508         case SS_CLI_TYPE_CLIR:
2509                 cmd_prefix = "+CLIR";
2510                 rsp_prefix = "+CLIR";
2511                 break;
2512
2513         case SS_CLI_TYPE_COLP:
2514                 cmd_prefix = "+COLP";
2515                 rsp_prefix = "+COLP";
2516                 break;
2517
2518         case SS_CLI_TYPE_COLR:
2519                 cmd_prefix = "+COLR";
2520                 rsp_prefix = "+COLR";
2521                 break;
2522
2523         case SS_CLI_TYPE_CNAP:
2524                 cmd_prefix = "+CNAP";
2525                 rsp_prefix = "+CNAP";
2526                 break;
2527
2528         case SS_CLI_TYPE_CDIP:
2529         default:
2530                 dbg("unsupported cli_type : %d", cli->type);
2531                 return TCORE_RETURN_FAILURE;
2532                 break;
2533         }
2534         dbg("cmd_prefix : %s", cmd_prefix);
2535
2536         cmd_str = g_strdup_printf("AT%s?", cmd_prefix);
2537         dbg("request cmd : %s", cmd_str);
2538
2539         user_data = g_new0(enum telephony_ss_cli_type, 1);
2540         if (!user_data) {
2541                 dbg("[ error ] failed to allocate memory");
2542                 g_free(cmd_str);
2543                 return TCORE_RETURN_ENOMEM;
2544         }
2545         *user_data = cli->type;
2546
2547         pending = tcore_pending_new(o, 0);
2548
2549         req = tcore_at_request_new(cmd_str, rsp_prefix, TCORE_AT_SINGLELINE);
2550         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2551         tcore_pending_set_request_data(pending, 0, req);
2552
2553         ret = _ss_request_message(pending, o, ur, on_response_ss_cli_get, user_data);
2554         g_free(cmd_str);
2555         if (!ret) {
2556                 dbg("AT request sent failed ");
2557                 if (user_data != NULL) {
2558                         g_free(user_data);
2559                         tcore_pending_free(pending);
2560                         tcore_at_request_free(req);
2561                 }
2562                 return TCORE_RETURN_FAILURE;
2563         }
2564         return TCORE_RETURN_SUCCESS;
2565 }
2566
2567 static TReturn imc_ss_send_ussd(CoreObject *o, UserRequest *ur)
2568 {
2569         UssdSession *ussd_s = 0;
2570         struct treq_ss_ussd *ussd = 0;
2571         struct ss_confirm_info *user_data = 0;
2572         gboolean ret = FALSE;
2573         char *cmd_str;
2574         TcorePending *pending = NULL;
2575         TcoreATRequest *req;
2576
2577         dbg("function enter");
2578
2579         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2580                 dbg("cp not ready/n");
2581                 return TCORE_RETURN_ENOSYS;
2582         }
2583
2584         ussd = (struct treq_ss_ussd *) tcore_user_request_ref_data(ur, 0);
2585
2586         user_data = g_new0(struct ss_confirm_info, 1);
2587
2588         user_data->resp = TRESP_SS_SEND_USSD;
2589         ussd_s = tcore_ss_ussd_get_session(o);
2590         if (!ussd_s) {
2591                 dbg("USSD session does not  exist");
2592                 tcore_ss_ussd_create_session(o, (enum tcore_ss_ussd_type) ussd->type, (void *) tcore_user_request_ref(ur), 0);
2593         } else {
2594                 if (ussd->type == SS_USSD_TYPE_USER_INITIATED) {
2595                         dbg("[ error ] ussd session is already exist");
2596                         g_free(user_data);
2597                         return TCORE_RETURN_FAILURE;
2598                 }
2599
2600                 tcore_ss_ussd_set_session_type(ussd_s, (enum tcore_ss_ussd_type) ussd->type);
2601         }
2602
2603         cmd_str = g_strdup_printf("AT+CUSD=1,\"%s\",%d", ussd->str, 0x0f); // always enable +CUSD: unsolicited cmd. set to dcs to 0x0f. only supports HEX type
2604         dbg("request command : %s", cmd_str);
2605
2606         pending = tcore_pending_new(o, 0);
2607         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2608         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2609
2610         tcore_pending_set_request_data(pending, 0, req);
2611
2612         ret = _ss_request_message(pending, o, ur, on_confirmation_ss_ussd, user_data);
2613         g_free(cmd_str);
2614
2615         if (!ret) {
2616                 dbg("AT request sent failed ");
2617                 if (user_data != NULL) {
2618                         g_free(user_data);
2619                         tcore_pending_free(pending);
2620                         tcore_at_request_free(req);
2621                 }
2622                 return TCORE_RETURN_FAILURE;
2623         }
2624         return TCORE_RETURN_SUCCESS;
2625 }
2626
2627 static TReturn imc_ss_set_aoc(CoreObject *o, UserRequest *ur)
2628 {
2629         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2630                 dbg("cp not ready/n");
2631                 return TCORE_RETURN_ENOSYS;
2632         }
2633
2634         dbg("[ error ] unsupported function");
2635         return TCORE_RETURN_SUCCESS;
2636 }
2637
2638 static TReturn imc_ss_get_aoc(CoreObject *o, UserRequest *ur)
2639 {
2640         if(FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))){
2641                 dbg("cp not ready/n");
2642                 return TCORE_RETURN_ENOSYS;
2643         }
2644
2645         dbg("[ error ] unsupported function");
2646         return TCORE_RETURN_SUCCESS;
2647 }
2648
2649
2650 static struct tcore_call_control_operations call_ops = {
2651         .answer_hold_and_accept = imc_ss_manage_call_2_send,
2652         .answer_replace = imc_ss_manage_call_1_send,
2653         .answer_reject = imc_ss_manage_call_0_send,
2654         .end_specific = imc_ss_manage_call_1x_send,
2655         .end_all_active = imc_ss_manage_call_1_send,
2656         .end_all_held = imc_ss_manage_call_0_send,
2657         .active = imc_ss_manage_call_2_send,
2658         .hold = imc_ss_manage_call_2_send,
2659         .swap = imc_ss_manage_call_2_send,
2660         .join = imc_ss_manage_call_3_send,
2661         .split = imc_ss_manage_call_2x_send,
2662         .transfer = imc_ss_manage_call_4_send,
2663         .deflect = imc_ss_manage_call_4dn_send,
2664 };
2665
2666 static TReturn imc_ss_manage_call_send(CoreObject *o, UserRequest *ur, const char *cmd, ConfirmCallback cb, void *user_data)
2667 {
2668         TcorePending *pending = NULL;
2669         TcoreATRequest *req;
2670         gboolean ret = FALSE;
2671
2672         pending = tcore_pending_new(o, 0);
2673         req = tcore_at_request_new(cmd, NULL, TCORE_AT_NO_RESULT);
2674         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2675         tcore_pending_set_request_data(pending, 0, req);
2676
2677         ret = _ss_request_message(pending, o, ur, (TcorePendingResponseCallback) cb, user_data);
2678         if (!ret) {
2679                 dbg("AT request sent failed ");
2680                 return TCORE_RETURN_FAILURE;
2681         }
2682         return TCORE_RETURN_SUCCESS;
2683 }
2684
2685 static TReturn imc_ss_manage_call_0_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2686 {
2687         char *cmd_str = NULL;
2688         gboolean ret = FALSE;
2689
2690         dbg("function enter");
2691         cmd_str = g_strdup_printf("%s", "AT+CHLD=0");
2692         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2693
2694         ret = imc_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2695         g_free(cmd_str);
2696         return ret;
2697 }
2698
2699 static TReturn imc_ss_manage_call_1_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2700 {
2701         char *cmd_str = NULL;
2702         gboolean ret = FALSE;
2703
2704         dbg("function enter");
2705         cmd_str = g_strdup_printf("%s", "AT+CHLD=1");
2706         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2707
2708         ret = imc_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2709         g_free(cmd_str);
2710         return ret;
2711 }
2712
2713 static TReturn imc_ss_manage_call_1x_send(CoreObject *o, UserRequest *ur, const int id, ConfirmCallback cb, void *user_data)
2714 {
2715         char *cmd_str = NULL;
2716         gboolean ret = FALSE;
2717
2718         dbg("function enter");
2719         cmd_str = g_strdup_printf("%s%d", "AT+CHLD=1", id);
2720         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2721
2722         ret = imc_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2723         g_free(cmd_str);
2724         return ret;
2725 }
2726
2727 static TReturn imc_ss_manage_call_2_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2728 {
2729         char *cmd_str = NULL;
2730         gboolean ret = FALSE;
2731
2732         dbg("function enter");
2733         cmd_str = g_strdup_printf("%s", "AT+CHLD=2");
2734         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2735
2736         ret = imc_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2737         g_free(cmd_str);
2738         return ret;
2739 }
2740
2741 static TReturn imc_ss_manage_call_2x_send(CoreObject *o, UserRequest *ur, const int id, ConfirmCallback cb, void *user_data)
2742 {
2743         char *cmd_str = NULL;
2744         gboolean ret = FALSE;
2745
2746         dbg("function enter");
2747         cmd_str = g_strdup_printf("%s%d", "AT+CHLD=2", id);
2748         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2749
2750         ret = imc_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2751         g_free(cmd_str);
2752         return ret;
2753 }
2754
2755 static TReturn imc_ss_manage_call_3_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2756 {
2757         char *cmd_str = NULL;
2758         gboolean ret = FALSE;
2759
2760         dbg("function enter");
2761         cmd_str = g_strdup_printf("%s", "AT+CHLD=3");
2762
2763         ret = imc_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2764         g_free(cmd_str);
2765         return ret;
2766 }
2767
2768
2769 static TReturn imc_ss_manage_call_4_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2770 {
2771         char *cmd_str = NULL;
2772         gboolean ret = FALSE;
2773
2774         dbg("function enter");
2775         cmd_str = g_strdup_printf("%s", "AT+CHLD=4");
2776
2777         ret = imc_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2778         g_free(cmd_str);
2779         return ret;
2780 }
2781
2782 static TReturn imc_ss_manage_call_4dn_send(CoreObject *o, UserRequest *ur, const char *number, ConfirmCallback cb, void *user_data)
2783 {
2784         char *cmd_str = NULL;
2785         gboolean ret = FALSE;
2786
2787         dbg("function enter");
2788         cmd_str = g_strdup_printf("%s%s", "AT+CHLD=4", number);
2789
2790         ret = imc_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2791         g_free(cmd_str);
2792
2793         return ret;
2794 }
2795
2796 gboolean imc_ss_init(TcorePlugin *cp, CoreObject *co_ss)
2797 {
2798         CoreObject *co_call = NULL;
2799
2800         /* Set operations */
2801         tcore_ss_set_ops(co_ss, &ss_ops);
2802
2803
2804         co_call = tcore_plugin_ref_core_object(cp,
2805                                                 CORE_OBJECT_TYPE_CALL);
2806         if (co_call == NULL) {
2807                 err("Can't find CALL core object");
2808                 return FALSE;
2809         }
2810
2811         /* Set operations */
2812         tcore_call_control_set_operations(co_call, &call_ops);
2813
2814         tcore_object_add_callback(co_ss, "+CSSU", on_notification_ss_info, NULL);
2815         tcore_object_add_callback(co_ss, "+CSSI", on_notification_ss_info, NULL);
2816         tcore_object_add_callback(co_ss, "+CUSD", on_notification_ss_ussd, NULL);
2817
2818         return TRUE;
2819 }
2820
2821 void imc_ss_exit(TcorePlugin *cp, CoreObject *co_ss)
2822 {
2823         dbg("Exit");
2824 }