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