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