Revert manifest to default one
[framework/telephony/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         char old_password[MAX_SS_BARRING_PASSWORD_LEN + 1];
1796         char new_password[MAX_SS_BARRING_PASSWORD_LEN + 1];
1797
1798         dbg("function enter");
1799         barring = (struct treq_ss_barring_change_password *) tcore_user_request_ref_data(ur, 0);
1800
1801         if (barring->password_old == NULL || barring->password_new == NULL) {
1802                 dbg("[error]password is null");
1803                 return TCORE_RETURN_FAILURE;
1804         }
1805         memcpy(old_password, barring->password_old, MAX_SS_BARRING_PASSWORD_LEN);
1806         old_password[MAX_SS_BARRING_PASSWORD_LEN] = '\0';
1807         memcpy(new_password, barring->password_new, MAX_SS_BARRING_PASSWORD_LEN);
1808         new_password[MAX_SS_BARRING_PASSWORD_LEN] = '\0';
1809
1810         dbg("old passwd - %s new passwd- %s", old_password, new_password);
1811         cmd_str = g_strdup_printf("AT+CPWD=\"%s\",\"%s\",\"%s\"", "AB", old_password, new_password);
1812         dbg("request command : %s", cmd_str);
1813
1814         hal = tcore_object_get_hal(o);
1815         pending = tcore_pending_new(o, 0);
1816         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
1817         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
1818
1819         tcore_pending_set_request_data(pending, 0, req);
1820
1821         user_data = g_new0(struct ss_confirm_info, 1);
1822         user_data->resp = TRESP_SS_BARRING_CHANGE_PASSWORD;
1823
1824         ret = _ss_request_message(pending, o, ur, on_response_ss_barring_change_pwd, user_data);
1825         g_free(cmd_str);
1826         if (!ret) {
1827                 dbg("AT request sent failed ")
1828                 return TCORE_RETURN_FAILURE;
1829         }
1830         return TCORE_RETURN_SUCCESS;
1831 }
1832
1833 static TReturn s_ss_barring_get_status(CoreObject *o, UserRequest *ur)
1834 {
1835         struct treq_ss_barring *barring = 0;
1836         barring = (struct treq_ss_barring *) tcore_user_request_ref_data(ur, 0);
1837
1838         return _ss_barring_get(o, ur, barring->class, barring->mode, TRESP_SS_BARRING_GET_STATUS);
1839 }
1840
1841 static TReturn _ss_forwarding_set(CoreObject *o, UserRequest *ur, enum telephony_ss_opcode op)
1842 {
1843         struct treq_ss_forwarding *forwarding = 0;
1844         struct ss_confirm_info *user_data = 0;
1845         gboolean ret = FALSE;
1846         int len = 0;
1847         char *cmd_str = NULL;
1848         char *tmp_str = NULL;
1849         int reason = 0, mode = 0, num_type = 0, classx = 0, time = 0;
1850         gboolean valid_num = FALSE;
1851         TcoreHal *hal;
1852         TcorePending *pending = NULL;
1853         TcoreATRequest *req;
1854
1855         dbg("_ss_forwarding_set with opco %d ", op);
1856
1857         forwarding = (struct treq_ss_forwarding *) tcore_user_request_ref_data(ur, 0);
1858         switch (forwarding->mode) {
1859         case SS_CF_MODE_CFU:
1860                 reason = 0;
1861                 break;
1862
1863         case SS_CF_MODE_CFB:
1864                 reason = 1;
1865                 break;
1866
1867         case SS_CF_MODE_CFNRy:
1868                 reason = 2;
1869                 break;
1870
1871         case SS_CF_MODE_CFNRc:
1872                 reason = 3;
1873                 break;
1874
1875         case SS_CF_MODE_CF_ALL:
1876                 reason = 4;
1877                 break;
1878
1879         case SS_CF_MODE_CFC:
1880                 reason = 5;
1881                 break;
1882
1883         default:
1884                 dbg("unsupported reason : %d");
1885                 return TCORE_RETURN_FAILURE;
1886                 break;
1887         }
1888
1889         dbg("reason = %d", reason);
1890         switch (op) {
1891         case SS_OPCO_DEACTIVATE:
1892                 mode = 0;
1893                 break;
1894
1895         case SS_OPCO_ACTIVATE:
1896                 mode = 1;
1897                 break;
1898
1899         case SS_OPCO_REG:
1900                 mode = 3;
1901                 break;
1902
1903         case SS_OPCO_DEREG:
1904                 mode = 4;
1905                 break;
1906
1907         default:
1908                 dbg("unsupported opco : %d", op);
1909                 return TCORE_RETURN_FAILURE;
1910         }
1911
1912         dbg("mode = %d", mode);
1913
1914         // class
1915         switch (forwarding->class) {
1916         case SS_CLASS_ALL_TELE:
1917                 classx = 7;
1918                 break;
1919
1920         case SS_CLASS_VOICE:
1921                 classx = 1;
1922                 break;
1923
1924         case SS_CLASS_ALL_DATA_TELE:
1925                 classx = 2;
1926                 break;
1927
1928         case SS_CLASS_FAX:
1929                 classx = 4;
1930                 break;
1931
1932         case SS_CLASS_SMS:
1933                 classx = 8;
1934                 break;
1935
1936         case SS_CLASS_ALL_CS_SYNC:
1937                 classx = 16;
1938                 break;
1939
1940         default:
1941                 classx = 7;
1942                 dbg("unsupported class %d. set to default : 7", forwarding->class);
1943                 break;
1944         }
1945         dbg("classx = %d", classx);
1946
1947         // number
1948         len = strlen(forwarding->number);
1949         if (len > 0) {
1950                 valid_num = TRUE;
1951                 if (forwarding->number[0] == '+')
1952                         num_type = ((NUM_TYPE_INTERNATIONAL << 4) | NUM_PLAN_ISDN);
1953                 else
1954                         num_type = 0;
1955         }
1956         dbg("number = %s", forwarding->number);
1957
1958         user_data = g_new0(struct ss_confirm_info, 1);
1959
1960         switch (op) {
1961         case SS_OPCO_REG:
1962                 user_data->resp = TRESP_SS_FORWARDING_REGISTER;
1963                 break;
1964
1965         case SS_OPCO_DEREG:
1966                 user_data->resp = TRESP_SS_FORWARDING_DEREGISTER;
1967                 break;
1968
1969         case SS_OPCO_ACTIVATE:
1970                 user_data->resp = TRESP_SS_FORWARDING_ACTIVATE;
1971                 break;
1972
1973         case SS_OPCO_DEACTIVATE:
1974                 user_data->resp = TRESP_SS_FORWARDING_DEACTIVATE;
1975                 break;
1976
1977         default:
1978                 dbg("[ error ] unknown op (0x%x)", op);
1979                 break;
1980         }
1981
1982         if (forwarding->number[0] == '+')
1983                 num_type = 145;
1984         else
1985                 num_type = 129;
1986
1987         if (op == SS_OPCO_REG)
1988                 tmp_str = g_strdup_printf("AT+CCFC=%d,%d,\"%s\",%d,%d", reason, mode, forwarding->number, num_type, classx);
1989         else // other opcode does not need num field
1990                 tmp_str = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
1991
1992         if (forwarding->mode == SS_CF_MODE_CFNRy) {
1993                 // add time info to 'no reply' case
1994                 time = (int) (forwarding->time);
1995                 cmd_str = g_strdup_printf("%s,,,%d", tmp_str, time);
1996         } else {
1997                 cmd_str = g_strdup_printf("%s", tmp_str);
1998         }
1999
2000         dbg("request command : %s", cmd_str);
2001         hal = tcore_object_get_hal(o);
2002         pending = tcore_pending_new(o, 0);
2003         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2004         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2005
2006         tcore_pending_set_request_data(pending, 0, req);
2007
2008         user_data->flavor_type = forwarding->mode;
2009         user_data->class = forwarding->class;
2010
2011         ret = _ss_request_message(pending, o, ur, on_response_ss_forwarding_set, user_data);
2012
2013         g_free(tmp_str);
2014         g_free(cmd_str);
2015
2016         if (!ret) {
2017                 dbg("AT request sent failed ")
2018                 return TCORE_RETURN_FAILURE;
2019         }
2020
2021         return TCORE_RETURN_SUCCESS;
2022 }
2023
2024 static TReturn _ss_forwarding_get(CoreObject *o,
2025                                                                   UserRequest *ur,
2026                                                                   enum telephony_ss_class class,
2027                                                                   enum telephony_ss_forwarding_mode type,
2028                                                                   enum tcore_response_command resp)
2029 {
2030         struct ss_confirm_info *user_data = 0;
2031         gboolean ret = FALSE;
2032         char *cmd_str = NULL;
2033         int reason = 0, mode = 0, classx = 0;
2034         TcoreHal *hal;
2035         TcorePending *pending = NULL;
2036         TcoreATRequest *req;
2037
2038         dbg("function enter");
2039
2040         switch (type) {
2041         case SS_CF_MODE_CFU:
2042                 reason = 0;
2043                 break;
2044
2045         case SS_CF_MODE_CFB:
2046                 reason = 1;
2047                 break;
2048
2049         case SS_CF_MODE_CFNRy:
2050                 reason = 2;
2051                 break;
2052
2053         case SS_CF_MODE_CFNRc:
2054                 reason = 3;
2055                 break;
2056
2057         case SS_CF_MODE_CF_ALL:
2058                 reason = 4;
2059                 break;
2060
2061         case SS_CF_MODE_CFC:
2062                 reason = 5;
2063                 break;
2064
2065         default:
2066                 dbg("unsupported reason : %d");
2067                 break;
2068         }
2069         dbg("reason  = %d", reason);
2070
2071         switch (class) {
2072         case SS_CLASS_ALL_TELE:
2073                 classx = 7;
2074                 break;
2075
2076         case SS_CLASS_VOICE:
2077                 classx = 1;
2078                 break;
2079
2080         case SS_CLASS_ALL_DATA_TELE:
2081                 classx = 2;
2082                 break;
2083
2084         case SS_CLASS_FAX:
2085                 classx = 4;
2086                 break;
2087
2088         case SS_CLASS_SMS:
2089                 classx = 8;
2090                 break;
2091
2092         case SS_CLASS_ALL_CS_SYNC:
2093                 classx = 16;
2094                 break;
2095
2096         default:
2097                 classx = 7;
2098                 dbg("unsupported class %d. set to default : 7", class);
2099                 break;
2100         }
2101
2102         dbg("classx  = %d", classx);
2103
2104         // query status - mode set to 2
2105         mode = 2;
2106         user_data = g_new0(struct ss_confirm_info, 1);
2107         user_data->resp = resp;
2108         user_data->class = class;
2109         user_data->flavor_type = type;
2110
2111         if (classx == 7)
2112                 cmd_str = g_strdup_printf("AT+CCFC=%d,%d", reason, mode);
2113         else
2114                 cmd_str = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
2115
2116         dbg("request command : %s", cmd_str);
2117
2118         hal = tcore_object_get_hal(o);
2119         pending = tcore_pending_new(o, 0);
2120         req = tcore_at_request_new(cmd_str, "+CCFC", TCORE_AT_MULTILINE);
2121         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2122
2123         tcore_pending_set_request_data(pending, 0, req);
2124
2125         ret = _ss_request_message(pending, o, ur, on_response_ss_forwarding_get, user_data);
2126         g_free(cmd_str);
2127
2128         if (!ret) {
2129                 dbg("AT request sent failed ")
2130                 return TCORE_RETURN_FAILURE;
2131         }
2132
2133         return TCORE_RETURN_SUCCESS;
2134 }
2135
2136 static TReturn s_ss_forwarding_activate(CoreObject *o, UserRequest *ur)
2137 {
2138         return _ss_forwarding_set(o, ur, SS_OPCO_ACTIVATE);
2139 }
2140
2141 static TReturn s_ss_forwarding_deactivate(CoreObject *o, UserRequest *ur)
2142 {
2143         return _ss_forwarding_set(o, ur, SS_OPCO_DEACTIVATE);
2144 }
2145
2146 static TReturn s_ss_forwarding_register(CoreObject *o, UserRequest *ur)
2147 {
2148         return _ss_forwarding_set(o, ur, SS_OPCO_REG);
2149 }
2150
2151 static TReturn s_ss_forwarding_deregister(CoreObject *o, UserRequest *ur)
2152 {
2153         return _ss_forwarding_set(o, ur, SS_OPCO_DEREG);
2154 }
2155
2156 static TReturn s_ss_forwarding_get_status(CoreObject *o, UserRequest *ur)
2157 {
2158         struct treq_ss_forwarding *forwarding = 0;
2159         forwarding = (struct treq_ss_forwarding *) tcore_user_request_ref_data(ur, 0);
2160
2161         return _ss_forwarding_get(o, ur, forwarding->class, forwarding->mode, TRESP_SS_FORWARDING_GET_STATUS);
2162 }
2163
2164
2165 static TReturn _ss_waiting_set(CoreObject *o, UserRequest *ur, enum telephony_ss_opcode opco)
2166 {
2167         struct treq_ss_waiting *waiting = 0;
2168         struct ss_confirm_info *user_data = 0;
2169         gboolean ret = FALSE;
2170         int mode = 0, classx = 0;
2171         char *cmd_str;
2172         TcoreHal *hal;
2173         TcorePending *pending = NULL;
2174         TcoreATRequest *req;
2175
2176         dbg("function enter ");
2177         waiting = (struct treq_ss_waiting *) tcore_user_request_ref_data(ur, 0);
2178         user_data = g_new0(struct ss_confirm_info, 1);
2179
2180         if (opco == SS_OPCO_ACTIVATE) {
2181                 user_data->resp = TRESP_SS_WAITING_ACTIVATE;
2182                 mode = 1; // enable
2183         } else if (opco == SS_OPCO_DEACTIVATE) {
2184                 user_data->resp = TRESP_SS_WAITING_DEACTIVATE;
2185                 mode = 0; // disable
2186         } else
2187                 dbg("[ error ] unknown ss mode (0x%x)", opco);
2188
2189         switch (waiting->class) {
2190         case SS_CLASS_ALL_TELE:
2191                 classx = 7;
2192                 break;
2193
2194         case SS_CLASS_VOICE:
2195                 classx = 1;
2196                 break;
2197
2198         case SS_CLASS_ALL_DATA_TELE:
2199                 classx = 2;
2200                 break;
2201
2202         case SS_CLASS_FAX:
2203                 classx = 4;
2204                 break;
2205
2206         case SS_CLASS_SMS:
2207                 classx = 8;
2208                 break;
2209
2210         default:
2211                 classx = 1;
2212                 dbg("unsupported class %d. set to default : 1", waiting->class);
2213                 break;
2214         }
2215         dbg("mode = %d classxx- %d", mode, classx);
2216
2217         user_data->class = waiting->class;
2218         user_data->flavor_type = (int) opco;
2219
2220         cmd_str = g_strdup_printf("AT+CCWA=1,%d,%d", mode, classx); // always enable +CCWA: unsolicited cmd
2221         dbg("request command : %s", cmd_str);
2222
2223         hal = tcore_object_get_hal(o);
2224         pending = tcore_pending_new(o, 0);
2225         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2226         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2227
2228         tcore_pending_set_request_data(pending, 0, req);
2229
2230         ret = _ss_request_message(pending, o, ur, on_response_ss_waiting_set, user_data);
2231         g_free(cmd_str);
2232         if (!ret) {
2233                 dbg("AT request sent failed ")
2234                 return TCORE_RETURN_FAILURE;
2235         }
2236         return TCORE_RETURN_SUCCESS;
2237 }
2238
2239 static TReturn _ss_waiting_get(CoreObject *o,
2240                                                            UserRequest *ur,
2241                                                            enum telephony_ss_class class,
2242                                                            enum tcore_response_command resp)
2243 {
2244         struct ss_confirm_info *user_data = 0;
2245         gboolean ret = FALSE;
2246         int classx; // mode,
2247         char *cmd_str;
2248         TcoreHal *hal;
2249         TcorePending *pending = NULL;
2250         TcoreATRequest *req;
2251
2252         dbg("function  enter")
2253         switch (class) {
2254         case SS_CLASS_ALL_TELE:
2255                 classx = 7;
2256                 break;
2257
2258         case SS_CLASS_VOICE:
2259                 classx = 1;
2260                 break;
2261
2262         case SS_CLASS_ALL_DATA_TELE:
2263                 classx = 2;
2264                 break;
2265
2266         case SS_CLASS_FAX:
2267                 classx = 4;
2268                 break;
2269
2270         case SS_CLASS_SMS:
2271                 classx = 8;
2272                 break;
2273
2274         default:
2275                 classx = 7;
2276                 dbg("unsupported class %d. set to default : 7", class);
2277                 break;
2278         }
2279         dbg("classx - %d", classx);
2280
2281         dbg("allocating user data");
2282         user_data = g_new0(struct ss_confirm_info, 1);
2283         user_data->resp = resp;
2284         user_data->class = class;
2285
2286         cmd_str = g_strdup_printf("AT+CCWA=1,2,%d", classx); // always enable +CCWA: unsolicited cmd , mode is fixed to 2(query status)
2287         dbg("request cmd : %s", cmd_str);
2288
2289         hal = tcore_object_get_hal(o);
2290         pending = tcore_pending_new(o, 0);
2291         req = tcore_at_request_new(cmd_str, "+CCWA", TCORE_AT_MULTILINE);
2292         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2293
2294         tcore_pending_set_request_data(pending, 0, req);
2295
2296         ret = _ss_request_message(pending, o, ur, on_response_ss_waiting_get, user_data);
2297         g_free(cmd_str);
2298         if (!ret) {
2299                 dbg("AT request sent failed ")
2300                 return TCORE_RETURN_FAILURE;
2301         }
2302         return TCORE_RETURN_SUCCESS;
2303 }
2304
2305 static TReturn s_ss_waiting_activate(CoreObject *o, UserRequest *ur)
2306 {
2307         return _ss_waiting_set(o, ur, SS_OPCO_ACTIVATE);
2308 }
2309
2310 static TReturn s_ss_waiting_deactivate(CoreObject *o, UserRequest *ur)
2311 {
2312         return _ss_waiting_set(o, ur, SS_OPCO_DEACTIVATE);
2313 }
2314
2315 static TReturn s_ss_waiting_get_status(CoreObject *o, UserRequest *ur)
2316 {
2317         struct treq_ss_waiting *waiting = 0;
2318         waiting = (struct treq_ss_waiting *) tcore_user_request_ref_data(ur, 0);
2319
2320         return _ss_waiting_get(o, ur, waiting->class, TRESP_SS_WAITING_GET_STATUS);
2321 }
2322
2323 static TReturn s_ss_cli_activate(CoreObject *o, UserRequest *ur)
2324 {
2325         return TCORE_RETURN_SUCCESS;
2326 }
2327
2328 static TReturn s_ss_cli_deactivate(CoreObject *o, UserRequest *ur)
2329 {
2330         return TCORE_RETURN_SUCCESS;
2331 }
2332
2333 static TReturn s_ss_cli_get_status(CoreObject *o, UserRequest *ur)
2334 {
2335         struct treq_ss_cli *cli = 0;
2336         gboolean ret = FALSE;
2337         char *cmd_prefix = NULL, *rsp_prefix = NULL, *cmd_str = NULL;
2338         enum  telephony_ss_cli_type *user_data = 0;
2339         TcoreHal *hal;
2340         TcorePending *pending = NULL;
2341         TcoreATRequest *req;
2342
2343         cli = (struct treq_ss_cli *) tcore_user_request_ref_data(ur, 0);
2344         switch (cli->type) {
2345         case SS_CLI_TYPE_CLIP:
2346                 cmd_prefix = "+CLIP";
2347                 rsp_prefix = "+CLIP";
2348                 break;
2349
2350         case SS_CLI_TYPE_CLIR:
2351                 cmd_prefix = "+CLIR";
2352                 rsp_prefix = "+CLIR";
2353                 break;
2354
2355         case SS_CLI_TYPE_COLP:
2356                 cmd_prefix = "+COLP";
2357                 rsp_prefix = "+COLP";
2358                 break;
2359
2360         case SS_CLI_TYPE_COLR:
2361                 cmd_prefix = "+COLR";
2362                 rsp_prefix = "+COLR";
2363                 break;
2364
2365         case SS_CLI_TYPE_CNAP:
2366                 cmd_prefix = "+CNAP";
2367                 rsp_prefix = "+CNAP";
2368                 break;
2369
2370         case SS_CLI_TYPE_CDIP:
2371         default:
2372                 dbg("unsupported cli_type : %d", cli->type);
2373                 return TCORE_RETURN_FAILURE;
2374                 break;
2375         }
2376         dbg("cmd_prefix : %s", cmd_prefix);
2377
2378         cmd_str = g_strdup_printf("AT%s?", cmd_prefix);
2379         dbg("request cmd : %s", cmd_str);
2380
2381         user_data = g_new0(enum telephony_ss_cli_type, 1);
2382         *user_data = cli->type;
2383
2384         hal = tcore_object_get_hal(o);
2385         pending = tcore_pending_new(o, 0);
2386
2387         req = tcore_at_request_new(cmd_str, rsp_prefix, TCORE_AT_SINGLELINE);
2388         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2389         tcore_pending_set_request_data(pending, 0, req);
2390
2391         ret = _ss_request_message(pending, o, ur, on_response_ss_cli_get, user_data);
2392         g_free(cmd_str);
2393         if (!ret) {
2394                 dbg("AT request sent failed ")
2395                 return TCORE_RETURN_FAILURE;
2396         }
2397         return TCORE_RETURN_SUCCESS;
2398 }
2399
2400 static TReturn s_ss_send_ussd(CoreObject *o, UserRequest *ur)
2401 {
2402         UssdSession *ussd_s = 0;
2403         struct treq_ss_ussd *ussd = 0;
2404         struct ss_confirm_info *user_data = 0;
2405         gboolean ret = FALSE;
2406         char *cmd_str;
2407         TcoreHal *hal;
2408         TcorePending *pending = NULL;
2409         TcoreATRequest *req;
2410
2411         dbg("function enter");
2412         ussd = (struct treq_ss_ussd *) tcore_user_request_ref_data(ur, 0);
2413         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
2414         dbg("request command : %s", cmd_str);
2415
2416         user_data = g_new0(struct ss_confirm_info, 1);
2417         user_data->resp = TRESP_SS_SEND_USSD;
2418         ussd_s = tcore_ss_ussd_get_session(o);
2419         if (!ussd_s) {
2420                 dbg("USSD session does not  exist");
2421                 tcore_ss_ussd_create_session(o, (enum tcore_ss_ussd_type) ussd->type, (void *) tcore_user_request_ref(ur), 0);
2422         } else {
2423                 if (ussd->type == SS_USSD_TYPE_USER_INITIATED) {
2424                         dbg("[ error ] ussd session is already exist");
2425                         g_free(user_data);
2426                         return TCORE_RETURN_FAILURE;
2427                 }
2428
2429                 tcore_ss_ussd_set_session_type(ussd_s, (enum tcore_ss_ussd_type) ussd->type);
2430         }
2431
2432         hal = tcore_object_get_hal(o);
2433         pending = tcore_pending_new(o, 0);
2434         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2435         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2436
2437         tcore_pending_set_request_data(pending, 0, req);
2438
2439         ret = _ss_request_message(pending, o, ur, on_confirmation_ss_ussd, user_data);
2440         g_free(cmd_str);
2441
2442         if (!ret) {
2443                 dbg("AT request sent failed ")
2444                 return TCORE_RETURN_FAILURE;
2445         }
2446         return TCORE_RETURN_SUCCESS;
2447 }
2448
2449 static TReturn s_ss_set_aoc(CoreObject *o, UserRequest *ur)
2450 {
2451         dbg("[ error ] unsupported function");
2452         return TCORE_RETURN_SUCCESS;
2453 }
2454
2455 static TReturn s_ss_get_aoc(CoreObject *o, UserRequest *ur)
2456 {
2457         dbg("[ error ] unsupported function");
2458         return TCORE_RETURN_SUCCESS;
2459 }
2460
2461
2462 static struct tcore_call_control_operations call_ops = {
2463         .answer_hold_and_accept = s_ss_manage_call_2_send,
2464         .answer_replace = s_ss_manage_call_1_send,
2465         .answer_reject = s_ss_manage_call_0_send,
2466         .end_specific = s_ss_manage_call_1x_send,
2467         .end_all_active = s_ss_manage_call_1_send,
2468         .end_all_held = s_ss_manage_call_0_send,
2469         .active = s_ss_manage_call_2_send,
2470         .hold = s_ss_manage_call_2_send,
2471         .swap = s_ss_manage_call_2_send,
2472         .join = s_ss_manage_call_3_send,
2473         .split = s_ss_manage_call_2x_send,
2474         .transfer = s_ss_manage_call_4_send,
2475         .deflect = s_ss_manage_call_4dn_send,
2476 };
2477
2478 static TReturn s_ss_manage_call_send(CoreObject *o, UserRequest *ur, const char *cmd, ConfirmCallback cb, void *user_data)
2479 {
2480         TcorePending *pending = NULL;
2481         TcoreATRequest *req;
2482         gboolean ret = FALSE;
2483
2484         pending = tcore_pending_new(o, 0);
2485         req = tcore_at_request_new(cmd, NULL, TCORE_AT_NO_RESULT);
2486         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2487         tcore_pending_set_request_data(pending, 0, req);
2488
2489         ret = _ss_request_message(pending, o, ur, (TcorePendingResponseCallback) cb, user_data);
2490         if (!ret) {
2491                 dbg("AT request sent failed ")
2492                 return TCORE_RETURN_FAILURE;
2493         }
2494         return TCORE_RETURN_SUCCESS;
2495 }
2496
2497 static TReturn s_ss_manage_call_0_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2498 {
2499         char *cmd_str = NULL;
2500         gboolean ret = FALSE;
2501
2502         dbg("function enter");
2503         cmd_str = g_strdup_printf("%s", "AT+CHLD=0");
2504         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2505
2506         ret = s_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2507         g_free(cmd_str);
2508         return ret;
2509 }
2510
2511 static TReturn s_ss_manage_call_1_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2512 {
2513         char *cmd_str = NULL;
2514         gboolean ret = FALSE;
2515
2516         dbg("function enter");
2517         cmd_str = g_strdup_printf("%s", "AT+CHLD=1");
2518         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2519
2520         ret = s_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2521         g_free(cmd_str);
2522         return ret;
2523 }
2524
2525 static TReturn s_ss_manage_call_1x_send(CoreObject *o, UserRequest *ur, const int id, ConfirmCallback cb, void *user_data)
2526 {
2527         char *cmd_str = NULL;
2528         gboolean ret = FALSE;
2529
2530         dbg("function enter");
2531         cmd_str = g_strdup_printf("%s%d", "AT+CHLD=1", id);
2532         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2533
2534         ret = s_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2535         g_free(cmd_str);
2536         return ret;
2537 }
2538
2539 static TReturn s_ss_manage_call_2_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2540 {
2541         char *cmd_str = NULL;
2542         gboolean ret = FALSE;
2543
2544         dbg("function enter");
2545         cmd_str = g_strdup_printf("%s", "AT+CHLD=2");
2546         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2547
2548         ret = s_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2549         g_free(cmd_str);
2550         return ret;
2551 }
2552
2553 static TReturn s_ss_manage_call_2x_send(CoreObject *o, UserRequest *ur, const int id, ConfirmCallback cb, void *user_data)
2554 {
2555         char *cmd_str = NULL;
2556         gboolean ret = FALSE;
2557
2558         dbg("function enter");
2559         cmd_str = g_strdup_printf("%s%d", "AT+CHLD=2", id);
2560         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d", cmd_str, "N/A", strlen(cmd_str));
2561
2562         ret = s_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2563         g_free(cmd_str);
2564         return ret;
2565 }
2566
2567 static TReturn s_ss_manage_call_3_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2568 {
2569         char *cmd_str = NULL;
2570         gboolean ret = FALSE;
2571
2572         dbg("function enter");
2573         cmd_str = g_strdup_printf("%s", "AT+CHLD=3");
2574
2575         ret = s_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2576         g_free(cmd_str);
2577         return ret;
2578 }
2579
2580
2581 static TReturn s_ss_manage_call_4_send(CoreObject *o, UserRequest *ur, ConfirmCallback cb, void *user_data)
2582 {
2583         char *cmd_str = NULL;
2584         gboolean ret = FALSE;
2585
2586         dbg("function enter");
2587         cmd_str = g_strdup_printf("%s", "AT+CHLD=4");
2588
2589         ret = s_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2590         g_free(cmd_str);
2591         return ret;
2592 }
2593
2594 static TReturn s_ss_manage_call_4dn_send(CoreObject *o, UserRequest *ur, const char *number, ConfirmCallback cb, void *user_data)
2595 {
2596         char *cmd_str = NULL;
2597         gboolean ret = FALSE;
2598
2599         dbg("function enter");
2600         cmd_str = g_strdup_printf("%s%s", "AT+CHLD=4", number);
2601
2602         ret = s_ss_manage_call_send(o, ur, cmd_str, cb, user_data);
2603         g_free(cmd_str);
2604
2605         return ret;
2606 }
2607
2608 gboolean s_ss_init(TcorePlugin *p, TcoreHal *h)
2609 {
2610         CoreObject *so = 0, *co = 0;
2611         struct property_call_info *data = 0;
2612
2613         so = tcore_ss_new(p, "ss", &ss_ops, h);
2614         if (!so) {
2615                 dbg("[ error ] ss_new()");
2616                 return FALSE;
2617         }
2618
2619         co = tcore_plugin_ref_core_object(p, "call");
2620         if (!co) {
2621                 dbg("[ error ] plugin_ref_core_object");
2622                 return FALSE;
2623         }
2624
2625         tcore_call_control_set_operations(co, &call_ops);
2626
2627         tcore_object_add_callback(so, "+CSSU", on_notification_ss_info, 0);
2628         tcore_object_add_callback(so, "+CSSI", on_notification_ss_info, 0);
2629         tcore_object_add_callback(so, "+CUSD", on_notification_ss_ussd, 0);
2630
2631         data = calloc(sizeof(struct property_call_info *), 1);
2632         tcore_plugin_link_property(p, "SS", data);
2633
2634         return TRUE;
2635 }
2636
2637 void s_ss_exit(TcorePlugin *p)
2638 {
2639         CoreObject *o;
2640         struct property_network_info *data;
2641
2642         o = tcore_plugin_ref_core_object(p, "ss");
2643
2644         data = tcore_plugin_ref_property(p, "SS");
2645         if (data)
2646                 free(data);
2647
2648         tcore_ss_free(o);
2649 }