Updating IMC Plug-in - 1. Send Notification PLUGIN_ADD after Core Objects loading...
[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 call_prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback)
784 {
785         TcoreATRequest *req = NULL;
786         TcoreHal *hal = NULL;
787         TcorePending *pending = NULL;
788         TReturn ret;
789
790         hal = tcore_object_get_hal(co);
791         dbg("hal: %p", hal);
792
793         pending = tcore_pending_new(co, 0);
794         if (!pending)
795                 dbg("Pending is NULL");
796         req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
797
798         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
799
800         tcore_pending_set_request_data(pending, 0, req);
801         tcore_pending_set_response_callback(pending, callback, NULL);
802         tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL);
803         ret = tcore_hal_send_request(hal, pending);
804 }
805
806 static void on_confirmation_call_outgoing(TcorePending *p, int data_len, const void *data, void *user_data)
807 {
808         UserRequest *ur = NULL;
809         GSList *tokens = NULL;
810         const char *line = NULL;
811         const TcoreATResponse *response = data;
812         struct tresp_call_dial resp;
813         enum telephony_call_error error;
814         dbg("Entry");
815
816         ur = tcore_pending_ref_user_request(p);
817         if (ur) {
818                 if (response->success > 0) {
819                         dbg("RESPONSE OK");
820                         resp.err = CALL_ERROR_NONE;
821                 } else {
822                         dbg("RESPONSE NOT OK");
823
824                         line = (const char *) response->final_response;
825                         tokens = tcore_at_tok_new(line);
826
827                         if (g_slist_length(tokens) < 1) {
828                                 err("Unspecified error cause OR string corrupted");
829                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
830                         } else {
831                                 error = atoi(g_slist_nth_data(tokens, 0));
832
833                                 // TODO: CMEE error mapping is required.
834                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
835                         }
836
837                         // Free tokens
838                         tcore_at_tok_free(tokens);
839                 }
840
841                 // Send Response to TAPI
842                 tcore_user_request_send_response(ur, TRESP_CALL_DIAL, sizeof(struct tresp_call_dial), &resp);
843         } else {
844                 err("User Request is NULL");
845         }
846
847         dbg("Exit")
848         return;
849 }
850
851 static void on_confirmation_call_accept(TcorePending *p, int data_len, const void *data, void *user_data)
852 {
853         UserRequest *ur = NULL;
854         GSList *tokens = NULL;
855         const char *line = NULL;
856         const TcoreATResponse *response = data;
857         struct tresp_call_answer resp;
858         enum telephony_call_error error;
859         dbg("Entry");
860
861         ur = tcore_pending_ref_user_request(p);
862         if (ur) {
863                 if (response->success > 0) {
864                         dbg("RESPONSE OK");
865                         resp.err = CALL_ERROR_NONE;
866                 } else {
867                         dbg("RESPONSE NOT OK");
868
869                         line = (const char *) response->final_response;
870                         tokens = tcore_at_tok_new(line);
871
872                         if (g_slist_length(tokens) < 1) {
873                                 err("Unspecified error cause OR string corrupted");
874                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
875                         } else {
876                                 error = atoi(g_slist_nth_data(tokens, 0));
877
878                                 // TODO: CMEE error mapping is required.
879                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
880                         }
881
882                         // Free tokens
883                         tcore_at_tok_free(tokens);
884                 }
885
886                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
887
888                 // Send Response to TAPI
889                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
890         } else {
891                 err("User Request is NULL");
892         }
893
894         dbg("Exit");
895         return;
896 }
897
898
899 static void on_confirmation_call_reject(TcorePending *p, int data_len, const void *data, void *user_data)
900 {
901         UserRequest *ur = NULL;
902         GSList *tokens = NULL;
903         const char *line = NULL;
904         const TcoreATResponse *response = data;
905         struct tresp_call_answer resp;
906         enum telephony_call_error error;
907
908         dbg("Entry");
909
910         ur = tcore_pending_ref_user_request(p);
911         if (ur) {
912                 if (response->success > 0) {
913                         dbg("RESPONSE OK");
914                         resp.err = CALL_ERROR_NONE;
915                 } else {
916                         dbg("RESPONSE NOT OK");
917                         line = (const char *) response->final_response;
918                         tokens = tcore_at_tok_new(line);
919
920                         if (g_slist_length(tokens) < 1) {
921                                 err("Unspecified error cause OR string corrupted");
922                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
923                         } else {
924                                 error = atoi(g_slist_nth_data(tokens, 0));
925                                 // TODO: CMEE error mapping is required.
926                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
927                         }
928
929                         // Free tokens
930                         tcore_at_tok_free(tokens);
931                 }
932
933                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
934
935                 // Send Response to TAPI
936                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
937         } else {
938                 err("User Request is NULL");
939         }
940
941         dbg("Exit");
942         return;
943 }
944
945 static void on_confirmation_call_replace(TcorePending *p, int data_len, const void *data, void *user_data)
946 {
947         UserRequest *ur = NULL;
948         GSList *tokens = NULL;
949         const char *line = NULL;
950         const TcoreATResponse *response = data;
951         struct tresp_call_answer resp;
952         enum telephony_call_error error;
953
954         dbg("Entry");
955         ur = tcore_pending_ref_user_request(p);
956         if (ur) {
957                 if (response->success > 0) {
958                         dbg("RESPONSE OK");
959                         resp.err = CALL_ERROR_NONE;
960                 } else {
961                         dbg("RESPONSE NOT OK");
962                         line = (const char *) response->final_response;
963                         tokens = tcore_at_tok_new(line);
964
965                         if (g_slist_length(tokens) < 1) {
966                                 err("Unspecified error cause OR string corrupted");
967                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
968                         } else {
969                                 error = atoi(g_slist_nth_data(tokens, 0));
970                                 // TODO: CMEE error mapping is required.
971                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
972                         }
973
974                         // Free tokens
975                         tcore_at_tok_free(tokens);
976                 }
977                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
978
979                 // Send Response to TAPI
980                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
981         } else {
982                 dbg("User Request is NULL");
983         }
984
985         dbg("Exit");
986         return;
987 }
988
989 static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data)
990 {
991         CoreObject *o = NULL;
992         UserRequest *ur = NULL;
993         GSList *tokens = NULL;
994         const char *line = NULL;
995         const TcoreATResponse *response = data;
996         struct tresp_call_answer resp;
997         enum telephony_call_error error;
998
999         dbg("Entry");
1000
1001         o = tcore_pending_ref_core_object(p);
1002         ur = tcore_pending_ref_user_request(p);
1003         resp.id = tcore_call_object_get_id((CallObject *) user_data);
1004
1005         if (ur) {
1006                 if (response->success > 0) {
1007                         dbg("RESPONSE OK");
1008                         resp.err = CALL_ERROR_NONE;
1009                 } else {
1010                         err("RESPONSE NOT OK");
1011                         line = (const char *) response->final_response;
1012                         tokens = tcore_at_tok_new(line);
1013
1014                         if (g_slist_length(tokens) < 1) {
1015                                 err("Unspecified error cause OR string corrupted");
1016                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1017                         } else {
1018                                 error = atoi(g_slist_nth_data(tokens, 0));
1019
1020                                 // TODO: CMEE error mapping is required.
1021                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1022                         }
1023
1024                         // Free tokens
1025                         tcore_at_tok_free(tokens);
1026                 }
1027
1028                 // Send response to TAPI
1029                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
1030                 if (!resp.err) {
1031                         GSList *list = 0;
1032                         CallObject *co = NULL;
1033
1034                         // Active Call
1035                         list = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_ACTIVE);
1036                         if (!list) {
1037                                 err("Can't find active Call");
1038                                 return;
1039                         }
1040
1041                         co = (CallObject *) list->data;
1042                         if (!co) {
1043                                 err("Can't get active Call object");
1044                                 return;
1045                         }
1046
1047                         // Set Call Status
1048                         tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD);
1049                         dbg("Call status is set to HELD");
1050                 }
1051         } else {
1052                 err("User Request is NULL");
1053         }
1054
1055         dbg("Exit");
1056         return;
1057 }
1058
1059 static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type)
1060 {
1061         UserRequest *ur = NULL;
1062         struct tresp_call_end resp;
1063         GSList *tokens = NULL;
1064         const char *line = NULL;
1065         enum telephony_call_error error;
1066         const TcoreATResponse *response = data;
1067
1068         dbg("Entry");
1069         ur = tcore_pending_ref_user_request(p);
1070         if (ur) {
1071                 if (response->success > 0) {
1072                         dbg("RESPONSE OK");
1073                         resp.err = CALL_ERROR_NONE;
1074                 } else {
1075                         err("RESPONSE NOT OK");
1076
1077                         line = (const char *) response->final_response;
1078                         tokens = tcore_at_tok_new(line);
1079
1080                         if (g_slist_length(tokens) < 1) {
1081                                 err("Unspecified error cause OR string corrupted");
1082                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1083                         } else {
1084                                 error = atoi(g_slist_nth_data(tokens, 0));
1085
1086                                 // TODO: CMEE error mapping is required.
1087                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1088                         }
1089                         tcore_at_tok_free(tokens);
1090                 }
1091
1092                 resp.type = type;
1093                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1094                 dbg("resp.type = %d  resp.id= %d", resp.type, resp.id);
1095
1096                 // Send reponse to TAPI
1097                 tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
1098         } else {
1099                 err("User Request is NULL");
1100         }
1101
1102         dbg("Exit");
1103         return;
1104 }
1105
1106 // RESPONSE
1107 static void on_confirmation_call_endall(TcorePending *p, int data_len, const void *data, void *user_data)
1108 {
1109         // skip response handling - actual result will be handled in on_confirmation_call_release_all
1110         const TcoreATResponse *response = data;
1111
1112         dbg("Entry");
1113
1114         if (response->success > 0) {
1115                 dbg("RESPONSE OK");
1116         } else {
1117                 err("RESPONSE NOT OK");
1118         }
1119
1120         dbg("Exit");
1121         return;
1122 }
1123
1124
1125 static void on_confirmation_call_release_all(TcorePending *p, int data_len, const void *data, void *user_data)
1126 {
1127         dbg("Entry");
1128         _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ALL);
1129
1130         return;
1131 }
1132
1133
1134 static void on_confirmation_call_release_specific(TcorePending *p, int data_len, const void *data, void *user_data)
1135 {
1136         dbg("Entry");
1137         _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_DEFAULT);
1138
1139         return;
1140 }
1141
1142 static void on_confirmation_call_release_all_active(TcorePending *p, int data_len, const void *data, void *user_data)
1143 {
1144         dbg("Entry");
1145         _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ACTIVE_ALL);
1146
1147         return;
1148 }
1149
1150 static void on_confirmation_call_release_all_held(TcorePending *p, int data_len, const void *data, void *user_data)
1151 {
1152         dbg("Entry");
1153         _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_HOLD_ALL);
1154
1155         return;
1156 }
1157
1158 static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type)
1159 {
1160         UserRequest *ur = NULL;
1161         GSList *tokens = NULL;
1162         const char *line = NULL;
1163         const TcoreATResponse *response = NULL;
1164         enum telephony_call_error error;
1165
1166         dbg("Entry");
1167         ur = tcore_pending_ref_user_request(p);
1168         response = (TcoreATResponse *) data;
1169         if (response->success > 0) {
1170                 dbg("RESPONSE OK");
1171                 error = CALL_ERROR_NONE;
1172         } else {
1173                 err("RESPONSE NOT OK");
1174
1175                 line = (const char *) response->final_response;
1176                 tokens = tcore_at_tok_new(line);
1177
1178                 if (g_slist_length(tokens) < 1) {
1179                         err("Unspecified error cause OR string corrupted");
1180                         error = CALL_ERROR_SERVICE_UNAVAIL;
1181                 } else {
1182                         error = atoi(g_slist_nth_data(tokens, 0));
1183
1184                         // TODO: CMEE error mapping is required.
1185                         error = CALL_ERROR_SERVICE_UNAVAIL;
1186                 }
1187
1188                 // Free tokens
1189                 tcore_at_tok_free(tokens);
1190         }
1191
1192         dbg("Response Call type -%d", type);
1193         switch (type) {
1194         case TRESP_CALL_HOLD:
1195         {
1196                 struct tresp_call_hold resp;
1197
1198                 resp.err = error;
1199                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1200                 dbg("call hold response");
1201                 // Send reponse to TAPI
1202                 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
1203         }
1204         break;
1205
1206         case TRESP_CALL_ACTIVE:
1207         {
1208                 struct tresp_call_active resp;
1209
1210                 resp.err = error;
1211                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1212                 dbg("call active response");
1213                 // Send reponse to TAPI
1214                 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
1215         }
1216         break;
1217
1218         case TRESP_CALL_JOIN:
1219         {
1220                 struct tresp_call_join resp;
1221
1222                 resp.err = error;
1223                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1224                 dbg("call join response");
1225
1226                 // Send reponse to TAPI
1227                 tcore_user_request_send_response(ur, TRESP_CALL_JOIN, sizeof(struct tresp_call_join), &resp);
1228         }
1229         break;
1230
1231         case TRESP_CALL_SPLIT:
1232         {
1233                 struct tresp_call_split resp;
1234
1235                 resp.err = error;
1236                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1237                 dbg("call split response");
1238                 // Send reponse to TAPI
1239                 tcore_user_request_send_response(ur, TRESP_CALL_SPLIT, sizeof(struct tresp_call_split), &resp);
1240         }
1241         break;
1242
1243         case TRESP_CALL_DEFLECT:
1244         {
1245                 struct tresp_call_deflect resp;
1246
1247                 resp.err = error;
1248                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1249                 dbg("call deflect response");
1250                 // Send reponse to TAPI
1251                 tcore_user_request_send_response(ur, TRESP_CALL_DEFLECT, sizeof(struct tresp_call_deflect), &resp);
1252         }
1253
1254         break;
1255
1256         case TRESP_CALL_TRANSFER:
1257         {
1258                 struct tresp_call_transfer resp;
1259
1260                 resp.err = error;
1261                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1262                 dbg("call transfer response");
1263                 // Send reponse to TAPI
1264                 tcore_user_request_send_response(ur, TRESP_CALL_TRANSFER, sizeof(struct tresp_call_transfer), &resp);
1265         }
1266         break;
1267
1268         case TRESP_CALL_SEND_DTMF:
1269         {
1270                 struct tresp_call_dtmf resp;
1271
1272                 resp.err = error;
1273                 dbg("call dtmf response");
1274                 // Send reponse to TAPI
1275                 tcore_user_request_send_response(ur, TRESP_CALL_SEND_DTMF, sizeof(struct tresp_call_dtmf), &resp);
1276         }
1277         break;
1278
1279         default:
1280         {
1281                 dbg("type not supported");
1282                 return;
1283         }
1284         }
1285
1286         if ((type == TRESP_CALL_HOLD) || (type == TRESP_CALL_ACTIVE) || (type == TRESP_CALL_JOIN)
1287                 || (type == TRESP_CALL_SPLIT)) {
1288                 if (!error) {
1289                         CoreObject *core_obj = NULL;
1290                         gboolean *eflag = g_new0(gboolean, 1);
1291
1292                         core_obj = tcore_pending_ref_core_object(p);
1293                         *eflag = FALSE;
1294
1295                         dbg("Calling _call_list_get");
1296                         _call_list_get(core_obj, eflag);
1297                 }
1298         }
1299
1300         dbg("Exit");
1301         return;
1302 }
1303
1304 static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data)
1305 {
1306         dbg("Entry");
1307         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_HOLD);
1308
1309         return;
1310 }
1311
1312 static void on_confirmation_call_active(TcorePending *p, int data_len, const void *data, void *user_data)
1313 {
1314         dbg("Entry");
1315         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_ACTIVE);
1316
1317         return;
1318 }
1319
1320 static void on_confirmation_call_join(TcorePending *p, int data_len, const void *data, void *user_data)
1321 {
1322         dbg("Entry");
1323         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_JOIN);
1324
1325         return;
1326 }
1327
1328 static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data)
1329 {
1330         dbg("Entry");
1331         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_SPLIT);
1332
1333         return;
1334 }
1335
1336 static void on_confirmation_call_deflect(TcorePending *p, int data_len, const void *data, void *user_data)
1337 {
1338         dbg("Entry");
1339         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_DEFLECT);
1340
1341         return;
1342 }
1343
1344 static void on_confirmation_call_transfer(TcorePending *p, int data_len, const void *data, void *user_data)
1345 {
1346         dbg("Entry");
1347         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_TRANSFER);
1348
1349         return;
1350 }
1351
1352 static void on_confirmation_call_dtmf(TcorePending *p, int data_len, const void *data, void *user_data)
1353 {
1354         dbg("Entry");
1355         _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_SEND_DTMF);
1356
1357         return;
1358 }
1359
1360 static void _on_confirmation_dtmf_tone_duration(TcorePending *p, int data_len, const void *data, void *user_data)
1361 {
1362         GSList *tokens = NULL;
1363         const char *line = NULL;
1364         const TcoreATResponse *response = data;
1365         enum telephony_call_error error;
1366
1367         dbg("Entry");
1368
1369         if (response->success > 0) {
1370                 dbg("RESPONSE OK");
1371                 error = CALL_ERROR_NONE;
1372         } else {
1373                 err("RESPONSE NOT OK");
1374                 line = (const char *) response->final_response;
1375                 tokens = tcore_at_tok_new(line);
1376                 if (g_slist_length(tokens) < 1) {
1377                         err("err cause not specified or string corrupted");
1378                         error = CALL_ERROR_SERVICE_UNAVAIL;
1379                 } else {
1380                         error = atoi(g_slist_nth_data(tokens, 0));
1381                         // TODO: CMEE error mapping is required.
1382                 }
1383
1384                 // Free tokens
1385                 tcore_at_tok_free(tokens);
1386         }
1387
1388         dbg("Set dtmf tone duration response - %d", error);
1389         return;
1390 }
1391
1392 static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data)
1393 {
1394         CoreObject *core_obj = NULL;
1395         UserRequest *ur = NULL;
1396         const TcoreATResponse *response = data;
1397         struct tresp_call_swap resp;
1398         GSList *tokens = NULL;
1399         const char *line = NULL;
1400
1401         dbg("Entry");
1402         core_obj = tcore_pending_ref_core_object(p);
1403         ur = tcore_pending_ref_user_request(p);
1404
1405         if (ur) {
1406                 if (response->success > 0) {
1407                         dbg("RESPONSE OK");
1408                         resp.err = CALL_ERROR_NONE;
1409                 } else {
1410                         err("RESPONSE NOT OK");
1411                         line = (const char *) response->final_response;
1412                         tokens = tcore_at_tok_new(line);
1413                         if (g_slist_length(tokens) < 1) {
1414                                 err("err cause not specified or string corrupted");
1415                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1416                         } else {
1417                                 resp.err = atoi(g_slist_nth_data(tokens, 0));
1418
1419                                 // TODO: CMEE error mapping is required.
1420                                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1421                         }
1422
1423                         // Free tokens
1424                         tcore_at_tok_free(tokens);
1425                 }
1426
1427                 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1428                 dbg("resp.id = %d", resp.id);
1429
1430                 // Send response to TAPI
1431                 tcore_user_request_send_response(ur, TRESP_CALL_SWAP, sizeof(struct tresp_call_swap), &resp);
1432
1433                 if (!resp.err) {
1434                         GSList *active = NULL;
1435                         GSList *held = NULL;
1436                         CallObject *co = NULL;
1437                         gboolean *eflag = NULL;
1438
1439                         held = tcore_call_object_find_by_status(core_obj, TCORE_CALL_STATUS_HELD);
1440                         if (!held) {
1441                                 err("Can't find held Call");
1442                                 return;
1443                         }
1444
1445                         active = tcore_call_object_find_by_status(core_obj, TCORE_CALL_STATUS_ACTIVE);
1446                         if (!active) {
1447                                 dbg("Can't find active Call");
1448                                 return;
1449                         }
1450
1451                         while (held) {
1452                                 co = (CallObject *) held->data;
1453                                 if (!co) {
1454                                         err("Can't get held Call object");
1455                                         return;
1456                                 }
1457
1458                                 resp.id = tcore_call_object_get_id(co);
1459
1460                                 // Send response to TAPI
1461                                 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
1462
1463                                 held = g_slist_next(held);
1464                         }
1465
1466                         while (active) {
1467                                 co = (CallObject *) active->data;
1468                                 if (!co) {
1469                                         err("[ error ] can't get active call object");
1470                                         return;
1471                                 }
1472
1473                                 resp.id = tcore_call_object_get_id(co);
1474
1475                                 // Send response to TAPI
1476                                 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
1477                                 active = g_slist_next(active);
1478                         }
1479
1480                         eflag = g_new0(gboolean, 1);
1481                         *eflag = FALSE;
1482
1483                         dbg("calling _call_list_get");
1484                         _call_list_get(core_obj, eflag);
1485                 }
1486         } else {
1487                 err("User Request is NULL");
1488         }
1489
1490         dbg("Exit");
1491         return;
1492 }
1493
1494 static void on_confirmation_set_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1495 {
1496         const TcoreATResponse *resp = data;
1497         struct tnoti_call_sound_path *snd_path = user_data;
1498         TcorePlugin *plugin = tcore_pending_ref_plugin(p);
1499
1500         if (resp->success > 0) {
1501                 tcore_server_send_notification(tcore_plugin_ref_server(plugin),
1502                                                                 tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL),
1503                                                                 TNOTI_CALL_SOUND_PATH,
1504                                                                 sizeof(struct tnoti_call_sound_path),
1505                                                                 (void *)snd_path);
1506         } else {
1507                 dbg("Error in set sound path");
1508         }
1509 }
1510
1511 static void on_confirmation_call_set_source_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1512 {
1513         UserRequest *ur = NULL;
1514         GSList *tokens = NULL;
1515         const char *line = NULL;
1516         const TcoreATResponse *response = data;
1517         char *resp_str = NULL;
1518         struct tresp_call_sound_set_path resp;
1519         gboolean error;
1520
1521         dbg("Entry");
1522         ur = tcore_pending_ref_user_request(p);
1523
1524         // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]\ 3
1525         if (!response) {
1526                 err("Input data is NULL");
1527                 return;
1528         }
1529
1530         if (response->success > 0) {
1531                 dbg("RESPONSE OK");
1532
1533                 line = (const char *) (((GSList *) response->lines)->data);
1534                 tokens = tcore_at_tok_new(line);
1535
1536                 resp_str = g_slist_nth_data(tokens, 0);
1537                 if (!g_slist_nth_data(tokens, 0)) {
1538                         err("group_id is missing");
1539                         resp.err = TRUE;
1540                         goto OUT;
1541                 }
1542
1543                 if (!g_slist_nth_data(tokens, 1)) {
1544                         err(" function_id is missing");
1545                         resp.err = TRUE;
1546                         goto OUT;
1547                 }
1548
1549                 resp_str = g_slist_nth_data(tokens, 2);
1550
1551                 if (resp_str) {
1552                         error = atoi(resp_str);
1553                         if (0 == error) {
1554                                 dbg("Response is Success");
1555                                 resp.err = FALSE;
1556                         } else {
1557                                 resp.err = TRUE;
1558                         }
1559                 }
1560 OUT:
1561                 // Free tokens
1562                 tcore_at_tok_free(tokens);
1563         } else {
1564                 dbg("RESPONSE NOT OK");
1565
1566                 line = (const char *) response->final_response;
1567                 tokens = tcore_at_tok_new(line);
1568
1569                 if (g_slist_length(tokens) < 1) {
1570                         err("err cause not specified or string corrupted");
1571                         resp.err = TRUE;
1572                 } else {
1573                         error = atoi(g_slist_nth_data(tokens, 0));
1574
1575                         // TODO: CMEE error mapping is required.
1576                         resp.err = TRUE;
1577                 }
1578
1579                 // Free tokens
1580                 tcore_at_tok_free(tokens);
1581         }
1582
1583         if (ur) {
1584                 if ( resp.err ) {  // Send only failed notification . success notification send when destination device is set.
1585                         // Send notification to TAPI
1586                         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_sound_set_path), &resp);
1587                         setsoundpath = TRUE;
1588                 }
1589         } else {
1590                 err("User Request is NULL");
1591         }
1592
1593         dbg("Exit");
1594         return;
1595 }
1596
1597 static void on_confirmation_call_set_destination_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1598 {
1599         UserRequest *ur = NULL;
1600         GSList *tokens = NULL;
1601         const char *line = NULL;
1602         char *resp_str = NULL;
1603         struct tresp_call_sound_set_path resp;
1604         const TcoreATResponse *response = data;
1605         gboolean error;
1606
1607         dbg("Entry");
1608
1609         ur = tcore_pending_ref_user_request(p);
1610         // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]\ 3
1611
1612         if (!response) {
1613                 err("Input data is NULL");
1614                 return;
1615         }
1616
1617         if (ur) {
1618                 if (response->success > 0) {
1619                         dbg("RESPONSE OK");
1620
1621                         line = (const char *) (((GSList *) response->lines)->data);
1622                         tokens = tcore_at_tok_new(line);
1623
1624                         resp_str = g_slist_nth_data(tokens, 0);
1625                         if (!g_slist_nth_data(tokens, 0)) {
1626                                 dbg("group_id is missing");
1627                                 resp.err = TRUE;
1628                                 goto OUT;
1629                         }
1630
1631                         if (!g_slist_nth_data(tokens, 1)) {
1632                                 dbg("function_id is missing");
1633                                 resp.err = TRUE;
1634                                 goto OUT;
1635                         }
1636
1637                         resp_str = g_slist_nth_data(tokens, 2);
1638                         if (resp_str) {
1639                                 error = atoi(resp_str);
1640                                 if (0 == error) {
1641                                         dbg("Response is Success");
1642                                         resp.err = FALSE;
1643                                 } else {
1644                                         resp.err = TRUE;
1645                                 }
1646                         }
1647
1648 OUT:
1649                         // Free tokens
1650                         tcore_at_tok_free(tokens);
1651                 } else {
1652                         dbg("RESPONSE NOT OK");
1653
1654                         line = (const char *) response->final_response;
1655                         tokens = tcore_at_tok_new(line);
1656
1657                         if (g_slist_length(tokens) < 1) {
1658                                 err("err cause not specified or string corrupted");
1659                                 resp.err = TRUE;
1660                         } else {
1661                                 error = atoi(g_slist_nth_data(tokens, 0));
1662                                 // TODO: CMEE error mapping is required.
1663                                 resp.err = TRUE;
1664                         }
1665
1666                         // Free tokens
1667                         tcore_at_tok_free(tokens);
1668                 }
1669
1670                 if (setsoundpath == TRUE) {
1671                         setsoundpath = FALSE;
1672                 } else {
1673                         // Send response to TAPI
1674                         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_sound_set_path), &resp);
1675                 }
1676         } else {
1677                 dbg("User Request is NULL");
1678         }
1679
1680         dbg("Exit");
1681         return;
1682 }
1683
1684 static void on_confirmation_call_set_source_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data)
1685 {
1686         UserRequest *ur = NULL;
1687         GSList *tokens = NULL;
1688         const char *line = NULL;
1689         const TcoreATResponse *response = data;
1690         char *resp_str = NULL;
1691         struct tresp_call_sound_set_volume_level resp;
1692         gboolean error;
1693
1694         ur = tcore_pending_ref_user_request(p);
1695         dbg("Entry");
1696         // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]\ 3
1697         if (!response) {
1698                 err("Input data is NULL");
1699                 return;
1700         }
1701
1702         if (response->success > 0) {
1703                 dbg("RESPONSE OK");
1704
1705                 line = (const char *) (((GSList *) response->lines)->data);
1706                 tokens = tcore_at_tok_new(line);
1707
1708                 resp_str = g_slist_nth_data(tokens, 0);
1709                 if (!g_slist_nth_data(tokens, 0)) {
1710                         err("group_id is missing");
1711                         resp.err = TRUE;
1712                         goto OUT;
1713                 }
1714
1715                 if (!g_slist_nth_data(tokens, 1)) {
1716                         err("function_id is missing");
1717                         resp.err = TRUE;
1718                         goto OUT;
1719                 }
1720
1721                 resp_str = g_slist_nth_data(tokens, 2);
1722                 if (resp_str) {
1723                         error = atoi(resp_str);
1724
1725                         if (0 == error) {
1726                                 dbg("Response is Success ");
1727                                 resp.err = FALSE;
1728                         } else {
1729                                 resp.err = TRUE;
1730                         }
1731                 }
1732
1733 OUT:
1734                 // Free tokens
1735                 tcore_at_tok_free(tokens);
1736         } else {
1737                 dbg("RESPONSE NOT OK");
1738
1739                 line = (const char *) response->final_response;
1740                 tokens = tcore_at_tok_new(line);
1741
1742                 if (g_slist_length(tokens) < 1) {
1743                         err("err cause not specified or string corrupted");
1744                         resp.err = TRUE;
1745                 } else {
1746                         error = atoi(g_slist_nth_data(tokens, 0));
1747
1748                         // TODO: CMEE error mapping is required.
1749                         resp.err = TRUE;
1750                 }
1751
1752                 // Free tokens
1753                 tcore_at_tok_free(tokens);
1754         }
1755
1756         if (ur) {
1757                 if (resp.err && soundvolume == FALSE) {  // Send only failed notification . success notification send when destination device is set.
1758                         // Send reposne to TAPI
1759                         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_sound_set_volume_level), &resp);
1760                         soundvolume = TRUE;
1761                 }
1762         } else {
1763                 err("User Request is NULL");
1764         }
1765
1766         dbg("Exit");
1767         return;
1768 }
1769
1770
1771 static void on_confirmation_call_set_destination_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data)
1772 {
1773         UserRequest *ur = NULL;
1774         GSList *tokens = NULL;
1775         const char *line = NULL;
1776         char *resp_str = NULL;
1777         const TcoreATResponse *response = data;
1778         struct tresp_call_sound_set_volume_level resp;
1779         gboolean error;
1780
1781         dbg("Entry");
1782
1783         ur = tcore_pending_ref_user_request(p);
1784
1785         // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]\ 3
1786         if (!response) {
1787                 err("Input data is NULL");
1788                 return;
1789         }
1790
1791         if (ur) {
1792                 if (response->success > 0) {
1793                         dbg("RESPONSE OK");
1794                         line = (const char *) (((GSList *) response->lines)->data);
1795                         tokens = tcore_at_tok_new(line);
1796                         resp_str = g_slist_nth_data(tokens, 0);
1797
1798                         if (!g_slist_nth_data(tokens, 0)) {
1799                                 err("group_id is missing");
1800                                 resp.err = TRUE;
1801                                 goto OUT;
1802                         }
1803
1804                         if (!g_slist_nth_data(tokens, 1)) {
1805                                 err("function_id is missing");
1806                                 resp.err = TRUE;
1807                                 goto OUT;
1808                         }
1809
1810                         resp_str = g_slist_nth_data(tokens, 2);
1811
1812                         if (resp_str) {
1813                                 error = atoi(resp_str);
1814
1815                                 if (0 == error) {
1816                                         dbg("Response is Success");
1817                                         resp.err = FALSE;
1818                                 } else {
1819                                         resp.err = TRUE;
1820                                 }
1821                         }
1822
1823 OUT:
1824                         // Free tokens
1825                         tcore_at_tok_free(tokens);
1826                 } else {
1827                         dbg("RESPONSE NOT OK");
1828
1829                         line = (const char *) response->final_response;
1830                         tokens = tcore_at_tok_new(line);
1831
1832                         if (g_slist_length(tokens) < 1) {
1833                                 err("err cause not specified or string corrupted");
1834                                 resp.err = TRUE;
1835                         } else {
1836                                 error = atoi(g_slist_nth_data(tokens, 0));
1837
1838                                 // TODO: CMEE error mapping is required.
1839                                 resp.err = TRUE;
1840                         }
1841
1842                         tcore_at_tok_free(tokens);
1843                 }
1844
1845                 if (soundvolume == TRUE) {
1846                         soundvolume = FALSE;
1847                 } else {
1848                         // Send reposne to TAPI
1849                         tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_sound_set_volume_level), &resp);
1850                 }
1851         } else {
1852                 err("User Request is NULL");
1853         }
1854
1855         dbg("Exit");
1856         return;
1857 }
1858
1859
1860 static void on_confirmation_call_mute(TcorePending *p, int data_len, const void *data, void *user_data)
1861 {
1862         UserRequest *ur = NULL;
1863         GSList *tokens = NULL;
1864         const char *line = NULL;
1865         char *resp_str = NULL;
1866         struct tresp_call_mute resp;
1867         const TcoreATResponse *response = data;
1868         gboolean error;
1869
1870         dbg("Entry");
1871
1872         ur = tcore_pending_ref_user_request(p);
1873
1874         if (!response) {
1875                 err("Input data is NULL");
1876                 return;
1877         }
1878
1879         if (response->success > 0) {
1880                 dbg("RESPONSE OK");
1881
1882                 line = (const char *) (((GSList *) response->lines)->data);
1883                 tokens = tcore_at_tok_new(line);
1884                 resp_str = g_slist_nth_data(tokens, 0);
1885
1886                 if (!g_slist_nth_data(tokens, 0)) {
1887                         err("group_id is missing");
1888                         resp.err = TRUE;
1889                         goto OUT;
1890                 }
1891
1892                 if (!g_slist_nth_data(tokens, 1)) {
1893                         err(" function_id is missing");
1894                         resp.err = TRUE;
1895                         goto OUT;
1896                 }
1897
1898                 resp_str = g_slist_nth_data(tokens, 2);
1899
1900                 if (resp_str) {
1901                         error = atoi(resp_str);
1902                         if (0 == error) {
1903                                 dbg("Response is Success");
1904                                 resp.err = FALSE;
1905                         } else {
1906                                 resp.err = TRUE;
1907                         }
1908                 }
1909 OUT:
1910                 // Free tokens
1911                 tcore_at_tok_free(tokens);
1912         } else {
1913                 dbg("RESPONSE NOT OK");
1914
1915                 line = (const char *) response->final_response;
1916                 tokens = tcore_at_tok_new(line);
1917
1918                 if (g_slist_length(tokens) < 1) {
1919                         err("err cause not specified or string corrupted");
1920                         resp.err = TRUE;
1921                 } else {
1922                         error = atoi(g_slist_nth_data(tokens, 0));
1923
1924                         // TODO: CMEE error mapping is required.
1925                         resp.err = TRUE;
1926                 }
1927
1928                 // Free tokens
1929                 tcore_at_tok_free(tokens);
1930         }
1931
1932         if (ur) {
1933                 tcore_user_request_send_response(ur, TRESP_CALL_MUTE, sizeof(struct tresp_call_mute), &resp);
1934         } else {
1935                 err("User Request is NULL");
1936         }
1937
1938         dbg("Exit");
1939         return;
1940 }
1941
1942 static void on_confirmation_call_unmute(TcorePending *p, int data_len, const void *data, void *user_data)
1943 {
1944         const TcoreATResponse *response = NULL;
1945         struct tresp_call_unmute resp;
1946         GSList *tokens = NULL;
1947         const char *line = NULL;
1948         UserRequest *ur = NULL;
1949         char *resp_str = NULL;
1950         gboolean error;
1951
1952         dbg("Entry");
1953
1954         response = (TcoreATResponse *) data;
1955         ur = tcore_pending_ref_user_request(p);
1956
1957         if (!response) {
1958                 err("Input data is NULL");
1959                 return;
1960         }
1961
1962         if (response->success > 0) {
1963                 dbg("RESPONSE OK");
1964
1965                 line = (const char *) (((GSList *) response->lines)->data);
1966                 tokens = tcore_at_tok_new(line);
1967                 resp_str = g_slist_nth_data(tokens, 0);
1968
1969                 if (!g_slist_nth_data(tokens, 0)) {
1970                         err("group_id is missing");
1971                         resp.err = TRUE;
1972                         goto OUT;
1973                 }
1974
1975                 if (!g_slist_nth_data(tokens, 1)) {
1976                         err(" function_id is missing");
1977                         resp.err = TRUE;
1978                         goto OUT;
1979                 }
1980
1981                 resp_str = g_slist_nth_data(tokens, 2);
1982
1983                 if (resp_str) {
1984                         error = atoi(resp_str);
1985                         if (0 == error) {
1986                                 dbg("Response is Success");
1987                                 resp.err = FALSE;
1988                         } else {
1989                                 resp.err = TRUE;
1990                         }
1991                 }
1992 OUT:
1993                 // Free tokens
1994                 tcore_at_tok_free(tokens);
1995         } else {
1996                 dbg("RESPONSE NOT OK");
1997
1998                 line = (const char *) response->final_response;
1999                 tokens = tcore_at_tok_new(line);
2000
2001                 if (g_slist_length(tokens) < 1) {
2002                         err("err cause not specified or string corrupted");
2003                         resp.err = TRUE;
2004                 } else {
2005                         error = atoi(g_slist_nth_data(tokens, 0));
2006
2007                         // TODO: CMEE error mapping is required.
2008                         resp.err = TRUE;
2009                 }
2010
2011                 // Free tokens
2012                 tcore_at_tok_free(tokens);
2013         }
2014
2015         if (ur) {
2016                 tcore_user_request_send_response(ur, TRESP_CALL_UNMUTE, sizeof(struct tresp_call_unmute), &resp);
2017         } else {
2018                 err("User Request is NULL");
2019         }
2020
2021         dbg("Exit");
2022         return;
2023 }
2024
2025 // RESPONSE
2026 static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data)
2027 {
2028         TcorePlugin *plugin = NULL;
2029         CoreObject *core_obj = NULL;
2030         CallObject *co = NULL;
2031         struct clcc_call_t *call_list = NULL;
2032         gboolean *event_flag = (gboolean *) user_data;
2033         const TcoreATResponse *response = data;
2034         GSList *resp_data = NULL;
2035         char *line = NULL;
2036
2037         int cllc_info = 0, countCalls = 0, countValidCalls = 0;
2038         int error = 0;
2039
2040         dbg("Entry");
2041
2042         plugin = tcore_pending_ref_plugin(p);
2043         core_obj = tcore_pending_ref_core_object(p);
2044
2045         if (response->success > 0) {
2046                 dbg("RESPONCE OK");
2047                 if (response->lines) {
2048                         resp_data = (GSList *) response->lines;
2049                         countCalls = g_slist_length(resp_data);
2050                         dbg("Total records : %d", countCalls);
2051                 }
2052
2053                 if (0 == countCalls) {
2054                         err("Call count is zero");
2055                         if (event_flag) {
2056                                 g_free(event_flag);
2057                                 event_flag = NULL;
2058                         }
2059                         return;
2060                 }
2061
2062                 call_list = g_new0(struct clcc_call_t, countCalls);
2063
2064                 for (countValidCalls = 0; resp_data != NULL; resp_data = resp_data->next, countValidCalls++, cllc_info++) {
2065                         line = (char *) (resp_data->data);
2066
2067                         error = _callFromCLCCLine(line, call_list + countValidCalls);
2068                         if (0 != error) {
2069                                 continue;
2070                         }
2071
2072                         co = tcore_call_object_find_by_id(core_obj, call_list[cllc_info].info.id);
2073                         if (!co) {
2074                                 co = tcore_call_object_new(core_obj, call_list[cllc_info].info.id);
2075                                 if (!co) {
2076                                         err("error : tcore_call_object_new [ id : %d ]", call_list[cllc_info].info.id);
2077                                         continue;
2078                                 }
2079                         }
2080
2081                         // Call set parameters
2082                         tcore_call_object_set_type(co, call_type(call_list[cllc_info].info.type));
2083                         tcore_call_object_set_direction(co, call_list[cllc_info].info.direction);
2084                         tcore_call_object_set_multiparty_state(co, _call_is_in_mpty(call_list[cllc_info].info.mpty));
2085                         tcore_call_object_set_cli_info(co, CALL_CLI_MODE_DEFAULT, call_list[cllc_info].number);
2086                         tcore_call_object_set_active_line(co, 0);
2087
2088                         if (*event_flag) {
2089                                 dbg("Call status before calling _call_branch_by_status() : (%d)", call_list[cllc_info].info.status);
2090                                 _call_branch_by_status(plugin, co, call_list[cllc_info].info.status);
2091                         } else {
2092                                 // Set Status
2093                                 tcore_call_object_set_status(co, call_list[cllc_info].info.status);
2094
2095                                 dbg("Call id : (%d)", call_list[cllc_info].info.id);
2096                                 dbg("Call direction : (%d)", call_list[cllc_info].info.direction);
2097                                 dbg("Call type : (%d)", call_list[cllc_info].info.type);
2098                                 dbg("Call mpty : (%d)", call_list[cllc_info].info.mpty);
2099                                 dbg("Call number : (%s)", call_list[cllc_info].number);
2100                                 dbg("Call status : (%d)", call_list[cllc_info].info.status);
2101                         }
2102                 }
2103
2104                 // Free Call list
2105                 g_free(call_list);
2106         }
2107
2108         // Free User data
2109         if (event_flag) {
2110         g_free(event_flag);
2111                 event_flag = NULL;
2112         }
2113
2114         dbg("Exit");
2115         return;
2116 }
2117
2118 static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data)
2119 {
2120         TcorePlugin *plugin = NULL;
2121         CoreObject *core_obj = NULL;
2122         CallObject *co = (CallObject *) user_data;
2123         const TcoreATResponse *response = data;
2124         const char *line = NULL;
2125         struct tnoti_call_status_idle call_status;
2126         GSList *tokens = NULL;
2127         char *resp_str;
2128         int error;
2129
2130         dbg("Entry");
2131         plugin = tcore_pending_ref_plugin(p);
2132         core_obj = tcore_pending_ref_core_object(p);
2133
2134         if (response->success > 0) {
2135                 dbg("RESPONSE OK");
2136                 line = (const char *) (((GSList *) response->lines)->data);
2137                 tokens = tcore_at_tok_new(line);
2138                 resp_str = g_slist_nth_data(tokens, 0);
2139                 if (!resp_str) {
2140                         err("call end cause - report value missing");
2141                 } else {
2142                         resp_str = g_slist_nth_data(tokens, 1);
2143                         if (!resp_str) {
2144                                 err("call end cause value missing");
2145                         }
2146                         error = atoi(resp_str);
2147                         dbg("call end cause - %d", error);
2148                         call_status.cause = _compare_call_end_cause(error);
2149                         dbg("TAPI call end cause - %d", call_status.cause);
2150                 }
2151
2152                 // Free tokens
2153                 tcore_at_tok_free(tokens);
2154         } else {
2155                 err("RESPONSE NOT OK");
2156                 line = (char *) response->final_response;
2157                 tokens = tcore_at_tok_new(line);
2158                 if (g_slist_length(tokens) < 1) {
2159                         err("err cause not specified or string corrupted");
2160                 } else {
2161                         err(" err cause  value: %d", atoi(g_slist_nth_data(tokens, 0)));
2162                 }
2163                 call_status.cause = CC_CAUSE_NORMAL_CALL_CLEARING;
2164                 // Free tokens
2165                 tcore_at_tok_free(tokens);
2166         }
2167
2168         call_status.type = tcore_call_object_get_type(co);
2169         dbg("data.type : [%d]", call_status.type);
2170
2171         call_status.id = tcore_call_object_get_id(co);
2172         dbg("data.id : [%d]", call_status.id);
2173
2174         // Set Status
2175         tcore_call_object_set_status(co, TCORE_CALL_STATUS_IDLE);
2176
2177         // Send Notification to TAPI
2178         tcore_server_send_notification(tcore_plugin_ref_server(plugin),
2179                                                                    core_obj,
2180                                                                    TNOTI_CALL_STATUS_IDLE,
2181                                                                    sizeof(struct tnoti_call_status_idle),
2182                                                                    (void *) &call_status);
2183
2184         // Free Call object
2185         tcore_call_object_free(core_obj, co);
2186 }
2187
2188 static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call)
2189 {
2190         // +CLCC: 1,0,2,0,0,"18005551212",145
2191         // [+CLCC: <id1>, <dir>, <stat>, <mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>]]]
2192         int state;
2193         int mode;
2194         int isMT;
2195         char *num = NULL;
2196         unsigned int num_type;
2197         GSList *tokens = NULL;
2198         char *resp = NULL;
2199
2200         dbg("Entry");
2201
2202         tokens = tcore_at_tok_new(line);
2203         // parse <id>
2204         resp = g_slist_nth_data(tokens, 0);
2205         if (!resp) {
2206                 err("InValid ID");
2207                 goto ERROR;
2208         }
2209         p_call->info.id = atoi(resp);
2210         dbg("id : [%d]\n", p_call->info.id);
2211
2212         // parse <dir>
2213         resp = g_slist_nth_data(tokens, 1);
2214         if (!resp) {
2215                 err("InValid Dir");
2216                 goto ERROR;
2217         }
2218         isMT = atoi(resp);
2219         if (0 == isMT) {
2220                 p_call->info.direction = TCORE_CALL_DIRECTION_OUTGOING;
2221         } else {
2222                 p_call->info.direction = TCORE_CALL_DIRECTION_INCOMING;
2223         }
2224         dbg("Direction : [ %d ]\n", p_call->info.direction);
2225
2226         // parse <stat>
2227         resp = g_slist_nth_data(tokens, 2);
2228         if (!resp) {
2229                 err("InValid Stat");
2230                 goto ERROR;
2231         }
2232         state = atoi(resp);
2233         dbg("Call state : %d", state);
2234         switch (state) {
2235         case 0:     // active
2236                 p_call->info.status = TCORE_CALL_STATUS_ACTIVE;
2237                 break;
2238
2239         case 1:
2240                 p_call->info.status = TCORE_CALL_STATUS_HELD;
2241                 break;
2242
2243         case 2:
2244                 p_call->info.status = TCORE_CALL_STATUS_DIALING;
2245                 break;
2246
2247         case 3:
2248                 p_call->info.status = TCORE_CALL_STATUS_ALERT;
2249                 break;
2250
2251         case 4:
2252                 p_call->info.status = TCORE_CALL_STATUS_INCOMING;
2253                 break;
2254
2255         case 5:
2256                 p_call->info.status = TCORE_CALL_STATUS_WAITING;
2257                 break;
2258         }
2259         dbg("Status : [%d]\n", p_call->info.status);
2260
2261         // parse <mode>
2262         resp = g_slist_nth_data(tokens, 3);
2263         if (!resp) {
2264                 err("InValid Mode");
2265                 goto ERROR;
2266         }
2267         mode = atoi(resp);
2268         switch (mode) {
2269         case 0:
2270                 p_call->info.type = TCORE_CALL_TYPE_VOICE;
2271                 break;
2272
2273         case 1:
2274                 p_call->info.type = TCORE_CALL_TYPE_VIDEO;
2275                 break;
2276
2277         default:        // only Voice/VT call is supported in CS. treat other unknown calls as error
2278                 dbg("invalid type : [%d]\n", mode);
2279                 goto ERROR;
2280         }
2281         dbg("Call type : [%d]\n", p_call->info.type);
2282
2283         // parse <mpty>
2284         resp = g_slist_nth_data(tokens, 4);
2285         if (!resp) {
2286                 err("InValid Mpty");
2287                 goto ERROR;
2288         }
2289
2290         p_call->info.mpty = atoi(resp);
2291         dbg("Mpty : [ %d ]\n", p_call->info.mpty);
2292
2293         // parse <num>
2294         resp = g_slist_nth_data(tokens, 5);
2295         dbg("Incoming number - %s and its len  - %d", resp, strlen(resp));
2296
2297         // tolerate null here
2298         if (!resp) {
2299                 err("Number is NULL");
2300                 goto ERROR;
2301         }
2302         // Strike off double quotes
2303         num = util_removeQuotes(resp);
2304         dbg("num  after removing quotes - %s", num);
2305
2306         p_call->info.num_len = strlen(resp);
2307         dbg("num_len : [0x%x]\n", p_call->info.num_len);
2308
2309         // parse <num type>
2310         resp = g_slist_nth_data(tokens, 6);
2311         if (!resp) {
2312                 dbg("InValid Num type");
2313                 goto ERROR;
2314         }
2315         p_call->info.num_type = atoi(resp);
2316         dbg("BCD num type: [0x%x]\n", p_call->info.num_type);
2317
2318         // check number is international or national.
2319         num_type = ((p_call->info.num_type) >> 4) & 0x07;
2320         dbg("called party's type of number : [0x%x]\n", num_type);
2321
2322         if (num_type == 1 && num[0] != '+') {
2323                 // international number
2324                 p_call->number[0] = '+';
2325                 memcpy(&(p_call->number[1]), num, strlen(num));
2326         } else {
2327                 memcpy(&(p_call->number), num, strlen(num));
2328         }
2329         dbg("incoming number - %s", p_call->number);
2330
2331         g_free(num);
2332         num = NULL;
2333         // Free tokens
2334         tcore_at_tok_free(tokens);
2335
2336         dbg("Exit");
2337         return 0;
2338
2339 ERROR:
2340         err("Invalid CLCC line");
2341
2342         if (num) {
2343                 g_free(num);
2344                 num = NULL;
2345         }
2346
2347         // Free tokens
2348         tcore_at_tok_free(tokens);
2349         err("Exit");
2350         return -1;
2351 }
2352
2353 // NOTIFICATION
2354 static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data)
2355 {
2356         GSList *tokens = NULL;
2357         const char *line = NULL;
2358         char *pId;
2359         int call_id;
2360         gboolean *eflag;
2361         GSList *pList = NULL;
2362         CallObject *co = NULL, *dupco = NULL;
2363
2364         dbg("function entrance");
2365         // check call with waiting status already exist
2366         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_WAITING);
2367
2368         if (pList != NULL) {
2369                 dbg("[error]Waiting call already exist. skip");
2370                 return;
2371         }
2372         // check call with incoming status already exist
2373         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
2374
2375         if (pList != NULL) {
2376                 dbg("[error]incoming call already exist. skip");
2377                 return;
2378         }
2379         line = (char *) data;
2380         tokens = tcore_at_tok_new(line);
2381
2382         pId = g_slist_nth_data(tokens, 0);
2383         if (!pId) {
2384                 dbg("[error]:Call id is missing from +XCALLSTAT indication");
2385                 tcore_at_tok_free(tokens);
2386                 return;
2387         }
2388
2389         call_id = atoi(pId);
2390         dupco = tcore_call_object_find_by_id(o, call_id);
2391         if (dupco != NULL) {
2392                 dbg("co with same id already exist. skip");
2393                 tcore_at_tok_free(tokens);
2394                 return;
2395         }
2396         co = tcore_call_object_new(o, call_id);
2397         if (!co) {
2398                 dbg("[ error ] co is NULL");
2399                 tcore_at_tok_free(tokens);
2400                 return;
2401         }
2402
2403         tcore_at_tok_free(tokens);
2404
2405         eflag = g_new0(gboolean, 1);
2406         *eflag = TRUE;
2407         dbg("calling _call_list_get");
2408         _call_list_get(o, eflag);
2409 }
2410
2411 static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data)
2412 {
2413         GSList *tokens = NULL;
2414         const char *line = NULL;
2415         char *pId;
2416         int call_id;
2417         gboolean *eflag;
2418         GSList *pList = NULL;
2419         CallObject *co = NULL, *dupco = NULL;
2420
2421         dbg("function entrance");
2422         // check call with incoming status already exist
2423         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
2424
2425         if (pList != NULL) {
2426                 dbg("incoming call already exist. skip");
2427                 return;
2428         }
2429
2430         line = (char *) data;
2431         tokens = tcore_at_tok_new(line);
2432
2433         pId = g_slist_nth_data(tokens, 0);
2434         if (!pId) {
2435                 dbg("Error:Call id is missing from %XCALLSTAT indication");
2436                 tcore_at_tok_free(tokens);
2437                 return;
2438         }
2439
2440         call_id = atoi(pId);
2441
2442         dupco = tcore_call_object_find_by_id(o, call_id);
2443         if (dupco != NULL) {
2444                 dbg("co with same id already exist. skip");
2445                 tcore_at_tok_free(tokens);
2446                 return;
2447         }
2448
2449         co = tcore_call_object_new(o, call_id);
2450         if (!co) {
2451                 dbg("[ error ] co is NULL");
2452                 tcore_at_tok_free(tokens);
2453                 return;
2454         }
2455
2456         dbg("freeing  at token")
2457         tcore_at_tok_free(tokens);
2458
2459         eflag = g_new0(gboolean, 1);
2460         *eflag = TRUE;
2461
2462         dbg("calling  _call_list_get");
2463         _call_list_get(o, eflag);
2464 }
2465
2466 static void on_notification_call_status(CoreObject *o, const void *data, void *user_data)
2467 {
2468         char *cmd = NULL;
2469         TcorePlugin *plugin = NULL;
2470         CallObject *co = NULL;
2471         int id = -1;
2472         int status = 0;
2473         int type = 0;
2474         char *stat = NULL;
2475         char *pCallId = NULL;
2476         GSList *tokens = NULL;
2477         gboolean *eflag = NULL;
2478         enum tcore_call_status co_status;
2479
2480         dbg("function entrance");
2481         plugin = tcore_object_ref_plugin(o);
2482         cmd = (char *) data;
2483         tokens = tcore_at_tok_new(cmd);
2484
2485         // parse <Call Id>
2486         pCallId = g_slist_nth_data(tokens, 0);
2487         if (!pCallId) {
2488                 dbg("CallId is missing from %XCALLSTAT indication");
2489                 tcore_at_tok_free(tokens);
2490                 return;
2491         } else {
2492                 id = atoi(pCallId);
2493                 dbg("call id = %d", id);
2494                 // parse <Stat>
2495                 if ((stat = g_slist_nth_data(tokens, 1))) {
2496                         status = atoi(stat);
2497                 }
2498                 dbg("call status = %d", status);
2499         }
2500
2501         tcore_at_tok_free(tokens);
2502         co_status = _call_status(status);
2503
2504         dbg("co_status = %d", co_status);
2505         switch (co_status) {
2506         case CALL_STATUS_ACTIVE:
2507         {
2508                 dbg("call(%d) status : [ ACTIVE ]", id);
2509                 co = tcore_call_object_find_by_id(o, id);
2510                 if (!co) {
2511                         dbg("co is NULL");
2512                         return;
2513                 }
2514                 _call_status_active(plugin, co);
2515         }
2516         break;
2517
2518         case CALL_STATUS_HELD:
2519                 dbg("call(%d) status : [ held ]", id);
2520                 break;
2521
2522         case CALL_STATUS_DIALING:
2523         {
2524                 dbg("call(%d) status : [ dialing ]", id);
2525                 co = tcore_call_object_find_by_id(o, id);
2526                 if (!co) {
2527                         co = tcore_call_object_new(o, id);
2528                         if (!co) {
2529                                 dbg("error : tcore_call_object_new [ id : %d ]", id);
2530                                 return;
2531                         }
2532                 }
2533
2534                 tcore_call_object_set_type(co, call_type(type));
2535                 tcore_call_object_set_direction(co, TCORE_CALL_DIRECTION_OUTGOING);
2536                 _call_status_dialing(plugin, co);
2537         }
2538         break;
2539
2540         case CALL_STATUS_ALERT:
2541         {
2542                 dbg("call(%d) status : [ alert ]", id);
2543                 co = tcore_call_object_find_by_id(o, id);
2544                 if (!co) {
2545                         dbg("co is NULL");
2546                         return;
2547                 }
2548                 // Store dialed number information into Call object.
2549                 eflag = g_new0(gboolean, 1);
2550                 *eflag = TRUE;
2551                 dbg("calling _call_list_get");
2552                 _call_list_get(o, eflag);
2553         }
2554         break;
2555
2556         case CALL_STATUS_INCOMING:
2557         case CALL_STATUS_WAITING:
2558                 dbg("call(%d) status : [ incoming ]", id);
2559                 break;
2560
2561         case CALL_STATUS_IDLE:
2562         {
2563                 dbg("call(%d) status : [ release ]", id);
2564
2565                 co = tcore_call_object_find_by_id(o, id);
2566                 if (!co) {
2567                         dbg("co is NULL");
2568                         return;
2569                 }
2570
2571                 plugin = tcore_object_ref_plugin(o);
2572                 if (!plugin) {
2573                         dbg("plugin is NULL");
2574                         return;
2575                 }
2576                 _call_status_idle(plugin, co);
2577         }
2578         break;
2579
2580         default:
2581                 dbg("invalid call status", id);
2582                 break;
2583         }
2584 }
2585
2586 static TReturn s_call_outgoing(CoreObject *o, UserRequest *ur)
2587 {
2588         struct treq_call_dial *data = 0;
2589         char *raw_str = NULL;
2590         char *cmd_str = NULL;
2591         const char *cclir;
2592         enum tcore_call_cli_mode clir = CALL_CLI_MODE_DEFAULT;
2593         TcorePending *pending = NULL;
2594         TcoreATRequest *req;
2595         gboolean ret = FALSE;
2596
2597         dbg("function entrance");
2598
2599         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2600                 dbg("cp not ready/n");
2601                 return TCORE_RETURN_ENOSYS;
2602         }
2603
2604         data = (struct treq_call_dial *) tcore_user_request_ref_data(ur, 0);
2605         if (data->type == CALL_TYPE_VIDEO) {
2606                 dbg("invalid call type")
2607                 return TCORE_RETURN_FAILURE;
2608         }
2609
2610         clir = _get_clir_status(data->number);
2611
2612         // Compose ATD Cmd string
2613         switch (clir) {
2614         case TCORE_CALL_CLI_MODE_PRESENT:
2615                 dbg("CALL_CLI_MODE_PRESENT");
2616                 cclir = "I";
2617                 break;  // invocation
2618
2619         case TCORE_CALL_CLI_MODE_RESTRICT:
2620                 dbg("CALL_CLI_MODE_RESTRICT");
2621                 cclir = "i";
2622                 break;  // suppression
2623
2624         case TCORE_CALL_CLI_MODE_DEFAULT:
2625         default:
2626                 cclir = "";
2627                 dbg("CALL_CLI_MODE_DEFAULT");
2628                 break;   // subscription default
2629         }
2630
2631         dbg("data->number = %s", data->number);
2632
2633         raw_str = g_strdup_printf("ATD%s%s;", data->number, cclir);
2634         cmd_str = g_strdup_printf("%s", raw_str);
2635
2636         dbg("request command : %s", cmd_str);
2637
2638         pending = tcore_pending_new(o, 0);
2639         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2640         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2641
2642         tcore_pending_set_request_data(pending, 0, req);
2643         ret = _call_request_message(pending, o, ur, on_confirmation_call_outgoing, NULL);
2644
2645         g_free(raw_str);
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
2653         dbg("AT request(%s) sent success", req->cmd);
2654
2655         return TCORE_RETURN_SUCCESS;
2656 }
2657
2658 static TReturn s_call_answer(CoreObject *o, UserRequest *ur)
2659 {
2660         char *cmd_str = NULL;
2661         CallObject *co = NULL;
2662         struct treq_call_answer *data = 0;
2663         TcorePending *pending = NULL;
2664         TcoreATRequest *req;
2665         gboolean ret = FALSE;
2666
2667         dbg("function entrance");
2668
2669         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2670                 dbg("cp not ready/n");
2671                 return TCORE_RETURN_ENOSYS;
2672         }
2673
2674         data = (struct treq_call_answer *) tcore_user_request_ref_data(ur, 0);
2675         co = tcore_call_object_find_by_id(o, data->id);
2676         if (data->type == CALL_ANSWER_TYPE_ACCEPT) {
2677                 dbg(" request type CALL_ANSWER_TYPE_ACCEPT");
2678
2679                 cmd_str = g_strdup_printf("%s", "ATA");
2680                 pending = tcore_pending_new(o, 0);
2681                 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2682                 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2683
2684                 tcore_pending_set_request_data(pending, 0, req);
2685                 ret = _call_request_message(pending, o, ur, on_confirmation_call_accept, co);
2686                 g_free(cmd_str);
2687
2688                 if (!ret) {
2689                         dbg("AT request(%s) sent failed", req->cmd);
2690                         return TCORE_RETURN_FAILURE;
2691                 }
2692         } else {
2693                 switch (data->type) {
2694                 case CALL_ANSWER_TYPE_REJECT:
2695                 {
2696                         dbg("call answer reject");
2697                         tcore_call_control_answer_reject(o, ur, on_confirmation_call_reject, co);
2698                 }
2699                 break;
2700
2701                 case CALL_ANSWER_TYPE_REPLACE:
2702                 {
2703                         dbg("call answer replace");
2704                         tcore_call_control_answer_replace(o, ur, on_confirmation_call_replace, co);
2705                 }
2706                 break;
2707
2708                 case CALL_ANSWER_TYPE_HOLD_ACCEPT:
2709                 {
2710                         dbg("call answer hold and accept");
2711                         tcore_call_control_answer_hold_and_accept(o, ur, on_confirmation_call_hold_and_accept, co);
2712                 }
2713                 break;
2714
2715                 default:
2716                         dbg("[ error ] wrong answer type [ %d ]", data->type);
2717                         return TCORE_RETURN_FAILURE;
2718                 }
2719         }
2720
2721         return TCORE_RETURN_SUCCESS;
2722 }
2723
2724 static TReturn s_call_release(CoreObject *o, UserRequest *ur)
2725 {
2726         CallObject *co = NULL;
2727         struct treq_call_end *data = 0;
2728         UserRequest *ur_dup = NULL;
2729         char *chld0_cmd = NULL;
2730         char *chld1_cmd = NULL;
2731         TcorePending *pending = NULL, *pending1 = NULL;
2732         TcoreATRequest *req, *req1;
2733         gboolean ret = FALSE;
2734
2735         dbg("function entrance");
2736         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2737                 dbg("cp not ready/n");
2738                 return TCORE_RETURN_ENOSYS;
2739         }
2740         data = (struct treq_call_end *) tcore_user_request_ref_data(ur, 0);
2741         co = tcore_call_object_find_by_id(o, data->id);
2742
2743         dbg("type of release call = %d", data->type);
2744
2745         if (data->type == CALL_END_TYPE_ALL) {
2746                 // releaseAll do not exist on legacy request. send CHLD=0, CHLD=1 in sequence
2747                 chld0_cmd = g_strdup("AT+CHLD=0");
2748                 chld1_cmd = g_strdup("AT+CHLD=1");
2749
2750                 pending = tcore_pending_new(o, 0);
2751                 req = tcore_at_request_new(chld0_cmd, NULL, TCORE_AT_NO_RESULT);
2752
2753                 dbg("input command is %s", chld0_cmd);
2754                 dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2755
2756                 tcore_pending_set_request_data(pending, 0, req);
2757                 ur_dup = tcore_user_request_new(NULL, NULL);
2758                 ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_endall, NULL);
2759                 g_free(chld0_cmd);
2760
2761                 if (!ret) {
2762                         dbg("AT request %s has failed ", req->cmd);
2763                         if (ur_dup) {
2764                                 tcore_user_request_free(ur_dup);
2765                                 ur_dup = NULL;
2766                         }
2767                         g_free(chld1_cmd);
2768                         return TCORE_RETURN_FAILURE;
2769                 }
2770
2771                 pending1 = tcore_pending_new(o, 0);
2772                 req1 = tcore_at_request_new(chld1_cmd, NULL, TCORE_AT_NO_RESULT);
2773
2774                 dbg("input command is %s", chld1_cmd);
2775                 dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd));
2776
2777                 tcore_pending_set_request_data(pending1, 0, req1);
2778                 ret = _call_request_message(pending1, o, ur, on_confirmation_call_release_all, co);
2779                 g_free(chld1_cmd);
2780
2781                 if (!ret) {
2782                         dbg("AT request %s has failed ", req->cmd);
2783                         return TCORE_RETURN_FAILURE;
2784                 }
2785         } else {
2786                 switch (data->type) {
2787                 case CALL_END_TYPE_DEFAULT:
2788                 {
2789                         int id = 0;
2790                         id = tcore_call_object_get_id(co);
2791
2792                         dbg("call end call id [%d]", id);
2793                         tcore_call_control_end_specific(o, ur, id, on_confirmation_call_release_specific, co);
2794                 }
2795                 break;
2796
2797                 case CALL_END_TYPE_ACTIVE_ALL:
2798                 {
2799                         dbg("call end all active");
2800                         tcore_call_control_end_all_active(o, ur, on_confirmation_call_release_all_active, co);
2801                 }
2802                 break;
2803
2804                 case CALL_END_TYPE_HOLD_ALL:
2805                 {
2806                         dbg("call end all held");
2807                         tcore_call_control_end_all_held(o, ur, on_confirmation_call_release_all_held, co);
2808                 }
2809                 break;
2810
2811                 default:
2812                         dbg("[ error ] wrong end type [ %d ]", data->type);
2813                         return TCORE_RETURN_FAILURE;
2814                 }
2815         }
2816
2817         return TCORE_RETURN_SUCCESS;
2818 }
2819
2820 static TReturn s_call_hold(CoreObject *o, UserRequest *ur)
2821 {
2822         struct treq_call_hold *hold = 0;
2823         CallObject *co = NULL;
2824
2825         dbg("function entrance");
2826
2827         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2828                 dbg("cp not ready/n");
2829                 return TCORE_RETURN_ENOSYS;
2830         }
2831
2832         hold = (struct treq_call_hold *) tcore_user_request_ref_data(ur, 0);
2833         dbg("call id : [ %d ]", hold->id);
2834
2835         co = tcore_call_object_find_by_id(o, hold->id);
2836         tcore_call_control_hold(o, ur, on_confirmation_call_hold, co);
2837
2838         return TCORE_RETURN_SUCCESS;
2839 }
2840
2841 static TReturn s_call_active(CoreObject *o, UserRequest *ur)
2842 {
2843         struct treq_call_active *active = 0;
2844         CallObject *co = NULL;
2845
2846         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2847                 dbg("cp not ready/n");
2848                 return TCORE_RETURN_ENOSYS;
2849         }
2850
2851         active = (struct treq_call_active *) tcore_user_request_ref_data(ur, 0);
2852         dbg("call id : [ %d ]", active->id);
2853
2854         co = tcore_call_object_find_by_id(o, active->id);
2855         tcore_call_control_active(o, ur, on_confirmation_call_active, co);
2856
2857         return TCORE_RETURN_SUCCESS;
2858 }
2859
2860 static TReturn s_call_swap(CoreObject *o, UserRequest *ur)
2861 {
2862         struct treq_call_swap *swap = NULL;
2863         CallObject *co = NULL;
2864
2865         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2866                 dbg("cp not ready/n");
2867                 return TCORE_RETURN_ENOSYS;
2868         }
2869
2870         swap = (struct treq_call_swap *) tcore_user_request_ref_data(ur, 0);
2871         dbg("call id : [ %d ]", swap->id);
2872
2873         co = tcore_call_object_find_by_id(o, swap->id);
2874         tcore_call_control_swap(o, ur, on_confirmation_call_swap, co);
2875
2876         return TCORE_RETURN_SUCCESS;
2877 }
2878
2879 static TReturn s_call_join(CoreObject *o, UserRequest *ur)
2880 {
2881         struct treq_call_join *join = 0;
2882         CallObject *co = NULL;
2883
2884         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2885                 dbg("cp not ready/n");
2886                 return TCORE_RETURN_ENOSYS;
2887         }
2888
2889         join = (struct treq_call_join *) tcore_user_request_ref_data(ur, 0);
2890         dbg("call id : [ %d ]", join->id);
2891
2892         co = tcore_call_object_find_by_id(o, join->id);
2893         tcore_call_control_join(o, ur, on_confirmation_call_join, co);
2894
2895         return TCORE_RETURN_SUCCESS;
2896 }
2897
2898 static TReturn s_call_split(CoreObject *o, UserRequest *ur)
2899 {
2900         struct treq_call_split *split = 0;
2901         CallObject *co = NULL;
2902
2903         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2904                 dbg("cp not ready/n");
2905                 return TCORE_RETURN_ENOSYS;
2906         }
2907
2908         split = (struct treq_call_split *) tcore_user_request_ref_data(ur, 0);
2909         co = tcore_call_object_find_by_id(o, split->id);
2910         dbg("call id : [ %d ]", split->id);
2911
2912         tcore_call_control_split(o, ur, split->id, on_confirmation_call_split, co);
2913
2914         return TCORE_RETURN_SUCCESS;
2915 }
2916
2917 static TReturn s_call_deflect(CoreObject *o, UserRequest *ur)
2918 {
2919         struct treq_call_deflect *deflect = 0;
2920         CallObject *co = NULL;
2921
2922         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2923                 dbg("cp not ready/n");
2924                 return TCORE_RETURN_ENOSYS;
2925         }
2926
2927         deflect = (struct treq_call_deflect *) tcore_user_request_ref_data(ur, 0);
2928         co = tcore_call_object_find_by_number(o, deflect->number);
2929         dbg("deflect number: [ %s ]", deflect->number);
2930
2931         tcore_call_control_deflect(o, ur, deflect->number, on_confirmation_call_deflect, co);
2932
2933         return TCORE_RETURN_SUCCESS;
2934 }
2935
2936 static TReturn s_call_transfer(CoreObject *o, UserRequest *ur)
2937 {
2938         struct treq_call_transfer *transfer = 0;
2939         CallObject *co = NULL;
2940
2941         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2942                 dbg("cp not ready/n");
2943                 return TCORE_RETURN_ENOSYS;
2944         }
2945
2946         transfer = (struct treq_call_transfer *) tcore_user_request_ref_data(ur, 0);
2947         dbg("call id : [ %d ]", transfer->id);
2948
2949         co = tcore_call_object_find_by_id(o, transfer->id);
2950         tcore_call_control_transfer(o, ur, on_confirmation_call_transfer, co);
2951
2952         return TCORE_RETURN_SUCCESS;
2953 }
2954
2955 static TReturn s_call_send_dtmf(CoreObject *o, UserRequest *ur)
2956 {
2957         char *cmd_str = NULL;
2958         TcorePending *pending = NULL;
2959         TcoreATRequest *req;
2960         UserRequest *dup;
2961         gboolean ret = FALSE;
2962         struct treq_call_dtmf *dtmf = 0;
2963         char *dtmfstr = NULL, *tmp_dtmf = NULL;
2964         unsigned int dtmf_count;
2965
2966         dbg("Function enter");
2967
2968         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2969                 dbg("cp not ready/n");
2970                 return TCORE_RETURN_ENOSYS;
2971         }
2972
2973         dup = tcore_user_request_new(NULL, NULL);
2974         (void) _set_dtmf_tone_duration(o, dup);
2975
2976         dtmf = (struct treq_call_dtmf *) tcore_user_request_ref_data(ur, 0);
2977         dtmfstr = g_malloc0((MAX_CALL_DTMF_DIGITS_LEN * 2) + 1);    // DTMF digits + comma for each dtmf digit.
2978
2979         if (dtmfstr == NULL) {
2980                 dbg("Memory allocation failed");
2981                 return TCORE_RETURN_FAILURE;
2982         }
2983
2984         tmp_dtmf = dtmfstr;
2985
2986         for (dtmf_count = 0; dtmf_count < strlen(dtmf->digits); dtmf_count++) {
2987                 *tmp_dtmf = dtmf->digits[dtmf_count];
2988                 tmp_dtmf++;
2989
2990                 *tmp_dtmf = COMMA;
2991                 tmp_dtmf++;
2992         }
2993
2994         // last digit is having COMMA , overwrite it with '\0' .
2995         *(--tmp_dtmf) = '\0';
2996         dbg("Input DTMF string(%s)", dtmfstr);
2997
2998         // AT+VTS = <d1>,<d2>,<d3>,<d4>,<d5>,<d6>, ..... <d32>
2999         cmd_str = g_strdup_printf("AT+VTS=%s", dtmfstr);
3000         dbg("request command : %s", cmd_str);
3001
3002         pending = tcore_pending_new(o, 0);
3003         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
3004         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3005
3006         tcore_pending_set_request_data(pending, 0, req);
3007         ret = _call_request_message(pending, o, ur, on_confirmation_call_dtmf, NULL);
3008         g_free(dtmfstr);
3009         g_free(cmd_str);
3010
3011         if (!ret) {
3012                 dbg("AT request sent failed")
3013                 return TCORE_RETURN_FAILURE;
3014         }
3015
3016         return TCORE_RETURN_SUCCESS;
3017 }
3018
3019 static TReturn s_call_set_sound_path(CoreObject *o, UserRequest *ur)
3020 {
3021         UserRequest *ur_dup = NULL;
3022         TcorePending *pending = NULL, *pending1 = NULL;
3023         TcoreATRequest *req, *req1;
3024         char *cmd_str = NULL, *cmd_str1 = NULL;
3025         int device_type = -1;
3026         struct treq_call_sound_set_path *sound_path = 0;
3027         gboolean ret = FALSE;
3028         TcorePlugin *plugin = tcore_object_ref_plugin(o);
3029         const char *cp_name = tcore_server_get_cp_name_by_plugin(plugin);
3030
3031         dbg("function entrance");
3032
3033         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3034                 dbg("cp not ready/n");
3035                 return TCORE_RETURN_ENOSYS;
3036         }
3037         sound_path = (struct treq_call_sound_set_path *) tcore_user_request_ref_data(ur, 0);
3038         if (sound_path == NULL) {
3039                 dbg("invaling user request");
3040                 return TCORE_RETURN_FAILURE;
3041         }
3042         dbg("audio device type - 0x%x", sound_path->path);
3043         switch (sound_path->path) {
3044         case CALL_SOUND_PATH_HANDSET:
3045                 device_type = 1;
3046                 break;
3047
3048         case CALL_SOUND_PATH_HEADSET:
3049                 device_type = 2;
3050                 break;
3051
3052         case CALL_SOUND_PATH_HEADSET_3_5PI:
3053                 device_type = 3;
3054                 break;
3055
3056         case CALL_SOUND_PATH_SPEAKER:
3057                 device_type = 4;
3058                 break;
3059
3060         case CALL_SOUND_PATH_HANDFREE:
3061                 device_type = 5;
3062                 break;
3063
3064         case CALL_SOUND_PATH_HEADSET_HAC:
3065                 device_type = 6;
3066                 break;
3067
3068         case CALL_SOUND_PATH_BLUETOOTH:
3069         case CALL_SOUND_PATH_STEREO_BLUETOOTH:
3070                 device_type = 7;
3071                 break;
3072
3073         case CALL_SOUND_PATH_BT_NSEC_OFF:
3074         case CALL_SOUND_PATH_MIC1:
3075         case CALL_SOUND_PATH_MIC2:
3076         default:
3077                 dbg("unsupported device type");
3078                 return TCORE_RETURN_FAILURE;
3079         }
3080
3081         if (g_str_has_prefix(cp_name, "mfld_blackbay") == TRUE) {
3082                 struct tnoti_call_sound_path tnoti_snd_path;
3083                 tnoti_snd_path.path = sound_path->path;
3084                 /* Configure modem I2S1 to 8khz, mono, PCM if routing to bluetooth */
3085                 if (sound_path->path == CALL_SOUND_PATH_BLUETOOTH || sound_path->path == CALL_SOUND_PATH_STEREO_BLUETOOTH) {
3086                         call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,3,0,1,0,0,0,0,0,0,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3087                         call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,2,0,1,0,0,0,0,0,0,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3088                 }
3089                 else {
3090                         call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,3,0,1,0,8,0,1,0,2,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3091                         call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,2,0,1,0,8,0,1,0,2,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3092                 }
3093
3094                 /* Configure modem I2S2 and do the modem routing */
3095                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,4,0,0,0,8,0,1,0,2,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3096                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,3,0,0,0,8,0,1,0,2,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3097                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,0,4", NULL, TCORE_AT_NO_RESULT, NULL);
3098                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,3,0", NULL, TCORE_AT_NO_RESULT, NULL);
3099                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,4,2", NULL, TCORE_AT_NO_RESULT, NULL);
3100                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,5,2", NULL, TCORE_AT_NO_RESULT, NULL);
3101
3102                 /* amc enable */
3103                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,2,4", NULL, TCORE_AT_NO_RESULT, NULL); //AMC_I2S2_RX
3104                 call_prepare_and_send_pending_request(o, "AT+XDRV=40,2,3", NULL, TCORE_AT_NO_RESULT, NULL); //AMC_I2S1_RX
3105                 /* amc route: AMC_RADIO_RX => AMC_I2S1_TX */
3106
3107                 pending = tcore_pending_new(o, 0);
3108                 req = tcore_at_request_new("AT+XDRV=40,6,0,2", "+XDRV", TCORE_AT_SINGLELINE);
3109                 dbg("XDRV req-cmd for source type  : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3110                 tcore_pending_set_request_data(pending, 0, req);
3111                 ur_dup = tcore_user_request_ref(ur);
3112                 ret = _call_request_message(pending, o, ur_dup, on_confirmation_set_sound_path, &tnoti_snd_path);
3113
3114         } else {
3115
3116                 cmd_str = g_strdup_printf("AT+XDRV=40,4,3,0,0,0,0,0,1,0,1,0,%d",device_type); // source type.
3117                 pending = tcore_pending_new(o, 0);
3118                 req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3119                 dbg("XDRV req-cmd for source type  : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3120                 tcore_pending_set_request_data(pending, 0, req);
3121                 ur_dup = tcore_user_request_ref(ur);
3122                 ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_set_source_sound_path, NULL);
3123                 g_free(cmd_str);
3124
3125                 if (!ret) {
3126                         dbg("At request(%s) sent failed", req->cmd);
3127                         return TCORE_RETURN_FAILURE;
3128                 }
3129
3130                 cmd_str1 = g_strdup_printf("AT+XDRV=40,5,2,0,0,0,0,0,1,0,1,0,%d",device_type); // destination type
3131                 pending1 = tcore_pending_new(o, 0);
3132                 req1 = tcore_at_request_new(cmd_str1, "+XDRV", TCORE_AT_SINGLELINE);
3133                 dbg("XDRV req-cmd for destination type : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd));
3134                 tcore_pending_set_request_data(pending1, 0, req1);
3135                 ret = _call_request_message(pending1, o, ur, on_confirmation_call_set_destination_sound_path, NULL);
3136                 g_free(cmd_str1);
3137
3138                 if (!ret) {
3139                         dbg("AT request %s has failed ", req1->cmd);
3140                         return TCORE_RETURN_FAILURE;
3141                 }
3142         }
3143
3144         return TCORE_RETURN_SUCCESS;
3145 }
3146
3147 static TReturn s_call_set_sound_volume_level(CoreObject *o, UserRequest *ur)
3148 {
3149         UserRequest *src_ur = NULL;
3150         UserRequest *dest_ur = NULL;
3151         TcorePending *src_pending = NULL;
3152         TcorePending *dest_pending = NULL;
3153         TcoreATRequest *src_req = NULL;
3154         TcoreATRequest *dest_req = NULL;
3155         char *cmd_str = NULL, *volume_level = NULL;
3156         gboolean ret = FALSE;
3157         struct treq_call_sound_set_volume_level *data = NULL;
3158
3159         dbg("Entry");
3160
3161         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3162                 dbg("cp not ready/n");
3163                 return TCORE_RETURN_ENOSYS;
3164         }
3165
3166         data = (struct treq_call_sound_set_volume_level *) tcore_user_request_ref_data(ur, 0);
3167
3168         // Hard-coded values for MIC & Speakers
3169         // Source volume
3170         dbg("Set Source volume");
3171
3172         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,7,3,88");   // Source type
3173         dbg("Request command string: %s", cmd_str);
3174
3175         // Create new Pending request
3176         src_pending = tcore_pending_new(o, 0);
3177
3178         // Create new AT-Command request
3179         src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3180         dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd));
3181
3182         // Free Command string
3183         g_free(cmd_str);
3184
3185         tcore_pending_set_request_data(src_pending, 0, src_req);
3186         src_ur = tcore_user_request_ref(ur);
3187
3188         // Send request
3189         ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3190         if (!ret) {
3191                 err("Failed to send AT-Command request");
3192                 return TCORE_RETURN_FAILURE;
3193         }
3194
3195         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,7,0,88");   // Destination type
3196         dbg("Request command string: %s", cmd_str);
3197
3198         // Create new Pending request
3199         src_pending = tcore_pending_new(o, 0);
3200
3201         // Create new AT-Command request
3202         src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3203         dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd));
3204
3205         // Free Command string
3206         g_free(cmd_str);
3207
3208         tcore_pending_set_request_data(src_pending, 0, src_req);
3209
3210         src_ur = tcore_user_request_ref(ur);
3211
3212         // Send request
3213         ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3214         if (!ret) {
3215                 err("Failed to send AT-Command request");
3216                 return TCORE_RETURN_FAILURE;
3217         }
3218
3219         // Destination volume
3220         dbg("Set Source volume");
3221
3222         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,88");   // Source type
3223         dbg("Request command string: %s", cmd_str);
3224
3225         // Create new Pending request
3226         dest_pending = tcore_pending_new(o, 0);
3227
3228         // Create new AT-Command request
3229         dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3230         dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd));
3231
3232         // Free Command string
3233         g_free(cmd_str);
3234
3235         tcore_pending_set_request_data(dest_pending, 0, dest_req);
3236         dest_ur = tcore_user_request_ref(ur);
3237
3238         // Send request
3239         ret = _call_request_message(dest_pending, o, dest_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3240         if (!ret) {
3241                 err("Failed to send AT-Command request");
3242                 return TCORE_RETURN_FAILURE;
3243         }
3244
3245         dbg("Input volume level - %d", data->volume);
3246         switch (data->volume) {
3247         case CALL_SOUND_MUTE:
3248                 volume_level = "0";
3249                 break;
3250
3251         case CALL_SOUND_VOLUME_LEVEL_1:
3252                 volume_level = "40";
3253                 break;
3254
3255         case CALL_SOUND_VOLUME_LEVEL_2:
3256                 volume_level = "46";
3257                 break;
3258
3259         case CALL_SOUND_VOLUME_LEVEL_3:
3260                 volume_level = "52";
3261                 break;
3262
3263         case CALL_SOUND_VOLUME_LEVEL_4:
3264                 volume_level = "58";
3265                 break;
3266
3267         case CALL_SOUND_VOLUME_LEVEL_5:
3268                 volume_level = "64";
3269                 break;
3270
3271         case CALL_SOUND_VOLUME_LEVEL_6:
3272                 volume_level = "70";
3273                 break;
3274
3275         case CALL_SOUND_VOLUME_LEVEL_7:
3276                 volume_level = "76";
3277                 break;
3278
3279         case CALL_SOUND_VOLUME_LEVEL_8:
3280                 volume_level = "82";
3281                 break;
3282
3283         case CALL_SOUND_VOLUME_LEVEL_9:
3284         default:
3285                 volume_level = "88";
3286                 break;
3287         }
3288         cmd_str = g_strdup_printf("%s%s", "AT+XDRV=40,8,2,", volume_level);   // Destination type
3289         dbg("Request command string: %s", cmd_str);
3290
3291         // Create new Pending request
3292         dest_pending = tcore_pending_new(o, 0);
3293
3294         // Create new AT-Command request
3295         dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3296         dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd));
3297
3298         // Free Command string
3299         g_free(cmd_str);
3300
3301         tcore_pending_set_request_data(dest_pending, 0, dest_req);
3302
3303         // Send request
3304         ret = _call_request_message(dest_pending, o, ur, on_confirmation_call_set_destination_sound_volume_level, NULL);
3305         if (!ret) {
3306                 err("Failed to send AT-Command request");
3307                 return TCORE_RETURN_FAILURE;
3308         }
3309
3310         return TCORE_RETURN_SUCCESS;
3311 }
3312
3313
3314 static TReturn s_call_get_sound_volume_level(CoreObject *o, UserRequest *ur)
3315 {
3316         dbg("Entry");
3317
3318         dbg("Exit");
3319         return TCORE_RETURN_SUCCESS;
3320 }
3321
3322 static TReturn s_call_mute(CoreObject *o, UserRequest *ur)
3323 {
3324         char *cmd_str = NULL;
3325         TcorePending *pending = NULL;
3326         TcoreATRequest *req = NULL;
3327         gboolean ret = FALSE;
3328
3329         dbg("Entry");
3330
3331         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3332                 dbg("cp not ready/n");
3333                 return TCORE_RETURN_ENOSYS;
3334         }
3335
3336         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,0");
3337
3338         dbg("Request command string: %s", cmd_str);
3339
3340         // Create new Pending request
3341         pending = tcore_pending_new(o, 0);
3342
3343         // Create new AT-Command request
3344         req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3345         dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3346
3347         // Free command string
3348         g_free(cmd_str);
3349
3350         // Set request data (AT command) to Pending request
3351         tcore_pending_set_request_data(pending, 0, req);
3352
3353         // Send request
3354         ret = _call_request_message(pending, o, ur, on_confirmation_call_mute, NULL);
3355         if (!ret) {
3356                 err("Failed to send AT-Command request");
3357                 return TCORE_RETURN_FAILURE;
3358         }
3359
3360         dbg("Exit");
3361         return TCORE_RETURN_SUCCESS;
3362 }
3363
3364 static TReturn s_call_unmute(CoreObject *o, UserRequest *ur)
3365 {
3366         char *cmd_str = NULL;
3367         TcorePending *pending = NULL;
3368         TcoreATRequest *req = NULL;
3369         gboolean ret = FALSE;
3370
3371         dbg("Entry");
3372
3373         if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3374                 dbg("cp not ready/n");
3375                 return TCORE_RETURN_ENOSYS;
3376         }
3377
3378         cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,88");
3379         dbg("Request command string: %s", cmd_str);
3380
3381         // Create new Pending request
3382         pending = tcore_pending_new(o, 0);
3383
3384         // Create new AT-Command request
3385         req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3386         dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3387
3388         // Free command string
3389         g_free(cmd_str);
3390
3391         // Set request data (AT command) to Pending request
3392         tcore_pending_set_request_data(pending, 0, req);
3393
3394         // Send request
3395         ret = _call_request_message(pending, o, ur, on_confirmation_call_unmute, NULL);
3396         if (!ret) {
3397                 err("Failed to send AT-Command request");
3398                 return TCORE_RETURN_FAILURE;
3399         }
3400
3401         dbg("Exit");
3402         return TCORE_RETURN_SUCCESS;
3403 }
3404
3405
3406 static TReturn s_call_get_mute_status(CoreObject *o, UserRequest *ur)
3407 {
3408         dbg("Entry");
3409
3410         dbg("Exit");
3411         return TCORE_RETURN_SUCCESS;
3412 }
3413
3414 static TReturn _set_dtmf_tone_duration(CoreObject *o, UserRequest *ur)
3415 {
3416         char *cmd_str = NULL;
3417         TcorePending *pending = NULL;
3418         TcoreATRequest *req = NULL;
3419         gboolean ret = FALSE;
3420
3421         dbg("Entry");
3422
3423         cmd_str = g_strdup_printf("%s", "AT+VTD=3"); // ~300 mili secs. +VTD= n, where  n = (0 - 255) * 1/10 secs.
3424         dbg("Request command string: %s", cmd_str);
3425
3426         // Create new Pending request
3427         pending = tcore_pending_new(o, 0);
3428
3429         // Create new AT-Command request
3430         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
3431         dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3432
3433         // Free command string */
3434         g_free(cmd_str);
3435
3436         // Set request data (AT command) to Pending request
3437         tcore_pending_set_request_data(pending, 0, req);
3438
3439         // Send request
3440         ret = _call_request_message(pending, o, ur, _on_confirmation_dtmf_tone_duration, NULL);
3441         if (!ret) {
3442                 err("Failed to send AT-Command request");
3443                 if (ur) {
3444                         tcore_user_request_free(ur);
3445                         ur = NULL;
3446                 }
3447                 return TCORE_RETURN_FAILURE;
3448         }
3449
3450         dbg("Exit");
3451         return TCORE_RETURN_SUCCESS;
3452 }
3453
3454 // Call Operations
3455 static struct tcore_call_operations call_ops = {
3456         .dial = s_call_outgoing,
3457         .answer = s_call_answer,
3458         .end = s_call_release,
3459         .hold = s_call_hold,
3460         .active = s_call_active,
3461         .swap = s_call_swap,
3462         .join = s_call_join,
3463         .split = s_call_split,
3464         .deflect = s_call_deflect,
3465         .transfer = s_call_transfer,
3466         .send_dtmf = s_call_send_dtmf,
3467         .set_sound_path = s_call_set_sound_path,
3468         .set_sound_volume_level = s_call_set_sound_volume_level,
3469         .get_sound_volume_level = s_call_get_sound_volume_level,
3470         .mute = s_call_mute,
3471         .unmute = s_call_unmute,
3472         .get_mute_status = s_call_get_mute_status,
3473         .set_sound_recording = NULL,
3474         .set_sound_equalization = NULL,
3475         .set_sound_noise_reduction = NULL,
3476 };
3477
3478 gboolean s_call_init(TcorePlugin *cp, CoreObject *co_call)
3479 {
3480         dbg("Entry");
3481
3482         tcore_call_override_ops(co_call, &call_ops, NULL);
3483
3484         /* Add Callbacks */
3485         tcore_object_override_callback(co_call, "+XCALLSTAT", on_notification_call_info, NULL);
3486         tcore_object_override_callback(co_call, "+CLIP", on_notification_call_clip_info, NULL);
3487
3488         dbg("Exit");
3489
3490         return TRUE;
3491 }
3492
3493 void s_call_exit(TcorePlugin *cp, CoreObject *co_call)
3494 {
3495         dbg("Exit");
3496 }