Fix tel_hold_call() will be rejected, when existing Incoming Call
[platform/core/telephony/tel-plugin-atmodem.git] / src / s_call.c
1 /*
2  * tel-plugin-atmodem
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hayoon Ko <hayoon.ko@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 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
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 <server.h>
33 #include <co_call.h>
34 #include <user_request.h>
35
36 #include "s_common.h"
37 #include "s_call.h"
38
39 #include "atchannel.h"
40 #include "at_tok.h"
41
42
43 extern struct ATResponse *sp_response;
44 extern char *s_responsePrefix;
45 extern enum ATCommandType s_type;
46
47 struct CLCC_call_t {
48         struct CLCC_call_info_t {
49                 int                             id;
50                 enum tcore_call_direction       direction;
51                 enum tcore_call_status          status;
52                 enum tcore_call_type            type;
53                 int     mpty;
54                 int     num_len;
55                 int     num_type;
56         } info;
57         char number[90];
58 };
59
60
61 static gboolean _call_request_message( CoreObject *o, UserRequest* ur, char* cmd_string,
62                                                                                                 unsigned int cmd_length, void* on_resp, void* user_data);
63
64 static void             _call_status_idle( TcorePlugin *p, CallObject *co );
65 static void             _call_status_active( TcorePlugin *p, CallObject *co );
66 static void             _call_status_dialing( TcorePlugin *p, CallObject *co );
67 static void             _call_status_alert( TcorePlugin *p, CallObject *co );
68 static void             _call_status_incoming( TcorePlugin *p, CallObject *co );
69 static void             _call_status_waiting( TcorePlugin *p, CallObject *co );
70
71 static void             _call_branch_by_status( TcorePlugin *p, CallObject *co, unsigned int status );
72 static enum tcore_call_type _call_type( int type );
73 static enum tcore_call_status _call_status(unsigned int status);
74 static gboolean _call_is_in_mpty(int mpty);
75
76 static TReturn  _call_list_get( CoreObject *o, CallObject *co );
77
78 static void             on_confirmation_call_message_send( TcorePending *p, gboolean result, void *user_data ); // from Kernel
79
80 static void             on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data);
81 static gboolean on_notification_call_waiting( CoreObject *o, const void *data, void *user_data );
82 static gboolean on_notification_call_incoming( CoreObject *o, const void *data, void *user_data );
83 static gboolean on_notification_call_status( CoreObject *o, const void *data, void *user_data);
84
85
86 static int _callFromCLCCLine(char *line, struct CLCC_call_t *p_call);
87
88
89 static enum tcore_call_cli_mode _get_clir_status( char *num )
90 {
91         enum tcore_call_cli_mode clir = CALL_CLI_MODE_DEFAULT;
92
93         if( !strncmp( num, "*31#", 4 ) )
94                 return TCORE_CALL_CLI_MODE_RESTRICT;
95
96         if( !strncmp( num, "#31#", 4 ) )
97                 return TCORE_CALL_CLI_MODE_PRESENT;
98
99         return clir;
100 }
101
102
103 static enum tcore_call_status _call_status(unsigned int status)
104 {
105         switch(status)
106         {
107                 case 0:
108                         return TCORE_CALL_STATUS_ACTIVE;
109         case 1:
110                         return TCORE_CALL_STATUS_HELD;
111         case 2:
112                         return TCORE_CALL_STATUS_DIALING;
113                 case 3:
114                         return TCORE_CALL_STATUS_ALERT;
115                 case 4:
116                         return TCORE_CALL_STATUS_INCOMING;
117                 case 5:
118                         return TCORE_CALL_STATUS_WAITING;
119                 case 6:
120                         return TCORE_CALL_STATUS_DIALING; //connecting not exist. set to dialing
121         case 7:
122                         return TCORE_CALL_STATUS_IDLE;
123
124                 default:
125                         return TCORE_CALL_STATUS_IDLE;
126                 break;
127         }
128
129         return TCORE_CALL_STATUS_IDLE;
130 }
131
132 static gboolean _call_is_in_mpty(int mpty)
133 {
134         switch(mpty){
135                 case 0:
136                         return FALSE;
137                 break;
138
139                 case 1:
140                         return TRUE;
141
142                 default:
143                 break;
144         }
145         return FALSE;
146 }
147
148 static enum tcore_call_type _call_type(int type )
149 {
150         switch (type) {
151         case 0:
152                 return TCORE_CALL_TYPE_VOICE;
153         case 1:
154                 return TCORE_CALL_TYPE_VIDEO;
155         default:
156                 break;
157         }
158
159         return TCORE_CALL_TYPE_VOICE;
160 }
161
162 static gboolean _call_request_message(  CoreObject *o,
163                                                                                 UserRequest *ur,
164                                                                                 char *cmd_string,
165                                                                                 unsigned int cmd_len,
166                                                                                 void* on_resp,
167                                                                                 void* user_data)
168 {
169         TcorePending *pending = NULL;
170         TcoreHal *h = NULL;
171
172         unsigned int info_len = 0;
173         info_len = sizeof(struct ATReqMetaInfo);
174
175         dbg("_call_request_message - cmd : %s, cmdlen :%d (including '\r')",cmd_string, cmd_len);
176
177
178         pending = tcore_pending_new(o, ID_RESERVED_AT);
179         tcore_pending_set_request_data(pending, cmd_len, cmd_string);
180         tcore_pending_set_timeout(pending, 0);
181         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
182
183         if ( on_resp )
184                 tcore_pending_set_response_callback(pending, on_resp, user_data);
185
186         tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL);
187
188         if ( !ur ) {
189                 dbg("[ check ] ur is NULL, is this internal request??");
190         } else {
191                 tcore_pending_link_user_request(pending, ur);
192         }
193
194         h = tcore_object_get_hal(o);
195
196         tcore_hal_send_request(h, pending);
197
198         return TRUE;
199 }
200
201 static void _call_status_idle( TcorePlugin *p, CallObject *co )
202 {
203         struct tnoti_call_status_idle data;
204         CoreObject *o;
205
206         o = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL);
207         dbg("call id [%d], call status [%d]", tcore_call_object_get_id(co), tcore_call_object_get_status(co));
208
209         if ( tcore_call_object_get_status( co ) != TCORE_CALL_STATUS_IDLE ) {
210                 data.type = tcore_call_object_get_type( co );
211                 dbg("data.type : [%d]", data.type );
212
213                 data.id = tcore_call_object_get_id( co );
214                 dbg("data.id : [%d]", data.id );
215
216                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_IDLE );
217
218                 tcore_server_send_notification( tcore_plugin_ref_server(p),
219                                                                         o,
220                                                                         TNOTI_CALL_STATUS_IDLE,
221                                                                         sizeof(struct tnoti_call_status_idle),
222                                                                         (void*)&data    );
223
224                 tcore_call_object_free( o, co );
225         } else {
226                 dbg("call object was freed");
227                 tcore_call_object_free(o, co);
228         }
229 }
230
231 static void _call_status_dialing( TcorePlugin *p, CallObject *co )
232 {
233         CoreObject* o = 0;
234
235         struct tnoti_call_status_dialing data;
236
237         o = tcore_plugin_ref_core_object( p, CORE_OBJECT_TYPE_CALL);
238
239         if ( tcore_call_object_get_status( co ) != TCORE_CALL_STATUS_DIALING ) {
240
241                 data.type = tcore_call_object_get_type( co );
242                 dbg("data.type : [%d]", data.type );
243
244                 data.id = tcore_call_object_get_id( co );
245                 dbg("data.id : [%d]", data.id );
246
247                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_DIALING );
248
249                 tcore_server_send_notification( tcore_plugin_ref_server(p),
250                                                                         tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
251                                                                         TNOTI_CALL_STATUS_DIALING,
252                                                                         sizeof(struct tnoti_call_status_dialing),
253                                                                         (void*)&data );
254
255         }
256
257 #if 0
258         _call_list_get( o, co );
259 #endif
260 }
261
262 static void _call_status_alert( TcorePlugin *p, CallObject *co )
263 {
264         CoreObject* o = 0;
265         struct tnoti_call_status_alert data;
266
267         o = tcore_plugin_ref_core_object( p, CORE_OBJECT_TYPE_CALL);
268
269         if ( tcore_call_object_get_status( co ) != TCORE_CALL_STATUS_ALERT ) {
270
271                 data.type = tcore_call_object_get_type( co );
272                 dbg("data.type : [%d]", data.type );
273
274                 data.id = tcore_call_object_get_id( co );
275                 dbg("data.id : [%d]", data.id );
276
277                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_ALERT );
278
279                 tcore_server_send_notification( tcore_plugin_ref_server(p),
280                                                                         tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
281                                                                         TNOTI_CALL_STATUS_ALERT,
282                                                                         sizeof(struct tnoti_call_status_alert),
283                                                                         (void*)&data );
284
285         }
286
287 #if 0
288         _call_list_get( o, co );
289 #endif
290 }
291
292 static void _call_status_active( TcorePlugin *p, CallObject *co )
293 {
294         struct tnoti_call_status_active data;
295
296         if ( tcore_call_object_get_status( co ) != TCORE_CALL_STATUS_ACTIVE ) {
297
298                 data.type = tcore_call_object_get_type( co );
299                 dbg("data.type : [%d]", data.type );
300
301                 data.id = tcore_call_object_get_id( co );
302                 dbg("data.id : [%d]", data.id );
303
304                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_ACTIVE );
305
306                 tcore_server_send_notification( tcore_plugin_ref_server(p),
307                                                                         tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
308                                                                         TNOTI_CALL_STATUS_ACTIVE,
309                                                                         sizeof(struct tnoti_call_status_active),
310                                                                         (void*)&data );
311
312         }
313 }
314
315 static void _call_status_held( TcorePlugin *p, CallObject *co )
316 {
317         struct tnoti_call_status_held data;
318
319         if ( tcore_call_object_get_status( co ) != TCORE_CALL_STATUS_HELD ) {
320
321                 data.type = tcore_call_object_get_type( co );
322                 dbg("data.type : [%d]", data.type );
323
324                 data.id = tcore_call_object_get_id( co );
325                 dbg("data.id : [%d]", data.id );
326
327                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_HELD );
328
329                 tcore_server_send_notification( tcore_plugin_ref_server(p),
330                                                                         tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
331                                                                         TNOTI_CALL_STATUS_HELD,
332                                                                         sizeof(struct tnoti_call_status_held),
333                                                                         (void*)&data );
334
335         }
336 }
337
338 static void _call_status_incoming( TcorePlugin *p, CallObject *co )
339 {
340         struct tnoti_call_status_incoming data;
341         CoreObject* o = 0;
342         o = tcore_plugin_ref_core_object( p, CORE_OBJECT_TYPE_CALL);
343
344         if ( tcore_call_object_get_status( co ) != TCORE_CALL_STATUS_INCOMING ) {
345
346                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_INCOMING );
347
348                 data.type = tcore_call_object_get_type( co );
349                 dbg("data.type : [%d]", data.type );
350
351                 data.id = tcore_call_object_get_id( co );
352                 dbg("data.id : [%d]", data.id );
353
354                 data.cli.mode = tcore_call_object_get_cli_mode( co );
355                 dbg("data.cli.mode : [%d]", data.cli.mode );
356
357                 tcore_call_object_get_number( co, data.cli.number );
358                 dbg("data.cli.number : [%s]", data.cli.number );
359
360                 data.cna.mode = tcore_call_object_get_cna_mode( co );
361                 dbg("data.cna.mode : [%d]", data.cna.mode );
362
363                 tcore_call_object_get_name( co, data.cna.name );
364                 dbg("data.cna.name : [%s]", data.cna.name );
365
366                 data.forward = FALSE; // this is tmp code
367                 data.active_line = tcore_call_object_get_active_line( co );
368                 dbg("data.active_line : [%d]", data.active_line );
369
370                 tcore_server_send_notification( tcore_plugin_ref_server(p),
371                                 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
372                                 TNOTI_CALL_STATUS_INCOMING,
373                                 sizeof(struct tnoti_call_status_incoming),
374                                 (void*)&data    );
375         }
376
377 }
378
379 static void _call_status_waiting( TcorePlugin *p, CallObject *co )
380 {
381         _call_status_incoming( p, co );
382 }
383
384 static void _call_branch_by_status( TcorePlugin *p, CallObject *co, unsigned int status )
385 {
386         switch ( status ) {
387         case TCORE_CALL_STATUS_IDLE:
388                 _call_status_idle( p, co );
389                 break;
390
391         case TCORE_CALL_STATUS_ACTIVE:
392                 _call_status_active( p, co );
393                 break;
394
395         case TCORE_CALL_STATUS_HELD:
396                 _call_status_held( p, co );
397                 break;
398
399         case TCORE_CALL_STATUS_DIALING:
400                 _call_status_dialing( p, co );
401                 break;
402
403         case TCORE_CALL_STATUS_ALERT:
404                 _call_status_alert( p, co );
405                 break;
406
407         case TCORE_CALL_STATUS_INCOMING:
408                 _call_status_incoming( p, co );
409                 break;
410
411         case TCORE_CALL_STATUS_WAITING:
412                 _call_status_waiting( p, co );
413                 break;
414         }
415 }
416
417
418 static TReturn _call_list_get( CoreObject *o, CallObject *co )
419 {
420         gboolean ret = FALSE;
421         UserRequest* ur = NULL;
422
423         char*   cmd_str = NULL;
424         struct ATReqMetaInfo metainfo;
425         int info_len =0;
426
427         if ( !o )
428                 return TCORE_RETURN_FAILURE;
429
430         ur = tcore_user_request_new(NULL, NULL);
431
432         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
433
434         metainfo.type = MULTILINE;
435         memcpy(metainfo.responsePrefix,"+CLCC:",strlen("+CLCC:"));
436         info_len = sizeof(struct ATReqMetaInfo);
437         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
438
439         cmd_str = g_strdup("AT+CLCC\r");
440
441         ret = _call_request_message ( o, ur, cmd_str, strlen(cmd_str), on_response_call_list_get, NULL);
442
443         if ( !ret )
444                 return TCORE_RETURN_FAILURE;
445
446         return TCORE_RETURN_SUCCESS;
447 }
448
449
450
451
452 // CONFIRMATION
453
454 static void on_confirmation_call_message_send( TcorePending *p, gboolean result, void *user_data )
455 {
456         UserRequest* ur = NULL;
457         struct ATReqMetaInfo* metainfo = NULL;
458         unsigned int info_len =0;
459         dbg("on_confirmation_call_message_send - msg out from queue. alloc ATRsp buffer & write rspPrefix if needed\n");
460
461         ReleaseResponse(); //release leftover
462 //alloc new sp_response
463
464         sp_response = at_response_new();
465
466         ur = tcore_pending_ref_user_request(p);
467         metainfo = (struct ATReqMetaInfo*)tcore_user_request_ref_metainfo(ur,&info_len);
468
469         if((metainfo->type == SINGLELINE)||
470                         (metainfo->type == MULTILINE))
471         {
472                 //cp rsp prefix
473                 s_responsePrefix = strdup(metainfo->responsePrefix);
474                 dbg("duplicating responsePrefix : %s\n", s_responsePrefix);
475         }
476         else
477         {
478                 s_responsePrefix = NULL;
479         }
480
481 //set atcmd type into s_type
482         s_type = metainfo->type;
483
484         if (result == FALSE) {
485                 /* Fail */
486                 dbg("SEND FAIL");
487         }
488         else {
489                 dbg("SEND OK");
490         }
491 }
492
493 static void on_confirmation_call_outgoing( TcorePending *p, int data_len, const void *data, void *user_data )
494 {
495         CoreObject *o = 0;
496         UserRequest *ur = 0;
497
498         struct tresp_call_dial resp;
499
500         o  = tcore_pending_ref_core_object(p);
501         ur = tcore_pending_ref_user_request(p);
502
503         if(sp_response->success >0)
504                 resp.err = CALL_ERROR_NONE;
505         else
506                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
507
508         ReleaseResponse();
509
510         if (ur) {
511                 tcore_user_request_send_response(ur, TRESP_CALL_DIAL, sizeof(struct tresp_call_dial), &resp);
512
513         } else {
514                 dbg("[ error ] ur is NULL");
515                 return ;
516         }
517 }
518
519 static void on_confirmation_call_accept( TcorePending *p, int data_len, const void *data, void *user_data )
520 {
521         CoreObject *o = 0;
522         UserRequest *ur = 0;
523
524         struct tresp_call_answer resp;
525
526         o  = tcore_pending_ref_core_object(p);
527         ur = tcore_pending_ref_user_request(p);
528
529         if(sp_response->success >0)
530                 resp.err = CALL_ERROR_NONE;
531         else
532                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
533
534         ReleaseResponse();
535
536         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
537
538         if (ur) {
539                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
540
541         } else {
542                 dbg("[ error ] ur is NULL");
543                 return ;
544         }
545 }
546
547
548 static void on_confirmation_call_reject( TcorePending *p, int data_len, const void *data, void *user_data )
549 {
550         CoreObject *o = 0;
551         UserRequest *ur = 0;
552
553         struct tresp_call_answer resp;
554
555         o  = tcore_pending_ref_core_object(p);
556         ur = tcore_pending_ref_user_request(p);
557
558         if(sp_response->success >0)
559                 resp.err = CALL_ERROR_NONE;
560         else
561                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
562
563         ReleaseResponse();
564
565         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
566
567         if (ur) {
568                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
569
570         } else {
571                 dbg("[ error ] ur is NULL");
572                 return ;
573         }
574 }
575
576 static void on_confirmation_call_replace( TcorePending *p, int data_len, const void *data, void *user_data )
577 {
578         CoreObject *o = 0;
579         UserRequest *ur = 0;
580
581         struct tresp_call_answer resp;
582
583         o  = tcore_pending_ref_core_object(p);
584         ur = tcore_pending_ref_user_request(p);
585
586         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
587
588         if(sp_response->success >0)
589                 resp.err = CALL_ERROR_NONE;
590         else
591                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
592
593         ReleaseResponse();
594
595
596         if (ur) {
597                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
598
599         } else {
600                 dbg("[ error ] ur is NULL");
601                 return ;
602         }
603 }
604
605 static void on_confirmation_call_hold_and_accept( TcorePending *p, int data_len, const void *data, void *user_data )
606 {
607         CoreObject*             o = 0;
608         UserRequest*    ur = 0;
609
610         struct tresp_call_answer resp;
611
612         dbg("ok, function entrance");
613
614         o  = tcore_pending_ref_core_object(p);
615         ur = tcore_pending_ref_user_request(p);
616
617         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
618
619         if(sp_response->success >0)
620                 resp.err = CALL_ERROR_NONE;
621         else
622                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
623
624         ReleaseResponse();
625
626
627         if ( ur ) {
628                 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
629
630         } else {
631                 dbg("[ error ] ur is NULL");
632                 return ;
633         }
634
635         if ( !resp.err ) {
636
637                 GSList *l = 0;
638                 CallObject *co = 0;
639
640                 l = tcore_call_object_find_by_status( o, TCORE_CALL_STATUS_ACTIVE );
641                 if ( !l ) {
642                         dbg("[ error ] can't find active call");
643                         return ;
644                 }
645
646                 co = (CallObject*)l->data;
647                 if ( !co ) {
648                         dbg("[ error ] can't get active call object");
649                         return ;
650                 }
651
652                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_HELD );
653         }
654 }
655
656 static void on_confirmation_call_release_all( TcorePending *p, int data_len, const void *data, void *user_data )
657 {
658         CoreObject *o = 0;
659         UserRequest *ur = 0;
660
661         struct tresp_call_end resp;
662
663         o  = tcore_pending_ref_core_object(p);
664         ur = tcore_pending_ref_user_request(p);
665
666
667         resp.type = CALL_END_TYPE_ALL;
668         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
669
670         if(sp_response->success >0)
671                 resp.err = CALL_ERROR_NONE;
672         else
673                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
674
675         ReleaseResponse();
676
677         if (ur) {
678                 tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
679
680         } else {
681                 dbg("[ error ] ur is NULL");
682                 return ;
683         }
684 }
685
686
687
688 static void on_confirmation_call_release_specific( TcorePending *p, int data_len, const void *data, void *user_data )
689 {
690         CoreObject *o = 0;
691         UserRequest *ur = 0;
692
693         struct tresp_call_end resp;
694
695         o  = tcore_pending_ref_core_object(p);
696         ur = tcore_pending_ref_user_request(p);
697
698         resp.type = CALL_END_TYPE_DEFAULT;
699         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
700
701         if(sp_response->success >0)
702                 resp.err = CALL_ERROR_NONE;
703         else
704                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
705
706         ReleaseResponse();
707
708         if (ur) {
709                 tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
710
711         } else {
712                 dbg("[ error ] ur is NULL");
713                 return ;
714         }
715 }
716
717 static void on_confirmation_call_release_all_active( TcorePending *p, int data_len, const void *data, void *user_data )
718 {
719         CoreObject *o = 0;
720         UserRequest *ur = 0;
721
722         struct tresp_call_end resp;
723
724         o  = tcore_pending_ref_core_object(p);
725         ur = tcore_pending_ref_user_request(p);
726
727         resp.type = CALL_END_TYPE_ACTIVE_ALL;
728         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
729
730         if(sp_response->success >0)
731                 resp.err = CALL_ERROR_NONE;
732         else
733                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
734
735         ReleaseResponse();
736
737         if (ur) {
738                 tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
739
740         } else {
741                 dbg("[ error ] ur is NULL");
742                 return ;
743         }
744 }
745
746 static void on_confirmation_call_release_all_held( TcorePending *p, int data_len, const void *data, void *user_data )
747 {
748         CoreObject *o = 0;
749         UserRequest *ur = 0;
750
751         struct tresp_call_end resp;
752
753         o  = tcore_pending_ref_core_object(p);
754         ur = tcore_pending_ref_user_request(p);
755
756         resp.type = CALL_END_TYPE_HOLD_ALL;
757         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
758
759         if(sp_response->success >0)
760                 resp.err = CALL_ERROR_NONE;
761         else
762                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
763
764         ReleaseResponse();
765
766         if (ur) {
767                 tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
768
769         } else {
770                 dbg("[ error ] ur is NULL");
771                 return ;
772         }
773 }
774
775 static void on_confirmation_call_hold( TcorePending *p, int data_len, const void *data, void *user_data )
776 {
777         CoreObject*             o = 0;
778         UserRequest*    ur = 0;
779
780         struct tresp_call_hold resp;
781
782         dbg("ok, function entrance");
783
784         o  = tcore_pending_ref_core_object(p);
785         ur = tcore_pending_ref_user_request(p);
786
787         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
788
789         if(sp_response->success >0)
790                 resp.err = CALL_ERROR_NONE;
791         else
792                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
793
794         ReleaseResponse();
795
796         if ( ur ) {
797                 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
798
799         } else {
800                 dbg("[ error ] ur is NULL");
801                 return ;
802         }
803
804         if ( !resp.err ) {
805
806                 GSList *active = 0;
807                 CallObject *co = 0;
808
809                 active = tcore_call_object_find_by_status( o, TCORE_CALL_STATUS_ACTIVE );
810                 if ( !active ) {
811                         dbg("[ error ] can't find active call");
812                         return ;
813                 }
814
815                 co = (CallObject*)active->data;
816                 if ( !co ) {
817                         dbg("[ error ] can't get active call object");
818                         return ;
819                 }
820
821                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_HELD );
822         }
823
824 }
825
826 static void on_confirmation_call_active( TcorePending *p, int data_len, const void *data, void *user_data )
827 {
828         CoreObject *o = 0;
829         UserRequest *ur = 0;
830
831         struct tresp_call_active resp;
832
833         o  = tcore_pending_ref_core_object(p);
834         ur = tcore_pending_ref_user_request(p);
835
836         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
837
838         if(sp_response->success >0)
839                 resp.err = CALL_ERROR_NONE;
840         else
841                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
842
843         ReleaseResponse();
844
845         if (ur) {
846                 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
847
848         } else {
849                 dbg("[ error ] ur is NULL");
850                 return ;
851         }
852
853 }
854
855 static void on_confirmation_call_swap( TcorePending *p, int data_len, const void *data, void *user_data )
856 {
857         CoreObject*             o = 0;
858         UserRequest*    ur = 0;
859
860         struct tresp_call_swap resp;
861
862         dbg("ok, function entrance");
863
864         o  = tcore_pending_ref_core_object(p);
865         ur = tcore_pending_ref_user_request(p);
866
867         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
868
869         if(sp_response->success >0)
870                 resp.err = CALL_ERROR_NONE;
871         else
872                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
873
874         ReleaseResponse();
875
876         if ( ur ) {
877                 tcore_user_request_send_response(ur, TRESP_CALL_SWAP, sizeof(struct tresp_call_swap), &resp);
878
879         } else {
880                 dbg("[ error ] ur is NULL");
881                 return ;
882         }
883
884         if ( !resp.err ) {
885
886                 GSList *active = 0, *held = 0;
887                 CallObject *co = 0;
888
889                 held = tcore_call_object_find_by_status( o, TCORE_CALL_STATUS_HELD );
890                 if ( !held ) {
891                         dbg("[ error ] can't find held call");
892                         return ;
893                 }
894
895                 active = tcore_call_object_find_by_status( o, TCORE_CALL_STATUS_ACTIVE );
896                 if ( !active ) {
897                         dbg("[ error ] can't find active call");
898                         return ;
899                 }
900
901                 co = (CallObject*)held->data;
902                 if ( !co ) {
903                         dbg("[ error ] can't get held call object");
904                         return ;
905                 }
906
907                 resp.id  =  tcore_call_object_get_id( co );
908                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_ACTIVE );
909
910                 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
911
912                 co = (CallObject*)active->data;
913                 if ( !co ) {
914                         dbg("[ error ] can't get active call object");
915                         return ;
916                 }
917
918                 resp.id  =  tcore_call_object_get_id( co );
919                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_HELD );
920
921                 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
922         }
923 }
924
925 static void on_confirmation_call_join( TcorePending *p, int data_len, const void *data, void *user_data )
926 {
927         CoreObject *o = 0;
928         UserRequest *ur = 0;
929
930         struct tresp_call_join resp;
931
932         o  = tcore_pending_ref_core_object(p);
933         ur = tcore_pending_ref_user_request(p);
934
935         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
936
937         if(sp_response->success >0)
938                 resp.err = CALL_ERROR_NONE;
939         else
940                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
941
942         ReleaseResponse();
943
944         if (ur) {
945                 tcore_user_request_send_response(ur, TRESP_CALL_JOIN, sizeof(struct tresp_call_join), &resp);
946
947         } else {
948                 dbg("[ error ] ur is NULL");
949                 return ;
950         }
951 }
952
953 static void on_confirmation_call_split( TcorePending *p, int data_len, const void *data, void *user_data )
954 {
955         CoreObject*             o = 0;
956         UserRequest*    ur = 0;
957
958
959         struct tresp_call_split resp;
960
961         dbg("ok, function entrance");
962
963         o  = tcore_pending_ref_core_object(p);
964         ur = tcore_pending_ref_user_request(p);
965
966         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
967
968         if(sp_response->success >0)
969                 resp.err = CALL_ERROR_NONE;
970         else
971                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
972
973         ReleaseResponse();
974
975         if ( ur ) {
976                 tcore_user_request_send_response(ur, TRESP_CALL_SPLIT, sizeof(struct tresp_call_split), &resp);
977
978         } else {
979                 dbg("[ error ] ur is NULL");
980                 return ;
981         }
982
983         if ( !resp.err ) {
984
985                 GSList *active = 0;
986                 CallObject *co = 0;
987
988                 active = tcore_call_object_find_by_status( o, TCORE_CALL_STATUS_ACTIVE );
989                 if ( !active ) {
990                         dbg("[ error ] can't find active call");
991                         return ;
992                 }
993
994                 co = (CallObject*)active->data;
995                 if ( !co ) {
996                         dbg("[ error ] can't get active call object");
997                         return ;
998                 }
999
1000                 tcore_call_object_set_status( co, TCORE_CALL_STATUS_HELD );
1001                 tcore_call_object_set_status( (CallObject*)user_data, TCORE_CALL_STATUS_ACTIVE );
1002         }
1003 }
1004
1005 static void on_confirmation_call_deflect( TcorePending *p, int data_len, const void *data, void *user_data )
1006 {
1007         CoreObject *o = 0;
1008         UserRequest *ur = 0;
1009
1010         struct tresp_call_deflect resp;
1011
1012         o  = tcore_pending_ref_core_object(p);
1013         ur = tcore_pending_ref_user_request(p);
1014
1015         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
1016
1017         if(sp_response->success >0)
1018                 resp.err = CALL_ERROR_NONE;
1019         else
1020                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1021
1022         ReleaseResponse();
1023
1024         if (ur) {
1025                 tcore_user_request_send_response(ur, TRESP_CALL_DEFLECT, sizeof(struct tresp_call_deflect), &resp);
1026
1027         } else {
1028                 dbg("[ error ] ur is NULL");
1029                 return ;
1030         }
1031 }
1032
1033 static void on_confirmation_call_transfer( TcorePending *p, int data_len, const void *data, void *user_data )
1034 {
1035         CoreObject *o = 0;
1036         UserRequest *ur = 0;
1037
1038         struct tresp_call_transfer resp;
1039
1040         o  = tcore_pending_ref_core_object(p);
1041         ur = tcore_pending_ref_user_request(p);
1042
1043         resp.id   =  tcore_call_object_get_id( (CallObject*)user_data );
1044
1045         if(sp_response->success >0)
1046                 resp.err = CALL_ERROR_NONE;
1047         else
1048                 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1049
1050         ReleaseResponse();
1051
1052         if (ur) {
1053                 tcore_user_request_send_response(ur, TRESP_CALL_TRANSFER, sizeof(struct tresp_call_transfer), &resp);
1054
1055         } else {
1056                 dbg("[ error ] ur is NULL");
1057                 return ;
1058         }
1059 }
1060
1061 // RESPONSE
1062 static void on_confirmation_call_endall( TcorePending *p, int data_len, const void *data, void *user_data )
1063 {
1064         CoreObject*             o = 0;
1065         UserRequest*    ur = 0;
1066
1067         dbg("on_confirmation_call_endall - 1st result. wait for final result");
1068
1069
1070         o  = tcore_pending_ref_core_object(p);
1071         ur = tcore_pending_ref_user_request(p);
1072
1073 //skip response handling - actual result will be handled in on_confirmation_call_request
1074         ReleaseResponse();
1075 }
1076
1077 // RESPONSE
1078
1079 static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data)
1080 {
1081         TcorePlugin* plugin = 0;
1082         CoreObject*     o = 0;
1083         CallObject*     co = 0;
1084         struct ATLine *p_cur;
1085
1086         char* cmd= 0;
1087         struct CLCC_call_t*     call_list = 0;
1088
1089         int i = 0, countCalls =0, countValidCalls =0, err =0;
1090
1091
1092         plugin  = tcore_pending_ref_plugin( p );
1093         o               = tcore_pending_ref_core_object( p );
1094
1095         cmd             = (char*)data;
1096
1097
1098         if(sp_response->success > 0)
1099         {
1100
1101                 /* count the calls */
1102                 for (countCalls = 0, p_cur = sp_response->p_intermediates
1103                                 ; p_cur != NULL
1104                                 ; p_cur = p_cur->p_next
1105                         ) {
1106                         countCalls++;
1107                 }
1108                 dbg("total calls : %d",countCalls);
1109
1110                 if(countCalls ==0)
1111                         return;
1112
1113                 call_list       = g_new0( struct CLCC_call_t, countCalls);
1114
1115
1116                 for (countValidCalls = 0, p_cur = sp_response->p_intermediates
1117                                 ; p_cur != NULL
1118                                 ; p_cur = p_cur->p_next)
1119                 {
1120
1121                         err = _callFromCLCCLine( p_cur->line, &call_list[countValidCalls] );
1122
1123                         if ( countCalls > countValidCalls )
1124                                 countValidCalls++;
1125
1126                         if (err != 0) {
1127                                 continue;
1128                         }
1129
1130                         co = tcore_call_object_find_by_id( o, call_list[i].info.id );
1131                         if ( !co ) {
1132                                 co = tcore_call_object_new( o, call_list[i].info.id );
1133                                 if ( !co ) {
1134                                         dbg("error : tcore_call_object_new [ id : %d ]", call_list[i].info.id);
1135                                         continue ;
1136                                 }
1137                         }
1138
1139                         tcore_call_object_set_type( co, _call_type( call_list[i].info.type ) );
1140                         tcore_call_object_set_direction( co, call_list[i].info.direction );
1141                         tcore_call_object_set_multiparty_state( co, _call_is_in_mpty(call_list[i].info.mpty) );
1142                         tcore_call_object_set_cli_info( co, CALL_CLI_MODE_DEFAULT, call_list[i].number );
1143
1144                         _call_branch_by_status( plugin, co, call_list[i].info.status );
1145
1146                         i++;
1147
1148                         if ( i == countCalls )
1149                                 break;
1150                 }
1151         }
1152
1153         ReleaseResponse();
1154 }
1155
1156 static int _callFromCLCCLine(char *line, struct CLCC_call_t*p_call)
1157 {
1158         //+CLCC: 1,0,2,0,0,\"+18005551212\",145
1159         //     index,isMT,state,mode,isMpty(,number,TOA)?
1160
1161     int err;
1162     int state;
1163         int mode;
1164         int isMT;
1165         char* num;
1166
1167         err = at_tok_start(&line);
1168         if (err < 0) goto error;
1169
1170         //id
1171         err = at_tok_nextint(&line, &(p_call->info.id));
1172         if (err < 0) goto error;
1173         dbg("id : [%d]\n", p_call->info.id );
1174         //MO/MTcall
1175         err = at_tok_nextint(&line, &isMT);
1176         if (err < 0) goto error;
1177
1178         if(isMT ==0)
1179                 p_call->info.direction = TCORE_CALL_DIRECTION_OUTGOING;
1180         else
1181                 p_call->info.direction = TCORE_CALL_DIRECTION_INCOMING;
1182
1183         dbg("direction : [ %d ]\n", p_call->info.direction);
1184
1185         //state
1186         err = at_tok_nextint(&line, &state);
1187         if (err < 0) goto error;
1188
1189         switch(state){
1190                 case 0: //active
1191                         p_call->info.status = TCORE_CALL_STATUS_ACTIVE;
1192                         break;
1193                 case 1:
1194                         p_call->info.status = TCORE_CALL_STATUS_HELD;
1195                         break;
1196                 case 2:
1197                         p_call->info.status = TCORE_CALL_STATUS_DIALING;
1198                         break;
1199                 case 3:
1200                         p_call->info.status = TCORE_CALL_STATUS_ALERT;
1201                         break;
1202                 case 4:
1203                         p_call->info.status = TCORE_CALL_STATUS_INCOMING;
1204                         break;
1205                 case 5:
1206                         p_call->info.status = TCORE_CALL_STATUS_WAITING;
1207                         break;
1208         }
1209         dbg("status     : [%d]\n", p_call->info.status );
1210
1211         //mode
1212         err = at_tok_nextint(&line, &mode);
1213         if (err < 0) goto error;
1214
1215         switch(mode)
1216         {
1217                 case 0:
1218                         p_call->info.type       = TCORE_CALL_TYPE_VOICE;
1219                         break;
1220
1221                 case 1:
1222                         p_call->info.type       = TCORE_CALL_TYPE_VIDEO;
1223                         break;
1224
1225                 default:        // only Voice/VT call is supported in CS. treat other unknown calls as error
1226                         dbg("invalid type : [%d]\n", mode );
1227                         goto error;
1228                         break;
1229         }
1230         dbg("type : [%d]\n", p_call->info.type );
1231
1232
1233         err = at_tok_nextint(&line, &(p_call->info.mpty));
1234     if (err < 0) goto error;
1235         dbg("mpty       : [%d]\n", p_call->info.mpty );
1236
1237         if (at_tok_hasmore(&line)) {
1238                 err = at_tok_nextstr(&line, &num);
1239
1240                 /* tolerate null here */
1241                 if (err < 0) return 0;
1242
1243                 memcpy(p_call->number, num, strlen(num));
1244                 dbg("number     : [ %s ]\n", p_call->number );
1245
1246                 p_call->info.num_len = strlen(num);
1247                 dbg("num_len : [0x%x]\n", p_call->info.num_len );
1248
1249                 err = at_tok_nextint(&line, &(p_call->info.num_type));
1250                 if (err < 0) goto error;
1251                 dbg("num_type : [0x%x]\n", p_call->info.num_type );
1252
1253         }
1254
1255     return 0;
1256
1257 error:
1258     err("invalid CLCC line\n");
1259     return -1;
1260 }
1261
1262 // NOTIFICATION
1263
1264 static gboolean on_notification_call_waiting( CoreObject *o, const void *data, void *user_data )
1265 {
1266         TcorePlugin* plugin = NULL;
1267         char* cmd = NULL, *num = NULL;
1268         CallObject *co, *dupco = 0;
1269         int id, status, err, type, mpty,direction;
1270         GSList* pList = NULL;
1271 #define LINE_DEFAULT 0
1272
1273         dbg("call waiting noti : %s", cmd);
1274         plugin = tcore_object_ref_plugin(o);
1275
1276         cmd = (char*)data;
1277
1278         at_tok_start(&cmd);
1279
1280         err = at_tok_nextint(&cmd,&id);
1281         err = at_tok_nextint(&cmd,&direction);
1282         err = at_tok_nextint(&cmd,&status);
1283         err = at_tok_nextint(&cmd,&type);
1284         err = at_tok_nextint(&cmd,&mpty);
1285
1286         if(at_tok_hasmore(&cmd)){
1287                 err = at_tok_nextstr(&cmd,&num);
1288                 dbg("id: %d, direction : %d, status : %d, type :%d, mpty : %d, num : %s", id,direction,status, type, mpty, num);
1289         }
1290         else    {
1291                 dbg("id: %d, direction : %d, status : %d, type :%d, mpty : %d, num : NULL", id,direction,status, type, mpty);
1292         }
1293 // check call with incoming status already exist
1294         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_WAITING);
1295         if(pList != NULL){
1296                 dbg("waiting call already exist. skip");
1297                 return TRUE;
1298         }
1299
1300         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
1301         if(pList != NULL){
1302                 dbg("incoming call already exist. skip");
1303                 return TRUE;
1304         }
1305
1306         dupco = tcore_call_object_find_by_id(o, id);
1307         if(dupco!= NULL){
1308                 dbg("co with same id already exist. skip");
1309                 return TRUE;
1310         }
1311
1312 // make new co, add to list
1313         co = tcore_call_object_new( o, id);
1314         if ( !co ) {
1315                 dbg("[ error ] co is NULL");
1316                 return TRUE;
1317         }
1318
1319         tcore_call_object_set_type(co, _call_type(type));
1320         tcore_call_object_set_multiparty_state(co,_call_is_in_mpty(mpty));
1321         tcore_call_object_set_direction(co, TCORE_CALL_DIRECTION_INCOMING);
1322         tcore_call_object_set_cli_info(co, TCORE_CALL_CLI_MODE_DEFAULT,  num);
1323         tcore_call_object_set_active_line(co, LINE_DEFAULT);
1324
1325         _call_status_incoming(plugin, co);
1326
1327         return TRUE;
1328 }
1329
1330 static gboolean on_notification_call_incoming( CoreObject *o, const void *data, void *user_data )
1331 {
1332         TcorePlugin* plugin = NULL;
1333         char* cmd = NULL, *num = NULL;
1334         CallObject *co, *dupco = 0;
1335         int id, status, err, type, mpty,direction;
1336         GSList* pList = NULL;
1337 #define LINE_DEFAULT 0
1338
1339         dbg("call incoming noti : %s", cmd);
1340         plugin = tcore_object_ref_plugin(o);
1341
1342         cmd = (char*)data;
1343
1344         at_tok_start(&cmd);
1345
1346         err = at_tok_nextint(&cmd,&id);
1347         err = at_tok_nextint(&cmd,&direction);
1348         err = at_tok_nextint(&cmd,&status);
1349         err = at_tok_nextint(&cmd,&type);
1350         err = at_tok_nextint(&cmd,&mpty);
1351
1352         if(at_tok_hasmore(&cmd))        {
1353                 err = at_tok_nextstr(&cmd,&num);
1354                 dbg("id: %d, direction : %d, status : %d, type :%d, mpty : %d, num : %s", id,direction,status, type, mpty, num);
1355         }
1356         else    {
1357                 dbg("id: %d, direction : %d, status : %d, type :%d, mpty : %d, num : NULL", id,direction,status, type, mpty);
1358         }
1359 // check call with incoming status already exist
1360         pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
1361         if(pList != NULL){
1362                 dbg("incoming call already exist. skip");
1363                 return TRUE;
1364         }
1365
1366         dupco = tcore_call_object_find_by_id(o, id);
1367         if(dupco!= NULL){
1368                 dbg("co with same id already exist. skip");
1369                 return TRUE;
1370         }
1371
1372 // make new co, add to list
1373         co = tcore_call_object_new( o, id);
1374         if ( !co ) {
1375                 dbg("[ error ] co is NULL");
1376                 return TRUE;
1377         }
1378
1379         tcore_call_object_set_type(co, _call_type(type));
1380         tcore_call_object_set_multiparty_state(co,_call_is_in_mpty(mpty));
1381         tcore_call_object_set_direction(co, TCORE_CALL_DIRECTION_INCOMING);
1382         tcore_call_object_set_cli_info(co, TCORE_CALL_CLI_MODE_DEFAULT,  num);
1383         tcore_call_object_set_active_line(co, LINE_DEFAULT);
1384
1385         _call_status_incoming(plugin, co);
1386
1387         return TRUE;
1388 }
1389
1390 static gboolean on_notification_call_status( CoreObject *o, const void *data, void *user_data)
1391 {
1392         char* cmd = NULL, *num = NULL;
1393         TcorePlugin*    p  = 0;
1394         CallObject*                     co = 0;
1395         int id, status, type, mpty,direction;
1396         int err;
1397
1398         enum tcore_call_status co_status;
1399
1400         p       = tcore_object_ref_plugin( o );
1401         cmd = (char*)data;
1402
1403         at_tok_start(&cmd);
1404
1405         err = at_tok_nextint(&cmd,&id);
1406         err = at_tok_nextint(&cmd,&direction);
1407         err = at_tok_nextint(&cmd,&status);
1408         err = at_tok_nextint(&cmd,&type);
1409         err = at_tok_nextint(&cmd,&mpty);
1410
1411         if (at_tok_hasmore(&cmd)) {
1412                 err = at_tok_nextstr(&cmd,&num);
1413                 dbg("id: %d, direction : %d, status : %d, type :%d, mpty : %d, num : %s", id,direction,status, type, mpty, num);
1414         }
1415         else {
1416                 dbg("id: %d, direction : %d, status : %d, type :%d, mpty : %d, num : NULL", id,direction,status, type, mpty);
1417         }
1418
1419         co_status = _call_status(status);
1420
1421         switch (co_status) {
1422                 case CALL_STATUS_ACTIVE:{
1423
1424                 dbg("call(%d) status : [ ACTIVE ]", id);
1425                 co      = tcore_call_object_find_by_id(o,id);
1426                 if ( !co ) {
1427                         dbg("co is NULL");
1428                         return TRUE;
1429                 }
1430                 _call_status_active( p, co );
1431
1432                 } break;
1433                 case CALL_STATUS_HELD:
1434                 break;
1435                 case CALL_STATUS_DIALING:
1436                 {
1437                 dbg("call(%d) status : [ dialing ]", id);
1438                 co      = tcore_call_object_find_by_id(o,id);
1439                 if ( !co ) {
1440                         co = tcore_call_object_new( o, id );
1441                         if ( !co ) {
1442                                 dbg("error : tcore_call_object_new [ id : %d ]", id);
1443                                 return TRUE;
1444                         }
1445                 }
1446
1447                 tcore_call_object_set_type( co, _call_type(type) );
1448                 tcore_call_object_set_direction( co, TCORE_CALL_DIRECTION_OUTGOING );
1449
1450                 _call_status_dialing( p, co );
1451                 }
1452                 break;
1453                 case CALL_STATUS_ALERT:
1454                 {
1455
1456                 dbg("call(%d) status : [ alert ]", id);
1457                 co      = tcore_call_object_find_by_id(o, id);
1458                 if ( !co ) {
1459                         dbg("co is NULL");
1460                         return TRUE;
1461                 }
1462
1463                 _call_list_get( o, co );
1464
1465                 } break;
1466                 case CALL_STATUS_INCOMING:
1467                 case CALL_STATUS_WAITING:
1468                 break;
1469                 case CALL_STATUS_IDLE: {
1470
1471                                 dbg("call(%d) status : [ release ]", id);
1472
1473                                 co      = tcore_call_object_find_by_id( o, id );
1474                                 if ( !co )
1475                                         dbg("co is NULL");
1476
1477                                 p       = tcore_object_ref_plugin( o );
1478                                 if ( !p )
1479                                         dbg("plugin is NULL");
1480
1481                                 _call_status_idle( p, co );
1482
1483                         } break;
1484
1485                 default:
1486                         break;
1487         }
1488
1489         return TRUE;
1490 }
1491
1492 static TReturn s_call_outgoing( CoreObject *o, UserRequest *ur )
1493 {
1494         TcorePlugin*                    p = NULL;
1495         CallObject*                                     co = 0;
1496         struct treq_call_dial*          data = 0;
1497         char*                                           raw_str= NULL;
1498         char*                                           cmd_str = NULL;
1499     const char *cclir;
1500         struct ATReqMetaInfo metainfo;
1501         int info_len =0;
1502         enum tcore_call_cli_mode clir = CALL_CLI_MODE_DEFAULT;
1503
1504         gboolean                                        ret = FALSE;
1505
1506         data    = (struct treq_call_dial*)tcore_user_request_ref_data( ur, 0 );
1507         p               = tcore_object_ref_plugin( o );
1508
1509         clir = _get_clir_status( data->number );
1510
1511 //Compose ATCmd string
1512         switch (clir)
1513         {
1514                 case TCORE_CALL_CLI_MODE_PRESENT:
1515                         cclir = "I";
1516                 break;  /*invocation*/
1517                 case TCORE_CALL_CLI_MODE_RESTRICT:
1518                         cclir = "i";
1519                 break;  /*suppression*/
1520                 case TCORE_CALL_CLI_MODE_DEFAULT:
1521                 default:
1522                         cclir = "";
1523                 break;   /*subscription default*/
1524         }
1525
1526         raw_str = g_strdup_printf("ATD%s%s;", data->number, cclir);
1527         cmd_str = g_strdup_printf("%s%s",raw_str,"\r");
1528
1529         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
1530
1531 //set metainfo
1532         metainfo.type = NO_RESULT;
1533         metainfo.responsePrefix[0] ='\0';
1534         info_len = sizeof(struct ATReqMetaInfo);
1535
1536         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
1537
1538         ret = _call_request_message ( o, ur, cmd_str, strlen(cmd_str), on_confirmation_call_outgoing, co);
1539
1540         free(raw_str);
1541         free(cmd_str);
1542
1543         if ( !ret ) {
1544                 tcore_call_object_free( o, co );
1545                 return TCORE_RETURN_FAILURE;
1546         }
1547
1548         return TCORE_RETURN_SUCCESS;
1549 }
1550
1551 static TReturn s_call_answer( CoreObject *o, UserRequest *ur )
1552 {
1553         CallObject*                                     co = 0;
1554         struct treq_call_answer*        data = 0;
1555         gboolean                                        ret = FALSE;
1556         char*                                           cmd_str = NULL;
1557         struct ATReqMetaInfo metainfo ;
1558         unsigned int info_len =0;
1559
1560         data = (struct treq_call_answer*)tcore_user_request_ref_data( ur, 0 );
1561
1562         co = tcore_call_object_find_by_id( o, data->id );
1563
1564         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
1565
1566 //set metainfo
1567         metainfo.type = NO_RESULT;
1568         metainfo.responsePrefix[0] = '\0';
1569         info_len = sizeof(struct ATReqMetaInfo);
1570
1571         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
1572
1573         if ( data->type == CALL_ANSWER_TYPE_ACCEPT ) {
1574
1575                 cmd_str = g_strdup_printf("%s%s","ATA","\r");
1576                 ret = _call_request_message ( o, ur, (void*)cmd_str, strlen(cmd_str), on_confirmation_call_accept, co);
1577                 free(cmd_str);
1578                 if ( !ret )
1579                         return TCORE_RETURN_FAILURE;
1580
1581         } else {
1582
1583                 switch ( data->type ) {
1584                         case CALL_ANSWER_TYPE_REJECT: {
1585                                 dbg("call answer reject");
1586                                 tcore_call_control_answer_reject( o, ur, on_confirmation_call_reject, co );
1587                         } break;
1588
1589                         case CALL_ANSWER_TYPE_REPLACE: {
1590                                 dbg("call answer replace");
1591                                 tcore_call_control_answer_replace( o, ur, on_confirmation_call_replace, co );
1592                         } break;
1593
1594                         case CALL_ANSWER_TYPE_HOLD_ACCEPT: {
1595                                 dbg("call answer hold and accept");
1596                                 tcore_call_control_answer_hold_and_accept( o, ur, on_confirmation_call_hold_and_accept, co );
1597                         } break;
1598
1599                         default :
1600                                 dbg("[ error ] wrong answer type [ %d ]", data->type);
1601                                 return TCORE_RETURN_FAILURE;
1602                 }
1603         }
1604
1605         return TCORE_RETURN_SUCCESS;
1606 }
1607
1608 static TReturn s_call_release( CoreObject *o, UserRequest *ur )
1609 {
1610         CallObject*                                     co = 0;
1611
1612         struct treq_call_end*           data = 0;
1613         gboolean                                        ret = FALSE;
1614         UserRequest* ur_dup = 0;
1615
1616         char*                                   chld0_cmd = NULL;
1617         char*                                   chld1_cmd = NULL;
1618         struct ATReqMetaInfo metainfo1 ;
1619         struct ATReqMetaInfo  metainfo2 ;
1620         unsigned int info_len1, info_len2 =0;
1621
1622         data = (struct treq_call_end*)tcore_user_request_ref_data( ur, 0 );
1623
1624         co = tcore_call_object_find_by_id( o, data->id );
1625
1626         if ( data->type == CALL_END_TYPE_ALL ) {
1627
1628         //releaseAll do not exist on legacy request. send CHLD=0, CHLD=1 in sequence
1629         chld0_cmd = g_strdup("AT+CHLD=0\r");
1630         chld1_cmd = g_strdup("AT+CHLD=1\r");
1631
1632         memset(&metainfo1, 0, sizeof(struct ATReqMetaInfo));
1633         memset(&metainfo2, 0, sizeof(struct ATReqMetaInfo));
1634
1635
1636 //set metainfo
1637                 metainfo1.type = NO_RESULT;
1638                 metainfo1.responsePrefix[0] = '\0';
1639                 info_len1 = sizeof(struct ATReqMetaInfo);
1640
1641 //set metainfo
1642                 metainfo2.type = NO_RESULT;
1643                 metainfo2.responsePrefix[0] = '\0';
1644                 info_len2 = sizeof(struct ATReqMetaInfo);
1645
1646                 ur_dup = tcore_user_request_new(NULL, NULL);
1647
1648                 tcore_user_request_set_metainfo(ur_dup, info_len1, &metainfo1);
1649                 tcore_user_request_set_metainfo(ur, info_len2, &metainfo2);
1650
1651                 ret = _call_request_message(o, ur_dup, chld0_cmd, strlen(chld0_cmd), on_confirmation_call_endall, NULL);
1652                 free(chld0_cmd);
1653                 if ( !ret )
1654                         return TCORE_RETURN_FAILURE;
1655
1656                 ret = _call_request_message(o, ur, chld1_cmd, strlen(chld1_cmd), on_confirmation_call_release_all, co);
1657                 free(chld1_cmd);
1658                 if ( !ret )
1659                         return TCORE_RETURN_FAILURE;
1660
1661         } else {
1662
1663                 switch ( data->type ) {
1664                         case CALL_END_TYPE_DEFAULT: {
1665                                 int id = 0;
1666                                 id = tcore_call_object_get_id( co );
1667
1668                                 dbg("call end call id [%d]", id);
1669                                 tcore_call_control_end_specific( o, ur, id, on_confirmation_call_release_specific, co );
1670                         } break;
1671
1672                         case CALL_END_TYPE_ACTIVE_ALL: {
1673
1674                                 dbg("call end all active");
1675                                 tcore_call_control_end_all_active( o, ur, on_confirmation_call_release_all_active, co );
1676                         } break;
1677
1678                         case TCORE_CALL_END_ALL_HELD: {
1679
1680                                 dbg("call end all held");
1681                                 tcore_call_control_end_all_held( o, ur, on_confirmation_call_release_all_held, co );
1682                         } break;
1683
1684                         default :
1685                                 dbg("[ error ] wrong end type [ %d ]", data->type);
1686                                 return TCORE_RETURN_FAILURE;
1687                 }
1688
1689         }
1690
1691         return TCORE_RETURN_SUCCESS;
1692 }
1693
1694 static TReturn s_call_hold( CoreObject *o, UserRequest *ur )
1695 {
1696         struct treq_call_hold *hold = 0;
1697         CallObject *co = 0;
1698         GSList *list_active, *list_incoming, *list_held;
1699
1700         hold = (struct treq_call_hold*)tcore_user_request_ref_data( ur, 0 );
1701
1702         /*
1703          * When Incoming Call and Outgoing Call operates concurrently with one
1704          * already exist Call. Telephony intend to having one Active Call and
1705          * one Incoming Call. But, at that time, Application does not received
1706          * Incoming Call Notification. Therefore, Application call
1707          * tel_hold_call() to hold already exist Active Call. At this point,
1708          * Telephony should reject the request of tel_hold_call() because
1709          * tel_hold_call() sends AT+CHLD=2 which means "place active call on
1710          * hold and accepts the incoming call".
1711          */
1712         list_active = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_ACTIVE);
1713         list_incoming = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
1714         list_held = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_HELD);
1715         if (!(list_active != NULL && list_incoming == NULL && list_held == NULL)) {
1716                 struct tresp_call_hold resp;
1717
1718                 dbg("Hold Call operation is not allowed");
1719
1720                 resp.err = CALL_ERROR_SERVICE_NOT_ALLOWED;
1721                 resp.id = hold->id;
1722                 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(resp), &resp);
1723
1724                 return TCORE_RETURN_FAILURE;
1725         }
1726
1727         dbg("call id : [ %d ]", hold->id);
1728
1729         co = tcore_call_object_find_by_id( o, hold->id );
1730
1731         tcore_call_control_hold( o, ur, on_confirmation_call_hold, co );
1732
1733         return TCORE_RETURN_SUCCESS;
1734 }
1735
1736 static TReturn s_call_active( CoreObject *o, UserRequest *ur )
1737 {
1738         struct treq_call_active *active = 0;
1739         CallObject *co = 0;
1740
1741         active = (struct treq_call_active*)tcore_user_request_ref_data( ur, 0 );
1742
1743         dbg("call id : [ %d ]", active->id);
1744
1745         co = tcore_call_object_find_by_id( o, active->id );
1746
1747         tcore_call_control_active( o, ur, on_confirmation_call_active, co );
1748
1749         return TCORE_RETURN_SUCCESS;
1750 }
1751
1752 static TReturn s_call_swap( CoreObject *o, UserRequest *ur )
1753 {
1754         struct treq_call_swap *swap = 0;
1755         CallObject *co = 0;
1756         swap = (struct treq_call_swap*)tcore_user_request_ref_data( ur, 0 );
1757
1758         dbg("call id : [ %d ]", swap->id);
1759
1760         co = tcore_call_object_find_by_id( o, swap->id );
1761
1762         tcore_call_control_swap( o, ur, on_confirmation_call_swap, co );
1763
1764         return TCORE_RETURN_SUCCESS;
1765 }
1766
1767 static TReturn s_call_join( CoreObject *o, UserRequest *ur )
1768 {
1769         struct treq_call_join *join = 0;
1770         CallObject *co = 0;
1771
1772         join = (struct treq_call_join*)tcore_user_request_ref_data( ur, 0 );
1773
1774         dbg("call id : [ %d ]", join->id);
1775
1776         co = tcore_call_object_find_by_id( o, join->id );
1777
1778         tcore_call_control_join( o, ur, on_confirmation_call_join, co );
1779
1780         return TCORE_RETURN_SUCCESS;
1781 }
1782
1783 static TReturn s_call_split( CoreObject *o, UserRequest *ur )
1784 {
1785         struct treq_call_split *split = 0;
1786         CallObject *co = 0;
1787
1788         split = (struct treq_call_split*)tcore_user_request_ref_data( ur, 0 );
1789
1790         co = tcore_call_object_find_by_id ( o, split->id );
1791
1792         tcore_call_control_split( o, ur, split->id, on_confirmation_call_split, co );
1793
1794         return TCORE_RETURN_SUCCESS;
1795 }
1796
1797 static TReturn s_call_deflect( CoreObject *o, UserRequest *ur )
1798 {
1799         struct treq_call_deflect *deflect = 0;
1800         CallObject *co = 0;
1801
1802         deflect = (struct treq_call_deflect*)tcore_user_request_ref_data( ur, 0 );
1803
1804         co = tcore_call_object_find_by_number( o, deflect->number );
1805
1806         tcore_call_control_deflect( o, ur, deflect->number, on_confirmation_call_deflect, co );
1807
1808         return TCORE_RETURN_SUCCESS;
1809 }
1810
1811 static TReturn s_call_transfer( CoreObject *o, UserRequest *ur )
1812 {
1813         struct treq_call_transfer *transfer = 0;
1814         CallObject *co = 0;
1815
1816         transfer = (struct treq_call_transfer*)tcore_user_request_ref_data( ur, 0 );
1817
1818         dbg("call id : [ %d ]", transfer->id);
1819
1820         co = tcore_call_object_find_by_id( o, transfer->id );
1821
1822         tcore_call_control_transfer( o, ur, on_confirmation_call_transfer, co );
1823
1824         return TCORE_RETURN_SUCCESS;
1825 }
1826
1827 static TReturn s_call_send_dtmf( CoreObject *o, UserRequest *ur )
1828 {
1829         return TCORE_RETURN_SUCCESS;
1830 }
1831
1832 static TReturn s_call_set_sound_path( CoreObject *o, UserRequest *ur )
1833 {
1834
1835         return TCORE_RETURN_SUCCESS;
1836 }
1837
1838 static TReturn s_call_set_sound_volume_level( CoreObject *o, UserRequest *ur )
1839 {
1840
1841         return TCORE_RETURN_SUCCESS;
1842 }
1843
1844 static TReturn s_call_get_sound_volume_level( CoreObject *o, UserRequest *ur )
1845 {
1846
1847         return TCORE_RETURN_SUCCESS;
1848 }
1849
1850 static TReturn s_call_mute( CoreObject *o, UserRequest *ur )
1851 {
1852
1853         return TCORE_RETURN_SUCCESS;
1854 }
1855
1856 static TReturn s_call_unmute( CoreObject *o, UserRequest *ur )
1857 {
1858
1859         return TCORE_RETURN_SUCCESS;
1860 }
1861
1862 static TReturn s_call_get_mute_status( CoreObject *o, UserRequest *ur )
1863 {
1864
1865         return TCORE_RETURN_SUCCESS;
1866 }
1867
1868 static struct tcore_call_operations call_ops = {
1869         .dial                                   = s_call_outgoing,
1870         .answer                                 = s_call_answer,
1871         .end                                    = s_call_release,
1872         .hold                                   = s_call_hold,
1873         .active                                 = s_call_active,
1874         .swap                                   = s_call_swap,
1875         .join                                   = s_call_join,
1876         .split                                  = s_call_split,
1877         .deflect                                = s_call_deflect,
1878         .transfer                               = s_call_transfer,
1879         .send_dtmf                              = s_call_send_dtmf,
1880         .set_sound_path                 = s_call_set_sound_path,
1881         .set_sound_volume_level = s_call_set_sound_volume_level,
1882         .get_sound_volume_level = s_call_get_sound_volume_level,
1883         .mute                                   = s_call_mute,
1884         .unmute                                 = s_call_unmute,
1885         .get_mute_status                = s_call_get_mute_status,
1886 };
1887
1888 gboolean s_call_init(TcorePlugin *cp, CoreObject *co)
1889 {
1890         tcore_call_override_ops(co, &call_ops, NULL);
1891
1892         tcore_object_override_callback( co, EVENT_CALL_STATUS, on_notification_call_status, NULL );
1893         tcore_object_override_callback( co, EVENT_CALL_INCOMING, on_notification_call_incoming, NULL );
1894         tcore_object_override_callback( co, EVENT_CALL_WAITING, on_notification_call_waiting, NULL );
1895
1896         return TRUE;
1897 }
1898
1899 void s_call_exit(TcorePlugin *cp, CoreObject *co)
1900 {
1901         dbg("Exit");
1902 }