4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: sharanayya mathapati <sharan.m@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
29 #include <core_object.h>
34 #include <user_request.h>
39 #include "imc_common.h"
43 #define STATUS_INCOMING 4
44 #define STATUS_WAITING 5
45 #define STATUS_CONNECTED 7
47 #define MAX_CALL_DTMF_DIGITS_LEN 32
49 static gboolean setsoundpath = FALSE;
50 static gboolean soundvolume = FALSE;
52 // End Cause field - Call state end cause
57 // These definitions are taken from GSM 04.08 Table 10.86
59 CC_CAUSE_UNASSIGNED_NUMBER,
60 CC_CAUSE_NO_ROUTE_TO_DEST,
61 CC_CAUSE_CHANNEL_UNACCEPTABLE,
62 CC_CAUSE_OPERATOR_DETERMINED_BARRING,
63 CC_CAUSE_NORMAL_CALL_CLEARING,
65 CC_CAUSE_NO_USER_RESPONDING,
66 CC_CAUSE_USER_ALERTING_NO_ANSWER,
67 CC_CAUSE_CALL_REJECTED,
68 CC_CAUSE_NUMBER_CHANGED,
69 CC_CAUSE_NON_SELECTED_USER_CLEARING,
70 CC_CAUSE_DESTINATION_OUT_OF_ORDER,
71 CC_CAUSE_INVALID_NUMBER_FORMAT,
72 CC_CAUSE_FACILITY_REJECTED,
73 CC_CAUSE_RESPONSE_TO_STATUS_ENQUIRY,
74 CC_CAUSE_NORMAL_UNSPECIFIED,
75 CC_CAUSE_NO_CIRCUIT_CHANNEL_AVAILABLE,
76 CC_CAUSE_NETWORK_OUT_OF_ORDER,
77 CC_CAUSE_TEMPORARY_FAILURE,
78 CC_CAUSE_SWITCHING_EQUIPMENT_CONGESTION,
79 CC_CAUSE_ACCESS_INFORMATION_DISCARDED,
80 CC_CAUSE_REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE,
81 CC_CAUSE_RESOURCES_UNAVAILABLE_UNSPECIFIED,
82 CC_CAUSE_QUALITY_OF_SERVICE_UNAVAILABLE,
83 CC_CAUSE_REQUESTED_FACILITY_NOT_SUBSCRIBED,
84 CC_CAUSE_INCOMING_CALL_BARRED_WITHIN_CUG,
85 CC_CAUSE_BEARER_CAPABILITY_NOT_AUTHORISED,
86 CC_CAUSE_BEARER_CAPABILITY_NOT_PRESENTLY_AVAILABLE,
87 CC_CAUSE_SERVICE_OR_OPTION_NOT_AVAILABLE,
88 CC_CAUSE_BEARER_SERVICE_NOT_IMPLEMENTED,
89 CC_CAUSE_ACM_GEQ_ACMMAX,
90 CC_CAUSE_REQUESTED_FACILITY_NOT_IMPLEMENTED,
91 CC_CAUSE_ONLY_RESTRICTED_DIGITAL_INFO_BC_AVAILABLE,
92 CC_CAUSE_SERVICE_OR_OPTION_NOT_IMPLEMENTED,
93 CC_CAUSE_INVALID_TRANSACTION_ID_VALUE,
94 CC_CAUSE_USER_NOT_MEMBER_OF_CUG,
95 CC_CAUSE_INCOMPATIBLE_DESTINATION,
96 CC_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION,
97 CC_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE,
98 CC_CAUSE_INVALID_MANDATORY_INFORMATION,
99 CC_CAUSE_MESSAGE_TYPE_NON_EXISTENT,
100 CC_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROT_STATE,
101 CC_CAUSE_IE_NON_EXISTENT_OR_NOT_IMPLEMENTED,
102 CC_CAUSE_CONDITIONAL_IE_ERROR,
103 CC_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE,
104 CC_CAUSE_RECOVERY_ON_TIMER_EXPIRY,
105 CC_CAUSE_PROTOCOL_ERROR_UNSPECIFIED,
106 CC_CAUSE_INTERWORKING_UNSPECIFIED,
110 REJECT_CAUSE_IMSI_UNKNOWN_IN_HLR,
111 REJECT_CAUSE_ILLEGAL_MS,
112 REJECT_CAUSE_IMSI_UNKNOWN_IN_VLR,
113 REJECT_CAUSE_IMEI_NOT_ACCEPTED,
114 REJECT_CAUSE_ILLEGAL_ME,
115 REJECT_CAUSE_GPRS_SERVICES_NOT_ALLOWED,
116 REJECT_CAUSE_GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED,
117 REJECT_CAUSE_MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK,
118 REJECT_CAUSE_IMPLICITLY_DETACHED,
119 REJECT_CAUSE_PLMN_NOT_ALLOWED,
120 REJECT_CAUSE_LA_NOT_ALLOWED,
121 REJECT_CAUSE_NATIONAL_ROAMING_NOT_ALLOWED,
122 REJECT_CAUSE_GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN,
123 REJECT_CAUSE_NO_SUITABLE_CELLS_IN_LA,
124 REJECT_CAUSE_MSC_TEMPORARILY_NOT_REACHABLE,
125 REJECT_CAUSE_NETWORK_FAILURE,
126 REJECT_CAUSE_MAC_FAILURE,
127 REJECT_CAUSE_SYNCH_FAILURE,
128 REJECT_CAUSE_CONGESTTION,
129 REJECT_CAUSE_GSM_AUTH_UNACCEPTED,
130 REJECT_CAUSE_SERVICE_OPTION_NOT_SUPPORTED,
131 REJECT_CAUSE_REQ_SERV_OPT_NOT_SUBSCRIBED,
132 REJECT_CAUSE_SERVICE_OPT__OUT_OF_ORDER,
133 REJECT_CAUSE_CALL_CANNOT_BE_IDENTIFIED,
134 REJECT_CAUSE_NO_PDP_CONTEXT_ACTIVATED,
135 REJECT_CAUSE_RETRY_UPON_ENTRY_INTO_A_NEW_CELL_MIN_VALUE,
136 REJECT_CAUSE_RETRY_UPON_ENTRY_INTO_A_NEW_CELL_MAX_VALUE,
137 REJECT_CAUSE_SEMANTICALLY_INCORRECT_MSG,
138 REJECT_CAUSE_INVALID_MANDATORY_INFO,
139 REJECT_CAUSE_MESSAGE_TYPE_NON_EXISTANT,
140 REJECT_CAUSE_MESSAGE_TYPE_NOT_COMP_PRT_ST,
141 REJECT_CAUSE_IE_NON_EXISTANT,
142 REJECT_CAUSE_MSG_NOT_COMPATIBLE_PROTOCOL_STATE,
145 // Connection Management establishment rejection cause
146 REJECT_CAUSE_REJ_UNSPECIFIED,
149 REJECT_CAUSE_AS_REJ_RR_REL_IND,
150 REJECT_CAUSE_AS_REJ_RR_RANDOM_ACCESS_FAILURE,
151 REJECT_CAUSE_AS_REJ_RRC_REL_IND,
152 REJECT_CAUSE_AS_REJ_RRC_CLOSE_SESSION_IND,
153 REJECT_CAUSE_AS_REJ_RRC_OPEN_SESSION_FAILURE,
154 REJECT_CAUSE_AS_REJ_LOW_LEVEL_FAIL,
155 REJECT_CAUSE_AS_REJ_LOW_LEVEL_FAIL_REDIAL_NOT_ALLOWED,
156 REJECT_CAUSE_AS_REJ_LOW_LEVEL_IMMED_RETRY,
159 REJECT_CAUSE_MM_REJ_INVALID_SIM,
160 REJECT_CAUSE_MM_REJ_NO_SERVICE,
161 REJECT_CAUSE_MM_REJ_TIMER_T3230_EXP,
162 REJECT_CAUSE_MM_REJ_NO_CELL_AVAILABLE,
163 REJECT_CAUSE_MM_REJ_WRONG_STATE,
164 REJECT_CAUSE_MM_REJ_ACCESS_CLASS_BLOCKED,
165 // Definitions for release ind causes between MM and CNM
166 REJECT_CAUSE_ABORT_MSG_RECEIVED,
167 REJECT_CAUSE_OTHER_CAUSE,
170 REJECT_CAUSE_CNM_REJ_TIMER_T303_EXP,
171 REJECT_CAUSE_CNM_REJ_NO_RESOURCES,
172 REJECT_CAUSE_CNM_MM_REL_PENDING,
173 REJECT_CAUSE_CNM_INVALID_USER_DATA,
174 CALL_END_CAUSE_MAX = 255
175 } call_end_cause_e_type;
179 struct call_CLCC_info {
181 enum tcore_call_direction direction;
182 enum tcore_call_status status;
183 enum tcore_call_type type;
195 } call_end_cause_info;
197 /**************************************************************************
198 * Local Function Prototypes
199 **************************************************************************/
200 /************************* REQUESTS ***************************/
201 static void _call_status_idle(TcorePlugin *p, CallObject *co);
202 static void _call_status_active(TcorePlugin *p, CallObject *co);
203 static void _call_status_dialing(TcorePlugin *p, CallObject *co);
204 static void _call_status_alert(TcorePlugin *p, CallObject *co);
205 static void _call_status_incoming(TcorePlugin *p, CallObject *co);
206 static void _call_status_waiting(TcorePlugin *p, CallObject *co);
207 static TReturn _call_list_get(CoreObject *o, gboolean *event_flag);
208 /* Todo Need to check whether this api is required */
209 //static TReturn _set_dtmf_tone_duration(CoreObject *o, UserRequest *ur);
211 /************************* CONFIRMATION ***************************/
212 static void on_confirmation_call_message_send(TcorePending *p, gboolean result, void *user_data); // from Kernel
213 static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data);
214 static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data);
215 static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data);
216 static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data);
218 static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type);
219 static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type);
220 //static void _on_confirmation_dtmf_tone_duration(TcorePending *p, int data_len, const void *data, void *user_data);
221 static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data);
223 /************************* RESPONSES ***************************/
224 static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data);
226 /************************* NOTIIFICATIONS ***************************/
227 static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data);
228 static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data);
229 static void on_notification_call_status(CoreObject *o, const void *data, void *user_data);
230 static gboolean on_notification_call_info(CoreObject *o, const void *data, void *user_data);
231 static gboolean on_notification_call_clip_info(CoreObject *o, const void *data, void *user_data);
234 /**************************************************************************
235 * Local Utility Function Prototypes
236 **************************************************************************/
237 static gboolean _call_request_message(TcorePending *pending, CoreObject *o, UserRequest *ur, void *on_resp, void *user_data);
238 static void _call_branch_by_status(TcorePlugin *p, CallObject *co, unsigned int status);
239 static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call);
241 /**************************************************************************
242 * Local Function Definitions
243 **************************************************************************/
245 const call_end_cause_info call_end_cause_table[] = // call end cause table to convert Netwotk cause to TAPI cause
247 { 1, CC_CAUSE_UNASSIGNED_NUMBER}, { 3, CC_CAUSE_NO_ROUTE_TO_DEST},
248 { 6, CC_CAUSE_CHANNEL_UNACCEPTABLE}, { 8, CC_CAUSE_OPERATOR_DETERMINED_BARRING},
249 { 16, CC_CAUSE_NORMAL_CALL_CLEARING}, { 17, CC_CAUSE_USER_BUSY},
250 { 18, CC_CAUSE_NO_USER_RESPONDING}, { 19, CC_CAUSE_USER_ALERTING_NO_ANSWER},
251 { 21, CC_CAUSE_CALL_REJECTED}, { 22, CC_CAUSE_NUMBER_CHANGED},
252 { 26, CC_CAUSE_NON_SELECTED_USER_CLEARING}, { 27, CC_CAUSE_DESTINATION_OUT_OF_ORDER},
253 { 28, CC_CAUSE_INVALID_NUMBER_FORMAT}, { 29, CC_CAUSE_FACILITY_REJECTED},
254 { 30, CC_CAUSE_RESPONSE_TO_STATUS_ENQUIRY}, { 31, CC_CAUSE_NORMAL_UNSPECIFIED},
255 { 34, CC_CAUSE_NO_CIRCUIT_CHANNEL_AVAILABLE}, { 38, CC_CAUSE_NETWORK_OUT_OF_ORDER},
256 { 41, CC_CAUSE_TEMPORARY_FAILURE}, { 42, CC_CAUSE_SWITCHING_EQUIPMENT_CONGESTION},
257 { 43, CC_CAUSE_ACCESS_INFORMATION_DISCARDED}, { 44, CC_CAUSE_REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE},
258 { 47, CC_CAUSE_RESOURCES_UNAVAILABLE_UNSPECIFIED}, { 49, CC_CAUSE_QUALITY_OF_SERVICE_UNAVAILABLE},
259 { 50, CC_CAUSE_REQUESTED_FACILITY_NOT_SUBSCRIBED}, { 55, CC_CAUSE_INCOMING_CALL_BARRED_WITHIN_CUG},
260 { 57, CC_CAUSE_BEARER_CAPABILITY_NOT_AUTHORISED}, { 58, CC_CAUSE_BEARER_CAPABILITY_NOT_PRESENTLY_AVAILABLE},
261 { 63, CC_CAUSE_SERVICE_OR_OPTION_NOT_AVAILABLE}, { 65, CC_CAUSE_BEARER_SERVICE_NOT_IMPLEMENTED},
262 { 68, CC_CAUSE_ACM_GEQ_ACMMAX}, { 69, CC_CAUSE_REQUESTED_FACILITY_NOT_IMPLEMENTED},
263 { 70, CC_CAUSE_ONLY_RESTRICTED_DIGITAL_INFO_BC_AVAILABLE}, { 79, CC_CAUSE_SERVICE_OR_OPTION_NOT_IMPLEMENTED},
264 { 81, CC_CAUSE_INVALID_TRANSACTION_ID_VALUE}, { 87, CC_CAUSE_USER_NOT_MEMBER_OF_CUG},
265 { 88, CC_CAUSE_INCOMPATIBLE_DESTINATION}, { 91, CC_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION},
266 { 95, CC_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE}, { 96, CC_CAUSE_INVALID_MANDATORY_INFORMATION},
267 { 97, CC_CAUSE_MESSAGE_TYPE_NON_EXISTENT}, { 98, CC_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROT_STATE},
268 { 99, CC_CAUSE_IE_NON_EXISTENT_OR_NOT_IMPLEMENTED}, { 100, CC_CAUSE_CONDITIONAL_IE_ERROR},
269 { 101, CC_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE}, { 102, CC_CAUSE_RECOVERY_ON_TIMER_EXPIRY},
270 { 111, CC_CAUSE_PROTOCOL_ERROR_UNSPECIFIED}, {127, CC_CAUSE_INTERWORKING_UNSPECIFIED},
273 static enum tcore_call_status _call_status(unsigned int status)
279 return TCORE_CALL_STATUS_ACTIVE;
282 return TCORE_CALL_STATUS_HELD;
285 return TCORE_CALL_STATUS_DIALING;
288 return TCORE_CALL_STATUS_ALERT;
291 return TCORE_CALL_STATUS_INCOMING;
294 return TCORE_CALL_STATUS_WAITING;
296 case 6: // DISCONNECTED state // FALL THROUGH
298 return TCORE_CALL_STATUS_IDLE;
302 static gboolean _call_is_in_mpty(int mpty)
320 static enum tcore_call_type call_type(int type)
326 return TCORE_CALL_TYPE_VOICE;
329 return TCORE_CALL_TYPE_VIDEO;
335 return TCORE_CALL_TYPE_VOICE;
338 static int _compare_call_end_cause(int networkcause)
342 for (count = 0; count < sizeof(call_end_cause_table) / sizeof(call_end_cause_info); count++) {
343 if (call_end_cause_table[count].network_cause == networkcause)
344 return (call_end_cause_table[count].tapi_cause);
346 return CC_CAUSE_NORMAL_CALL_CLEARING;
350 static gboolean on_notification_call_clip_info(CoreObject *o, const void *data, void *user_data)
359 static gboolean on_notification_call_info(CoreObject *o, const void *data, void *user_data)
361 GSList *tokens = NULL;
362 GSList *lines = NULL;
363 const char *line = NULL;
369 lines = (GSList *) data;
370 if (1 != g_slist_length(lines)) {
371 err("Unsolicited message, BUT multiple lines present");
375 line = (char *) (lines->data);
376 tokens = tcore_at_tok_new(line);
378 stat = g_slist_nth_data(tokens, 1);
380 dbg("Stat is missing from %XCALLSTAT indiaction");
385 case STATUS_INCOMING:
386 dbg("calling on_notification_call_incoming");
387 on_notification_call_incoming(o, line, user_data);
391 dbg("calling on_notification_call_waiting");
392 on_notification_call_waiting(o, line, user_data);
395 case STATUS_CONNECTED: /*igonre Connected state. */
396 dbg("Connected state");
400 dbg("calling on_notification_call_status");
401 on_notification_call_status(o, line, user_data);
407 tcore_at_tok_free(tokens);
414 static gboolean _call_request_message(TcorePending *pending,
420 TcoreHal *hal = NULL;
425 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
428 tcore_pending_set_response_callback(pending, on_resp, user_data);
430 tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL);
433 tcore_pending_link_user_request(pending, ur);
435 err("User Request is NULL, is this internal request??");
439 hal = tcore_object_get_hal(o);
440 // Send request to HAL
441 ret = tcore_hal_send_request(hal, pending);
442 if (TCORE_RETURN_SUCCESS != ret) {
443 err("Request send failed");
451 static void _call_status_idle(TcorePlugin *p, CallObject *co)
453 CoreObject *core_obj = NULL;
454 char *cmd_str = NULL;
455 TcorePending *pending = NULL;
456 TcoreATRequest *req = NULL;
457 gboolean ret = FALSE;
461 core_obj = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL);
462 dbg("Call ID [%d], Call Status [%d]", tcore_call_object_get_id(co), tcore_call_object_get_status(co));
464 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_IDLE) {
465 // get call end cause.
466 cmd_str = g_strdup_printf("%s", "AT+XCEER");
467 dbg("Request command string: %s", cmd_str);
469 // Create new Pending request
470 pending = tcore_pending_new(core_obj, 0);
472 // Create new AT-Command request
473 req = tcore_at_request_new(cmd_str, "+XCEER", TCORE_AT_SINGLELINE);
474 dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
475 // Free command string
478 // Set request data (AT command) to Pending request
479 tcore_pending_set_request_data(pending, 0, req);
481 ur = tcore_user_request_new(NULL, NULL);
483 ret = _call_request_message(pending, core_obj, ur, _on_confirmation_call_end_cause, co);
486 err("Failed to send AT-Command request");
487 // free only UserRequest.
489 tcore_user_request_free(ur);
495 err("Call object was not free");
496 tcore_call_object_free(core_obj, co);
502 static void _call_status_dialing(TcorePlugin *p, CallObject *co)
504 struct tnoti_call_status_dialing data;
508 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_DIALING) {
509 data.type = tcore_call_object_get_type(co);
510 dbg("data.type : [%d]", data.type);
512 data.id = tcore_call_object_get_id(co);
513 dbg("data.id : [%d]", data.id);
516 tcore_call_object_set_status(co, TCORE_CALL_STATUS_DIALING);
518 // Send notification to TAPI
519 tcore_server_send_notification(tcore_plugin_ref_server(p),
520 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
521 TNOTI_CALL_STATUS_DIALING,
522 sizeof(struct tnoti_call_status_dialing),
530 static void _call_status_alert(TcorePlugin *p, CallObject *co)
532 struct tnoti_call_status_alert data;
536 // Alerting has just 1 data 'CALL ID'
537 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_ALERT) {
538 data.type = tcore_call_object_get_type(co);
539 dbg("data.type : [%d]", data.type);
541 data.id = tcore_call_object_get_id(co);
542 dbg("data.id : [%d]", data.id);
545 tcore_call_object_set_status(co, TCORE_CALL_STATUS_ALERT);
547 // Send notification to TAPI
548 tcore_server_send_notification(tcore_plugin_ref_server(p),
549 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
550 TNOTI_CALL_STATUS_ALERT,
551 sizeof(struct tnoti_call_status_alert),
559 static void _call_status_active(TcorePlugin *p, CallObject *co)
561 struct tnoti_call_status_active data;
565 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_ACTIVE) {
566 data.type = tcore_call_object_get_type(co);
567 dbg("data.type : [%d]", data.type);
569 data.id = tcore_call_object_get_id(co);
570 dbg("data.id : [%d]", data.id);
573 tcore_call_object_set_status(co, TCORE_CALL_STATUS_ACTIVE);
575 // Send notification to TAPI
576 tcore_server_send_notification(tcore_plugin_ref_server(p),
577 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
578 TNOTI_CALL_STATUS_ACTIVE,
579 sizeof(struct tnoti_call_status_active),
587 static void _call_status_held(TcorePlugin *p, CallObject *co)
589 struct tnoti_call_status_held data;
593 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_HELD) {
594 data.type = tcore_call_object_get_type(co);
595 dbg("data.type : [%d]", data.type);
597 data.id = tcore_call_object_get_id(co);
598 dbg("data.id : [%d]", data.id);
601 tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD);
603 // Send notification to TAPI
604 tcore_server_send_notification(tcore_plugin_ref_server(p),
605 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
606 TNOTI_CALL_STATUS_HELD,
607 sizeof(struct tnoti_call_status_held),
615 static void _call_status_incoming(TcorePlugin *p, CallObject *co)
617 struct tnoti_call_status_incoming data;
621 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_INCOMING) {
622 tcore_call_object_set_status(co, TCORE_CALL_STATUS_INCOMING);
624 data.type = tcore_call_object_get_type(co);
625 dbg("data.type : [%d]", data.type);
627 data.id = tcore_call_object_get_id(co);
628 dbg("data.id : [%d]", data.id);
630 data.cli.mode = tcore_call_object_get_cli_mode(co);
631 dbg("data.cli.mode : [%d]", data.cli.mode);
633 tcore_call_object_get_number(co, data.cli.number);
634 dbg("data.cli.number : [%s]", data.cli.number);
636 data.cna.mode = tcore_call_object_get_cna_mode(co);
637 dbg("data.cna.mode : [%d]", data.cna.mode);
639 tcore_call_object_get_name(co, data.cna.name);
640 dbg("data.cna.name : [%s]", data.cna.name);
642 data.forward = FALSE; // this is tmp code
644 data.active_line = tcore_call_object_get_active_line(co);
645 dbg("data.active_line : [%d]", data.active_line);
647 // Send notification to TAPI
648 tcore_server_send_notification(tcore_plugin_ref_server(p),
649 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
650 TNOTI_CALL_STATUS_INCOMING,
651 sizeof(struct tnoti_call_status_incoming),
659 static void _call_status_waiting(TcorePlugin *p, CallObject *co)
662 _call_status_incoming(p, co);
668 static void _call_branch_by_status(TcorePlugin *p, CallObject *co, unsigned int status)
672 dbg("Call Status is %d", status);
674 case TCORE_CALL_STATUS_IDLE:
675 _call_status_idle(p, co);
678 case TCORE_CALL_STATUS_ACTIVE:
679 _call_status_active(p, co);
682 case TCORE_CALL_STATUS_HELD:
683 _call_status_held(p, co);
686 case TCORE_CALL_STATUS_DIALING:
687 _call_status_dialing(p, co);
690 case TCORE_CALL_STATUS_ALERT:
691 _call_status_alert(p, co);
694 case TCORE_CALL_STATUS_INCOMING:
695 _call_status_incoming(p, co);
698 case TCORE_CALL_STATUS_WAITING:
699 _call_status_waiting(p, co);
707 static TReturn _call_list_get(CoreObject *o, gboolean *event_flag)
709 UserRequest *ur = NULL;
710 TcorePending *pending = NULL;
711 char *cmd_str = NULL;
712 TcoreATRequest *req = NULL;
713 gboolean ret = FALSE;
717 err("Core Object is NULL");
718 return TCORE_RETURN_FAILURE;
721 // Create new User Request
722 ur = tcore_user_request_new(NULL, NULL);
725 cmd_str = g_strdup("AT+CLCC");
727 // Create new Pending Request
728 pending = tcore_pending_new(o, 0);
729 req = tcore_at_request_new(cmd_str, "+CLCC", TCORE_AT_MULTILINE);
733 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
735 tcore_pending_set_request_data(pending, 0, req);
737 ret = _call_request_message(pending, o, ur, on_response_call_list_get, event_flag);
739 err("AT request (%s) sending failed", req->cmd);
740 // free only UserRequest.
742 tcore_user_request_free(ur);
745 return TCORE_RETURN_FAILURE;
748 dbg("AT request sent success");
749 return TCORE_RETURN_SUCCESS;
753 static void on_confirmation_call_message_send(TcorePending *p, gboolean result, void *user_data)
757 if (result == FALSE) { // Fail
767 static void call_prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback)
769 TcoreATRequest *req = NULL;
770 TcoreHal *hal = NULL;
771 TcorePending *pending = NULL;
774 hal = tcore_object_get_hal(co);
777 pending = tcore_pending_new(co, 0);
779 dbg("Pending is NULL");
780 req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
782 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
784 tcore_pending_set_request_data(pending, 0, req);
785 tcore_pending_set_response_callback(pending, callback, NULL);
786 tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL);
787 ret = tcore_hal_send_request(hal, pending);
788 if (ret != TCORE_RETURN_SUCCESS)
789 err("Failed to process request");
792 static void on_confirmation_call_outgoing(TcorePending *p, int data_len, const void *data, void *user_data)
794 UserRequest *ur = NULL;
795 GSList *tokens = NULL;
796 const char *line = NULL;
797 const TcoreATResponse *response = data;
798 struct tresp_call_dial resp;
799 enum telephony_call_error error;
802 ur = tcore_pending_ref_user_request(p);
804 if (response->success > 0) {
806 resp.err = CALL_ERROR_NONE;
808 dbg("RESPONSE NOT OK");
810 line = (const char *) response->final_response;
811 tokens = tcore_at_tok_new(line);
813 if (g_slist_length(tokens) < 1) {
814 err("Unspecified error cause OR string corrupted");
815 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
817 error = atoi(g_slist_nth_data(tokens, 0));
818 err("Error: [%d]", error);
819 // TODO: CMEE error mapping is required.
820 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
824 tcore_at_tok_free(tokens);
827 // Send Response to TAPI
828 tcore_user_request_send_response(ur, TRESP_CALL_DIAL, sizeof(struct tresp_call_dial), &resp);
830 err("User Request is NULL");
837 static void on_confirmation_call_accept(TcorePending *p, int data_len, const void *data, void *user_data)
839 UserRequest *ur = NULL;
840 GSList *tokens = NULL;
841 const char *line = NULL;
842 const TcoreATResponse *response = data;
843 struct tresp_call_answer resp;
844 enum telephony_call_error error;
847 ur = tcore_pending_ref_user_request(p);
849 if (response->success > 0) {
851 resp.err = CALL_ERROR_NONE;
853 dbg("RESPONSE NOT OK");
855 line = (const char *) response->final_response;
856 tokens = tcore_at_tok_new(line);
858 if (g_slist_length(tokens) < 1) {
859 err("Unspecified error cause OR string corrupted");
860 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
862 error = atoi(g_slist_nth_data(tokens, 0));
863 err("Error: [%d]", error);
864 // TODO: CMEE error mapping is required.
865 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
869 tcore_at_tok_free(tokens);
872 resp.id = tcore_call_object_get_id((CallObject *) user_data);
874 // Send Response to TAPI
875 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
877 err("User Request is NULL");
885 static void on_confirmation_call_reject(TcorePending *p, int data_len, const void *data, void *user_data)
887 UserRequest *ur = NULL;
888 GSList *tokens = NULL;
889 const char *line = NULL;
890 const TcoreATResponse *response = data;
891 struct tresp_call_answer resp;
892 enum telephony_call_error error;
896 ur = tcore_pending_ref_user_request(p);
898 if (response->success > 0) {
900 resp.err = CALL_ERROR_NONE;
902 dbg("RESPONSE NOT OK");
903 line = (const char *) response->final_response;
904 tokens = tcore_at_tok_new(line);
906 if (g_slist_length(tokens) < 1) {
907 err("Unspecified error cause OR string corrupted");
908 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
910 error = atoi(g_slist_nth_data(tokens, 0));
911 err("Error: [%d]", error);
912 // TODO: CMEE error mapping is required.
913 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
917 tcore_at_tok_free(tokens);
920 resp.id = tcore_call_object_get_id((CallObject *) user_data);
922 // Send Response to TAPI
923 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
925 err("User Request is NULL");
932 static void on_confirmation_call_replace(TcorePending *p, int data_len, const void *data, void *user_data)
934 UserRequest *ur = NULL;
935 GSList *tokens = NULL;
936 const char *line = NULL;
937 const TcoreATResponse *response = data;
938 struct tresp_call_answer resp;
939 enum telephony_call_error error;
942 ur = tcore_pending_ref_user_request(p);
944 if (response->success > 0) {
946 resp.err = CALL_ERROR_NONE;
948 dbg("RESPONSE NOT OK");
949 line = (const char *) response->final_response;
950 tokens = tcore_at_tok_new(line);
952 if (g_slist_length(tokens) < 1) {
953 err("Unspecified error cause OR string corrupted");
954 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
956 error = atoi(g_slist_nth_data(tokens, 0));
957 err("Error: [%d]", error);
958 // TODO: CMEE error mapping is required.
959 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
963 tcore_at_tok_free(tokens);
965 resp.id = tcore_call_object_get_id((CallObject *) user_data);
967 // Send Response to TAPI
968 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
970 dbg("User Request is NULL");
977 static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data)
979 CoreObject *o = NULL;
980 UserRequest *ur = NULL;
981 GSList *tokens = NULL;
982 const char *line = NULL;
983 const TcoreATResponse *response = data;
984 struct tresp_call_answer resp;
985 enum telephony_call_error error;
989 o = tcore_pending_ref_core_object(p);
990 ur = tcore_pending_ref_user_request(p);
991 resp.id = tcore_call_object_get_id((CallObject *) user_data);
994 if (response->success > 0) {
996 resp.err = CALL_ERROR_NONE;
998 err("RESPONSE NOT OK");
999 line = (const char *) response->final_response;
1000 tokens = tcore_at_tok_new(line);
1002 if (g_slist_length(tokens) < 1) {
1003 err("Unspecified error cause OR string corrupted");
1004 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1006 error = atoi(g_slist_nth_data(tokens, 0));
1007 err("Error: [%d]", error);
1008 // TODO: CMEE error mapping is required.
1009 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1013 tcore_at_tok_free(tokens);
1016 // Send response to TAPI
1017 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
1020 CallObject *co = NULL;
1023 list = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_ACTIVE);
1025 err("Can't find active Call");
1029 co = (CallObject *) list->data;
1031 err("Can't get active Call object");
1036 tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD);
1037 dbg("Call status is set to HELD");
1040 err("User Request is NULL");
1047 static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type)
1049 UserRequest *ur = NULL;
1050 struct tresp_call_end resp;
1051 GSList *tokens = NULL;
1052 const char *line = NULL;
1053 enum telephony_call_error error;
1054 const TcoreATResponse *response = data;
1057 ur = tcore_pending_ref_user_request(p);
1059 if (response->success > 0) {
1061 resp.err = CALL_ERROR_NONE;
1063 err("RESPONSE NOT OK");
1065 line = (const char *) response->final_response;
1066 tokens = tcore_at_tok_new(line);
1068 if (g_slist_length(tokens) < 1) {
1069 err("Unspecified error cause OR string corrupted");
1070 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1072 error = atoi(g_slist_nth_data(tokens, 0));
1073 err("Error: [%d]", error);
1074 // TODO: CMEE error mapping is required.
1075 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1077 tcore_at_tok_free(tokens);
1081 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1082 dbg("resp.type = %d resp.id= %d", resp.type, resp.id);
1084 // Send reponse to TAPI
1085 tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
1087 err("User Request is NULL");
1095 static void on_confirmation_call_endall(TcorePending *p, int data_len, const void *data, void *user_data)
1097 // skip response handling - actual result will be handled in on_confirmation_call_release_all
1098 const TcoreATResponse *response = data;
1102 if (response->success > 0) {
1105 err("RESPONSE NOT OK");
1113 static void on_confirmation_call_release_all(TcorePending *p, int data_len, const void *data, void *user_data)
1116 _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ALL);
1122 static void on_confirmation_call_release_specific(TcorePending *p, int data_len, const void *data, void *user_data)
1125 _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_DEFAULT);
1130 static void on_confirmation_call_release_all_active(TcorePending *p, int data_len, const void *data, void *user_data)
1133 _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ACTIVE_ALL);
1138 static void on_confirmation_call_release_all_held(TcorePending *p, int data_len, const void *data, void *user_data)
1141 _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_HOLD_ALL);
1146 static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type)
1148 UserRequest *ur = NULL;
1149 GSList *tokens = NULL;
1150 const char *line = NULL;
1151 const TcoreATResponse *response = NULL;
1152 enum telephony_call_error error;
1155 ur = tcore_pending_ref_user_request(p);
1156 response = (TcoreATResponse *) data;
1157 if (response->success > 0) {
1159 error = CALL_ERROR_NONE;
1161 err("RESPONSE NOT OK");
1163 line = (const char *) response->final_response;
1164 tokens = tcore_at_tok_new(line);
1166 if (g_slist_length(tokens) < 1) {
1167 err("Unspecified error cause OR string corrupted");
1168 error = CALL_ERROR_SERVICE_UNAVAIL;
1170 error = atoi(g_slist_nth_data(tokens, 0));
1172 // TODO: CMEE error mapping is required.
1173 error = CALL_ERROR_SERVICE_UNAVAIL;
1177 tcore_at_tok_free(tokens);
1180 dbg("Response Call type -%d", type);
1182 case TRESP_CALL_HOLD:
1184 struct tresp_call_hold resp;
1187 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1188 dbg("call hold response");
1189 // Send reponse to TAPI
1190 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
1194 case TRESP_CALL_ACTIVE:
1196 struct tresp_call_active resp;
1199 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1200 dbg("call active response");
1201 // Send reponse to TAPI
1202 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
1206 case TRESP_CALL_JOIN:
1208 struct tresp_call_join resp;
1211 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1212 dbg("call join response");
1214 // Send reponse to TAPI
1215 tcore_user_request_send_response(ur, TRESP_CALL_JOIN, sizeof(struct tresp_call_join), &resp);
1219 case TRESP_CALL_SPLIT:
1221 struct tresp_call_split resp;
1224 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1225 dbg("call split response");
1226 // Send reponse to TAPI
1227 tcore_user_request_send_response(ur, TRESP_CALL_SPLIT, sizeof(struct tresp_call_split), &resp);
1231 case TRESP_CALL_DEFLECT:
1233 struct tresp_call_deflect resp;
1236 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1237 dbg("call deflect response");
1238 // Send reponse to TAPI
1239 tcore_user_request_send_response(ur, TRESP_CALL_DEFLECT, sizeof(struct tresp_call_deflect), &resp);
1244 case TRESP_CALL_TRANSFER:
1246 struct tresp_call_transfer resp;
1249 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1250 dbg("call transfer response");
1251 // Send reponse to TAPI
1252 tcore_user_request_send_response(ur, TRESP_CALL_TRANSFER, sizeof(struct tresp_call_transfer), &resp);
1256 case TRESP_CALL_START_CONT_DTMF:
1258 struct tresp_call_dtmf resp;
1261 dbg("call dtmf response");
1262 // Send reponse to TAPI
1263 tcore_user_request_send_response(ur, TRESP_CALL_START_CONT_DTMF, sizeof(struct tresp_call_dtmf), &resp);
1269 dbg("type not supported");
1274 if ((type == TRESP_CALL_HOLD) || (type == TRESP_CALL_ACTIVE) || (type == TRESP_CALL_JOIN)
1275 || (type == TRESP_CALL_SPLIT)) {
1277 CoreObject *core_obj = NULL;
1278 gboolean *eflag = g_new0(gboolean, 1);
1280 core_obj = tcore_pending_ref_core_object(p);
1283 dbg("Calling _call_list_get");
1284 _call_list_get(core_obj, eflag);
1292 static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data)
1295 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_HOLD);
1300 static void on_confirmation_call_active(TcorePending *p, int data_len, const void *data, void *user_data)
1303 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_ACTIVE);
1308 static void on_confirmation_call_join(TcorePending *p, int data_len, const void *data, void *user_data)
1311 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_JOIN);
1316 static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data)
1319 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_SPLIT);
1324 static void on_confirmation_call_deflect(TcorePending *p, int data_len, const void *data, void *user_data)
1327 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_DEFLECT);
1332 static void on_confirmation_call_transfer(TcorePending *p, int data_len, const void *data, void *user_data)
1335 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_TRANSFER);
1340 static void on_confirmation_call_dtmf(TcorePending *p, int data_len, const void *data, void *user_data)
1343 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_START_CONT_DTMF);
1349 static void _on_confirmation_dtmf_tone_duration(TcorePending *p, int data_len, const void *data, void *user_data)
1351 GSList *tokens = NULL;
1352 const char *line = NULL;
1353 const TcoreATResponse *response = data;
1354 enum telephony_call_error error;
1358 if (response->success > 0) {
1360 error = CALL_ERROR_NONE;
1362 err("RESPONSE NOT OK");
1363 line = (const char *) response->final_response;
1364 tokens = tcore_at_tok_new(line);
1365 if (g_slist_length(tokens) < 1) {
1366 err("err cause not specified or string corrupted");
1367 error = CALL_ERROR_SERVICE_UNAVAIL;
1369 error = atoi(g_slist_nth_data(tokens, 0));
1370 // TODO: CMEE error mapping is required.
1374 tcore_at_tok_free(tokens);
1377 dbg("Set dtmf tone duration response - %d", error);
1382 static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data)
1384 CoreObject *core_obj = NULL;
1385 UserRequest *ur = NULL;
1386 const TcoreATResponse *response = data;
1387 struct tresp_call_swap resp;
1388 GSList *tokens = NULL;
1389 const char *line = NULL;
1392 core_obj = tcore_pending_ref_core_object(p);
1393 ur = tcore_pending_ref_user_request(p);
1396 if (response->success > 0) {
1398 resp.err = CALL_ERROR_NONE;
1400 err("RESPONSE NOT OK");
1401 line = (const char *) response->final_response;
1402 tokens = tcore_at_tok_new(line);
1403 if (g_slist_length(tokens) < 1) {
1404 err("err cause not specified or string corrupted");
1405 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1407 resp.err = atoi(g_slist_nth_data(tokens, 0));
1409 // TODO: CMEE error mapping is required.
1410 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1414 tcore_at_tok_free(tokens);
1417 resp.id = tcore_call_object_get_id((CallObject *) user_data);
1418 dbg("resp.id = %d", resp.id);
1420 // Send response to TAPI
1421 tcore_user_request_send_response(ur, TRESP_CALL_SWAP, sizeof(struct tresp_call_swap), &resp);
1424 GSList *active = NULL;
1425 GSList *held = NULL;
1426 CallObject *co = NULL;
1427 gboolean *eflag = NULL;
1429 held = tcore_call_object_find_by_status(core_obj, TCORE_CALL_STATUS_HELD);
1431 err("Can't find held Call");
1435 active = tcore_call_object_find_by_status(core_obj, TCORE_CALL_STATUS_ACTIVE);
1437 dbg("Can't find active Call");
1442 co = (CallObject *) held->data;
1444 err("Can't get held Call object");
1448 resp.id = tcore_call_object_get_id(co);
1450 // Send response to TAPI
1451 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
1453 held = g_slist_next(held);
1457 co = (CallObject *) active->data;
1459 err("[ error ] can't get active call object");
1463 resp.id = tcore_call_object_get_id(co);
1465 // Send response to TAPI
1466 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
1467 active = g_slist_next(active);
1470 eflag = g_new0(gboolean, 1);
1473 dbg("calling _call_list_get");
1474 _call_list_get(core_obj, eflag);
1477 err("User Request is NULL");
1484 static void on_confirmation_set_sound_path(TcorePending *p, int data_len,
1488 const TcoreATResponse *resp = data;
1489 struct tnoti_call_sound_path *snd_path = user_data;
1490 struct tresp_call_set_sound_path resp_set_sound_path;
1491 UserRequest *ur = tcore_pending_ref_user_request(p);
1492 TcorePlugin *plugin = tcore_pending_ref_plugin(p);
1493 CoreObject *co_call;
1496 err("User Request is NULL");
1501 if (resp->success <= 0) {
1503 dbg("RESPONSE NOT OK");
1504 resp_set_sound_path.err = TRUE;
1510 resp_set_sound_path.err = FALSE;
1512 co_call = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL);
1514 /* Notify control plugin about sound path */
1515 tcore_server_send_notification(tcore_plugin_ref_server(plugin),
1516 co_call, TNOTI_CALL_SOUND_PATH,
1517 sizeof(struct tnoti_call_sound_path),
1521 /* Answer TAPI request */
1522 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH,
1523 sizeof(resp_set_sound_path),
1524 &resp_set_sound_path);
1529 static void on_confirmation_call_set_source_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1531 UserRequest *ur = NULL;
1532 GSList *tokens = NULL;
1533 const char *line = NULL;
1534 const TcoreATResponse *response = data;
1535 char *resp_str = NULL;
1536 struct tresp_call_set_sound_path resp;
1540 ur = tcore_pending_ref_user_request(p);
1542 // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]
\ 3
1544 err("Input data is NULL");
1548 if (response->success > 0) {
1551 line = (const char *) (((GSList *) response->lines)->data);
1552 tokens = tcore_at_tok_new(line);
1554 resp_str = g_slist_nth_data(tokens, 0);
1555 if (!g_slist_nth_data(tokens, 0)) {
1556 err("group_id is missing");
1561 if (!g_slist_nth_data(tokens, 1)) {
1562 err(" function_id is missing");
1567 resp_str = g_slist_nth_data(tokens, 2);
1570 error = atoi(resp_str);
1572 dbg("Response is Success");
1580 tcore_at_tok_free(tokens);
1582 dbg("RESPONSE NOT OK");
1584 line = (const char *) response->final_response;
1585 tokens = tcore_at_tok_new(line);
1587 if (g_slist_length(tokens) < 1) {
1588 err("err cause not specified or string corrupted");
1591 error = atoi(g_slist_nth_data(tokens, 0));
1593 // TODO: CMEE error mapping is required.
1598 tcore_at_tok_free(tokens);
1602 if ( resp.err ) { // Send only failed notification . success notification send when destination device is set.
1603 // Send notification to TAPI
1604 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_set_sound_path), &resp);
1605 setsoundpath = TRUE;
1608 err("User Request is NULL");
1615 static void on_confirmation_call_set_destination_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1617 UserRequest *ur = NULL;
1618 GSList *tokens = NULL;
1619 const char *line = NULL;
1620 char *resp_str = NULL;
1621 struct tresp_call_set_sound_path resp;
1622 const TcoreATResponse *response = data;
1627 ur = tcore_pending_ref_user_request(p);
1628 // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]
\ 3
1631 err("Input data is NULL");
1636 if (response->success > 0) {
1639 line = (const char *) (((GSList *) response->lines)->data);
1640 tokens = tcore_at_tok_new(line);
1642 resp_str = g_slist_nth_data(tokens, 0);
1643 if (!g_slist_nth_data(tokens, 0)) {
1644 dbg("group_id is missing");
1649 if (!g_slist_nth_data(tokens, 1)) {
1650 dbg("function_id is missing");
1655 resp_str = g_slist_nth_data(tokens, 2);
1657 error = atoi(resp_str);
1659 dbg("Response is Success");
1668 tcore_at_tok_free(tokens);
1670 dbg("RESPONSE NOT OK");
1672 line = (const char *) response->final_response;
1673 tokens = tcore_at_tok_new(line);
1675 if (g_slist_length(tokens) < 1) {
1676 err("err cause not specified or string corrupted");
1679 error = atoi(g_slist_nth_data(tokens, 0));
1680 // TODO: CMEE error mapping is required.
1685 tcore_at_tok_free(tokens);
1688 if (setsoundpath == TRUE) {
1689 setsoundpath = FALSE;
1691 // Send response to TAPI
1692 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_set_sound_path), &resp);
1695 dbg("User Request is NULL");
1702 static void on_confirmation_call_set_source_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data)
1704 UserRequest *ur = NULL;
1705 GSList *tokens = NULL;
1706 const char *line = NULL;
1707 const TcoreATResponse *response = data;
1708 char *resp_str = NULL;
1709 struct tresp_call_set_sound_volume_level resp;
1712 ur = tcore_pending_ref_user_request(p);
1714 // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]
\ 3
1716 err("Input data is NULL");
1720 if (response->success > 0) {
1723 line = (const char *) (((GSList *) response->lines)->data);
1724 tokens = tcore_at_tok_new(line);
1726 resp_str = g_slist_nth_data(tokens, 0);
1727 if (!g_slist_nth_data(tokens, 0)) {
1728 err("group_id is missing");
1733 if (!g_slist_nth_data(tokens, 1)) {
1734 err("function_id is missing");
1739 resp_str = g_slist_nth_data(tokens, 2);
1741 error = atoi(resp_str);
1744 dbg("Response is Success ");
1753 tcore_at_tok_free(tokens);
1755 dbg("RESPONSE NOT OK");
1757 line = (const char *) response->final_response;
1758 tokens = tcore_at_tok_new(line);
1760 if (g_slist_length(tokens) < 1) {
1761 err("err cause not specified or string corrupted");
1764 error = atoi(g_slist_nth_data(tokens, 0));
1766 // TODO: CMEE error mapping is required.
1771 tcore_at_tok_free(tokens);
1775 if (resp.err && soundvolume == FALSE) { // Send only failed notification . success notification send when destination device is set.
1776 // Send reposne to TAPI
1777 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_set_sound_volume_level), &resp);
1781 err("User Request is NULL");
1789 static void on_confirmation_call_set_destination_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data)
1791 UserRequest *ur = NULL;
1792 GSList *tokens = NULL;
1793 const char *line = NULL;
1794 char *resp_str = NULL;
1795 const TcoreATResponse *response = data;
1796 struct tresp_call_set_sound_volume_level resp;
1801 ur = tcore_pending_ref_user_request(p);
1803 // +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]
\ 3
1805 err("Input data is NULL");
1810 if (response->success > 0) {
1812 line = (const char *) (((GSList *) response->lines)->data);
1813 tokens = tcore_at_tok_new(line);
1814 resp_str = g_slist_nth_data(tokens, 0);
1816 if (!g_slist_nth_data(tokens, 0)) {
1817 err("group_id is missing");
1822 if (!g_slist_nth_data(tokens, 1)) {
1823 err("function_id is missing");
1828 resp_str = g_slist_nth_data(tokens, 2);
1831 error = atoi(resp_str);
1834 dbg("Response is Success");
1843 tcore_at_tok_free(tokens);
1845 dbg("RESPONSE NOT OK");
1847 line = (const char *) response->final_response;
1848 tokens = tcore_at_tok_new(line);
1850 if (g_slist_length(tokens) < 1) {
1851 err("err cause not specified or string corrupted");
1854 error = atoi(g_slist_nth_data(tokens, 0));
1856 // TODO: CMEE error mapping is required.
1860 tcore_at_tok_free(tokens);
1863 if (soundvolume == TRUE) {
1864 soundvolume = FALSE;
1866 // Send reposne to TAPI
1867 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_set_sound_volume_level), &resp);
1870 err("User Request is NULL");
1878 static void on_confirmation_call_set_sound_mute_status(TcorePending *p, int data_len, const void *data, void *user_data)
1880 UserRequest *ur = NULL;
1881 GSList *tokens = NULL;
1882 const char *line = NULL;
1883 char *resp_str = NULL;
1884 struct tresp_call_set_sound_mute_status resp;
1885 const TcoreATResponse *response = data;
1890 ur = tcore_pending_ref_user_request(p);
1893 err("Input data is NULL");
1897 if (response->success > 0) {
1900 line = (const char *) (((GSList *) response->lines)->data);
1901 tokens = tcore_at_tok_new(line);
1902 resp_str = g_slist_nth_data(tokens, 0);
1904 if (!g_slist_nth_data(tokens, 0)) {
1905 err("group_id is missing");
1910 if (!g_slist_nth_data(tokens, 1)) {
1911 err(" function_id is missing");
1916 resp_str = g_slist_nth_data(tokens, 2);
1919 error = atoi(resp_str);
1921 dbg("Response is Success");
1929 tcore_at_tok_free(tokens);
1931 dbg("RESPONSE NOT OK");
1933 line = (const char *) response->final_response;
1934 tokens = tcore_at_tok_new(line);
1936 if (g_slist_length(tokens) < 1) {
1937 err("err cause not specified or string corrupted");
1940 error = atoi(g_slist_nth_data(tokens, 0));
1942 // TODO: CMEE error mapping is required.
1947 tcore_at_tok_free(tokens);
1951 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_MUTE_STATUS, sizeof(struct tresp_call_set_sound_mute_status), &resp);
1953 err("User Request is NULL");
1961 static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data)
1963 TcorePlugin *plugin = NULL;
1964 CoreObject *core_obj = NULL;
1965 CallObject *co = NULL;
1966 struct clcc_call_t *call_list = NULL;
1967 gboolean *event_flag = (gboolean *) user_data;
1968 const TcoreATResponse *response = data;
1969 GSList *resp_data = NULL;
1972 int cllc_info = 0, countCalls = 0, countValidCalls = 0;
1977 plugin = tcore_pending_ref_plugin(p);
1978 core_obj = tcore_pending_ref_core_object(p);
1980 if (response->success > 0) {
1982 if (response->lines) {
1983 resp_data = (GSList *) response->lines;
1984 countCalls = g_slist_length(resp_data);
1985 dbg("Total records : %d", countCalls);
1988 if (0 == countCalls) {
1989 err("Call count is zero");
1997 call_list = g_new0(struct clcc_call_t, countCalls);
1999 for (countValidCalls = 0; resp_data != NULL; resp_data = resp_data->next, countValidCalls++, cllc_info++) {
2000 line = (char *) (resp_data->data);
2002 error = _callFromCLCCLine(line, call_list + countValidCalls);
2007 co = tcore_call_object_find_by_id(core_obj, call_list[cllc_info].info.id);
2009 co = tcore_call_object_new(core_obj, call_list[cllc_info].info.id);
2011 err("error : tcore_call_object_new [ id : %d ]", call_list[cllc_info].info.id);
2016 // Call set parameters
2017 tcore_call_object_set_type(co, call_type(call_list[cllc_info].info.type));
2018 tcore_call_object_set_direction(co, call_list[cllc_info].info.direction);
2019 tcore_call_object_set_multiparty_state(co, _call_is_in_mpty(call_list[cllc_info].info.mpty));
2020 tcore_call_object_set_cli_info(co, CALL_CLI_MODE_DEFAULT, 0, call_list[cllc_info].number, strlen(call_list[cllc_info].number));
2021 tcore_call_object_set_active_line(co, 0);
2024 dbg("Call status before calling _call_branch_by_status() : (%d)", call_list[cllc_info].info.status);
2025 _call_branch_by_status(plugin, co, call_list[cllc_info].info.status);
2028 tcore_call_object_set_status(co, call_list[cllc_info].info.status);
2030 dbg("Call id : (%d)", call_list[cllc_info].info.id);
2031 dbg("Call direction : (%d)", call_list[cllc_info].info.direction);
2032 dbg("Call type : (%d)", call_list[cllc_info].info.type);
2033 dbg("Call mpty : (%d)", call_list[cllc_info].info.mpty);
2034 dbg("Call number : (%s)", call_list[cllc_info].number);
2035 dbg("Call status : (%d)", call_list[cllc_info].info.status);
2053 static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data)
2055 TcorePlugin *plugin = NULL;
2056 CoreObject *core_obj = NULL;
2057 CallObject *co = (CallObject *) user_data;
2058 const TcoreATResponse *response = data;
2059 const char *line = NULL;
2060 struct tnoti_call_status_idle call_status;
2061 GSList *tokens = NULL;
2066 plugin = tcore_pending_ref_plugin(p);
2067 core_obj = tcore_pending_ref_core_object(p);
2069 if (response->success > 0) {
2071 line = (const char *) (((GSList *) response->lines)->data);
2072 tokens = tcore_at_tok_new(line);
2073 resp_str = g_slist_nth_data(tokens, 0);
2075 err("call end cause - report value missing");
2077 resp_str = g_slist_nth_data(tokens, 1);
2079 err("call end cause value missing");
2081 error = atoi(resp_str);
2082 dbg("call end cause - %d", error);
2083 call_status.cause = _compare_call_end_cause(error);
2084 dbg("TAPI call end cause - %d", call_status.cause);
2088 tcore_at_tok_free(tokens);
2090 err("RESPONSE NOT OK");
2091 line = (char *) response->final_response;
2092 tokens = tcore_at_tok_new(line);
2093 if (g_slist_length(tokens) < 1) {
2094 err("err cause not specified or string corrupted");
2096 err(" err cause value: %d", atoi(g_slist_nth_data(tokens, 0)));
2098 call_status.cause = CC_CAUSE_NORMAL_CALL_CLEARING;
2100 tcore_at_tok_free(tokens);
2103 call_status.type = tcore_call_object_get_type(co);
2104 dbg("data.type : [%d]", call_status.type);
2106 call_status.id = tcore_call_object_get_id(co);
2107 dbg("data.id : [%d]", call_status.id);
2110 tcore_call_object_set_status(co, TCORE_CALL_STATUS_IDLE);
2112 // Send Notification to TAPI
2113 tcore_server_send_notification(tcore_plugin_ref_server(plugin),
2115 TNOTI_CALL_STATUS_IDLE,
2116 sizeof(struct tnoti_call_status_idle),
2117 (void *) &call_status);
2120 tcore_call_object_free(core_obj, co);
2123 static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call)
2125 // +CLCC: 1,0,2,0,0,"18005551212",145
2126 // [+CLCC: <id1>, <dir>, <stat>, <mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>]]]
2131 unsigned int num_type;
2132 GSList *tokens = NULL;
2137 tokens = tcore_at_tok_new(line);
2139 resp = g_slist_nth_data(tokens, 0);
2144 p_call->info.id = atoi(resp);
2145 dbg("id : [%d]\n", p_call->info.id);
2148 resp = g_slist_nth_data(tokens, 1);
2155 p_call->info.direction = TCORE_CALL_DIRECTION_OUTGOING;
2157 p_call->info.direction = TCORE_CALL_DIRECTION_INCOMING;
2159 dbg("Direction : [ %d ]\n", p_call->info.direction);
2162 resp = g_slist_nth_data(tokens, 2);
2164 err("InValid Stat");
2168 dbg("Call state : %d", state);
2171 p_call->info.status = TCORE_CALL_STATUS_ACTIVE;
2175 p_call->info.status = TCORE_CALL_STATUS_HELD;
2179 p_call->info.status = TCORE_CALL_STATUS_DIALING;
2183 p_call->info.status = TCORE_CALL_STATUS_ALERT;
2187 p_call->info.status = TCORE_CALL_STATUS_INCOMING;
2191 p_call->info.status = TCORE_CALL_STATUS_WAITING;
2194 dbg("Status : [%d]\n", p_call->info.status);
2197 resp = g_slist_nth_data(tokens, 3);
2199 err("InValid Mode");
2205 p_call->info.type = TCORE_CALL_TYPE_VOICE;
2209 p_call->info.type = TCORE_CALL_TYPE_VIDEO;
2212 default: // only Voice/VT call is supported in CS. treat other unknown calls as error
2213 dbg("invalid type : [%d]\n", mode);
2216 dbg("Call type : [%d]\n", p_call->info.type);
2219 resp = g_slist_nth_data(tokens, 4);
2221 err("InValid Mpty");
2225 p_call->info.mpty = atoi(resp);
2226 dbg("Mpty : [ %d ]\n", p_call->info.mpty);
2229 resp = g_slist_nth_data(tokens, 5);
2230 dbg("Incoming number - %s and its len - %d", resp, strlen(resp));
2232 // tolerate null here
2234 err("Number is NULL");
2237 // Strike off double quotes
2238 num = util_removeQuotes(resp);
2239 dbg("num after removing quotes - %s", num);
2241 p_call->info.num_len = strlen(resp);
2242 dbg("num_len : [0x%x]\n", p_call->info.num_len);
2245 resp = g_slist_nth_data(tokens, 6);
2247 dbg("InValid Num type");
2250 p_call->info.num_type = atoi(resp);
2251 dbg("BCD num type: [0x%x]\n", p_call->info.num_type);
2253 // check number is international or national.
2254 num_type = ((p_call->info.num_type) >> 4) & 0x07;
2255 dbg("called party's type of number : [0x%x]\n", num_type);
2257 if (num_type == 1 && num[0] != '+') {
2258 // international number
2259 p_call->number[0] = '+';
2260 memcpy(&(p_call->number[1]), num, strlen(num));
2262 memcpy(&(p_call->number), num, strlen(num));
2264 dbg("incoming number - %s", p_call->number);
2269 tcore_at_tok_free(tokens);
2275 err("Invalid CLCC line");
2280 tcore_at_tok_free(tokens);
2286 static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data)
2288 GSList *tokens = NULL;
2289 const char *line = NULL;
2293 GSList *pList = NULL;
2294 CallObject *co = NULL, *dupco = NULL;
2296 dbg("function entrance");
2297 // check call with waiting status already exist
2298 pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_WAITING);
2300 if (pList != NULL) {
2301 dbg("[error]Waiting call already exist. skip");
2304 // check call with incoming status already exist
2305 pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
2307 if (pList != NULL) {
2308 dbg("[error]incoming call already exist. skip");
2311 line = (char *) data;
2312 tokens = tcore_at_tok_new(line);
2314 pId = g_slist_nth_data(tokens, 0);
2316 dbg("[error]:Call id is missing from +XCALLSTAT indication");
2317 tcore_at_tok_free(tokens);
2321 call_id = atoi(pId);
2322 dupco = tcore_call_object_find_by_id(o, call_id);
2323 if (dupco != NULL) {
2324 dbg("co with same id already exist. skip");
2325 tcore_at_tok_free(tokens);
2328 co = tcore_call_object_new(o, call_id);
2330 dbg("[ error ] co is NULL");
2331 tcore_at_tok_free(tokens);
2335 tcore_at_tok_free(tokens);
2337 eflag = g_new0(gboolean, 1);
2339 dbg("calling _call_list_get");
2340 _call_list_get(o, eflag);
2343 static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data)
2345 GSList *tokens = NULL;
2346 const char *line = NULL;
2350 GSList *pList = NULL;
2351 CallObject *co = NULL, *dupco = NULL;
2353 dbg("function entrance");
2354 // check call with incoming status already exist
2355 pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
2357 if (pList != NULL) {
2358 dbg("incoming call already exist. skip");
2362 line = (char *) data;
2363 tokens = tcore_at_tok_new(line);
2365 pId = g_slist_nth_data(tokens, 0);
2367 dbg("Error:Call id is missing from %XCALLSTAT indication");
2368 tcore_at_tok_free(tokens);
2372 call_id = atoi(pId);
2374 dupco = tcore_call_object_find_by_id(o, call_id);
2375 if (dupco != NULL) {
2376 dbg("co with same id already exist. skip");
2377 tcore_at_tok_free(tokens);
2381 co = tcore_call_object_new(o, call_id);
2383 dbg("[ error ] co is NULL");
2384 tcore_at_tok_free(tokens);
2388 dbg("freeing at token");
2389 tcore_at_tok_free(tokens);
2391 eflag = g_new0(gboolean, 1);
2394 dbg("calling _call_list_get");
2395 _call_list_get(o, eflag);
2398 static void on_notification_call_status(CoreObject *o, const void *data, void *user_data)
2401 TcorePlugin *plugin = NULL;
2402 CallObject *co = NULL;
2407 char *pCallId = NULL;
2408 GSList *tokens = NULL;
2409 gboolean *eflag = NULL;
2410 enum tcore_call_status co_status;
2412 dbg("function entrance");
2413 plugin = tcore_object_ref_plugin(o);
2414 cmd = (char *) data;
2415 tokens = tcore_at_tok_new(cmd);
2418 pCallId = g_slist_nth_data(tokens, 0);
2420 dbg("CallId is missing from %XCALLSTAT indication");
2421 tcore_at_tok_free(tokens);
2425 dbg("call id = %d", id);
2427 if ((stat = g_slist_nth_data(tokens, 1))) {
2428 status = atoi(stat);
2430 dbg("call status = %d", status);
2433 tcore_at_tok_free(tokens);
2434 co_status = _call_status(status);
2436 dbg("co_status = %d", co_status);
2437 switch (co_status) {
2438 case CALL_STATUS_ACTIVE:
2440 dbg("call(%d) status : [ ACTIVE ]", id);
2441 co = tcore_call_object_find_by_id(o, id);
2446 _call_status_active(plugin, co);
2450 case CALL_STATUS_HELD:
2451 dbg("call(%d) status : [ held ]", id);
2454 case CALL_STATUS_DIALING:
2456 dbg("call(%d) status : [ dialing ]", id);
2457 co = tcore_call_object_find_by_id(o, id);
2459 co = tcore_call_object_new(o, id);
2461 dbg("error : tcore_call_object_new [ id : %d ]", id);
2466 tcore_call_object_set_type(co, call_type(type));
2467 tcore_call_object_set_direction(co, TCORE_CALL_DIRECTION_OUTGOING);
2468 _call_status_dialing(plugin, co);
2472 case CALL_STATUS_ALERT:
2474 dbg("call(%d) status : [ alert ]", id);
2475 co = tcore_call_object_find_by_id(o, id);
2480 // Store dialed number information into Call object.
2481 eflag = g_new0(gboolean, 1);
2483 dbg("calling _call_list_get");
2484 _call_list_get(o, eflag);
2488 case CALL_STATUS_INCOMING:
2489 case CALL_STATUS_WAITING:
2490 dbg("call(%d) status : [ incoming ]", id);
2493 case CALL_STATUS_IDLE:
2495 dbg("call(%d) status : [ release ]", id);
2497 co = tcore_call_object_find_by_id(o, id);
2503 plugin = tcore_object_ref_plugin(o);
2505 dbg("plugin is NULL");
2508 _call_status_idle(plugin, co);
2513 dbg("invalid call status", id);
2518 static TReturn imc_call_outgoing(CoreObject *o, UserRequest *ur)
2520 struct treq_call_dial *data = 0;
2522 const char *clir, *num;
2523 TcorePending *pending;
2524 TcoreATRequest *req;
2529 data = (struct treq_call_dial *) tcore_user_request_ref_data(ur, 0);
2530 if (data->type == CALL_TYPE_VIDEO) {
2531 dbg("invalid call type");
2532 return TCORE_RETURN_FAILURE;
2535 if (!strncmp(data->number, "*31#", 4)) {
2536 dbg("clir suppression");
2538 num = data->number + 4;
2539 } else if (!strncmp(data->number, "#31#", 4)) {
2540 dbg("clir invocation");
2542 num = data->number + 4;
2546 dbg("no clir string in number");
2548 vconf_get_int("db/ciss/show_my_number", &cli);
2551 dbg("clir invocation from setting application");
2554 dbg("set clir state to default");
2560 dbg("data->number = %s", num);
2562 cmd_str = g_strdup_printf("ATD%s%s;", num, clir);
2564 dbg("request command : %s", cmd_str);
2566 pending = tcore_pending_new(o, 0);
2567 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2568 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2570 tcore_pending_set_request_data(pending, 0, req);
2571 ret = _call_request_message(pending, o, ur, on_confirmation_call_outgoing, NULL);
2576 dbg("AT request(%s) sent failed", req->cmd);
2577 return TCORE_RETURN_FAILURE;
2580 dbg("AT request(%s) sent success", req->cmd);
2584 return TCORE_RETURN_SUCCESS;
2587 static TReturn imc_call_answer(CoreObject *o, UserRequest *ur)
2589 char *cmd_str = NULL;
2590 CallObject *co = NULL;
2591 struct treq_call_answer *data = 0;
2592 TcorePending *pending = NULL;
2593 TcoreATRequest *req;
2594 gboolean ret = FALSE;
2596 dbg("function entrance");
2598 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2599 dbg("cp not ready/n");
2600 return TCORE_RETURN_ENOSYS;
2603 data = (struct treq_call_answer *) tcore_user_request_ref_data(ur, 0);
2604 co = tcore_call_object_find_by_id(o, data->id);
2605 if (data->type == CALL_ANSWER_TYPE_ACCEPT) {
2606 dbg(" request type CALL_ANSWER_TYPE_ACCEPT");
2608 cmd_str = g_strdup_printf("%s", "ATA");
2609 pending = tcore_pending_new(o, 0);
2610 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2611 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2613 tcore_pending_set_request_data(pending, 0, req);
2614 ret = _call_request_message(pending, o, ur, on_confirmation_call_accept, co);
2618 dbg("AT request(%s) sent failed", req->cmd);
2619 return TCORE_RETURN_FAILURE;
2622 switch (data->type) {
2623 case CALL_ANSWER_TYPE_REJECT:
2625 dbg("call answer reject");
2626 tcore_call_control_answer_reject(o, ur, on_confirmation_call_reject, co);
2630 case CALL_ANSWER_TYPE_REPLACE:
2632 dbg("call answer replace");
2633 tcore_call_control_answer_replace(o, ur, on_confirmation_call_replace, co);
2637 case CALL_ANSWER_TYPE_HOLD_ACCEPT:
2639 dbg("call answer hold and accept");
2640 tcore_call_control_answer_hold_and_accept(o, ur, on_confirmation_call_hold_and_accept, co);
2645 dbg("[ error ] wrong answer type [ %d ]", data->type);
2646 return TCORE_RETURN_FAILURE;
2650 return TCORE_RETURN_SUCCESS;
2653 static TReturn imc_call_release(CoreObject *o, UserRequest *ur)
2655 CallObject *co = NULL;
2656 struct treq_call_end *data = 0;
2657 UserRequest *ur_dup = NULL;
2658 char *chld0_cmd = NULL;
2659 char *chld1_cmd = NULL;
2660 TcorePending *pending = NULL, *pending1 = NULL;
2661 TcoreATRequest *req, *req1;
2662 gboolean ret = FALSE;
2664 dbg("function entrance");
2665 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2666 dbg("cp not ready/n");
2667 return TCORE_RETURN_ENOSYS;
2669 data = (struct treq_call_end *) tcore_user_request_ref_data(ur, 0);
2670 co = tcore_call_object_find_by_id(o, data->id);
2672 dbg("type of release call = %d", data->type);
2674 if (data->type == CALL_END_TYPE_ALL) {
2675 // releaseAll do not exist on legacy request. send CHLD=0, CHLD=1 in sequence
2676 chld0_cmd = g_strdup("AT+CHLD=0");
2677 chld1_cmd = g_strdup("AT+CHLD=1");
2679 pending = tcore_pending_new(o, 0);
2680 req = tcore_at_request_new(chld0_cmd, NULL, TCORE_AT_NO_RESULT);
2682 dbg("input command is %s", chld0_cmd);
2683 dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2685 tcore_pending_set_request_data(pending, 0, req);
2686 ur_dup = tcore_user_request_new(NULL, NULL);
2687 ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_endall, NULL);
2691 dbg("AT request %s has failed ", req->cmd);
2693 tcore_user_request_free(ur_dup);
2697 return TCORE_RETURN_FAILURE;
2700 pending1 = tcore_pending_new(o, 0);
2701 req1 = tcore_at_request_new(chld1_cmd, NULL, TCORE_AT_NO_RESULT);
2703 dbg("input command is %s", chld1_cmd);
2704 dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd));
2706 tcore_pending_set_request_data(pending1, 0, req1);
2707 ret = _call_request_message(pending1, o, ur, on_confirmation_call_release_all, co);
2711 dbg("AT request %s has failed ", req->cmd);
2712 return TCORE_RETURN_FAILURE;
2715 switch (data->type) {
2716 case CALL_END_TYPE_DEFAULT:
2719 id = tcore_call_object_get_id(co);
2721 dbg("call end call id [%d]", id);
2722 tcore_call_control_end_specific(o, ur, id, on_confirmation_call_release_specific, co);
2726 case CALL_END_TYPE_ACTIVE_ALL:
2728 dbg("call end all active");
2729 tcore_call_control_end_all_active(o, ur, on_confirmation_call_release_all_active, co);
2733 case CALL_END_TYPE_HOLD_ALL:
2735 dbg("call end all held");
2736 tcore_call_control_end_all_held(o, ur, on_confirmation_call_release_all_held, co);
2741 dbg("[ error ] wrong end type [ %d ]", data->type);
2742 return TCORE_RETURN_FAILURE;
2746 return TCORE_RETURN_SUCCESS;
2749 static TReturn imc_call_hold(CoreObject *o, UserRequest *ur)
2751 struct treq_call_hold *hold = 0;
2752 CallObject *co = NULL;
2754 dbg("function entrance");
2756 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2757 dbg("cp not ready/n");
2758 return TCORE_RETURN_ENOSYS;
2761 hold = (struct treq_call_hold *) tcore_user_request_ref_data(ur, 0);
2762 dbg("call id : [ %d ]", hold->id);
2764 co = tcore_call_object_find_by_id(o, hold->id);
2765 tcore_call_control_hold(o, ur, on_confirmation_call_hold, co);
2767 return TCORE_RETURN_SUCCESS;
2770 static TReturn imc_call_active(CoreObject *o, UserRequest *ur)
2772 struct treq_call_active *active = 0;
2773 CallObject *co = NULL;
2775 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2776 dbg("cp not ready/n");
2777 return TCORE_RETURN_ENOSYS;
2780 active = (struct treq_call_active *) tcore_user_request_ref_data(ur, 0);
2781 dbg("call id : [ %d ]", active->id);
2783 co = tcore_call_object_find_by_id(o, active->id);
2784 tcore_call_control_active(o, ur, on_confirmation_call_active, co);
2786 return TCORE_RETURN_SUCCESS;
2789 static TReturn imc_call_swap(CoreObject *o, UserRequest *ur)
2791 struct treq_call_swap *swap = NULL;
2792 CallObject *co = NULL;
2794 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2795 dbg("cp not ready/n");
2796 return TCORE_RETURN_ENOSYS;
2799 swap = (struct treq_call_swap *) tcore_user_request_ref_data(ur, 0);
2800 dbg("call id : [ %d ]", swap->id);
2802 co = tcore_call_object_find_by_id(o, swap->id);
2803 tcore_call_control_swap(o, ur, on_confirmation_call_swap, co);
2805 return TCORE_RETURN_SUCCESS;
2808 static TReturn imc_call_join(CoreObject *o, UserRequest *ur)
2810 struct treq_call_join *join = 0;
2811 CallObject *co = NULL;
2813 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2814 dbg("cp not ready/n");
2815 return TCORE_RETURN_ENOSYS;
2818 join = (struct treq_call_join *) tcore_user_request_ref_data(ur, 0);
2819 dbg("call id : [ %d ]", join->id);
2821 co = tcore_call_object_find_by_id(o, join->id);
2822 tcore_call_control_join(o, ur, on_confirmation_call_join, co);
2824 return TCORE_RETURN_SUCCESS;
2827 static TReturn imc_call_split(CoreObject *o, UserRequest *ur)
2829 struct treq_call_split *split = 0;
2830 CallObject *co = NULL;
2832 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2833 dbg("cp not ready/n");
2834 return TCORE_RETURN_ENOSYS;
2837 split = (struct treq_call_split *) tcore_user_request_ref_data(ur, 0);
2838 co = tcore_call_object_find_by_id(o, split->id);
2839 dbg("call id : [ %d ]", split->id);
2841 tcore_call_control_split(o, ur, split->id, on_confirmation_call_split, co);
2843 return TCORE_RETURN_SUCCESS;
2846 static TReturn imc_call_deflect(CoreObject *o, UserRequest *ur)
2848 struct treq_call_deflect *deflect = 0;
2849 CallObject *co = NULL;
2851 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2852 dbg("cp not ready/n");
2853 return TCORE_RETURN_ENOSYS;
2856 deflect = (struct treq_call_deflect *) tcore_user_request_ref_data(ur, 0);
2857 co = tcore_call_object_find_by_number(o, deflect->number);
2858 dbg("deflect number: [ %s ]", deflect->number);
2860 tcore_call_control_deflect(o, ur, deflect->number, on_confirmation_call_deflect, co);
2862 return TCORE_RETURN_SUCCESS;
2865 static TReturn imc_call_transfer(CoreObject *o, UserRequest *ur)
2867 struct treq_call_transfer *transfer = 0;
2868 CallObject *co = NULL;
2870 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2871 dbg("cp not ready/n");
2872 return TCORE_RETURN_ENOSYS;
2875 transfer = (struct treq_call_transfer *) tcore_user_request_ref_data(ur, 0);
2876 dbg("call id : [ %d ]", transfer->id);
2878 co = tcore_call_object_find_by_id(o, transfer->id);
2879 tcore_call_control_transfer(o, ur, on_confirmation_call_transfer, co);
2881 return TCORE_RETURN_SUCCESS;
2884 static TReturn imc_call_start_cont_dtmf(CoreObject *o, UserRequest *ur)
2886 char *cmd_str = NULL;
2887 gboolean ret = FALSE;
2888 TcoreATRequest *req;
2889 struct treq_call_start_cont_dtmf *dtmf = 0;
2890 char *dtmfstr = NULL, *tmp_dtmf = NULL;
2891 TcorePending *pending = NULL;
2892 //unsigned int dtmf_count;
2894 dbg("Function enter");
2896 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2897 dbg("cp not ready/n");
2898 return TCORE_RETURN_ENOSYS;
2901 dtmf = (struct treq_call_start_cont_dtmf *) tcore_user_request_ref_data(ur, 0);
2902 dtmfstr = g_malloc0((MAX_CALL_DTMF_DIGITS_LEN * 2) + 1); // DTMF digits + comma for each dtmf digit.
2904 if (dtmfstr == NULL) {
2905 dbg("Memory allocation failed");
2906 return TCORE_RETURN_FAILURE;
2912 *tmp_dtmf = dtmf->dtmf_digit;
2914 for (dtmf_count = 0; dtmf_count < (unsigned int)strlen((const char *)dtmf->dtmf_digit); dtmf_count++) {
2915 *tmp_dtmf = dtmf->dtmf_digit;
2922 // last digit is having COMMA , overwrite it with '\0' .
2923 *(--tmp_dtmf) = '\0';
2925 dbg("Input DTMF string(%s)", dtmfstr);
2927 // AT+VTS = <d1>,<d2>,<d3>,<d4>,<d5>,<d6>, ..... <d32>
2928 cmd_str = g_strdup_printf("AT+VTS=%s", dtmfstr);
2929 dbg("request command : %s", cmd_str);
2931 pending = tcore_pending_new(o, 0);
2932 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2933 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2935 tcore_pending_set_request_data(pending, 0, req);
2936 ret = _call_request_message(pending, o, ur, on_confirmation_call_dtmf, NULL);
2941 dbg("AT request sent failed");
2942 return TCORE_RETURN_FAILURE;
2945 return TCORE_RETURN_SUCCESS;
2948 static TReturn imc_call_set_sound_path(CoreObject *o, UserRequest *ur)
2950 UserRequest *ur_dup = NULL;
2951 TcorePending *pending = NULL, *pending1 = NULL;
2952 TcoreATRequest *req, *req1;
2953 char *cmd_str = NULL, *cmd_str1 = NULL;
2954 int device_type = -1;
2955 struct treq_call_set_sound_path *sound_path = 0;
2956 gboolean ret = FALSE;
2957 TcorePlugin *plugin = tcore_object_ref_plugin(o);
2958 const char *cp_name = tcore_server_get_cp_name_by_plugin(plugin);
2960 dbg("function entrance");
2962 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2963 dbg("cp not ready/n");
2964 return TCORE_RETURN_ENOSYS;
2966 sound_path = (struct treq_call_set_sound_path *) tcore_user_request_ref_data(ur, 0);
2967 if (sound_path == NULL) {
2968 dbg("invaling user request");
2969 return TCORE_RETURN_FAILURE;
2971 dbg("audio device type - 0x%x", sound_path->path);
2972 switch (sound_path->path) {
2973 case CALL_SOUND_PATH_HANDSET:
2977 case CALL_SOUND_PATH_HEADSET:
2981 case CALL_SOUND_PATH_HEADSET_3_5PI:
2985 case CALL_SOUND_PATH_SPEAKER:
2989 case CALL_SOUND_PATH_HANDFREE:
2993 case CALL_SOUND_PATH_HEADSET_HAC:
2997 case CALL_SOUND_PATH_BLUETOOTH:
2998 case CALL_SOUND_PATH_STEREO_BLUETOOTH:
3002 case CALL_SOUND_PATH_BT_NSEC_OFF:
3003 case CALL_SOUND_PATH_MIC1:
3004 case CALL_SOUND_PATH_MIC2:
3006 dbg("unsupported device type");
3007 return TCORE_RETURN_FAILURE;
3010 if (g_str_has_prefix(cp_name, "mfld_blackbay") == TRUE) {
3011 struct tnoti_call_sound_path *tnoti_snd_path;
3013 tnoti_snd_path = g_try_new0(struct tnoti_call_sound_path, 1);
3014 if (!tnoti_snd_path)
3015 return TCORE_RETURN_ENOMEM;
3017 tnoti_snd_path->path = sound_path->path;
3019 /* Configure modem I2S1 to 8khz, mono, PCM if routing to bluetooth */
3020 if (sound_path->path == CALL_SOUND_PATH_BLUETOOTH || sound_path->path == CALL_SOUND_PATH_STEREO_BLUETOOTH) {
3021 call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,3,0,1,0,0,0,0,0,0,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3022 call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,2,0,1,0,0,0,0,0,0,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3025 call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,3,0,1,0,8,0,1,0,2,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3026 call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,2,0,1,0,8,0,1,0,2,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3029 /* Configure modem I2S2 and do the modem routing */
3030 call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,4,0,0,0,8,0,1,0,2,0,21", NULL, TCORE_AT_NO_RESULT, NULL);
3031 call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,3,0,0,0,8,0,1,0,2,0,22", NULL, TCORE_AT_NO_RESULT, NULL);
3032 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,0,4", NULL, TCORE_AT_NO_RESULT, NULL);
3033 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,3,0", NULL, TCORE_AT_NO_RESULT, NULL);
3034 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,4,2", NULL, TCORE_AT_NO_RESULT, NULL);
3035 call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,5,2", NULL, TCORE_AT_NO_RESULT, NULL);
3038 call_prepare_and_send_pending_request(o, "AT+XDRV=40,2,4", NULL, TCORE_AT_NO_RESULT, NULL); //AMC_I2S2_RX
3039 call_prepare_and_send_pending_request(o, "AT+XDRV=40,2,3", NULL, TCORE_AT_NO_RESULT, NULL); //AMC_I2S1_RX
3040 /* amc route: AMC_RADIO_RX => AMC_I2S1_TX */
3042 pending = tcore_pending_new(o, 0);
3043 req = tcore_at_request_new("AT+XDRV=40,6,0,2", "+XDRV", TCORE_AT_SINGLELINE);
3044 dbg("XDRV req-cmd for source type : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3045 tcore_pending_set_request_data(pending, 0, req);
3046 ur_dup = tcore_user_request_ref(ur);
3047 ret = _call_request_message(pending, o, ur_dup, on_confirmation_set_sound_path, tnoti_snd_path);
3051 cmd_str = g_strdup_printf("AT+XDRV=40,4,3,0,0,0,0,0,1,0,1,0,%d",device_type); // source type.
3052 pending = tcore_pending_new(o, 0);
3053 req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3054 dbg("XDRV req-cmd for source type : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3055 tcore_pending_set_request_data(pending, 0, req);
3056 ur_dup = tcore_user_request_ref(ur);
3057 ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_set_source_sound_path, NULL);
3061 dbg("At request(%s) sent failed", req->cmd);
3062 return TCORE_RETURN_FAILURE;
3065 cmd_str1 = g_strdup_printf("AT+XDRV=40,5,2,0,0,0,0,0,1,0,1,0,%d",device_type); // destination type
3066 pending1 = tcore_pending_new(o, 0);
3067 req1 = tcore_at_request_new(cmd_str1, "+XDRV", TCORE_AT_SINGLELINE);
3068 dbg("XDRV req-cmd for destination type : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd));
3069 tcore_pending_set_request_data(pending1, 0, req1);
3070 ret = _call_request_message(pending1, o, ur, on_confirmation_call_set_destination_sound_path, NULL);
3074 dbg("AT request %s has failed ", req1->cmd);
3075 return TCORE_RETURN_FAILURE;
3079 return TCORE_RETURN_SUCCESS;
3082 static TReturn imc_call_set_sound_volume_level(CoreObject *o, UserRequest *ur)
3084 UserRequest *src_ur = NULL;
3085 UserRequest *dest_ur = NULL;
3086 TcorePending *src_pending = NULL;
3087 TcorePending *dest_pending = NULL;
3088 TcoreATRequest *src_req = NULL;
3089 TcoreATRequest *dest_req = NULL;
3090 char *cmd_str = NULL, *volume_level = NULL;
3091 gboolean ret = FALSE;
3092 struct treq_call_set_sound_volume_level *data = NULL;
3096 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3097 dbg("cp not ready/n");
3098 return TCORE_RETURN_ENOSYS;
3101 data = (struct treq_call_set_sound_volume_level *) tcore_user_request_ref_data(ur, 0);
3103 // Hard-coded values for MIC & Speakers
3105 dbg("Set Source volume");
3107 cmd_str = g_strdup_printf("%s", "AT+XDRV=40,7,3,88"); // Source type
3108 dbg("Request command string: %s", cmd_str);
3110 // Create new Pending request
3111 src_pending = tcore_pending_new(o, 0);
3113 // Create new AT-Command request
3114 src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3115 dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd));
3117 // Free Command string
3120 tcore_pending_set_request_data(src_pending, 0, src_req);
3121 src_ur = tcore_user_request_ref(ur);
3124 ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3126 err("Failed to send AT-Command request");
3127 return TCORE_RETURN_FAILURE;
3130 cmd_str = g_strdup_printf("%s", "AT+XDRV=40,7,0,88"); // Destination type
3131 dbg("Request command string: %s", cmd_str);
3133 // Create new Pending request
3134 src_pending = tcore_pending_new(o, 0);
3136 // Create new AT-Command request
3137 src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3138 dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd));
3140 // Free Command string
3143 tcore_pending_set_request_data(src_pending, 0, src_req);
3145 src_ur = tcore_user_request_ref(ur);
3148 ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3150 err("Failed to send AT-Command request");
3151 return TCORE_RETURN_FAILURE;
3154 // Destination volume
3155 dbg("Set Source volume");
3157 cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,88"); // Source type
3158 dbg("Request command string: %s", cmd_str);
3160 // Create new Pending request
3161 dest_pending = tcore_pending_new(o, 0);
3163 // Create new AT-Command request
3164 dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3165 dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd));
3167 // Free Command string
3170 tcore_pending_set_request_data(dest_pending, 0, dest_req);
3171 dest_ur = tcore_user_request_ref(ur);
3174 ret = _call_request_message(dest_pending, o, dest_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3176 err("Failed to send AT-Command request");
3177 return TCORE_RETURN_FAILURE;
3180 dbg("Input volume level - %d", data->volume);
3181 switch (data->volume) {
3182 case CALL_SOUND_MUTE:
3186 case CALL_SOUND_VOLUME_LEVEL_1:
3187 volume_level = "40";
3190 case CALL_SOUND_VOLUME_LEVEL_2:
3191 volume_level = "46";
3194 case CALL_SOUND_VOLUME_LEVEL_3:
3195 volume_level = "52";
3198 case CALL_SOUND_VOLUME_LEVEL_4:
3199 volume_level = "58";
3202 case CALL_SOUND_VOLUME_LEVEL_5:
3203 volume_level = "64";
3206 case CALL_SOUND_VOLUME_LEVEL_6:
3207 volume_level = "70";
3210 case CALL_SOUND_VOLUME_LEVEL_7:
3211 volume_level = "76";
3214 case CALL_SOUND_VOLUME_LEVEL_8:
3215 volume_level = "82";
3218 case CALL_SOUND_VOLUME_LEVEL_9:
3220 volume_level = "88";
3223 cmd_str = g_strdup_printf("%s%s", "AT+XDRV=40,8,2,", volume_level); // Destination type
3224 dbg("Request command string: %s", cmd_str);
3226 // Create new Pending request
3227 dest_pending = tcore_pending_new(o, 0);
3229 // Create new AT-Command request
3230 dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3231 dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd));
3233 // Free Command string
3236 tcore_pending_set_request_data(dest_pending, 0, dest_req);
3239 ret = _call_request_message(dest_pending, o, ur, on_confirmation_call_set_destination_sound_volume_level, NULL);
3241 err("Failed to send AT-Command request");
3242 return TCORE_RETURN_FAILURE;
3245 return TCORE_RETURN_SUCCESS;
3248 static TReturn imc_call_set_sound_mute_status(CoreObject *o, UserRequest *ur)
3250 struct treq_call_set_sound_mute_status *data = NULL;
3251 char *cmd_str = NULL;
3253 TcorePending *pending = NULL;
3254 TcoreATRequest *req = NULL;
3256 dbg("function entrance");
3258 data = (struct treq_call_set_sound_mute_status *) tcore_user_request_ref_data(ur, 0);
3260 if (data->status == CALL_SOUND_MUTE_STATUS_ON)
3261 cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,0");
3262 else if (data->status == CALL_SOUND_MUTE_STATUS_OFF)
3263 cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,88");
3265 dbg("Request command : [%s]", cmd_str);
3267 pending = tcore_pending_new(o, 0);
3269 req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3270 dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3274 // Set request data (AT command) to Pending request
3275 tcore_pending_set_request_data(pending, 0, req);
3278 ret = _call_request_message(pending, o, ur, on_confirmation_call_set_sound_mute_status, NULL);
3280 err("Failed to send AT-Command request");
3281 return TCORE_RETURN_FAILURE;
3285 return TCORE_RETURN_SUCCESS;
3288 static TReturn imc_call_set_preferred_voice_subscription(CoreObject *o, UserRequest *ur)
3290 struct treq_call_set_preferred_voice_subscription *req_data = NULL;
3292 Storage *strg = NULL;
3293 TReturn ret = TCORE_RETURN_FAILURE;
3297 server = tcore_plugin_ref_server(tcore_object_ref_plugin(o));
3298 strg = tcore_server_find_storage(server, "vconf");
3300 req_data = (struct treq_call_set_preferred_voice_subscription *) tcore_user_request_ref_data(ur, NULL);
3301 dbg("Preferred Subscription: [%d]", req_data->preferred_subs);
3303 /* Update VCONF through Storage - req_data->preferred_subs is aligned to VCONFKEY values */
3304 if (tcore_storage_set_int(strg, STORAGE_KEY_TELEPHONY_PREFERRED_VOICE_SUBSCRIPTION, req_data->preferred_subs)) {
3305 struct tresp_call_set_preferred_voice_subscription resp_data = {0, };
3308 resp_data.err = CALL_ERROR_NONE;
3309 ret = tcore_user_request_send_response(ur,
3310 TRESP_CALL_SET_PREFERRED_VOICE_SUBSCRIPTION,
3311 sizeof(struct tresp_call_set_preferred_voice_subscription), &resp_data);
3314 dbg("ret: [0x%x]", ret);
3318 static TReturn imc_call_get_preferred_voice_subscription(CoreObject *o, UserRequest *ur)
3320 struct tresp_call_get_preferred_voice_subscription resp_data = {0, };
3321 TReturn ret = TCORE_RETURN_FAILURE;
3323 Storage *strg = NULL;
3327 server = tcore_plugin_ref_server(tcore_object_ref_plugin(o));
3328 strg = tcore_server_find_storage(server, "vconf");
3330 /* VCONFKEY is aligned to resp_data->preferred_subs type */
3331 resp_data.preferred_subs = tcore_storage_get_int(strg, STORAGE_KEY_TELEPHONY_PREFERRED_VOICE_SUBSCRIPTION);
3332 dbg("Preferred Subscription: [%d]", resp_data.preferred_subs);
3334 resp_data.err = CALL_ERROR_NONE;
3336 ret = tcore_user_request_send_response(ur,
3337 TRESP_CALL_GET_PREFERRED_VOICE_SUBSCRIPTION,
3338 sizeof(struct tresp_call_get_preferred_voice_subscription), &resp_data);
3340 dbg("ret: [0x%x]", ret);
3345 static TReturn _set_dtmf_tone_duration(CoreObject *o, UserRequest *ur)
3347 char *cmd_str = NULL;
3348 TcorePending *pending = NULL;
3349 TcoreATRequest *req = NULL;
3350 gboolean ret = FALSE;
3354 cmd_str = g_strdup_printf("%s", "AT+VTD=3"); // ~300 mili secs. +VTD= n, where n = (0 - 255) * 1/10 secs.
3355 dbg("Request command string: %s", cmd_str);
3357 // Create new Pending request
3358 pending = tcore_pending_new(o, 0);
3360 // Create new AT-Command request
3361 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
3362 dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3364 // Free command string */
3367 // Set request data (AT command) to Pending request
3368 tcore_pending_set_request_data(pending, 0, req);
3371 ret = _call_request_message(pending, o, ur, _on_confirmation_dtmf_tone_duration, NULL);
3373 err("Failed to send AT-Command request");
3375 tcore_user_request_free(ur);
3378 return TCORE_RETURN_FAILURE;
3382 return TCORE_RETURN_SUCCESS;
3387 static struct tcore_call_operations call_ops = {
3388 .dial = imc_call_outgoing,
3389 .answer = imc_call_answer,
3390 .end = imc_call_release,
3391 .hold = imc_call_hold,
3392 .active = imc_call_active,
3393 .swap = imc_call_swap,
3394 .join = imc_call_join,
3395 .split = imc_call_split,
3396 .deflect = imc_call_deflect,
3397 .transfer = imc_call_transfer,
3398 .start_cont_dtmf = imc_call_start_cont_dtmf,
3399 .stop_cont_dtmf = NULL,
3400 .set_sound_path = imc_call_set_sound_path,
3401 .set_sound_volume_level = imc_call_set_sound_volume_level,
3402 .get_sound_volume_level = NULL,
3403 .set_sound_mute_status = imc_call_set_sound_mute_status,
3404 .get_sound_mute_status = NULL,
3405 .set_sound_equalization = NULL,
3406 .set_sound_noise_reduction = NULL,
3407 .set_preferred_voice_subscription = imc_call_set_preferred_voice_subscription,
3408 .get_preferred_voice_subscription = imc_call_get_preferred_voice_subscription,
3411 gboolean imc_call_init(TcorePlugin *cp, CoreObject *co_call)
3415 /* Set operations */
3416 tcore_call_set_ops(co_call, &call_ops);
3419 tcore_object_add_callback(co_call, "+XCALLSTAT", on_notification_call_info, NULL);
3420 tcore_object_add_callback(co_call, "+CLIP", on_notification_call_clip_info, NULL);
3427 void imc_call_exit(TcorePlugin *cp, CoreObject *co_call)