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