Fix telephony crash when SIM has invalid message
[platform/core/telephony/tel-plugin-imc.git] / src / s_call.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 <storage.h>
33 #include <co_call.h>
34 #include <user_request.h>
35 #include <server.h>
36 #include <at.h>
37
38 #include "s_common.h"
39 #include "s_call.h"
40
41
42 #define STATUS_INCOMING    4
43 #define STATUS_WAITING     5
44 #define STATUS_CONNECTED   7
45 #define COMMA              0X2c
46
47 static gboolean setsoundpath = FALSE;
48 static gboolean soundvolume = FALSE;
49
50 // End Cause field  - Call state end cause
51
52 typedef enum {
53         CALL_END_NO_CAUSE,
54
55         // These definitions are taken from GSM 04.08 Table 10.86
56
57         CC_CAUSE_UNASSIGNED_NUMBER,
58         CC_CAUSE_NO_ROUTE_TO_DEST,
59         CC_CAUSE_CHANNEL_UNACCEPTABLE,
60         CC_CAUSE_OPERATOR_DETERMINED_BARRING,
61         CC_CAUSE_NORMAL_CALL_CLEARING,
62         CC_CAUSE_USER_BUSY,
63         CC_CAUSE_NO_USER_RESPONDING,
64         CC_CAUSE_USER_ALERTING_NO_ANSWER,
65         CC_CAUSE_CALL_REJECTED,
66         CC_CAUSE_NUMBER_CHANGED,
67         CC_CAUSE_NON_SELECTED_USER_CLEARING,
68         CC_CAUSE_DESTINATION_OUT_OF_ORDER,
69         CC_CAUSE_INVALID_NUMBER_FORMAT,
70         CC_CAUSE_FACILITY_REJECTED,
71         CC_CAUSE_RESPONSE_TO_STATUS_ENQUIRY,
72         CC_CAUSE_NORMAL_UNSPECIFIED,
73         CC_CAUSE_NO_CIRCUIT_CHANNEL_AVAILABLE,
74         CC_CAUSE_NETWORK_OUT_OF_ORDER,
75         CC_CAUSE_TEMPORARY_FAILURE,
76         CC_CAUSE_SWITCHING_EQUIPMENT_CONGESTION,
77         CC_CAUSE_ACCESS_INFORMATION_DISCARDED,
78         CC_CAUSE_REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE,
79         CC_CAUSE_RESOURCES_UNAVAILABLE_UNSPECIFIED,
80         CC_CAUSE_QUALITY_OF_SERVICE_UNAVAILABLE,
81         CC_CAUSE_REQUESTED_FACILITY_NOT_SUBSCRIBED,
82         CC_CAUSE_INCOMING_CALL_BARRED_WITHIN_CUG,
83         CC_CAUSE_BEARER_CAPABILITY_NOT_AUTHORISED,
84         CC_CAUSE_BEARER_CAPABILITY_NOT_PRESENTLY_AVAILABLE,
85         CC_CAUSE_SERVICE_OR_OPTION_NOT_AVAILABLE,
86         CC_CAUSE_BEARER_SERVICE_NOT_IMPLEMENTED,
87         CC_CAUSE_ACM_GEQ_ACMMAX,
88         CC_CAUSE_REQUESTED_FACILITY_NOT_IMPLEMENTED,
89         CC_CAUSE_ONLY_RESTRICTED_DIGITAL_INFO_BC_AVAILABLE,
90         CC_CAUSE_SERVICE_OR_OPTION_NOT_IMPLEMENTED,
91         CC_CAUSE_INVALID_TRANSACTION_ID_VALUE,
92         CC_CAUSE_USER_NOT_MEMBER_OF_CUG,
93         CC_CAUSE_INCOMPATIBLE_DESTINATION,
94         CC_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION,
95         CC_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE,
96         CC_CAUSE_INVALID_MANDATORY_INFORMATION,
97         CC_CAUSE_MESSAGE_TYPE_NON_EXISTENT,
98         CC_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROT_STATE,
99         CC_CAUSE_IE_NON_EXISTENT_OR_NOT_IMPLEMENTED,
100         CC_CAUSE_CONDITIONAL_IE_ERROR,
101         CC_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE,
102         CC_CAUSE_RECOVERY_ON_TIMER_EXPIRY,
103         CC_CAUSE_PROTOCOL_ERROR_UNSPECIFIED,
104         CC_CAUSE_INTERWORKING_UNSPECIFIED,
105         CC_CAUSE_END = 128,
106
107         // Reject causes
108         REJECT_CAUSE_IMSI_UNKNOWN_IN_HLR,
109         REJECT_CAUSE_ILLEGAL_MS,
110         REJECT_CAUSE_IMSI_UNKNOWN_IN_VLR,
111         REJECT_CAUSE_IMEI_NOT_ACCEPTED,
112         REJECT_CAUSE_ILLEGAL_ME,
113         REJECT_CAUSE_GPRS_SERVICES_NOT_ALLOWED,
114         REJECT_CAUSE_GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED,
115         REJECT_CAUSE_MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK,
116         REJECT_CAUSE_IMPLICITLY_DETACHED,
117         REJECT_CAUSE_PLMN_NOT_ALLOWED,
118         REJECT_CAUSE_LA_NOT_ALLOWED,
119         REJECT_CAUSE_NATIONAL_ROAMING_NOT_ALLOWED,
120         REJECT_CAUSE_GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN,
121         REJECT_CAUSE_NO_SUITABLE_CELLS_IN_LA,
122         REJECT_CAUSE_MSC_TEMPORARILY_NOT_REACHABLE,
123         REJECT_CAUSE_NETWORK_FAILURE,
124         REJECT_CAUSE_MAC_FAILURE,
125         REJECT_CAUSE_SYNCH_FAILURE,
126         REJECT_CAUSE_CONGESTTION,
127         REJECT_CAUSE_GSM_AUTH_UNACCEPTED,
128         REJECT_CAUSE_SERVICE_OPTION_NOT_SUPPORTED,
129         REJECT_CAUSE_REQ_SERV_OPT_NOT_SUBSCRIBED,
130         REJECT_CAUSE_SERVICE_OPT__OUT_OF_ORDER,
131         REJECT_CAUSE_CALL_CANNOT_BE_IDENTIFIED,
132         REJECT_CAUSE_NO_PDP_CONTEXT_ACTIVATED,
133         REJECT_CAUSE_RETRY_UPON_ENTRY_INTO_A_NEW_CELL_MIN_VALUE,
134         REJECT_CAUSE_RETRY_UPON_ENTRY_INTO_A_NEW_CELL_MAX_VALUE,
135         REJECT_CAUSE_SEMANTICALLY_INCORRECT_MSG,
136         REJECT_CAUSE_INVALID_MANDATORY_INFO,
137         REJECT_CAUSE_MESSAGE_TYPE_NON_EXISTANT,
138         REJECT_CAUSE_MESSAGE_TYPE_NOT_COMP_PRT_ST,
139         REJECT_CAUSE_IE_NON_EXISTANT,
140         REJECT_CAUSE_MSG_NOT_COMPATIBLE_PROTOCOL_STATE,
141
142
143         // Connection Management establishment rejection cause
144         REJECT_CAUSE_REJ_UNSPECIFIED,
145
146         // AS reject causes
147         REJECT_CAUSE_AS_REJ_RR_REL_IND,
148         REJECT_CAUSE_AS_REJ_RR_RANDOM_ACCESS_FAILURE,
149         REJECT_CAUSE_AS_REJ_RRC_REL_IND,
150         REJECT_CAUSE_AS_REJ_RRC_CLOSE_SESSION_IND,
151         REJECT_CAUSE_AS_REJ_RRC_OPEN_SESSION_FAILURE,
152         REJECT_CAUSE_AS_REJ_LOW_LEVEL_FAIL,
153         REJECT_CAUSE_AS_REJ_LOW_LEVEL_FAIL_REDIAL_NOT_ALLOWED,
154         REJECT_CAUSE_AS_REJ_LOW_LEVEL_IMMED_RETRY,
155
156         // MM reject causes
157         REJECT_CAUSE_MM_REJ_INVALID_SIM,
158         REJECT_CAUSE_MM_REJ_NO_SERVICE,
159         REJECT_CAUSE_MM_REJ_TIMER_T3230_EXP,
160         REJECT_CAUSE_MM_REJ_NO_CELL_AVAILABLE,
161         REJECT_CAUSE_MM_REJ_WRONG_STATE,
162         REJECT_CAUSE_MM_REJ_ACCESS_CLASS_BLOCKED,
163         // Definitions for release ind causes between MM  and CNM
164         REJECT_CAUSE_ABORT_MSG_RECEIVED,
165         REJECT_CAUSE_OTHER_CAUSE,
166
167         // CNM reject causes
168         REJECT_CAUSE_CNM_REJ_TIMER_T303_EXP,
169         REJECT_CAUSE_CNM_REJ_NO_RESOURCES,
170         REJECT_CAUSE_CNM_MM_REL_PENDING,
171         REJECT_CAUSE_CNM_INVALID_USER_DATA,
172         CALL_END_CAUSE_MAX = 255
173 } call_end_cause_e_type;
174
175
176 struct clcc_call_t {
177         struct call_CLCC_info {
178                 int id;
179                 enum tcore_call_direction direction;
180                 enum tcore_call_status status;
181                 enum tcore_call_type type;
182                 int mpty;
183                 int num_len;
184                 int num_type;
185         }
186         info;
187         char number[90];
188 };
189
190 typedef struct {
191         int network_cause;
192         int tapi_cause;
193 } call_end_cause_info;
194
195 /**************************************************************************
196   *                                                     Local Function Prototypes
197   **************************************************************************/
198 /*************************              REQUESTS                ***************************/
199 static void _call_status_idle(TcorePlugin *p, CallObject *co);
200 static void _call_status_active(TcorePlugin *p, CallObject *co);
201 static void _call_status_dialing(TcorePlugin *p, CallObject *co);
202 static void _call_status_alert(TcorePlugin *p, CallObject *co);
203 static void _call_status_incoming(TcorePlugin *p, CallObject *co);
204 static void _call_status_waiting(TcorePlugin *p, CallObject *co);
205 static TReturn _call_list_get(CoreObject *o, gboolean *event_flag);
206 static TReturn _set_dtmf_tone_duration(CoreObject *o, UserRequest *ur);
207
208 /*************************              CONFIRMATION            ***************************/
209 static void on_confirmation_call_message_send(TcorePending *p, gboolean result, void *user_data);     // from Kernel
210 static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data);
211 static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data);
212 static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data);
213 static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data);
214
215 static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type);
216 static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type);
217 static void _on_confirmation_dtmf_tone_duration(TcorePending *p, int data_len, const void *data, void *user_data);
218 static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data);
219
220 /*************************              RESPONSES               ***************************/
221 static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data);
222
223 /*************************              NOTIIFICATIONS          ***************************/
224 static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data);
225 static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data);
226 static void on_notification_call_status(CoreObject *o, const void *data, void *user_data);
227 static gboolean on_notification_call_info(CoreObject *o, const void *data, void *user_data);
228 static gboolean on_notification_call_clip_info(CoreObject *o, const void *data, void *user_data);
229
230
231 /**************************************************************************
232   *                                                     Local Utility Function Prototypes
233   **************************************************************************/
234 static gboolean _call_request_message(TcorePending *pending, CoreObject *o, UserRequest *ur, void *on_resp, void *user_data);
235 static void _call_branch_by_status(TcorePlugin *p, CallObject *co, unsigned int status);
236 static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call);
237
238 /**************************************************************************
239   *                                                     Local Function Definitions
240   **************************************************************************/
241
242 const call_end_cause_info call_end_cause_table[] =   // call end cause table to convert Netwotk cause to TAPI cause
243 {
244         { 1, CC_CAUSE_UNASSIGNED_NUMBER}, { 3, CC_CAUSE_NO_ROUTE_TO_DEST},
245         { 6, CC_CAUSE_CHANNEL_UNACCEPTABLE}, { 8, CC_CAUSE_OPERATOR_DETERMINED_BARRING},
246         { 16, CC_CAUSE_NORMAL_CALL_CLEARING}, { 17, CC_CAUSE_USER_BUSY},
247         { 18, CC_CAUSE_NO_USER_RESPONDING}, { 19, CC_CAUSE_USER_ALERTING_NO_ANSWER},
248         { 21, CC_CAUSE_CALL_REJECTED}, { 22, CC_CAUSE_NUMBER_CHANGED},
249         { 26, CC_CAUSE_NON_SELECTED_USER_CLEARING}, { 27, CC_CAUSE_DESTINATION_OUT_OF_ORDER},
250         { 28, CC_CAUSE_INVALID_NUMBER_FORMAT}, { 29, CC_CAUSE_FACILITY_REJECTED},
251         { 30, CC_CAUSE_RESPONSE_TO_STATUS_ENQUIRY}, { 31, CC_CAUSE_NORMAL_UNSPECIFIED},
252         { 34, CC_CAUSE_NO_CIRCUIT_CHANNEL_AVAILABLE}, { 38, CC_CAUSE_NETWORK_OUT_OF_ORDER},
253         { 41, CC_CAUSE_TEMPORARY_FAILURE}, { 42, CC_CAUSE_SWITCHING_EQUIPMENT_CONGESTION},
254         { 43, CC_CAUSE_ACCESS_INFORMATION_DISCARDED}, { 44, CC_CAUSE_REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE},
255         { 47, CC_CAUSE_RESOURCES_UNAVAILABLE_UNSPECIFIED}, { 49, CC_CAUSE_QUALITY_OF_SERVICE_UNAVAILABLE},
256         { 50, CC_CAUSE_REQUESTED_FACILITY_NOT_SUBSCRIBED}, { 55, CC_CAUSE_INCOMING_CALL_BARRED_WITHIN_CUG},
257         { 57, CC_CAUSE_BEARER_CAPABILITY_NOT_AUTHORISED}, { 58, CC_CAUSE_BEARER_CAPABILITY_NOT_PRESENTLY_AVAILABLE},
258         { 63, CC_CAUSE_SERVICE_OR_OPTION_NOT_AVAILABLE}, { 65, CC_CAUSE_BEARER_SERVICE_NOT_IMPLEMENTED},
259         { 68, CC_CAUSE_ACM_GEQ_ACMMAX}, { 69, CC_CAUSE_REQUESTED_FACILITY_NOT_IMPLEMENTED},
260         { 70, CC_CAUSE_ONLY_RESTRICTED_DIGITAL_INFO_BC_AVAILABLE}, { 79, CC_CAUSE_SERVICE_OR_OPTION_NOT_IMPLEMENTED},
261         { 81, CC_CAUSE_INVALID_TRANSACTION_ID_VALUE}, { 87, CC_CAUSE_USER_NOT_MEMBER_OF_CUG},
262         { 88, CC_CAUSE_INCOMPATIBLE_DESTINATION}, { 91, CC_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION},
263         { 95, CC_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE}, { 96, CC_CAUSE_INVALID_MANDATORY_INFORMATION},
264         { 97, CC_CAUSE_MESSAGE_TYPE_NON_EXISTENT}, { 98, CC_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROT_STATE},
265         { 99, CC_CAUSE_IE_NON_EXISTENT_OR_NOT_IMPLEMENTED}, { 100, CC_CAUSE_CONDITIONAL_IE_ERROR},
266         { 101, CC_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE}, { 102, CC_CAUSE_RECOVERY_ON_TIMER_EXPIRY},
267         { 111, CC_CAUSE_PROTOCOL_ERROR_UNSPECIFIED}, {127, CC_CAUSE_INTERWORKING_UNSPECIFIED},
268 };
269
270 static enum tcore_call_cli_mode _get_clir_status(char *num)
271 {
272         enum tcore_call_cli_mode clir = TCORE_CALL_CLI_MODE_DEFAULT;
273
274         dbg("Entry");
275
276         if (!strncmp(num, "*31#", 4)) {
277                 dbg("CLI mode restricted");
278                 return TCORE_CALL_CLI_MODE_RESTRICT;
279         }
280
281         if (!strncmp(num, "#31#", 4)) {
282                 dbg("CLI mode allowed");
283                 return TCORE_CALL_CLI_MODE_PRESENT;
284         }
285
286         dbg("CLI mode default");
287
288         dbg("Exit");
289
290         return clir;
291 }
292
293 static enum tcore_call_status _call_status(unsigned int status)
294 {
295         dbg("Entry");
296
297         switch (status) {
298         case 0:
299                 return TCORE_CALL_STATUS_ACTIVE;
300
301         case 1:
302                 return TCORE_CALL_STATUS_HELD;
303
304         case 2:
305                 return TCORE_CALL_STATUS_DIALING;
306
307         case 3:
308                 return TCORE_CALL_STATUS_ALERT;
309
310         case 4:
311                 return TCORE_CALL_STATUS_INCOMING;
312
313         case 5:
314                 return TCORE_CALL_STATUS_WAITING;
315
316         case 6:         // DISCONNECTED state  // FALL THROUGH
317         default:
318                 return TCORE_CALL_STATUS_IDLE;
319         }
320 }
321
322 static gboolean _call_is_in_mpty(int mpty)
323 {
324         dbg("Entry");
325
326         switch (mpty) {
327         case 0:
328                 return FALSE;
329
330         case 1:
331                 return TRUE;
332
333         default:
334                 break;
335         }
336
337         return FALSE;
338 }
339
340 static enum tcore_call_type call_type(int type)
341 {
342         dbg("Entry");
343
344         switch (type) {
345         case 0:
346                 return TCORE_CALL_TYPE_VOICE;
347
348         case 1:
349                 return TCORE_CALL_TYPE_VIDEO;
350
351         default:
352                 break;
353         }
354
355         return TCORE_CALL_TYPE_VOICE;
356 }
357
358 static int _compare_call_end_cause(int networkcause)
359 {
360         unsigned int count;
361
362         for (count = 0; count < sizeof(call_end_cause_table) / sizeof(call_end_cause_info); count++) {
363                 if (call_end_cause_table[count].network_cause == networkcause)
364                         return (call_end_cause_table[count].tapi_cause);
365         }
366         return CC_CAUSE_NORMAL_CALL_CLEARING;
367         dbg("Exit");
368 }
369
370 static gboolean on_notification_call_clip_info(CoreObject *o, const void *data, void *user_data)
371 {
372         dbg("Entry");
373
374         // TODO
375
376         return TRUE;
377 }
378
379 static gboolean on_notification_call_info(CoreObject *o, const void *data, void *user_data)
380 {
381         GSList *tokens = NULL;
382         GSList *lines = NULL;
383         const char *line = NULL;
384         char *stat;
385         int status;
386
387         dbg("Entry");
388
389         lines = (GSList *) data;
390         if (1 != g_slist_length(lines)) {
391                 err("Unsolicited message, BUT multiple lines present");
392                 goto OUT;
393         }
394
395         line = (char *) (lines->data);
396         tokens = tcore_at_tok_new(line);
397
398         stat = g_slist_nth_data(tokens, 1);
399         if (!stat) {
400                 dbg("Stat is missing from %XCALLSTAT indiaction");
401         } else {
402                 status = atoi(stat);
403
404                 switch (status) {
405                 case STATUS_INCOMING:
406                         dbg("calling on_notification_call_incoming");
407                         on_notification_call_incoming(o, line, user_data);
408                         break;
409
410                 case STATUS_WAITING:
411                         dbg("calling on_notification_call_waiting");
412                         on_notification_call_waiting(o, line, user_data);
413                         break;
414
415                 case STATUS_CONNECTED:     /*igonre Connected state. */
416                         dbg("Connected state");
417                         break;
418
419                 default:
420                         dbg("calling on_notification_call_status");
421                         on_notification_call_status(o, line, user_data);
422                         break;
423                 }
424         }
425
426         // Free tokens
427         tcore_at_tok_free(tokens);
428
429 OUT:
430         dbg("Exit");
431         return TRUE;
432 }
433
434 static gboolean _call_request_message(TcorePending *pending,
435                                                                           CoreObject *o,
436                                                                           UserRequest *ur,
437                                                                           void *on_resp,
438                                                                           void *user_data)
439 {
440         TcoreHal *hal = NULL;
441         TReturn ret;
442
443         dbg("Entry");
444
445         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
446
447         if (on_resp) {
448                 tcore_pending_set_response_callback(pending, on_resp, user_data);
449         }
450         tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL);
451
452         if (ur) {
453                 tcore_pending_link_user_request(pending, ur);
454         } else {
455                 err("User Request is NULL, is this internal request??");
456         }
457
458         // HAL
459         hal = tcore_object_get_hal(o);
460         // Send request to HAL
461         ret = tcore_hal_send_request(hal, pending);
462         if (TCORE_RETURN_SUCCESS != ret) {
463                 err("Request send failed");
464                 return FALSE;
465         }
466
467         dbg("Exit");
468         return TRUE;
469 }
470
471 static void _call_status_idle(TcorePlugin *p, CallObject *co)
472 {
473         CoreObject *core_obj = NULL;
474         char *cmd_str = NULL;
475         TcorePending *pending = NULL;
476         TcoreATRequest *req = NULL;
477         gboolean ret = FALSE;
478         UserRequest *ur;
479
480         dbg("Entry");
481         core_obj = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL);
482         dbg("Call ID [%d], Call Status [%d]", tcore_call_object_get_id(co), tcore_call_object_get_status(co));
483
484         if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_IDLE) {
485                 // get call end cause.
486                 cmd_str = g_strdup_printf("%s", "AT+XCEER");
487                 dbg("Request command string: %s", cmd_str);
488
489                 // Create new Pending request
490                 pending = tcore_pending_new(core_obj, 0);
491
492                 // Create new AT-Command request
493                 req = tcore_at_request_new(cmd_str, "+XCEER", TCORE_AT_SINGLELINE);
494                 dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
495                 // Free command string
496                 g_free(cmd_str);
497
498                 // Set request data (AT command) to Pending request
499                 tcore_pending_set_request_data(pending, 0, req);
500
501                 ur = tcore_user_request_new(NULL, NULL);
502                 // Send request
503                 ret = _call_request_message(pending, core_obj, ur, _on_confirmation_call_end_cause, co);
504
505                 if (!ret) {
506                         err("Failed to send AT-Command request");
507                         // free only UserRequest.
508                         if (ur) {
509                                 tcore_user_request_free(ur);
510                                 ur = NULL;
511                         }
512                         return;
513                 }
514         } else {
515                 err("Call object was not free");
516                 tcore_call_object_free(core_obj, co);
517         }
518         dbg("Exit");
519         return;
520 }
521
522 static void _call_status_dialing(TcorePlugin *p, CallObject *co)
523 {
524         struct tnoti_call_status_dialing data;
525
526         dbg("Entry");
527
528         if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_DIALING) {
529                 data.type = tcore_call_object_get_type(co);
530                 dbg("data.type : [%d]", data.type);
531
532                 data.id = tcore_call_object_get_id(co);
533                 dbg("data.id : [%d]", data.id);
534
535                 // Set Status
536                 tcore_call_object_set_status(co, TCORE_CALL_STATUS_DIALING);
537
538                 // Send notification to TAPI
539                 tcore_server_send_notification(tcore_plugin_ref_server(p),
540                                                                            tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
541                                                                            TNOTI_CALL_STATUS_DIALING,
542                                                                            sizeof(struct tnoti_call_status_dialing),
543                                                                            (void *) &data);
544         }
545
546         dbg("Exit");
547         return;
548 }
549
550 static void _call_status_alert(TcorePlugin *p, CallObject *co)
551 {
552         struct tnoti_call_status_alert data;
553
554         dbg("Entry");
555
556         // Alerting has just 1 data 'CALL ID'
557         if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_ALERT) {
558                 data.type = tcore_call_object_get_type(co);
559                 dbg("data.type : [%d]", data.type);
560
561                 data.id = tcore_call_object_get_id(co);
562                 dbg("data.id : [%d]", data.id);
563
564                 // Set Status
565                 tcore_call_object_set_status(co, TCORE_CALL_STATUS_ALERT);
566
567                 // Send notification to TAPI
568                 tcore_server_send_notification(tcore_plugin_ref_server(p),
569                                                                            tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
570                                                                            TNOTI_CALL_STATUS_ALERT,
571                                                                            sizeof(struct tnoti_call_status_alert),
572                                                                            (void *) &data);
573         }
574
575         dbg("Exit");
576         return;
577 }
578
579 static void _call_status_active(TcorePlugin *p, CallObject *co)
580 {
581         struct tnoti_call_status_active data;
582
583         dbg("Entry");
584
585         if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_ACTIVE) {
586                 data.type = tcore_call_object_get_type(co);
587                 dbg("data.type : [%d]", data.type);
588
589                 data.id = tcore_call_object_get_id(co);
590                 dbg("data.id : [%d]", data.id);
591
592                 // Set Status
593                 tcore_call_object_set_status(co, TCORE_CALL_STATUS_ACTIVE);
594
595                 // Send notification to TAPI
596                 tcore_server_send_notification(tcore_plugin_ref_server(p),
597                                                                            tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
598                                                                            TNOTI_CALL_STATUS_ACTIVE,
599                                                                            sizeof(struct tnoti_call_status_active),
600                                                                            (void *) &data);
601         }
602
603         dbg("Exit");
604         return;
605 }
606
607 static void _call_status_held(TcorePlugin *p, CallObject *co)
608 {
609         struct tnoti_call_status_held data;
610
611         dbg("Entry");
612
613         if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_HELD) {
614                 data.type = tcore_call_object_get_type(co);
615                 dbg("data.type : [%d]", data.type);
616
617                 data.id = tcore_call_object_get_id(co);
618                 dbg("data.id : [%d]", data.id);
619
620                 // Set Status
621                 tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD);
622
623                 // Send notification to TAPI
624                 tcore_server_send_notification(tcore_plugin_ref_server(p),
625                                                                            tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
626                                                                            TNOTI_CALL_STATUS_HELD,
627                                                                            sizeof(struct tnoti_call_status_held),
628                                                                            (void *) &data);
629         }
630
631         dbg("Exit");
632         return;
633 }
634
635 static void _call_status_incoming(TcorePlugin *p, CallObject *co)
636 {
637         struct tnoti_call_status_incoming data;
638
639         dbg("Entry");
640
641         if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_INCOMING) {
642                 tcore_call_object_set_status(co, TCORE_CALL_STATUS_INCOMING);
643
644                 data.type = tcore_call_object_get_type(co);
645                 dbg("data.type : [%d]", data.type);
646
647                 data.id = tcore_call_object_get_id(co);
648                 dbg("data.id : [%d]", data.id);
649
650                 data.cli.mode = tcore_call_object_get_cli_mode(co);
651                 dbg("data.cli.mode : [%d]", data.cli.mode);
652
653                 tcore_call_object_get_number(co, data.cli.number);
654                 dbg("data.cli.number : [%s]", data.cli.number);
655
656                 data.cna.mode = tcore_call_object_get_cna_mode(co);
657                 dbg("data.cna.mode : [%d]", data.cna.mode);
658
659                 tcore_call_object_get_name(co, data.cna.name);
660                 dbg("data.cna.name : [%s]", data.cna.name);
661
662                 data.forward = FALSE; // this is tmp code
663
664                 data.active_line = tcore_call_object_get_active_line(co);
665                 dbg("data.active_line : [%d]", data.active_line);
666
667                 // Send notification to TAPI
668                 tcore_server_send_notification(tcore_plugin_ref_server(p),
669                                                                            tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
670                                                                            TNOTI_CALL_STATUS_INCOMING,
671                                                                            sizeof(struct tnoti_call_status_incoming),
672                                                                            (void *) &data);
673         }
674
675         dbg("Exit");
676         return;
677 }
678
679 static void _call_status_waiting(TcorePlugin *p, CallObject *co)
680 {
681         dbg("Entry");
682         _call_status_incoming(p, co);
683
684         dbg("Exit");
685         return;
686 }
687
688 static void _call_branch_by_status(TcorePlugin *p, CallObject *co, unsigned int status)
689 {
690         dbg("Entry");
691
692         dbg("Call Status is %d", status);
693         switch (status) {
694         case TCORE_CALL_STATUS_IDLE:
695                 _call_status_idle(p, co);
696                 break;
697
698         case TCORE_CALL_STATUS_ACTIVE:
699                 _call_status_active(p, co);
700                 break;
701
702         case TCORE_CALL_STATUS_HELD:
703                 _call_status_held(p, co);
704                 break;
705
706         case TCORE_CALL_STATUS_DIALING:
707                 _call_status_dialing(p, co);
708                 break;
709
710         case TCORE_CALL_STATUS_ALERT:
711                 _call_status_alert(p, co);
712                 break;
713
714         case TCORE_CALL_STATUS_INCOMING:
715                 _call_status_incoming(p, co);
716                 break;
717
718         case TCORE_CALL_STATUS_WAITING:
719                 _call_status_waiting(p, co);
720                 break;
721         }
722
723         dbg("Exit");
724         return;
725 }
726
727 static TReturn _call_list_get(CoreObject *o, gboolean *event_flag)
728 {
729         UserRequest *ur = NULL;
730         TcorePending *pending = NULL;
731         char *cmd_str = NULL;
732         TcoreATRequest *req = NULL;
733         gboolean ret = FALSE;
734
735         dbg("Entry");
736         if (!o) {
737                 err("Core Object is NULL");
738                 return TCORE_RETURN_FAILURE;
739         }
740
741         // Create new User Request
742         ur = tcore_user_request_new(NULL, NULL);
743
744         // Command string
745         cmd_str = g_strdup("AT+CLCC");
746
747         // Create new Pending Request
748         pending = tcore_pending_new(o, 0);
749         req = tcore_at_request_new(cmd_str, "+CLCC", TCORE_AT_MULTILINE);
750
751         g_free(cmd_str);
752
753         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
754
755         tcore_pending_set_request_data(pending, 0, req);
756
757         ret = _call_request_message(pending, o, ur, on_response_call_list_get, event_flag);
758         if (!ret) {
759                 err("AT request (%s) sending failed", req->cmd);
760                 // free only UserRequest.
761                 if (ur) {
762                         tcore_user_request_free(ur);
763                         ur = NULL;
764                 }
765                 return TCORE_RETURN_FAILURE;
766         }
767
768         dbg("AT request sent success");
769         return TCORE_RETURN_SUCCESS;
770 }
771
772 // CONFIRMATION
773 static void on_confirmation_call_message_send(TcorePending *p, gboolean result, void *user_data)
774 {
775         dbg("Entry");
776
777         if (result == FALSE) {  // Fail
778                 dbg("SEND FAIL");
779         } else {
780                 dbg("SEND OK");
781         }
782
783         dbg("Exit");
784         return;
785 }
786
787 static void call_prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback)
788 {
789         TcoreATRequest *req = NULL;
790         TcoreHal *hal = NULL;
791         TcorePending *pending = NULL;
792         TReturn ret;
793
794         hal = tcore_object_get_hal(co);
795         dbg("hal: %p", hal);
796
797         pending = tcore_pending_new(co, 0);
798         if (!pending)
799                 dbg("Pending is NULL");
800         req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
801
802         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
803
804         tcore_pending_set_request_data(pending, 0, req);
805         tcore_pending_set_response_callback(pending, callback, NULL);
806         tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL);
807         ret = tcore_hal_send_request(hal, pending);
808 }
809
810 static void on_confirmation_call_outgoing(TcorePending *p, int data_len, const void *data, void *user_data)
811 {
812         UserRequest *ur = NULL;
813         GSList *tokens = NULL;
814         const char *line = NULL;
815         const TcoreATResponse *response = data;
816         struct tresp_call_dial resp;
817         enum telephony_call_error error;
818         dbg("Entry");
819
820         ur = tcore_pending_ref_user_request(p);
821         if (ur) {
822                 if (response->success > 0) {
823                         dbg("RESPONSE OK");
824                         resp.err = CALL_ERROR_NONE;
825                 } else {
826                         dbg("RESPONSE NOT OK");
827
828                         line = (const char *) response->final_response;
829                         tokens = tcore_at_tok_new(line);
830
831                         if (g_slist_length(tokens) < 1) {
832                                 err("Unspecified error cause OR string corrupted");
833                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
834                         } else {
835                                 error = atoi(g_slist_nth_data(tokens, 0));
836
837                                 // TODO: CMEE error mapping is required.
838                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
839                         }
840
841                         // Free tokens
842                         tcore_at_tok_free(tokens);
843                 }
844
845                 // Send Response to TAPI
846                 tcore_user_request_send_response(ur, TRESP_CALL_DIAL, sizeof(struct tresp_call_dial), &resp);
847         } else {
848                 err("User Request is NULL");
849         }
850
851         dbg("Exit");
852         return;
853 }
854
855 static void on_confirmation_call_accept(TcorePending *p, int data_len, const void *data, void *user_data)
856 {
857         UserRequest *ur = NULL;
858         GSList *tokens = NULL;
859         const char *line = NULL;
860         const TcoreATResponse *response = data;
861         struct tresp_call_answer resp;
862         enum telephony_call_error error;
863         dbg("Entry");
864
865         ur = tcore_pending_ref_user_request(p);
866         if (ur) {
867                 if (response->success > 0) {
868                         dbg("RESPONSE OK");
869                         resp.err = CALL_ERROR_NONE;
870                 } else {
871                         dbg("RESPONSE NOT OK");
872
873                         line = (const char *) response->final_response;
874                         tokens = tcore_at_tok_new(line);
875
876                         if (g_slist_length(tokens) < 1) {
877                                 err("Unspecified error cause OR string corrupted");
878                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
879                         } else {
880                                 error = atoi(g_slist_nth_data(tokens, 0));
881
882                                 // TODO: CMEE error mapping is required.
883                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
884                         }
885
886                         // Free tokens
887                         tcore_at_tok_free(tokens);
888                 }
889
890                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
891
892                 // Send Response to TAPI
893                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
894         } else {
895                 err("User Request is NULL");
896         }
897
898         dbg("Exit");
899         return;
900 }
901
902
903 static void on_confirmation_call_reject(TcorePending *p, int data_len, const void *data, void *user_data)
904 {
905         UserRequest *ur = NULL;
906         GSList *tokens = NULL;
907         const char *line = NULL;
908         const TcoreATResponse *response = data;
909         struct tresp_call_answer resp;
910         enum telephony_call_error error;
911
912         dbg("Entry");
913
914         ur = tcore_pending_ref_user_request(p);
915         if (ur) {
916                 if (response->success > 0) {
917                         dbg("RESPONSE OK");
918                         resp.err = CALL_ERROR_NONE;
919                 } else {
920                         dbg("RESPONSE NOT OK");
921                         line = (const char *) response->final_response;
922                         tokens = tcore_at_tok_new(line);
923
924                         if (g_slist_length(tokens) < 1) {
925                                 err("Unspecified error cause OR string corrupted");
926                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
927                         } else {
928                                 error = atoi(g_slist_nth_data(tokens, 0));
929                                 // TODO: CMEE error mapping is required.
930                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
931                         }
932
933                         // Free tokens
934                         tcore_at_tok_free(tokens);
935                 }
936
937                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
938
939                 // Send Response to TAPI
940                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
941         } else {
942                 err("User Request is NULL");
943         }
944
945         dbg("Exit");
946         return;
947 }
948
949 static void on_confirmation_call_replace(TcorePending *p, int data_len, const void *data, void *user_data)
950 {
951         UserRequest *ur = NULL;
952         GSList *tokens = NULL;
953         const char *line = NULL;
954         const TcoreATResponse *response = data;
955         struct tresp_call_answer resp;
956         enum telephony_call_error error;
957
958         dbg("Entry");
959         ur = tcore_pending_ref_user_request(p);
960         if (ur) {
961                 if (response->success > 0) {
962                         dbg("RESPONSE OK");
963                         resp.err = CALL_ERROR_NONE;
964                 } else {
965                         dbg("RESPONSE NOT OK");
966                         line = (const char *) response->final_response;
967                         tokens = tcore_at_tok_new(line);
968
969                         if (g_slist_length(tokens) < 1) {
970                                 err("Unspecified error cause OR string corrupted");
971                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
972                         } else {
973                                 error = atoi(g_slist_nth_data(tokens, 0));
974                                 // TODO: CMEE error mapping is required.
975                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
976                         }
977
978                         // Free tokens
979                         tcore_at_tok_free(tokens);
980                 }
981                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
982
983                 // Send Response to TAPI
984                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
985         } else {
986                 dbg("User Request is NULL");
987         }
988
989         dbg("Exit");
990         return;
991 }
992
993 static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data)
994 {
995         CoreObject *o = NULL;
996         UserRequest *ur = NULL;
997         GSList *tokens = NULL;
998         const char *line = NULL;
999         const TcoreATResponse *response = data;
1000         struct tresp_call_answer resp;
1001         enum telephony_call_error error;
1002
1003         dbg("Entry");
1004
1005         o = tcore_pending_ref_core_object(p);
1006         ur = tcore_pending_ref_user_request(p);
1007         resp.id = tcore_call_object_get_id((CallObject *) user_data);
1008
1009         if (ur) {
1010                 if (response->success > 0) {
1011                         dbg("RESPONSE OK");
1012                         resp.err = CALL_ERROR_NONE;
1013                 } else {
1014                         err("RESPONSE NOT OK");
1015                         line = (const char *) response->final_response;
1016                         tokens = tcore_at_tok_new(line);
1017
1018                         if (g_slist_length(tokens) < 1) {
1019                                 err("Unspecified error cause OR string corrupted");
1020                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1021                         } else {
1022                                 error = atoi(g_slist_nth_data(tokens, 0));
1023
1024                                 // TODO: CMEE error mapping is required.
1025                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1026                         }
1027
1028                         // Free tokens
1029                         tcore_at_tok_free(tokens);
1030                 }
1031
1032                 // Send response to TAPI
1033                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
1034                 if (!resp.err) {
1035                         GSList *list = 0;
1036                         CallObject *co = NULL;
1037
1038                         // Active Call
1039                         list = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_ACTIVE);
1040                         if (!list) {
1041                                 err("Can't find active Call");
1042                                 return;
1043                         }
1044
1045                         co = (CallObject *) list->data;
1046                         if (!co) {
1047                                 err("Can't get active Call object");
1048                                 return;
1049                         }
1050
1051                         // Set Call Status
1052                         tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD);
1053                         dbg("Call status is set to HELD");
1054                 }
1055         } else {
1056                 err("User Request is NULL");
1057         }
1058
1059         dbg("Exit");
1060         return;
1061 }
1062
1063 static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type)
1064 {
1065         UserRequest *ur = NULL;
1066         struct tresp_call_end resp;
1067         GSList *tokens = NULL;
1068         const char *line = NULL;
1069         enum telephony_call_error error;
1070         const TcoreATResponse *response = data;
1071
1072         dbg("Entry");
1073         ur = tcore_pending_ref_user_request(p);
1074         if (ur) {
1075                 if (response->success > 0) {
1076                         dbg("RESPONSE OK");
1077                         resp.err = CALL_ERROR_NONE;
1078                 } else {
1079                         err("RESPONSE NOT OK");
1080
1081                         line = (const char *) response->final_response;
1082                         tokens = tcore_at_tok_new(line);
1083
1084                         if (g_slist_length(tokens) < 1) {
1085                                 err("Unspecified error cause OR string corrupted");
1086                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1087                         } else {
1088                                 error = atoi(g_slist_nth_data(tokens, 0));
1089
1090                                 // TODO: CMEE error mapping is required.
1091                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1092                         }
1093                         tcore_at_tok_free(tokens);
1094                 }
1095
1096                 resp.type = type;
1097                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1098                 dbg("resp.type = %d  resp.id= %d", resp.type, resp.id);
1099
1100                 // Send reponse to TAPI
1101                 tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
1102         } else {
1103                 err("User Request is NULL");
1104         }
1105
1106         dbg("Exit");
1107         return;
1108 }
1109
1110 // RESPONSE
1111 static void on_confirmation_call_endall(TcorePending *p, int data_len, const void *data, void *user_data)
1112 {
1113         // skip response handling - actual result will be handled in on_confirmation_call_release_all
1114         const TcoreATResponse *response = data;
1115
1116         dbg("Entry");
1117
1118         if (response->success > 0) {
1119                 dbg("RESPONSE OK");
1120         } else {
1121                 err("RESPONSE NOT OK");
1122         }
1123
1124         dbg("Exit");
1125         return;
1126 }
1127
1128
1129 static void on_confirmation_call_release_all(TcorePending *p, int data_len, const void *data, void *user_data)
1130 {
1131         dbg("Entry");
1132         _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ALL);
1133
1134         return;
1135 }
1136
1137
1138 static void on_confirmation_call_release_specific(TcorePending *p, int data_len, const void *data, void *user_data)
1139 {
1140         dbg("Entry");
1141         _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_DEFAULT);
1142
1143         return;
1144 }
1145
1146 static void on_confirmation_call_release_all_active(TcorePending *p, int data_len, const void *data, void *user_data)
1147 {
1148         dbg("Entry");
1149         _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ACTIVE_ALL);
1150
1151         return;
1152 }
1153
1154 static void on_confirmation_call_release_all_held(TcorePending *p, int data_len, const void *data, void *user_data)
1155 {
1156         dbg("Entry");
1157         _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_HOLD_ALL);
1158
1159         return;
1160 }
1161
1162 static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type)
1163 {
1164         UserRequest *ur = NULL;
1165         GSList *tokens = NULL;
1166         const char *line = NULL;
1167         const TcoreATResponse *response = NULL;
1168         enum telephony_call_error error;
1169
1170         dbg("Entry");
1171         ur = tcore_pending_ref_user_request(p);
1172         response = (TcoreATResponse *) data;
1173         if (response->success > 0) {
1174                 dbg("RESPONSE OK");
1175                 error = CALL_ERROR_NONE;
1176         } else {
1177                 err("RESPONSE NOT OK");
1178
1179                 line = (const char *) response->final_response;
1180                 tokens = tcore_at_tok_new(line);
1181
1182                 if (g_slist_length(tokens) < 1) {
1183                         err("Unspecified error cause OR string corrupted");
1184                         error = CALL_ERROR_SERVICE_UNAVAIL;
1185                 } else {
1186                         error = atoi(g_slist_nth_data(tokens, 0));
1187
1188                         // TODO: CMEE error mapping is required.
1189                         error = CALL_ERROR_SERVICE_UNAVAIL;
1190                 }
1191
1192                 // Free tokens
1193                 tcore_at_tok_free(tokens);
1194         }
1195
1196         dbg("Response Call type -%d", type);
1197         switch (type) {
1198         case TRESP_CALL_HOLD:
1199         {
1200                 struct tresp_call_hold resp;
1201
1202                 resp.err = error;
1203                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1204                 dbg("call hold response");
1205                 // Send reponse to TAPI
1206                 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
1207         }
1208         break;
1209
1210         case TRESP_CALL_ACTIVE:
1211         {
1212                 struct tresp_call_active resp;
1213
1214                 resp.err = error;
1215                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1216                 dbg("call active response");
1217                 // Send reponse to TAPI
1218                 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
1219         }
1220         break;
1221
1222         case TRESP_CALL_JOIN:
1223         {
1224                 struct tresp_call_join resp;
1225
1226                 resp.err = error;
1227                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1228                 dbg("call join response");
1229
1230                 // Send reponse to TAPI
1231                 tcore_user_request_send_response(ur, TRESP_CALL_JOIN, sizeof(struct tresp_call_join), &resp);
1232         }
1233         break;
1234
1235         case TRESP_CALL_SPLIT:
1236         {
1237                 struct tresp_call_split resp;
1238
1239                 resp.err = error;
1240                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1241                 dbg("call split response");
1242                 // Send reponse to TAPI
1243                 tcore_user_request_send_response(ur, TRESP_CALL_SPLIT, sizeof(struct tresp_call_split), &resp);
1244         }
1245         break;
1246
1247         case TRESP_CALL_DEFLECT:
1248         {
1249                 struct tresp_call_deflect resp;
1250
1251                 resp.err = error;
1252                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1253                 dbg("call deflect response");
1254                 // Send reponse to TAPI
1255                 tcore_user_request_send_response(ur, TRESP_CALL_DEFLECT, sizeof(struct tresp_call_deflect), &resp);
1256         }
1257
1258         break;
1259
1260         case TRESP_CALL_TRANSFER:
1261         {
1262                 struct tresp_call_transfer resp;
1263
1264                 resp.err = error;
1265                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1266                 dbg("call transfer response");
1267                 // Send reponse to TAPI
1268                 tcore_user_request_send_response(ur, TRESP_CALL_TRANSFER, sizeof(struct tresp_call_transfer), &resp);
1269         }
1270         break;
1271
1272         case TRESP_CALL_SEND_DTMF:
1273         {
1274                 struct tresp_call_dtmf resp;
1275
1276                 resp.err = error;
1277                 dbg("call dtmf response");
1278                 // Send reponse to TAPI
1279                 tcore_user_request_send_response(ur, TRESP_CALL_SEND_DTMF, sizeof(struct tresp_call_dtmf), &resp);
1280         }
1281         break;
1282
1283         default:
1284         {
1285                 dbg("type not supported");
1286                 return;
1287         }
1288         }
1289
1290         if ((type == TRESP_CALL_HOLD) || (type == TRESP_CALL_ACTIVE) || (type == TRESP_CALL_JOIN)
1291                 || (type == TRESP_CALL_SPLIT)) {
1292                 if (!error) {
1293                         CoreObject *core_obj = NULL;
1294                         gboolean *eflag = g_new0(gboolean, 1);
1295
1296                         core_obj = tcore_pending_ref_core_object(p);
1297                         *eflag = FALSE;
1298
1299                         dbg("Calling _call_list_get");
1300                         _call_list_get(core_obj, eflag);
1301                 }
1302         }
1303
1304         dbg("Exit");
1305         return;
1306 }
1307
1308 static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data)
1309 {
1310         dbg("Entry");
1311         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_HOLD);
1312
1313         return;
1314 }
1315
1316 static void on_confirmation_call_active(TcorePending *p, int data_len, const void *data, void *user_data)
1317 {
1318         dbg("Entry");
1319         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_ACTIVE);
1320
1321         return;
1322 }
1323
1324 static void on_confirmation_call_join(TcorePending *p, int data_len, const void *data, void *user_data)
1325 {
1326         dbg("Entry");
1327         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_JOIN);
1328
1329         return;
1330 }
1331
1332 static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data)
1333 {
1334         dbg("Entry");
1335         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_SPLIT);
1336
1337         return;
1338 }
1339
1340 static void on_confirmation_call_deflect(TcorePending *p, int data_len, const void *data, void *user_data)
1341 {
1342         dbg("Entry");
1343         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_DEFLECT);
1344
1345         return;
1346 }
1347
1348 static void on_confirmation_call_transfer(TcorePending *p, int data_len, const void *data, void *user_data)
1349 {
1350         dbg("Entry");
1351         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_TRANSFER);
1352
1353         return;
1354 }
1355
1356 static void on_confirmation_call_dtmf(TcorePending *p, int data_len, const void *data, void *user_data)
1357 {
1358         dbg("Entry");
1359         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_SEND_DTMF);
1360
1361         return;
1362 }
1363
1364 static void _on_confirmation_dtmf_tone_duration(TcorePending *p, int data_len, const void *data, void *user_data)
1365 {
1366         GSList *tokens = NULL;
1367         const char *line = NULL;
1368         const TcoreATResponse *response = data;
1369         enum telephony_call_error error;
1370
1371         dbg("Entry");
1372
1373         if (response->success > 0) {
1374                 dbg("RESPONSE OK");
1375                 error = CALL_ERROR_NONE;
1376         } else {
1377                 err("RESPONSE NOT OK");
1378                 line = (const char *) response->final_response;
1379                 tokens = tcore_at_tok_new(line);
1380                 if (g_slist_length(tokens) < 1) {
1381                         err("err cause not specified or string corrupted");
1382                         error = CALL_ERROR_SERVICE_UNAVAIL;
1383                 } else {
1384                         error = atoi(g_slist_nth_data(tokens, 0));
1385                         // TODO: CMEE error mapping is required.
1386                 }
1387
1388                 // Free tokens
1389                 tcore_at_tok_free(tokens);
1390         }
1391
1392         dbg("Set dtmf tone duration response - %d", error);
1393         return;
1394 }
1395
1396 static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data)
1397 {
1398         CoreObject *core_obj = NULL;
1399         UserRequest *ur = NULL;
1400         const TcoreATResponse *response = data;
1401         struct tresp_call_swap resp;
1402         GSList *tokens = NULL;
1403         const char *line = NULL;
1404
1405         dbg("Entry");
1406         core_obj = tcore_pending_ref_core_object(p);
1407         ur = tcore_pending_ref_user_request(p);
1408
1409         if (ur) {
1410                 if (response->success > 0) {
1411                         dbg("RESPONSE OK");
1412                         resp.err = CALL_ERROR_NONE;
1413                 } else {
1414                         err("RESPONSE NOT OK");
1415                         line = (const char *) response->final_response;
1416                         tokens = tcore_at_tok_new(line);
1417                         if (g_slist_length(tokens) < 1) {
1418                                 err("err cause not specified or string corrupted");
1419                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1420                         } else {
1421                                 resp.err = atoi(g_slist_nth_data(tokens, 0));
1422
1423                                 // TODO: CMEE error mapping is required.
1424                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1425                         }
1426
1427                         // Free tokens
1428                         tcore_at_tok_free(tokens);
1429                 }
1430
1431                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1432                 dbg("resp.id = %d", resp.id);
1433
1434                 // Send response to TAPI
1435                 tcore_user_request_send_response(ur, TRESP_CALL_SWAP, sizeof(struct tresp_call_swap), &resp);
1436
1437                 if (!resp.err) {
1438                         GSList *active = NULL;
1439                         GSList *held = NULL;
1440                         CallObject *co = NULL;
1441                         gboolean *eflag = NULL;
1442
1443                         held = tcore_call_object_find_by_status(core_obj, TCORE_CALL_STATUS_HELD);
1444                         if (!held) {
1445                                 err("Can't find held Call");
1446                                 return;
1447                         }
1448
1449                         active = tcore_call_object_find_by_status(core_obj, TCORE_CALL_STATUS_ACTIVE);
1450                         if (!active) {
1451                                 dbg("Can't find active Call");
1452                                 return;
1453                         }
1454
1455                         while (held) {
1456                                 co = (CallObject *) held->data;
1457                                 if (!co) {
1458                                         err("Can't get held Call object");
1459                                         return;
1460                                 }
1461
1462                                 resp.id = tcore_call_object_get_id(co);
1463
1464                                 // Send response to TAPI
1465                                 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
1466
1467                                 held = g_slist_next(held);
1468                         }
1469
1470                         while (active) {
1471                                 co = (CallObject *) active->data;
1472                                 if (!co) {
1473                                         err("[ error ] can't get active call object");
1474                                         return;
1475                                 }
1476
1477                                 resp.id = tcore_call_object_get_id(co);
1478
1479                                 // Send response to TAPI
1480                                 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
1481                                 active = g_slist_next(active);
1482                         }
1483
1484                         eflag = g_new0(gboolean, 1);
1485                         *eflag = FALSE;
1486
1487                         dbg("calling _call_list_get");
1488                         _call_list_get(core_obj, eflag);
1489                 }
1490         } else {
1491                 err("User Request is NULL");
1492         }
1493
1494         dbg("Exit");
1495         return;
1496 }
1497
1498 static void on_confirmation_set_sound_path(TcorePending *p, int data_len,
1499                                                 const void *data,
1500                                                 void *user_data)
1501 {
1502         const TcoreATResponse *resp = data;
1503         struct tnoti_call_sound_path *snd_path = user_data;
1504         struct tresp_call_sound_set_path resp_set_sound_path;
1505         UserRequest *ur = tcore_pending_ref_user_request(p);
1506         TcorePlugin *plugin = tcore_pending_ref_plugin(p);
1507         CoreObject *co_call;
1508
1509         if (ur == NULL) {
1510                 err("User Request is NULL");
1511                 g_free(user_data);
1512                 return;
1513         }
1514
1515         if (resp->success <= 0) {
1516
1517                 dbg("RESPONSE NOT OK");
1518                 resp_set_sound_path.err = TRUE;
1519
1520                 goto out;
1521         }
1522
1523         dbg("RESPONSE OK");
1524         resp_set_sound_path.err = FALSE;
1525
1526         co_call = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL);
1527
1528         /* Notify control plugin about sound path */
1529         tcore_server_send_notification(tcore_plugin_ref_server(plugin),
1530                                         co_call, TNOTI_CALL_SOUND_PATH,
1531                                         sizeof(struct tnoti_call_sound_path),
1532                                         snd_path);
1533
1534 out:
1535         /* Answer TAPI request */
1536         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH,
1537                                 sizeof(resp_set_sound_path),
1538                                 &resp_set_sound_path);
1539
1540         g_free(user_data);
1541 }
1542
1543 static void on_confirmation_call_set_source_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1544 {
1545         UserRequest *ur = NULL;
1546         GSList *tokens = NULL;
1547         const char *line = NULL;
1548         const TcoreATResponse *response = data;
1549         char *resp_str = NULL;
1550         struct tresp_call_sound_set_path resp;
1551         gboolean error;
1552
1553         dbg("Entry");
1554         ur = tcore_pending_ref_user_request(p);
1555
1556         // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]\ 3
1557         if (!response) {
1558                 err("Input data is NULL");
1559                 return;
1560         }
1561
1562         if (response->success > 0) {
1563                 dbg("RESPONSE OK");
1564
1565                 line = (const char *) (((GSList *) response->lines)->data);
1566                 tokens = tcore_at_tok_new(line);
1567
1568                 resp_str = g_slist_nth_data(tokens, 0);
1569                 if (!g_slist_nth_data(tokens, 0)) {
1570                         err("group_id is missing");
1571                         resp.err = TRUE;
1572                         goto OUT;
1573                 }
1574
1575                 if (!g_slist_nth_data(tokens, 1)) {
1576                         err(" function_id is missing");
1577                         resp.err = TRUE;
1578                         goto OUT;
1579                 }
1580
1581                 resp_str = g_slist_nth_data(tokens, 2);
1582
1583                 if (resp_str) {
1584                         error = atoi(resp_str);
1585                         if (0 == error) {
1586                                 dbg("Response is Success");
1587                                 resp.err = FALSE;
1588                         } else {
1589                                 resp.err = TRUE;
1590                         }
1591                 }
1592 OUT:
1593                 // Free tokens
1594                 tcore_at_tok_free(tokens);
1595         } else {
1596                 dbg("RESPONSE NOT OK");
1597
1598                 line = (const char *) response->final_response;
1599                 tokens = tcore_at_tok_new(line);
1600
1601                 if (g_slist_length(tokens) < 1) {
1602                         err("err cause not specified or string corrupted");
1603                         resp.err = TRUE;
1604                 } else {
1605                         error = atoi(g_slist_nth_data(tokens, 0));
1606
1607                         // TODO: CMEE error mapping is required.
1608                         resp.err = TRUE;
1609                 }
1610
1611                 // Free tokens
1612                 tcore_at_tok_free(tokens);
1613         }
1614
1615         if (ur) {
1616                 if ( resp.err ) {  // Send only failed notification . success notification send when destination device is set.
1617                         // Send notification to TAPI
1618                         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_sound_set_path), &resp);
1619                         setsoundpath = TRUE;
1620                 }
1621         } else {
1622                 err("User Request is NULL");
1623         }
1624
1625         dbg("Exit");
1626         return;
1627 }
1628
1629 static void on_confirmation_call_set_destination_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1630 {
1631         UserRequest *ur = NULL;
1632         GSList *tokens = NULL;
1633         const char *line = NULL;
1634         char *resp_str = NULL;
1635         struct tresp_call_sound_set_path resp;
1636         const TcoreATResponse *response = data;
1637         gboolean error;
1638
1639         dbg("Entry");
1640
1641         ur = tcore_pending_ref_user_request(p);
1642         // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]\ 3
1643
1644         if (!response) {
1645                 err("Input data is NULL");
1646                 return;
1647         }
1648
1649         if (ur) {
1650                 if (response->success > 0) {
1651                         dbg("RESPONSE OK");
1652
1653                         line = (const char *) (((GSList *) response->lines)->data);
1654                         tokens = tcore_at_tok_new(line);
1655
1656                         resp_str = g_slist_nth_data(tokens, 0);
1657                         if (!g_slist_nth_data(tokens, 0)) {
1658                                 dbg("group_id is missing");
1659                                 resp.err = TRUE;
1660                                 goto OUT;
1661                         }
1662
1663                         if (!g_slist_nth_data(tokens, 1)) {
1664                                 dbg("function_id is missing");
1665                                 resp.err = TRUE;
1666                                 goto OUT;
1667                         }
1668
1669                         resp_str = g_slist_nth_data(tokens, 2);
1670                         if (resp_str) {
1671                                 error = atoi(resp_str);
1672                                 if (0 == error) {
1673                                         dbg("Response is Success");
1674                                         resp.err = FALSE;
1675                                 } else {
1676                                         resp.err = TRUE;
1677                                 }
1678                         }
1679
1680 OUT:
1681                         // Free tokens
1682                         tcore_at_tok_free(tokens);
1683                 } else {
1684                         dbg("RESPONSE NOT OK");
1685
1686                         line = (const char *) response->final_response;
1687                         tokens = tcore_at_tok_new(line);
1688
1689                         if (g_slist_length(tokens) < 1) {
1690                                 err("err cause not specified or string corrupted");
1691                                 resp.err = TRUE;
1692                         } else {
1693                                 error = atoi(g_slist_nth_data(tokens, 0));
1694                                 // TODO: CMEE error mapping is required.
1695                                 resp.err = TRUE;
1696                         }
1697
1698                         // Free tokens
1699                         tcore_at_tok_free(tokens);
1700                 }
1701
1702                 if (setsoundpath == TRUE) {
1703                         setsoundpath = FALSE;
1704                 } else {
1705                         // Send response to TAPI
1706                         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_sound_set_path), &resp);
1707                 }
1708         } else {
1709                 dbg("User Request is NULL");
1710         }
1711
1712         dbg("Exit");
1713         return;
1714 }
1715
1716 static void on_confirmation_call_set_source_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data)
1717 {
1718         UserRequest *ur = NULL;
1719         GSList *tokens = NULL;
1720         const char *line = NULL;
1721         const TcoreATResponse *response = data;
1722         char *resp_str = NULL;
1723         struct tresp_call_sound_set_volume_level resp;
1724         gboolean error;
1725
1726         ur = tcore_pending_ref_user_request(p);
1727         dbg("Entry");
1728         // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]\ 3
1729         if (!response) {
1730                 err("Input data is NULL");
1731                 return;
1732         }
1733
1734         if (response->success > 0) {
1735                 dbg("RESPONSE OK");
1736
1737                 line = (const char *) (((GSList *) response->lines)->data);
1738                 tokens = tcore_at_tok_new(line);
1739
1740                 resp_str = g_slist_nth_data(tokens, 0);
1741                 if (!g_slist_nth_data(tokens, 0)) {
1742                         err("group_id is missing");
1743                         resp.err = TRUE;
1744                         goto OUT;
1745                 }
1746
1747                 if (!g_slist_nth_data(tokens, 1)) {
1748                         err("function_id is missing");
1749                         resp.err = TRUE;
1750                         goto OUT;
1751                 }
1752
1753                 resp_str = g_slist_nth_data(tokens, 2);
1754                 if (resp_str) {
1755                         error = atoi(resp_str);
1756
1757                         if (0 == error) {
1758                                 dbg("Response is Success ");
1759                                 resp.err = FALSE;
1760                         } else {
1761                                 resp.err = TRUE;
1762                         }
1763                 }
1764
1765 OUT:
1766                 // Free tokens
1767                 tcore_at_tok_free(tokens);
1768         } else {
1769                 dbg("RESPONSE NOT OK");
1770
1771                 line = (const char *) response->final_response;
1772                 tokens = tcore_at_tok_new(line);
1773
1774                 if (g_slist_length(tokens) < 1) {
1775                         err("err cause not specified or string corrupted");
1776                         resp.err = TRUE;
1777                 } else {
1778                         error = atoi(g_slist_nth_data(tokens, 0));
1779
1780                         // TODO: CMEE error mapping is required.
1781                         resp.err = TRUE;
1782                 }
1783
1784                 // Free tokens
1785                 tcore_at_tok_free(tokens);
1786         }
1787
1788         if (ur) {
1789                 if (resp.err && soundvolume == FALSE) {  // Send only failed notification . success notification send when destination device is set.
1790                         // Send reposne to TAPI
1791                         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_sound_set_volume_level), &resp);
1792                         soundvolume = TRUE;
1793                 }
1794         } else {
1795                 err("User Request is NULL");
1796         }
1797
1798         dbg("Exit");
1799         return;
1800 }
1801
1802
1803 static void on_confirmation_call_set_destination_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data)
1804 {
1805         UserRequest *ur = NULL;
1806         GSList *tokens = NULL;
1807         const char *line = NULL;
1808         char *resp_str = NULL;
1809         const TcoreATResponse *response = data;
1810         struct tresp_call_sound_set_volume_level resp;
1811         gboolean error;
1812
1813         dbg("Entry");
1814
1815         ur = tcore_pending_ref_user_request(p);
1816
1817         // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]\ 3
1818         if (!response) {
1819                 err("Input data is NULL");
1820                 return;
1821         }
1822
1823         if (ur) {
1824                 if (response->success > 0) {
1825                         dbg("RESPONSE OK");
1826                         line = (const char *) (((GSList *) response->lines)->data);
1827                         tokens = tcore_at_tok_new(line);
1828                         resp_str = g_slist_nth_data(tokens, 0);
1829
1830                         if (!g_slist_nth_data(tokens, 0)) {
1831                                 err("group_id is missing");
1832                                 resp.err = TRUE;
1833                                 goto OUT;
1834                         }
1835
1836                         if (!g_slist_nth_data(tokens, 1)) {
1837                                 err("function_id is missing");
1838                                 resp.err = TRUE;
1839                                 goto OUT;
1840                         }
1841
1842                         resp_str = g_slist_nth_data(tokens, 2);
1843
1844                         if (resp_str) {
1845                                 error = atoi(resp_str);
1846
1847                                 if (0 == error) {
1848                                         dbg("Response is Success");
1849                                         resp.err = FALSE;
1850                                 } else {
1851                                         resp.err = TRUE;
1852                                 }
1853                         }
1854
1855 OUT:
1856                         // Free tokens
1857                         tcore_at_tok_free(tokens);
1858                 } else {
1859                         dbg("RESPONSE NOT OK");
1860
1861                         line = (const char *) response->final_response;
1862                         tokens = tcore_at_tok_new(line);
1863
1864                         if (g_slist_length(tokens) < 1) {
1865                                 err("err cause not specified or string corrupted");
1866                                 resp.err = TRUE;
1867                         } else {
1868                                 error = atoi(g_slist_nth_data(tokens, 0));
1869
1870                                 // TODO: CMEE error mapping is required.
1871                                 resp.err = TRUE;
1872                         }
1873
1874                         tcore_at_tok_free(tokens);
1875                 }
1876
1877                 if (soundvolume == TRUE) {
1878                         soundvolume = FALSE;
1879                 } else {
1880                         // Send reposne to TAPI
1881                         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_sound_set_volume_level), &resp);
1882                 }
1883         } else {
1884                 err("User Request is NULL");
1885         }
1886
1887         dbg("Exit");
1888         return;
1889 }
1890
1891
1892 static void on_confirmation_call_mute(TcorePending *p, int data_len, const void *data, void *user_data)
1893 {
1894         UserRequest *ur = NULL;
1895         GSList *tokens = NULL;
1896         const char *line = NULL;
1897         char *resp_str = NULL;
1898         struct tresp_call_mute resp;
1899         const TcoreATResponse *response = data;
1900         gboolean error;
1901
1902         dbg("Entry");
1903
1904         ur = tcore_pending_ref_user_request(p);
1905
1906         if (!response) {
1907                 err("Input data is NULL");
1908                 return;
1909         }
1910
1911         if (response->success > 0) {
1912                 dbg("RESPONSE OK");
1913
1914                 line = (const char *) (((GSList *) response->lines)->data);
1915                 tokens = tcore_at_tok_new(line);
1916                 resp_str = g_slist_nth_data(tokens, 0);
1917
1918                 if (!g_slist_nth_data(tokens, 0)) {
1919                         err("group_id is missing");
1920                         resp.err = TRUE;
1921                         goto OUT;
1922                 }
1923
1924                 if (!g_slist_nth_data(tokens, 1)) {
1925                         err(" function_id is missing");
1926                         resp.err = TRUE;
1927                         goto OUT;
1928                 }
1929
1930                 resp_str = g_slist_nth_data(tokens, 2);
1931
1932                 if (resp_str) {
1933                         error = atoi(resp_str);
1934                         if (0 == error) {
1935                                 dbg("Response is Success");
1936                                 resp.err = FALSE;
1937                         } else {
1938                                 resp.err = TRUE;
1939                         }
1940                 }
1941 OUT:
1942                 // Free tokens
1943                 tcore_at_tok_free(tokens);
1944         } else {
1945                 dbg("RESPONSE NOT OK");
1946
1947                 line = (const char *) response->final_response;
1948                 tokens = tcore_at_tok_new(line);
1949
1950                 if (g_slist_length(tokens) < 1) {
1951                         err("err cause not specified or string corrupted");
1952                         resp.err = TRUE;
1953                 } else {
1954                         error = atoi(g_slist_nth_data(tokens, 0));
1955
1956                         // TODO: CMEE error mapping is required.
1957                         resp.err = TRUE;
1958                 }
1959
1960                 // Free tokens
1961                 tcore_at_tok_free(tokens);
1962         }
1963
1964         if (ur) {
1965                 tcore_user_request_send_response(ur, TRESP_CALL_MUTE, sizeof(struct tresp_call_mute), &resp);
1966         } else {
1967                 err("User Request is NULL");
1968         }
1969
1970         dbg("Exit");
1971         return;
1972 }
1973
1974 static void on_confirmation_call_unmute(TcorePending *p, int data_len, const void *data, void *user_data)
1975 {
1976         const TcoreATResponse *response = NULL;
1977         struct tresp_call_unmute resp;
1978         GSList *tokens = NULL;
1979         const char *line = NULL;
1980         UserRequest *ur = NULL;
1981         char *resp_str = NULL;
1982         gboolean error;
1983
1984         dbg("Entry");
1985
1986         response = (TcoreATResponse *) data;
1987         ur = tcore_pending_ref_user_request(p);
1988
1989         if (!response) {
1990                 err("Input data is NULL");
1991                 return;
1992         }
1993
1994         if (response->success > 0) {
1995                 dbg("RESPONSE OK");
1996
1997                 line = (const char *) (((GSList *) response->lines)->data);
1998                 tokens = tcore_at_tok_new(line);
1999                 resp_str = g_slist_nth_data(tokens, 0);
2000
2001                 if (!g_slist_nth_data(tokens, 0)) {
2002                         err("group_id is missing");
2003                         resp.err = TRUE;
2004                         goto OUT;
2005                 }
2006
2007                 if (!g_slist_nth_data(tokens, 1)) {
2008                         err(" function_id is missing");
2009                         resp.err = TRUE;
2010                         goto OUT;
2011                 }
2012
2013                 resp_str = g_slist_nth_data(tokens, 2);
2014
2015                 if (resp_str) {
2016                         error = atoi(resp_str);
2017                         if (0 == error) {
2018                                 dbg("Response is Success");
2019                                 resp.err = FALSE;
2020                         } else {
2021                                 resp.err = TRUE;
2022                         }
2023                 }
2024 OUT:
2025                 // Free tokens
2026                 tcore_at_tok_free(tokens);
2027         } else {
2028                 dbg("RESPONSE NOT OK");
2029
2030                 line = (const char *) response->final_response;
2031                 tokens = tcore_at_tok_new(line);
2032
2033                 if (g_slist_length(tokens) < 1) {
2034                         err("err cause not specified or string corrupted");
2035                         resp.err = TRUE;
2036                 } else {
2037                         error = atoi(g_slist_nth_data(tokens, 0));
2038
2039                         // TODO: CMEE error mapping is required.
2040                         resp.err = TRUE;
2041                 }
2042
2043                 // Free tokens
2044                 tcore_at_tok_free(tokens);
2045         }
2046
2047         if (ur) {
2048                 tcore_user_request_send_response(ur, TRESP_CALL_UNMUTE, sizeof(struct tresp_call_unmute), &resp);
2049         } else {
2050                 err("User Request is NULL");
2051         }
2052
2053         dbg("Exit");
2054         return;
2055 }
2056
2057 // RESPONSE
2058 static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data)
2059 {
2060         TcorePlugin *plugin = NULL;
2061         CoreObject *core_obj = NULL;
2062         CallObject *co = NULL;
2063         struct clcc_call_t *call_list = NULL;
2064         gboolean *event_flag = (gboolean *) user_data;
2065         const TcoreATResponse *response = data;
2066         GSList *resp_data = NULL;
2067         char *line = NULL;
2068
2069         int cllc_info = 0, countCalls = 0, countValidCalls = 0;
2070         int error = 0;
2071
2072         dbg("Entry");
2073
2074         plugin = tcore_pending_ref_plugin(p);
2075         core_obj = tcore_pending_ref_core_object(p);
2076
2077         if (response->success > 0) {
2078                 dbg("RESPONCE OK");
2079                 if (response->lines) {
2080                         resp_data = (GSList *) response->lines;
2081                         countCalls = g_slist_length(resp_data);
2082                         dbg("Total records : %d", countCalls);
2083                 }
2084
2085                 if (0 == countCalls) {
2086                         err("Call count is zero");
2087                         if (event_flag) {
2088                                 g_free(event_flag);
2089                                 event_flag = NULL;
2090                         }
2091                         return;
2092                 }
2093
2094                 call_list = g_new0(struct clcc_call_t, countCalls);
2095
2096                 for (countValidCalls = 0; resp_data != NULL; resp_data = resp_data->next, countValidCalls++, cllc_info++) {
2097                         line = (char *) (resp_data->data);
2098
2099                         error = _callFromCLCCLine(line, call_list + countValidCalls);
2100                         if (0 != error) {
2101                                 continue;
2102                         }
2103
2104                         co = tcore_call_object_find_by_id(core_obj, call_list[cllc_info].info.id);
2105                         if (!co) {
2106                                 co = tcore_call_object_new(core_obj, call_list[cllc_info].info.id);
2107                                 if (!co) {
2108                                         err("error : tcore_call_object_new [ id : %d ]", call_list[cllc_info].info.id);
2109                                         continue;
2110                                 }
2111                         }
2112
2113                         // Call set parameters
2114                         tcore_call_object_set_type(co, call_type(call_list[cllc_info].info.type));
2115                         tcore_call_object_set_direction(co, call_list[cllc_info].info.direction);
2116                         tcore_call_object_set_multiparty_state(co, _call_is_in_mpty(call_list[cllc_info].info.mpty));
2117                         tcore_call_object_set_cli_info(co, CALL_CLI_MODE_DEFAULT, call_list[cllc_info].number);
2118                         tcore_call_object_set_active_line(co, 0);
2119
2120                         if (*event_flag) {
2121                                 dbg("Call status before calling _call_branch_by_status() : (%d)", call_list[cllc_info].info.status);
2122                                 _call_branch_by_status(plugin, co, call_list[cllc_info].info.status);
2123                         } else {
2124                                 // Set Status
2125                                 tcore_call_object_set_status(co, call_list[cllc_info].info.status);
2126
2127                                 dbg("Call id : (%d)", call_list[cllc_info].info.id);
2128                                 dbg("Call direction : (%d)", call_list[cllc_info].info.direction);
2129                                 dbg("Call type : (%d)", call_list[cllc_info].info.type);
2130                                 dbg("Call mpty : (%d)", call_list[cllc_info].info.mpty);
2131                                 dbg("Call number : (%s)", call_list[cllc_info].number);
2132                                 dbg("Call status : (%d)", call_list[cllc_info].info.status);
2133                         }
2134                 }
2135
2136                 // Free Call list
2137                 g_free(call_list);
2138         }
2139
2140         // Free User data
2141         if (event_flag) {
2142         g_free(event_flag);
2143                 event_flag = NULL;
2144         }
2145
2146         dbg("Exit");
2147         return;
2148 }
2149
2150 static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data)
2151 {
2152         TcorePlugin *plugin = NULL;
2153         CoreObject *core_obj = NULL;
2154         CallObject *co = (CallObject *) user_data;
2155         const TcoreATResponse *response = data;
2156         const char *line = NULL;
2157         struct tnoti_call_status_idle call_status;
2158         GSList *tokens = NULL;
2159         char *resp_str;
2160         int error;
2161
2162         dbg("Entry");
2163         plugin = tcore_pending_ref_plugin(p);
2164         core_obj = tcore_pending_ref_core_object(p);
2165
2166         if (response->success > 0) {
2167                 dbg("RESPONSE OK");
2168                 line = (const char *) (((GSList *) response->lines)->data);
2169                 tokens = tcore_at_tok_new(line);
2170                 resp_str = g_slist_nth_data(tokens, 0);
2171                 if (!resp_str) {
2172                         err("call end cause - report value missing");
2173                 } else {
2174                         resp_str = g_slist_nth_data(tokens, 1);
2175                         if (!resp_str) {
2176                                 err("call end cause value missing");
2177                         }
2178                         error = atoi(resp_str);
2179                         dbg("call end cause - %d", error);
2180                         call_status.cause = _compare_call_end_cause(error);
2181                         dbg("TAPI call end cause - %d", call_status.cause);
2182                 }
2183
2184                 // Free tokens
2185                 tcore_at_tok_free(tokens);
2186         } else {
2187                 err("RESPONSE NOT OK");
2188                 line = (char *) response->final_response;
2189                 tokens = tcore_at_tok_new(line);
2190                 if (g_slist_length(tokens) < 1) {
2191                         err("err cause not specified or string corrupted");
2192                 } else {
2193                         err(" err cause  value: %d", atoi(g_slist_nth_data(tokens, 0)));
2194                 }
2195                 call_status.cause = CC_CAUSE_NORMAL_CALL_CLEARING;
2196                 // Free tokens
2197                 tcore_at_tok_free(tokens);
2198         }
2199
2200         call_status.type = tcore_call_object_get_type(co);
2201         dbg("data.type : [%d]", call_status.type);
2202
2203         call_status.id = tcore_call_object_get_id(co);
2204         dbg("data.id : [%d]", call_status.id);
2205
2206         // Set Status
2207         tcore_call_object_set_status(co, TCORE_CALL_STATUS_IDLE);
2208
2209         // Send Notification to TAPI
2210         tcore_server_send_notification(tcore_plugin_ref_server(plugin),
2211                                                                    core_obj,
2212                                                                    TNOTI_CALL_STATUS_IDLE,
2213                                                                    sizeof(struct tnoti_call_status_idle),
2214                                                                    (void *) &call_status);
2215
2216         // Free Call object
2217         tcore_call_object_free(core_obj, co);
2218 }
2219
2220 static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call)
2221 {
2222         // +CLCC: 1,0,2,0,0,"18005551212",145
2223         // [+CLCC: <id1>, <dir>, <stat>, <mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>]]]
2224         int state;
2225         int mode;
2226         int isMT;
2227         char *num = NULL;
2228         unsigned int num_type;
2229         GSList *tokens = NULL;
2230         char *resp = NULL;
2231
2232         dbg("Entry");
2233
2234         tokens = tcore_at_tok_new(line);
2235         // parse <id>
2236         resp = g_slist_nth_data(tokens, 0);
2237         if (!resp) {
2238                 err("InValid ID");
2239                 goto ERROR;
2240         }
2241         p_call->info.id = atoi(resp);
2242         dbg("id : [%d]\n", p_call->info.id);
2243
2244         // parse <dir>
2245         resp = g_slist_nth_data(tokens, 1);
2246         if (!resp) {
2247                 err("InValid Dir");
2248                 goto ERROR;
2249         }
2250         isMT = atoi(resp);
2251         if (0 == isMT) {
2252                 p_call->info.direction = TCORE_CALL_DIRECTION_OUTGOING;
2253         } else {
2254                 p_call->info.direction = TCORE_CALL_DIRECTION_INCOMING;
2255         }
2256         dbg("Direction : [ %d ]\n", p_call->info.direction);
2257
2258         // parse <stat>
2259         resp = g_slist_nth_data(tokens, 2);
2260         if (!resp) {
2261                 err("InValid Stat");
2262                 goto ERROR;
2263         }
2264         state = atoi(resp);
2265         dbg("Call state : %d", state);
2266         switch (state) {
2267         case 0:     // active
2268                 p_call->info.status = TCORE_CALL_STATUS_ACTIVE;
2269                 break;
2270
2271         case 1:
2272                 p_call->info.status = TCORE_CALL_STATUS_HELD;
2273                 break;
2274
2275         case 2:
2276                 p_call->info.status = TCORE_CALL_STATUS_DIALING;
2277                 break;
2278
2279         case 3:
2280                 p_call->info.status = TCORE_CALL_STATUS_ALERT;
2281                 break;
2282
2283         case 4:
2284                 p_call->info.status = TCORE_CALL_STATUS_INCOMING;
2285                 break;
2286
2287         case 5:
2288                 p_call->info.status = TCORE_CALL_STATUS_WAITING;
2289                 break;
2290         }
2291         dbg("Status : [%d]\n", p_call->info.status);
2292
2293         // parse <mode>
2294         resp = g_slist_nth_data(tokens, 3);
2295         if (!resp) {
2296                 err("InValid Mode");
2297                 goto ERROR;
2298         }
2299         mode = atoi(resp);
2300         switch (mode) {
2301         case 0:
2302                 p_call->info.type = TCORE_CALL_TYPE_VOICE;
2303                 break;
2304
2305         case 1:
2306                 p_call->info.type = TCORE_CALL_TYPE_VIDEO;
2307                 break;
2308
2309         default:        // only Voice/VT call is supported in CS. treat other unknown calls as error
2310                 dbg("invalid type : [%d]\n", mode);
2311                 goto ERROR;
2312         }
2313         dbg("Call type : [%d]\n", p_call->info.type);
2314
2315         // parse <mpty>
2316         resp = g_slist_nth_data(tokens, 4);
2317         if (!resp) {
2318                 err("InValid Mpty");
2319                 goto ERROR;
2320         }
2321
2322         p_call->info.mpty = atoi(resp);
2323         dbg("Mpty : [ %d ]\n", p_call->info.mpty);
2324
2325         // parse <num>
2326         resp = g_slist_nth_data(tokens, 5);
2327         dbg("Incoming number - %s and its len  - %d", resp, strlen(resp));
2328
2329         // tolerate null here
2330         if (!resp) {
2331                 err("Number is NULL");
2332                 goto ERROR;
2333         }
2334         // Strike off double quotes
2335         num = util_removeQuotes(resp);
2336         dbg("num  after removing quotes - %s", num);
2337
2338         p_call->info.num_len = strlen(resp);
2339         dbg("num_len : [0x%x]\n", p_call->info.num_len);
2340
2341         // parse <num type>
2342         resp = g_slist_nth_data(tokens, 6);
2343         if (!resp) {
2344                 dbg("InValid Num type");
2345                 goto ERROR;
2346         }
2347         p_call->info.num_type = atoi(resp);
2348         dbg("BCD num type: [0x%x]\n", p_call->info.num_type);
2349
2350         // check number is international or national.
2351         num_type = ((p_call->info.num_type) >> 4) & 0x07;
2352         dbg("called party's type of number : [0x%x]\n", num_type);
2353
2354         if (num_type == 1 && num[0] != '+') {
2355                 // international number
2356                 p_call->number[0] = '+';
2357                 memcpy(&(p_call->number[1]), num, strlen(num));
2358         } else {
2359                 memcpy(&(p_call->number), num, strlen(num));
2360         }
2361         dbg("incoming number - %s", p_call->number);
2362
2363         g_free(num);
2364         num = NULL;
2365         // Free tokens
2366         tcore_at_tok_free(tokens);
2367
2368         dbg("Exit");
2369         return 0;
2370
2371 ERROR:
2372         err("Invalid CLCC line");
2373
2374         g_free(num);
2375
2376         // Free tokens
2377         tcore_at_tok_free(tokens);
2378         err("Exit");
2379         return -1;
2380 }
2381
2382 // NOTIFICATION
2383 static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data)
2384 {
2385         GSList *tokens = NULL;
2386         const char *line = NULL;
2387         char *pId;
2388         int call_id;
2389         gboolean *eflag;
2390         GSList *pList = NULL;
2391         CallObject *co = NULL, *dupco = NULL;
2392
2393         dbg("function entrance");
2394         // check call with waiting status already exist
2395         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_WAITING);
2396
2397         if (pList != NULL) {
2398                 dbg("[error]Waiting call already exist. skip");
2399                 return;
2400         }
2401         // check call with incoming status already exist
2402         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
2403
2404         if (pList != NULL) {
2405                 dbg("[error]incoming call already exist. skip");
2406                 return;
2407         }
2408         line = (char *) data;
2409         tokens = tcore_at_tok_new(line);
2410
2411         pId = g_slist_nth_data(tokens, 0);
2412         if (!pId) {
2413                 dbg("[error]:Call id is missing from +XCALLSTAT indication");
2414                 tcore_at_tok_free(tokens);
2415                 return;
2416         }
2417
2418         call_id = atoi(pId);
2419         dupco = tcore_call_object_find_by_id(o, call_id);
2420         if (dupco != NULL) {
2421                 dbg("co with same id already exist. skip");
2422                 tcore_at_tok_free(tokens);
2423                 return;
2424         }
2425         co = tcore_call_object_new(o, call_id);
2426         if (!co) {
2427                 dbg("[ error ] co is NULL");
2428                 tcore_at_tok_free(tokens);
2429                 return;
2430         }
2431
2432         tcore_at_tok_free(tokens);
2433
2434         eflag = g_new0(gboolean, 1);
2435         *eflag = TRUE;
2436         dbg("calling _call_list_get");
2437         _call_list_get(o, eflag);
2438 }
2439
2440 static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data)
2441 {
2442         GSList *tokens = NULL;
2443         const char *line = NULL;
2444         char *pId;
2445         int call_id;
2446         gboolean *eflag;
2447         GSList *pList = NULL;
2448         CallObject *co = NULL, *dupco = NULL;
2449
2450         dbg("function entrance");
2451         // check call with incoming status already exist
2452         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
2453
2454         if (pList != NULL) {
2455                 dbg("incoming call already exist. skip");
2456                 return;
2457         }
2458
2459         line = (char *) data;
2460         tokens = tcore_at_tok_new(line);
2461
2462         pId = g_slist_nth_data(tokens, 0);
2463         if (!pId) {
2464                 dbg("Error:Call id is missing from %XCALLSTAT indication");
2465                 tcore_at_tok_free(tokens);
2466                 return;
2467         }
2468
2469         call_id = atoi(pId);
2470
2471         dupco = tcore_call_object_find_by_id(o, call_id);
2472         if (dupco != NULL) {
2473                 dbg("co with same id already exist. skip");
2474                 tcore_at_tok_free(tokens);
2475                 return;
2476         }
2477
2478         co = tcore_call_object_new(o, call_id);
2479         if (!co) {
2480                 dbg("[ error ] co is NULL");
2481                 tcore_at_tok_free(tokens);
2482                 return;
2483         }
2484
2485         dbg("freeing  at token");
2486         tcore_at_tok_free(tokens);
2487
2488         eflag = g_new0(gboolean, 1);
2489         *eflag = TRUE;
2490
2491         dbg("calling  _call_list_get");
2492         _call_list_get(o, eflag);
2493 }
2494
2495 static void on_notification_call_status(CoreObject *o, const void *data, void *user_data)
2496 {
2497         char *cmd = NULL;
2498         TcorePlugin *plugin = NULL;
2499         CallObject *co = NULL;
2500         int id = -1;
2501         int status = 0;
2502         int type = 0;
2503         char *stat = NULL;
2504         char *pCallId = NULL;
2505         GSList *tokens = NULL;
2506         gboolean *eflag = NULL;
2507         enum tcore_call_status co_status;
2508
2509         dbg("function entrance");
2510         plugin = tcore_object_ref_plugin(o);
2511         cmd = (char *) data;
2512         tokens = tcore_at_tok_new(cmd);
2513
2514         // parse <Call Id>
2515         pCallId = g_slist_nth_data(tokens, 0);
2516         if (!pCallId) {
2517                 dbg("CallId is missing from %XCALLSTAT indication");
2518                 tcore_at_tok_free(tokens);
2519                 return;
2520         } else {
2521                 id = atoi(pCallId);
2522                 dbg("call id = %d", id);
2523                 // parse <Stat>
2524                 if ((stat = g_slist_nth_data(tokens, 1))) {
2525                         status = atoi(stat);
2526                 }
2527                 dbg("call status = %d", status);
2528         }
2529
2530         tcore_at_tok_free(tokens);
2531         co_status = _call_status(status);
2532
2533         dbg("co_status = %d", co_status);
2534         switch (co_status) {
2535         case CALL_STATUS_ACTIVE:
2536         {
2537                 dbg("call(%d) status : [ ACTIVE ]", id);
2538                 co = tcore_call_object_find_by_id(o, id);
2539                 if (!co) {
2540                         dbg("co is NULL");
2541                         return;
2542                 }
2543                 _call_status_active(plugin, co);
2544         }
2545         break;
2546
2547         case CALL_STATUS_HELD:
2548                 dbg("call(%d) status : [ held ]", id);
2549                 break;
2550
2551         case CALL_STATUS_DIALING:
2552         {
2553                 dbg("call(%d) status : [ dialing ]", id);
2554                 co = tcore_call_object_find_by_id(o, id);
2555                 if (!co) {
2556                         co = tcore_call_object_new(o, id);
2557                         if (!co) {
2558                                 dbg("error : tcore_call_object_new [ id : %d ]", id);
2559                                 return;
2560                         }
2561                 }
2562
2563                 tcore_call_object_set_type(co, call_type(type));
2564                 tcore_call_object_set_direction(co, TCORE_CALL_DIRECTION_OUTGOING);
2565                 _call_status_dialing(plugin, co);
2566         }
2567         break;
2568
2569         case CALL_STATUS_ALERT:
2570         {
2571                 dbg("call(%d) status : [ alert ]", id);
2572                 co = tcore_call_object_find_by_id(o, id);
2573                 if (!co) {
2574                         dbg("co is NULL");
2575                         return;
2576                 }
2577                 // Store dialed number information into Call object.
2578                 eflag = g_new0(gboolean, 1);
2579                 *eflag = TRUE;
2580                 dbg("calling _call_list_get");
2581                 _call_list_get(o, eflag);
2582         }
2583         break;
2584
2585         case CALL_STATUS_INCOMING:
2586         case CALL_STATUS_WAITING:
2587                 dbg("call(%d) status : [ incoming ]", id);
2588                 break;
2589
2590         case CALL_STATUS_IDLE:
2591         {
2592                 dbg("call(%d) status : [ release ]", id);
2593
2594                 co = tcore_call_object_find_by_id(o, id);
2595                 if (!co) {
2596                         dbg("co is NULL");
2597                         return;
2598                 }
2599
2600                 plugin = tcore_object_ref_plugin(o);
2601                 if (!plugin) {
2602                         dbg("plugin is NULL");
2603                         return;
2604                 }
2605                 _call_status_idle(plugin, co);
2606         }
2607         break;
2608
2609         default:
2610                 dbg("invalid call status", id);
2611                 break;
2612         }
2613 }
2614
2615 static TReturn s_call_outgoing(CoreObject *o, UserRequest *ur)
2616 {
2617         struct treq_call_dial *data = 0;
2618         char *cmd_str;
2619         const char *cclir, *num;
2620         enum tcore_call_cli_mode clir = CALL_CLI_MODE_DEFAULT;
2621         TcorePending *pending;
2622         TcoreATRequest *req;
2623         gboolean ret;
2624
2625         dbg("Entry");
2626
2627         data = (struct treq_call_dial *) tcore_user_request_ref_data(ur, 0);
2628         if (data->type == CALL_TYPE_VIDEO) {
2629                 dbg("invalid call type");
2630                 return TCORE_RETURN_FAILURE;
2631         }
2632
2633         clir = _get_clir_status(data->number);
2634
2635         if (clir == TCORE_CALL_CLI_MODE_DEFAULT) {
2636                 TcorePlugin *plugin = tcore_object_ref_plugin(o);
2637                 Server *server = tcore_plugin_ref_server(plugin);
2638                 Storage *strg;
2639
2640                 dbg("Reading VCONF key");
2641
2642                 strg = tcore_server_find_storage(server, "vconf");
2643                 clir = tcore_storage_get_int(strg,
2644                                 STORAGE_KEY_CISSAPPL_SHOW_MY_NUMBER_INT);
2645
2646                 num = data->number;
2647         } else
2648                 /* Need to remove CLIR code from dialing number */
2649                 num = data->number + 4;
2650
2651         /* Compose ATD Cmd string */
2652         switch (clir) {
2653         case TCORE_CALL_CLI_MODE_PRESENT:
2654                 dbg("CALL_CLI_MODE_PRESENT");
2655                 cclir = "i";
2656                 break;
2657
2658         case TCORE_CALL_CLI_MODE_RESTRICT:
2659                 dbg("CALL_CLI_MODE_RESTRICT");
2660                 cclir = "I";
2661                 break;
2662
2663         case TCORE_CALL_CLI_MODE_DEFAULT:
2664         default:
2665                 cclir = "";
2666                 dbg("CALL_CLI_MODE_DEFAULT");
2667                 break;
2668         }
2669
2670         dbg("data->number = %s", data->number);
2671
2672         cmd_str = g_strdup_printf("ATD%s%s;", num, cclir);
2673
2674         dbg("request command : %s", cmd_str);
2675
2676         pending = tcore_pending_new(o, 0);
2677         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2678         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2679
2680         tcore_pending_set_request_data(pending, 0, req);
2681         ret = _call_request_message(pending, o, ur, on_confirmation_call_outgoing, NULL);
2682
2683         g_free(cmd_str);
2684
2685         if (ret == FALSE) {
2686                 dbg("AT request(%s) sent failed", req->cmd);
2687                 return TCORE_RETURN_FAILURE;
2688         }
2689
2690         dbg("AT request(%s) sent success", req->cmd);
2691
2692         dbg("Exit");
2693
2694         return TCORE_RETURN_SUCCESS;
2695 }
2696
2697 static TReturn s_call_answer(CoreObject *o, UserRequest *ur)
2698 {
2699         char *cmd_str = NULL;
2700         CallObject *co = NULL;
2701         struct treq_call_answer *data = 0;
2702         TcorePending *pending = NULL;
2703         TcoreATRequest *req;
2704         gboolean ret = FALSE;
2705
2706         dbg("function entrance");
2707
2708         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2709                 dbg("cp not ready/n");
2710                 return TCORE_RETURN_ENOSYS;
2711         }
2712
2713         data = (struct treq_call_answer *) tcore_user_request_ref_data(ur, 0);
2714         co = tcore_call_object_find_by_id(o, data->id);
2715         if (data->type == CALL_ANSWER_TYPE_ACCEPT) {
2716                 dbg(" request type CALL_ANSWER_TYPE_ACCEPT");
2717
2718                 cmd_str = g_strdup_printf("%s", "ATA");
2719                 pending = tcore_pending_new(o, 0);
2720                 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2721                 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2722
2723                 tcore_pending_set_request_data(pending, 0, req);
2724                 ret = _call_request_message(pending, o, ur, on_confirmation_call_accept, co);
2725                 g_free(cmd_str);
2726
2727                 if (!ret) {
2728                         dbg("AT request(%s) sent failed", req->cmd);
2729                         return TCORE_RETURN_FAILURE;
2730                 }
2731         } else {
2732                 switch (data->type) {
2733                 case CALL_ANSWER_TYPE_REJECT:
2734                 {
2735                         dbg("call answer reject");
2736                         tcore_call_control_answer_reject(o, ur, on_confirmation_call_reject, co);
2737                 }
2738                 break;
2739
2740                 case CALL_ANSWER_TYPE_REPLACE:
2741                 {
2742                         dbg("call answer replace");
2743                         tcore_call_control_answer_replace(o, ur, on_confirmation_call_replace, co);
2744                 }
2745                 break;
2746
2747                 case CALL_ANSWER_TYPE_HOLD_ACCEPT:
2748                 {
2749                         dbg("call answer hold and accept");
2750                         tcore_call_control_answer_hold_and_accept(o, ur, on_confirmation_call_hold_and_accept, co);
2751                 }
2752                 break;
2753
2754                 default:
2755                         dbg("[ error ] wrong answer type [ %d ]", data->type);
2756                         return TCORE_RETURN_FAILURE;
2757                 }
2758         }
2759
2760         return TCORE_RETURN_SUCCESS;
2761 }
2762
2763 static TReturn s_call_release(CoreObject *o, UserRequest *ur)
2764 {
2765         CallObject *co = NULL;
2766         struct treq_call_end *data = 0;
2767         UserRequest *ur_dup = NULL;
2768         char *chld0_cmd = NULL;
2769         char *chld1_cmd = NULL;
2770         TcorePending *pending = NULL, *pending1 = NULL;
2771         TcoreATRequest *req, *req1;
2772         gboolean ret = FALSE;
2773
2774         dbg("function entrance");
2775         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2776                 dbg("cp not ready/n");
2777                 return TCORE_RETURN_ENOSYS;
2778         }
2779         data = (struct treq_call_end *) tcore_user_request_ref_data(ur, 0);
2780         co = tcore_call_object_find_by_id(o, data->id);
2781
2782         dbg("type of release call = %d", data->type);
2783
2784         if (data->type == CALL_END_TYPE_ALL) {
2785                 // releaseAll do not exist on legacy request. send CHLD=0, CHLD=1 in sequence
2786                 chld0_cmd = g_strdup("AT+CHLD=0");
2787                 chld1_cmd = g_strdup("AT+CHLD=1");
2788
2789                 pending = tcore_pending_new(o, 0);
2790                 req = tcore_at_request_new(chld0_cmd, NULL, TCORE_AT_NO_RESULT);
2791
2792                 dbg("input command is %s", chld0_cmd);
2793                 dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2794
2795                 tcore_pending_set_request_data(pending, 0, req);
2796                 ur_dup = tcore_user_request_new(NULL, NULL);
2797                 ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_endall, NULL);
2798                 g_free(chld0_cmd);
2799
2800                 if (!ret) {
2801                         dbg("AT request %s has failed ", req->cmd);
2802                         if (ur_dup) {
2803                                 tcore_user_request_free(ur_dup);
2804                                 ur_dup = NULL;
2805                         }
2806                         g_free(chld1_cmd);
2807                         return TCORE_RETURN_FAILURE;
2808                 }
2809
2810                 pending1 = tcore_pending_new(o, 0);
2811                 req1 = tcore_at_request_new(chld1_cmd, NULL, TCORE_AT_NO_RESULT);
2812
2813                 dbg("input command is %s", chld1_cmd);
2814                 dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd));
2815
2816                 tcore_pending_set_request_data(pending1, 0, req1);
2817                 ret = _call_request_message(pending1, o, ur, on_confirmation_call_release_all, co);
2818                 g_free(chld1_cmd);
2819
2820                 if (!ret) {
2821                         dbg("AT request %s has failed ", req->cmd);
2822                         return TCORE_RETURN_FAILURE;
2823                 }
2824         } else {
2825                 switch (data->type) {
2826                 case CALL_END_TYPE_DEFAULT:
2827                 {
2828                         int id = 0;
2829                         id = tcore_call_object_get_id(co);
2830
2831                         dbg("call end call id [%d]", id);
2832                         tcore_call_control_end_specific(o, ur, id, on_confirmation_call_release_specific, co);
2833                 }
2834                 break;
2835
2836                 case CALL_END_TYPE_ACTIVE_ALL:
2837                 {
2838                         dbg("call end all active");
2839                         tcore_call_control_end_all_active(o, ur, on_confirmation_call_release_all_active, co);
2840                 }
2841                 break;
2842
2843                 case CALL_END_TYPE_HOLD_ALL:
2844                 {
2845                         dbg("call end all held");
2846                         tcore_call_control_end_all_held(o, ur, on_confirmation_call_release_all_held, co);
2847                 }
2848                 break;
2849
2850                 default:
2851                         dbg("[ error ] wrong end type [ %d ]", data->type);
2852                         return TCORE_RETURN_FAILURE;
2853                 }
2854         }
2855
2856         return TCORE_RETURN_SUCCESS;
2857 }
2858
2859 static TReturn s_call_hold(CoreObject *o, UserRequest *ur)
2860 {
2861         struct treq_call_hold *hold = 0;
2862         CallObject *co = NULL;
2863
2864         dbg("function entrance");
2865
2866         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2867                 dbg("cp not ready/n");
2868                 return TCORE_RETURN_ENOSYS;
2869         }
2870
2871         hold = (struct treq_call_hold *) tcore_user_request_ref_data(ur, 0);
2872         dbg("call id : [ %d ]", hold->id);
2873
2874         co = tcore_call_object_find_by_id(o, hold->id);
2875         tcore_call_control_hold(o, ur, on_confirmation_call_hold, co);
2876
2877         return TCORE_RETURN_SUCCESS;
2878 }
2879
2880 static TReturn s_call_active(CoreObject *o, UserRequest *ur)
2881 {
2882         struct treq_call_active *active = 0;
2883         CallObject *co = NULL;
2884
2885         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2886                 dbg("cp not ready/n");
2887                 return TCORE_RETURN_ENOSYS;
2888         }
2889
2890         active = (struct treq_call_active *) tcore_user_request_ref_data(ur, 0);
2891         dbg("call id : [ %d ]", active->id);
2892
2893         co = tcore_call_object_find_by_id(o, active->id);
2894         tcore_call_control_active(o, ur, on_confirmation_call_active, co);
2895
2896         return TCORE_RETURN_SUCCESS;
2897 }
2898
2899 static TReturn s_call_swap(CoreObject *o, UserRequest *ur)
2900 {
2901         struct treq_call_swap *swap = NULL;
2902         CallObject *co = NULL;
2903
2904         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2905                 dbg("cp not ready/n");
2906                 return TCORE_RETURN_ENOSYS;
2907         }
2908
2909         swap = (struct treq_call_swap *) tcore_user_request_ref_data(ur, 0);
2910         dbg("call id : [ %d ]", swap->id);
2911
2912         co = tcore_call_object_find_by_id(o, swap->id);
2913         tcore_call_control_swap(o, ur, on_confirmation_call_swap, co);
2914
2915         return TCORE_RETURN_SUCCESS;
2916 }
2917
2918 static TReturn s_call_join(CoreObject *o, UserRequest *ur)
2919 {
2920         struct treq_call_join *join = 0;
2921         CallObject *co = NULL;
2922
2923         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2924                 dbg("cp not ready/n");
2925                 return TCORE_RETURN_ENOSYS;
2926         }
2927
2928         join = (struct treq_call_join *) tcore_user_request_ref_data(ur, 0);
2929         dbg("call id : [ %d ]", join->id);
2930
2931         co = tcore_call_object_find_by_id(o, join->id);
2932         tcore_call_control_join(o, ur, on_confirmation_call_join, co);
2933
2934         return TCORE_RETURN_SUCCESS;
2935 }
2936
2937 static TReturn s_call_split(CoreObject *o, UserRequest *ur)
2938 {
2939         struct treq_call_split *split = 0;
2940         CallObject *co = NULL;
2941
2942         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2943                 dbg("cp not ready/n");
2944                 return TCORE_RETURN_ENOSYS;
2945         }
2946
2947         split = (struct treq_call_split *) tcore_user_request_ref_data(ur, 0);
2948         co = tcore_call_object_find_by_id(o, split->id);
2949         dbg("call id : [ %d ]", split->id);
2950
2951         tcore_call_control_split(o, ur, split->id, on_confirmation_call_split, co);
2952
2953         return TCORE_RETURN_SUCCESS;
2954 }
2955
2956 static TReturn s_call_deflect(CoreObject *o, UserRequest *ur)
2957 {
2958         struct treq_call_deflect *deflect = 0;
2959         CallObject *co = NULL;
2960
2961         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2962                 dbg("cp not ready/n");
2963                 return TCORE_RETURN_ENOSYS;
2964         }
2965
2966         deflect = (struct treq_call_deflect *) tcore_user_request_ref_data(ur, 0);
2967         co = tcore_call_object_find_by_number(o, deflect->number);
2968         dbg("deflect number: [ %s ]", deflect->number);
2969
2970         tcore_call_control_deflect(o, ur, deflect->number, on_confirmation_call_deflect, co);
2971
2972         return TCORE_RETURN_SUCCESS;
2973 }
2974
2975 static TReturn s_call_transfer(CoreObject *o, UserRequest *ur)
2976 {
2977         struct treq_call_transfer *transfer = 0;
2978         CallObject *co = NULL;
2979
2980         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2981                 dbg("cp not ready/n");
2982                 return TCORE_RETURN_ENOSYS;
2983         }
2984
2985         transfer = (struct treq_call_transfer *) tcore_user_request_ref_data(ur, 0);
2986         dbg("call id : [ %d ]", transfer->id);
2987
2988         co = tcore_call_object_find_by_id(o, transfer->id);
2989         tcore_call_control_transfer(o, ur, on_confirmation_call_transfer, co);
2990
2991         return TCORE_RETURN_SUCCESS;
2992 }
2993
2994 static TReturn s_call_send_dtmf(CoreObject *o, UserRequest *ur)
2995 {
2996         char *cmd_str = NULL;
2997         TcorePending *pending = NULL;
2998         TcoreATRequest *req;
2999         UserRequest *dup;
3000         gboolean ret = FALSE;
3001         struct treq_call_dtmf *dtmf = 0;
3002         char *dtmfstr = NULL, *tmp_dtmf = NULL;
3003         unsigned int dtmf_count;
3004
3005         dbg("Function enter");
3006
3007         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3008                 dbg("cp not ready/n");
3009                 return TCORE_RETURN_ENOSYS;
3010         }
3011
3012         dup = tcore_user_request_new(NULL, NULL);
3013         (void) _set_dtmf_tone_duration(o, dup);
3014
3015         dtmf = (struct treq_call_dtmf *) tcore_user_request_ref_data(ur, 0);
3016         dtmfstr = g_malloc0((MAX_CALL_DTMF_DIGITS_LEN * 2) + 1);    // DTMF digits + comma for each dtmf digit.
3017
3018         if (dtmfstr == NULL) {
3019                 dbg("Memory allocation failed");
3020                 return TCORE_RETURN_FAILURE;
3021         }
3022
3023         tmp_dtmf = dtmfstr;
3024
3025         for (dtmf_count = 0; dtmf_count < strlen(dtmf->digits); dtmf_count++) {
3026                 *tmp_dtmf = dtmf->digits[dtmf_count];
3027                 tmp_dtmf++;
3028
3029                 *tmp_dtmf = COMMA;
3030                 tmp_dtmf++;
3031         }
3032
3033         // last digit is having COMMA , overwrite it with '\0' .
3034         *(--tmp_dtmf) = '\0';
3035         dbg("Input DTMF string(%s)", dtmfstr);
3036
3037         // AT+VTS = <d1>,<d2>,<d3>,<d4>,<d5>,<d6>, ..... <d32>
3038         cmd_str = g_strdup_printf("AT+VTS=%s", dtmfstr);
3039         dbg("request command : %s", cmd_str);
3040
3041         pending = tcore_pending_new(o, 0);
3042         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
3043         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3044
3045         tcore_pending_set_request_data(pending, 0, req);
3046         ret = _call_request_message(pending, o, ur, on_confirmation_call_dtmf, NULL);
3047         g_free(dtmfstr);
3048         g_free(cmd_str);
3049
3050         if (!ret) {
3051                 dbg("AT request sent failed");
3052                 return TCORE_RETURN_FAILURE;
3053         }
3054
3055         return TCORE_RETURN_SUCCESS;
3056 }
3057
3058 static TReturn s_call_set_sound_path(CoreObject *o, UserRequest *ur)
3059 {
3060         UserRequest *ur_dup = NULL;
3061         TcorePending *pending = NULL, *pending1 = NULL;
3062         TcoreATRequest *req, *req1;
3063         char *cmd_str = NULL, *cmd_str1 = NULL;
3064         int device_type = -1;
3065         struct treq_call_sound_set_path *sound_path = 0;
3066         gboolean ret = FALSE;
3067         TcorePlugin *plugin = tcore_object_ref_plugin(o);
3068         const char *cp_name = tcore_server_get_cp_name_by_plugin(plugin);
3069
3070         dbg("function entrance");
3071
3072         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3073                 dbg("cp not ready/n");
3074                 return TCORE_RETURN_ENOSYS;
3075         }
3076         sound_path = (struct treq_call_sound_set_path *) tcore_user_request_ref_data(ur, 0);
3077         if (sound_path == NULL) {
3078                 dbg("invaling user request");
3079                 return TCORE_RETURN_FAILURE;
3080         }
3081         dbg("audio device type - 0x%x", sound_path->path);
3082         switch (sound_path->path) {
3083         case CALL_SOUND_PATH_HANDSET:
3084                 device_type = 1;
3085                 break;
3086
3087         case CALL_SOUND_PATH_HEADSET:
3088                 device_type = 2;
3089                 break;
3090
3091         case CALL_SOUND_PATH_HEADSET_3_5PI:
3092                 device_type = 3;
3093                 break;
3094
3095         case CALL_SOUND_PATH_SPEAKER:
3096                 device_type = 4;
3097                 break;
3098
3099         case CALL_SOUND_PATH_HANDFREE:
3100                 device_type = 5;
3101                 break;
3102
3103         case CALL_SOUND_PATH_HEADSET_HAC:
3104                 device_type = 6;
3105                 break;
3106
3107         case CALL_SOUND_PATH_BLUETOOTH:
3108         case CALL_SOUND_PATH_STEREO_BLUETOOTH:
3109                 device_type = 7;
3110                 break;
3111
3112         case CALL_SOUND_PATH_BT_NSEC_OFF:
3113         case CALL_SOUND_PATH_MIC1:
3114         case CALL_SOUND_PATH_MIC2:
3115         default:
3116                 dbg("unsupported device type");
3117                 return TCORE_RETURN_FAILURE;
3118         }
3119
3120         if (g_str_has_prefix(cp_name, "mfld_blackbay") == TRUE) {
3121                 struct tnoti_call_sound_path *tnoti_snd_path;
3122
3123                 tnoti_snd_path = g_try_new0(struct tnoti_call_sound_path, 1);
3124                 if (!tnoti_snd_path)
3125                         return TCORE_RETURN_ENOMEM;
3126
3127                 tnoti_snd_path->path = sound_path->path;
3128
3129                 /* Configure modem I2S1 to 8khz, mono, PCM if routing to bluetooth */
3130                 if (sound_path->path == CALL_SOUND_PATH_BLUETOOTH || sound_path->path == CALL_SOUND_PATH_STEREO_BLUETOOTH) {
3131                         call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,3,0,1,0,0,0,0,0,0,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3132                         call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,2,0,1,0,0,0,0,0,0,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3133                 }
3134                 else {
3135                         call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,3,0,1,0,8,0,1,0,2,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3136                         call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,2,0,1,0,8,0,1,0,2,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3137                 }
3138
3139                 /* Configure modem I2S2 and do the modem routing */
3140                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,4,0,0,0,8,0,1,0,2,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3141                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,3,0,0,0,8,0,1,0,2,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3142                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,0,4", NULL, TCORE_AT_NO_RESULT, NULL);
3143                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,3,0", NULL, TCORE_AT_NO_RESULT, NULL);
3144                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,4,2", NULL, TCORE_AT_NO_RESULT, NULL);
3145                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,5,2", NULL, TCORE_AT_NO_RESULT, NULL);
3146
3147                 /* amc enable */
3148                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,2,4", NULL, TCORE_AT_NO_RESULT, NULL); //AMC_I2S2_RX
3149                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,2,3", NULL, TCORE_AT_NO_RESULT, NULL); //AMC_I2S1_RX
3150                 /* amc route: AMC_RADIO_RX => AMC_I2S1_TX */
3151
3152                 pending = tcore_pending_new(o, 0);
3153                 req = tcore_at_request_new("AT+XDRV=40,6,0,2", "+XDRV", TCORE_AT_SINGLELINE);
3154                 dbg("XDRV req-cmd for source type  : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3155                 tcore_pending_set_request_data(pending, 0, req);
3156                 ur_dup = tcore_user_request_ref(ur);
3157                 ret = _call_request_message(pending, o, ur_dup, on_confirmation_set_sound_path, tnoti_snd_path);
3158
3159         } else {
3160
3161                 cmd_str = g_strdup_printf("AT+XDRV=40,4,3,0,0,0,0,0,1,0,1,0,%d",device_type); // source type.
3162                 pending = tcore_pending_new(o, 0);
3163                 req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3164                 dbg("XDRV req-cmd for source type  : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3165                 tcore_pending_set_request_data(pending, 0, req);
3166                 ur_dup = tcore_user_request_ref(ur);
3167                 ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_set_source_sound_path, NULL);
3168                 g_free(cmd_str);
3169
3170                 if (!ret) {
3171                         dbg("At request(%s) sent failed", req->cmd);
3172                         return TCORE_RETURN_FAILURE;
3173                 }
3174
3175                 cmd_str1 = g_strdup_printf("AT+XDRV=40,5,2,0,0,0,0,0,1,0,1,0,%d",device_type); // destination type
3176                 pending1 = tcore_pending_new(o, 0);
3177                 req1 = tcore_at_request_new(cmd_str1, "+XDRV", TCORE_AT_SINGLELINE);
3178                 dbg("XDRV req-cmd for destination type : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd));
3179                 tcore_pending_set_request_data(pending1, 0, req1);
3180                 ret = _call_request_message(pending1, o, ur, on_confirmation_call_set_destination_sound_path, NULL);
3181                 g_free(cmd_str1);
3182
3183                 if (!ret) {
3184                         dbg("AT request %s has failed ", req1->cmd);
3185                         return TCORE_RETURN_FAILURE;
3186                 }
3187         }
3188
3189         return TCORE_RETURN_SUCCESS;
3190 }
3191
3192 static TReturn s_call_set_sound_volume_level(CoreObject *o, UserRequest *ur)
3193 {
3194         UserRequest *src_ur = NULL;
3195         UserRequest *dest_ur = NULL;
3196         TcorePending *src_pending = NULL;
3197         TcorePending *dest_pending = NULL;
3198         TcoreATRequest *src_req = NULL;
3199         TcoreATRequest *dest_req = NULL;
3200         char *cmd_str = NULL, *volume_level = NULL;
3201         gboolean ret = FALSE;
3202         struct treq_call_sound_set_volume_level *data = NULL;
3203
3204         dbg("Entry");
3205
3206         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3207                 dbg("cp not ready/n");
3208                 return TCORE_RETURN_ENOSYS;
3209         }
3210
3211         data = (struct treq_call_sound_set_volume_level *) tcore_user_request_ref_data(ur, 0);
3212
3213         // Hard-coded values for MIC & Speakers
3214         // Source volume
3215         dbg("Set Source volume");
3216
3217         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,7,3,88");   // Source type
3218         dbg("Request command string: %s", cmd_str);
3219
3220         // Create new Pending request
3221         src_pending = tcore_pending_new(o, 0);
3222
3223         // Create new AT-Command request
3224         src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3225         dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd));
3226
3227         // Free Command string
3228         g_free(cmd_str);
3229
3230         tcore_pending_set_request_data(src_pending, 0, src_req);
3231         src_ur = tcore_user_request_ref(ur);
3232
3233         // Send request
3234         ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3235         if (!ret) {
3236                 err("Failed to send AT-Command request");
3237                 return TCORE_RETURN_FAILURE;
3238         }
3239
3240         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,7,0,88");   // Destination type
3241         dbg("Request command string: %s", cmd_str);
3242
3243         // Create new Pending request
3244         src_pending = tcore_pending_new(o, 0);
3245
3246         // Create new AT-Command request
3247         src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3248         dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd));
3249
3250         // Free Command string
3251         g_free(cmd_str);
3252
3253         tcore_pending_set_request_data(src_pending, 0, src_req);
3254
3255         src_ur = tcore_user_request_ref(ur);
3256
3257         // Send request
3258         ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3259         if (!ret) {
3260                 err("Failed to send AT-Command request");
3261                 return TCORE_RETURN_FAILURE;
3262         }
3263
3264         // Destination volume
3265         dbg("Set Source volume");
3266
3267         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,88");   // Source type
3268         dbg("Request command string: %s", cmd_str);
3269
3270         // Create new Pending request
3271         dest_pending = tcore_pending_new(o, 0);
3272
3273         // Create new AT-Command request
3274         dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3275         dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd));
3276
3277         // Free Command string
3278         g_free(cmd_str);
3279
3280         tcore_pending_set_request_data(dest_pending, 0, dest_req);
3281         dest_ur = tcore_user_request_ref(ur);
3282
3283         // Send request
3284         ret = _call_request_message(dest_pending, o, dest_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3285         if (!ret) {
3286                 err("Failed to send AT-Command request");
3287                 return TCORE_RETURN_FAILURE;
3288         }
3289
3290         dbg("Input volume level - %d", data->volume);
3291         switch (data->volume) {
3292         case CALL_SOUND_MUTE:
3293                 volume_level = "0";
3294                 break;
3295
3296         case CALL_SOUND_VOLUME_LEVEL_1:
3297                 volume_level = "40";
3298                 break;
3299
3300         case CALL_SOUND_VOLUME_LEVEL_2:
3301                 volume_level = "46";
3302                 break;
3303
3304         case CALL_SOUND_VOLUME_LEVEL_3:
3305                 volume_level = "52";
3306                 break;
3307
3308         case CALL_SOUND_VOLUME_LEVEL_4:
3309                 volume_level = "58";
3310                 break;
3311
3312         case CALL_SOUND_VOLUME_LEVEL_5:
3313                 volume_level = "64";
3314                 break;
3315
3316         case CALL_SOUND_VOLUME_LEVEL_6:
3317                 volume_level = "70";
3318                 break;
3319
3320         case CALL_SOUND_VOLUME_LEVEL_7:
3321                 volume_level = "76";
3322                 break;
3323
3324         case CALL_SOUND_VOLUME_LEVEL_8:
3325                 volume_level = "82";
3326                 break;
3327
3328         case CALL_SOUND_VOLUME_LEVEL_9:
3329         default:
3330                 volume_level = "88";
3331                 break;
3332         }
3333         cmd_str = g_strdup_printf("%s%s", "AT+XDRV=40,8,2,", volume_level);   // Destination type
3334         dbg("Request command string: %s", cmd_str);
3335
3336         // Create new Pending request
3337         dest_pending = tcore_pending_new(o, 0);
3338
3339         // Create new AT-Command request
3340         dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3341         dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd));
3342
3343         // Free Command string
3344         g_free(cmd_str);
3345
3346         tcore_pending_set_request_data(dest_pending, 0, dest_req);
3347
3348         // Send request
3349         ret = _call_request_message(dest_pending, o, ur, on_confirmation_call_set_destination_sound_volume_level, NULL);
3350         if (!ret) {
3351                 err("Failed to send AT-Command request");
3352                 return TCORE_RETURN_FAILURE;
3353         }
3354
3355         return TCORE_RETURN_SUCCESS;
3356 }
3357
3358
3359 static TReturn s_call_get_sound_volume_level(CoreObject *o, UserRequest *ur)
3360 {
3361         dbg("Entry");
3362
3363         dbg("Exit");
3364         return TCORE_RETURN_SUCCESS;
3365 }
3366
3367 static TReturn s_call_mute(CoreObject *o, UserRequest *ur)
3368 {
3369         char *cmd_str = NULL;
3370         TcorePending *pending = NULL;
3371         TcoreATRequest *req = NULL;
3372         gboolean ret = FALSE;
3373
3374         dbg("Entry");
3375
3376         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3377                 dbg("cp not ready/n");
3378                 return TCORE_RETURN_ENOSYS;
3379         }
3380
3381         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,0");
3382
3383         dbg("Request command string: %s", cmd_str);
3384
3385         // Create new Pending request
3386         pending = tcore_pending_new(o, 0);
3387
3388         // Create new AT-Command request
3389         req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3390         dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3391
3392         // Free command string
3393         g_free(cmd_str);
3394
3395         // Set request data (AT command) to Pending request
3396         tcore_pending_set_request_data(pending, 0, req);
3397
3398         // Send request
3399         ret = _call_request_message(pending, o, ur, on_confirmation_call_mute, NULL);
3400         if (!ret) {
3401                 err("Failed to send AT-Command request");
3402                 return TCORE_RETURN_FAILURE;
3403         }
3404
3405         dbg("Exit");
3406         return TCORE_RETURN_SUCCESS;
3407 }
3408
3409 static TReturn s_call_unmute(CoreObject *o, UserRequest *ur)
3410 {
3411         char *cmd_str = NULL;
3412         TcorePending *pending = NULL;
3413         TcoreATRequest *req = NULL;
3414         gboolean ret = FALSE;
3415
3416         dbg("Entry");
3417
3418         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3419                 dbg("cp not ready/n");
3420                 return TCORE_RETURN_ENOSYS;
3421         }
3422
3423         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,88");
3424         dbg("Request command string: %s", cmd_str);
3425
3426         // Create new Pending request
3427         pending = tcore_pending_new(o, 0);
3428
3429         // Create new AT-Command request
3430         req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3431         dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3432
3433         // Free command string
3434         g_free(cmd_str);
3435
3436         // Set request data (AT command) to Pending request
3437         tcore_pending_set_request_data(pending, 0, req);
3438
3439         // Send request
3440         ret = _call_request_message(pending, o, ur, on_confirmation_call_unmute, NULL);
3441         if (!ret) {
3442                 err("Failed to send AT-Command request");
3443                 return TCORE_RETURN_FAILURE;
3444         }
3445
3446         dbg("Exit");
3447         return TCORE_RETURN_SUCCESS;
3448 }
3449
3450
3451 static TReturn s_call_get_mute_status(CoreObject *o, UserRequest *ur)
3452 {
3453         dbg("Entry");
3454
3455         dbg("Exit");
3456         return TCORE_RETURN_SUCCESS;
3457 }
3458
3459 static TReturn _set_dtmf_tone_duration(CoreObject *o, UserRequest *ur)
3460 {
3461         char *cmd_str = NULL;
3462         TcorePending *pending = NULL;
3463         TcoreATRequest *req = NULL;
3464         gboolean ret = FALSE;
3465
3466         dbg("Entry");
3467
3468         cmd_str = g_strdup_printf("%s", "AT+VTD=3"); // ~300 mili secs. +VTD= n, where  n = (0 - 255) * 1/10 secs.
3469         dbg("Request command string: %s", cmd_str);
3470
3471         // Create new Pending request
3472         pending = tcore_pending_new(o, 0);
3473
3474         // Create new AT-Command request
3475         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
3476         dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3477
3478         // Free command string */
3479         g_free(cmd_str);
3480
3481         // Set request data (AT command) to Pending request
3482         tcore_pending_set_request_data(pending, 0, req);
3483
3484         // Send request
3485         ret = _call_request_message(pending, o, ur, _on_confirmation_dtmf_tone_duration, NULL);
3486         if (!ret) {
3487                 err("Failed to send AT-Command request");
3488                 if (ur) {
3489                         tcore_user_request_free(ur);
3490                         ur = NULL;
3491                 }
3492                 return TCORE_RETURN_FAILURE;
3493         }
3494
3495         dbg("Exit");
3496         return TCORE_RETURN_SUCCESS;
3497 }
3498
3499 // Call Operations
3500 static struct tcore_call_operations call_ops = {
3501         .dial = s_call_outgoing,
3502         .answer = s_call_answer,
3503         .end = s_call_release,
3504         .hold = s_call_hold,
3505         .active = s_call_active,
3506         .swap = s_call_swap,
3507         .join = s_call_join,
3508         .split = s_call_split,
3509         .deflect = s_call_deflect,
3510         .transfer = s_call_transfer,
3511         .send_dtmf = s_call_send_dtmf,
3512         .set_sound_path = s_call_set_sound_path,
3513         .set_sound_volume_level = s_call_set_sound_volume_level,
3514         .get_sound_volume_level = s_call_get_sound_volume_level,
3515         .mute = s_call_mute,
3516         .unmute = s_call_unmute,
3517         .get_mute_status = s_call_get_mute_status,
3518         .set_sound_recording = NULL,
3519         .set_sound_equalization = NULL,
3520         .set_sound_noise_reduction = NULL,
3521 };
3522
3523 gboolean s_call_init(TcorePlugin *cp, CoreObject *co_call)
3524 {
3525         dbg("Entry");
3526
3527         tcore_call_override_ops(co_call, &call_ops, NULL);
3528
3529         /* Add Callbacks */
3530         tcore_object_override_callback(co_call, "+XCALLSTAT", on_notification_call_info, NULL);
3531         tcore_object_override_callback(co_call, "+CLIP", on_notification_call_clip_info, NULL);
3532
3533         dbg("Exit");
3534
3535         return TRUE;
3536 }
3537
3538 void s_call_exit(TcorePlugin *cp, CoreObject *co_call)
3539 {
3540         dbg("Exit");
3541 }