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