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,
148 /* AS reject causes */
149 REJECT_CAUSE_AS_REJ_RR_REL_IND,
150 REJECT_CAUSE_AS_REJ_RR_RANDOM_ACCESS_FAILURE,
151 REJECT_CAUSE_AS_REJ_RRC_REL_IND,
152 REJECT_CAUSE_AS_REJ_RRC_CLOSE_SESSION_IND,
153 REJECT_CAUSE_AS_REJ_RRC_OPEN_SESSION_FAILURE,
154 REJECT_CAUSE_AS_REJ_LOW_LEVEL_FAIL,
155 REJECT_CAUSE_AS_REJ_LOW_LEVEL_FAIL_REDIAL_NOT_ALLOWED,
156 REJECT_CAUSE_AS_REJ_LOW_LEVEL_IMMED_RETRY,
158 /* MM reject causes */
159 REJECT_CAUSE_MM_REJ_INVALID_SIM,
160 REJECT_CAUSE_MM_REJ_NO_SERVICE,
161 REJECT_CAUSE_MM_REJ_TIMER_T3230_EXP,
162 REJECT_CAUSE_MM_REJ_NO_CELL_AVAILABLE,
163 REJECT_CAUSE_MM_REJ_WRONG_STATE,
164 REJECT_CAUSE_MM_REJ_ACCESS_CLASS_BLOCKED,
165 /* Definitions for release ind causes between MM and CNM */
166 REJECT_CAUSE_ABORT_MSG_RECEIVED,
167 REJECT_CAUSE_OTHER_CAUSE,
169 /* CNM reject causes */
170 REJECT_CAUSE_CNM_REJ_TIMER_T303_EXP,
171 REJECT_CAUSE_CNM_REJ_NO_RESOURCES,
172 REJECT_CAUSE_CNM_MM_REL_PENDING,
173 REJECT_CAUSE_CNM_INVALID_USER_DATA,
174 CALL_END_CAUSE_MAX = 255
175 } call_end_cause_e_type;
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 */
210 /************************* CONFIRMATION ***************************/
211 static void on_confirmation_call_message_send(TcorePending *p, gboolean result, void *user_data); /* from Kernel */
212 static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data);
213 static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data);
214 static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data);
215 static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data);
217 static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type);
218 static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type);
219 static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data);
221 /************************* RESPONSES ***************************/
222 static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data);
224 /************************* NOTIIFICATIONS ***************************/
225 static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data);
226 static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data);
227 static void on_notification_call_status(CoreObject *o, const void *data, void *user_data);
228 static gboolean on_notification_call_info(CoreObject *o, const void *data, void *user_data);
229 static gboolean on_notification_call_clip_info(CoreObject *o, const void *data, void *user_data);
232 /**************************************************************************
233 * Local Utility Function Prototypes
234 **************************************************************************/
235 static gboolean _call_request_message(TcorePending *pending, CoreObject *o, UserRequest *ur, void *on_resp, void *user_data);
236 static void _call_branch_by_status(TcorePlugin *p, CallObject *co, unsigned int status);
237 static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call);
239 /**************************************************************************
240 * Local Function Definitions
241 **************************************************************************/
243 const call_end_cause_info call_end_cause_table[] = /* call end cause table to convert Netwotk cause to TAPI cause */
245 { 1, CC_CAUSE_UNASSIGNED_NUMBER}, { 3, CC_CAUSE_NO_ROUTE_TO_DEST},
246 { 6, CC_CAUSE_CHANNEL_UNACCEPTABLE}, { 8, CC_CAUSE_OPERATOR_DETERMINED_BARRING},
247 { 16, CC_CAUSE_NORMAL_CALL_CLEARING}, { 17, CC_CAUSE_USER_BUSY},
248 { 18, CC_CAUSE_NO_USER_RESPONDING}, { 19, CC_CAUSE_USER_ALERTING_NO_ANSWER},
249 { 21, CC_CAUSE_CALL_REJECTED}, { 22, CC_CAUSE_NUMBER_CHANGED},
250 { 26, CC_CAUSE_NON_SELECTED_USER_CLEARING}, { 27, CC_CAUSE_DESTINATION_OUT_OF_ORDER},
251 { 28, CC_CAUSE_INVALID_NUMBER_FORMAT}, { 29, CC_CAUSE_FACILITY_REJECTED},
252 { 30, CC_CAUSE_RESPONSE_TO_STATUS_ENQUIRY}, { 31, CC_CAUSE_NORMAL_UNSPECIFIED},
253 { 34, CC_CAUSE_NO_CIRCUIT_CHANNEL_AVAILABLE}, { 38, CC_CAUSE_NETWORK_OUT_OF_ORDER},
254 { 41, CC_CAUSE_TEMPORARY_FAILURE}, { 42, CC_CAUSE_SWITCHING_EQUIPMENT_CONGESTION},
255 { 43, CC_CAUSE_ACCESS_INFORMATION_DISCARDED}, { 44, CC_CAUSE_REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE},
256 { 47, CC_CAUSE_RESOURCES_UNAVAILABLE_UNSPECIFIED}, { 49, CC_CAUSE_QUALITY_OF_SERVICE_UNAVAILABLE},
257 { 50, CC_CAUSE_REQUESTED_FACILITY_NOT_SUBSCRIBED}, { 55, CC_CAUSE_INCOMING_CALL_BARRED_WITHIN_CUG},
258 { 57, CC_CAUSE_BEARER_CAPABILITY_NOT_AUTHORISED}, { 58, CC_CAUSE_BEARER_CAPABILITY_NOT_PRESENTLY_AVAILABLE},
259 { 63, CC_CAUSE_SERVICE_OR_OPTION_NOT_AVAILABLE}, { 65, CC_CAUSE_BEARER_SERVICE_NOT_IMPLEMENTED},
260 { 68, CC_CAUSE_ACM_GEQ_ACMMAX}, { 69, CC_CAUSE_REQUESTED_FACILITY_NOT_IMPLEMENTED},
261 { 70, CC_CAUSE_ONLY_RESTRICTED_DIGITAL_INFO_BC_AVAILABLE}, { 79, CC_CAUSE_SERVICE_OR_OPTION_NOT_IMPLEMENTED},
262 { 81, CC_CAUSE_INVALID_TRANSACTION_ID_VALUE}, { 87, CC_CAUSE_USER_NOT_MEMBER_OF_CUG},
263 { 88, CC_CAUSE_INCOMPATIBLE_DESTINATION}, { 91, CC_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION},
264 { 95, CC_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE}, { 96, CC_CAUSE_INVALID_MANDATORY_INFORMATION},
265 { 97, CC_CAUSE_MESSAGE_TYPE_NON_EXISTENT}, { 98, CC_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROT_STATE},
266 { 99, CC_CAUSE_IE_NON_EXISTENT_OR_NOT_IMPLEMENTED}, { 100, CC_CAUSE_CONDITIONAL_IE_ERROR},
267 { 101, CC_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE}, { 102, CC_CAUSE_RECOVERY_ON_TIMER_EXPIRY},
268 { 111, CC_CAUSE_PROTOCOL_ERROR_UNSPECIFIED}, {127, CC_CAUSE_INTERWORKING_UNSPECIFIED},
271 static enum tcore_call_status _call_status(unsigned int status)
277 return TCORE_CALL_STATUS_ACTIVE;
280 return TCORE_CALL_STATUS_HELD;
283 return TCORE_CALL_STATUS_DIALING;
286 return TCORE_CALL_STATUS_ALERT;
289 return TCORE_CALL_STATUS_INCOMING;
292 return TCORE_CALL_STATUS_WAITING;
294 case 6: /* DISCONNECTED state - FALL THROUGH */
296 return TCORE_CALL_STATUS_IDLE;
300 static gboolean _call_is_in_mpty(int mpty)
318 static enum tcore_call_type call_type(int type)
324 return TCORE_CALL_TYPE_VOICE;
327 return TCORE_CALL_TYPE_VIDEO;
333 return TCORE_CALL_TYPE_VOICE;
336 static int _compare_call_end_cause(int networkcause)
340 for (count = 0; count < sizeof(call_end_cause_table) / sizeof(call_end_cause_info); count++) {
341 if (call_end_cause_table[count].network_cause == networkcause)
342 return (call_end_cause_table[count].tapi_cause);
344 return CC_CAUSE_NORMAL_CALL_CLEARING;
348 static gboolean on_notification_call_clip_info(CoreObject *o, const void *data, void *user_data)
357 static gboolean on_notification_call_info(CoreObject *o, const void *data, void *user_data)
359 GSList *tokens = NULL;
360 GSList *lines = NULL;
361 const char *line = NULL;
367 lines = (GSList *) data;
368 if (1 != g_slist_length(lines)) {
369 err("Unsolicited message, BUT multiple lines present");
373 line = (char *) (lines->data);
374 tokens = tcore_at_tok_new(line);
376 stat = g_slist_nth_data(tokens, 1);
378 dbg("Stat is missing from %XCALLSTAT indiaction");
383 case STATUS_INCOMING:
384 dbg("calling on_notification_call_incoming");
385 on_notification_call_incoming(o, line, user_data);
389 dbg("calling on_notification_call_waiting");
390 on_notification_call_waiting(o, line, user_data);
393 case STATUS_CONNECTED: /*igonre Connected state. */
394 dbg("Connected state");
398 dbg("calling on_notification_call_status");
399 on_notification_call_status(o, line, user_data);
405 tcore_at_tok_free(tokens);
412 static gboolean _call_request_message(TcorePending *pending,
418 TcoreHal *hal = NULL;
423 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
426 tcore_pending_set_response_callback(pending, on_resp, user_data);
428 tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL);
431 tcore_pending_link_user_request(pending, ur);
433 err("User Request is NULL, is this internal request??");
436 hal = tcore_object_get_hal(o);
437 /* Send request to HAL */
438 ret = tcore_hal_send_request(hal, pending);
439 if (TCORE_RETURN_SUCCESS != ret) {
440 err("Request send failed");
448 static void _call_status_idle(TcorePlugin *p, CallObject *co)
450 CoreObject *core_obj = NULL;
451 char *cmd_str = NULL;
452 TcorePending *pending = NULL;
453 TcoreATRequest *req = NULL;
454 gboolean ret = FALSE;
458 core_obj = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL);
459 dbg("Call Handle [%d], Call Status [%d]", tcore_call_object_get_handle(co), tcore_call_object_get_status(co));
461 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_IDLE) {
462 /* get call end cause. */
463 cmd_str = g_strdup_printf("%s", "AT+XCEER");
464 dbg("Request command string: %s", cmd_str);
466 /* Create new Pending request */
467 pending = tcore_pending_new(core_obj, 0);
469 /* Create new AT-Command request */
470 req = tcore_at_request_new(cmd_str, "+XCEER", TCORE_AT_SINGLELINE);
472 tcore_pending_free(pending);
477 dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
478 /* Free command string */
481 /* Set request data (AT command) to Pending request */
482 tcore_pending_set_request_data(pending, 0, req);
484 ur = tcore_user_request_new(NULL, NULL);
486 ret = _call_request_message(pending, core_obj, ur, _on_confirmation_call_end_cause, co);
489 err("Failed to send AT-Command request");
490 /* free only UserRequest. */
492 tcore_user_request_free(ur);
498 err("Call object was not free");
499 tcore_call_object_free(core_obj, co);
505 static void _call_status_dialing(TcorePlugin *p, CallObject *co)
507 struct tnoti_call_status_dialing data;
511 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_DIALING) {
512 data.type = tcore_call_object_get_type(co);
513 dbg("data.type : [%d]", data.type);
515 data.handle = tcore_call_object_get_handle(co);
516 dbg("data.handle = %d", data.handle);
519 tcore_call_object_set_status(co, TCORE_CALL_STATUS_DIALING);
521 /* Send notification to TAPI */
522 tcore_server_send_notification(tcore_plugin_ref_server(p),
523 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
524 TNOTI_CALL_STATUS_DIALING,
525 sizeof(struct tnoti_call_status_dialing),
533 static void _call_status_alert(TcorePlugin *p, CallObject *co)
535 struct tnoti_call_status_alert data;
539 /* Alerting has just 1 data 'CALL ID' */
540 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_ALERT) {
541 data.type = tcore_call_object_get_type(co);
542 dbg("data.type : [%d]", data.type);
544 data.handle = tcore_call_object_get_handle(co);
545 dbg("data.handle = %d", data.handle);
548 tcore_call_object_set_status(co, TCORE_CALL_STATUS_ALERT);
550 /* Send notification to TAPI */
551 tcore_server_send_notification(tcore_plugin_ref_server(p),
552 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
553 TNOTI_CALL_STATUS_ALERT,
554 sizeof(struct tnoti_call_status_alert),
562 static void _call_status_active(TcorePlugin *p, CallObject *co)
564 struct tnoti_call_status_active data;
568 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_ACTIVE) {
569 data.type = tcore_call_object_get_type(co);
570 dbg("data.type : [%d]", data.type);
572 data.handle = tcore_call_object_get_handle(co);
573 dbg("data.handle = %d", data.handle);
576 tcore_call_object_set_status(co, TCORE_CALL_STATUS_ACTIVE);
578 /* Send notification to TAPI */
579 tcore_server_send_notification(tcore_plugin_ref_server(p),
580 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
581 TNOTI_CALL_STATUS_ACTIVE,
582 sizeof(struct tnoti_call_status_active),
590 static void _call_status_held(TcorePlugin *p, CallObject *co)
592 struct tnoti_call_status_held data;
596 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_HELD) {
597 data.type = tcore_call_object_get_type(co);
598 dbg("data.type : [%d]", data.type);
600 data.handle = tcore_call_object_get_handle(co);
601 dbg("data.handle = %d", data.handle);
604 tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD);
606 /* Send notification to TAPI */
607 tcore_server_send_notification(tcore_plugin_ref_server(p),
608 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
609 TNOTI_CALL_STATUS_HELD,
610 sizeof(struct tnoti_call_status_held),
618 static void _call_status_incoming(TcorePlugin *p, CallObject *co)
620 struct tnoti_call_status_incoming data;
624 if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_INCOMING) {
625 tcore_call_object_set_status(co, TCORE_CALL_STATUS_INCOMING);
627 data.type = tcore_call_object_get_type(co);
628 dbg("data.type : [%d]", data.type);
630 data.handle = tcore_call_object_get_handle(co);
631 dbg("data.handle = %d", data.handle);
633 data.cli.mode = tcore_call_object_get_cli_mode(co);
634 dbg("data.cli.mode : [%d]", data.cli.mode);
636 tcore_call_object_get_number(co, data.cli.number);
637 dbg("data.cli.number : [%s]", data.cli.number);
639 data.cna.mode = tcore_call_object_get_cna_mode(co);
640 dbg("data.cna.mode : [%d]", data.cna.mode);
642 tcore_call_object_get_name(co, data.cna.name);
643 dbg("data.cna.name : [%s]", data.cna.name);
645 data.forward = FALSE; /* this is tmp code */
647 data.active_line = tcore_call_object_get_active_line(co);
648 dbg("data.active_line : [%d]", data.active_line);
650 /* Send notification to TAPI */
651 tcore_server_send_notification(tcore_plugin_ref_server(p),
652 tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL),
653 TNOTI_CALL_STATUS_INCOMING,
654 sizeof(struct tnoti_call_status_incoming),
662 static void _call_status_waiting(TcorePlugin *p, CallObject *co)
665 _call_status_incoming(p, co);
671 static void _call_branch_by_status(TcorePlugin *p, CallObject *co, unsigned int status)
675 dbg("Call Status is %d", status);
677 case TCORE_CALL_STATUS_IDLE:
678 _call_status_idle(p, co);
681 case TCORE_CALL_STATUS_ACTIVE:
682 _call_status_active(p, co);
685 case TCORE_CALL_STATUS_HELD:
686 _call_status_held(p, co);
689 case TCORE_CALL_STATUS_DIALING:
690 _call_status_dialing(p, co);
693 case TCORE_CALL_STATUS_ALERT:
694 _call_status_alert(p, co);
697 case TCORE_CALL_STATUS_INCOMING:
698 _call_status_incoming(p, co);
701 case TCORE_CALL_STATUS_WAITING:
702 _call_status_waiting(p, co);
710 static TReturn _call_list_get(CoreObject *o, gboolean *event_flag)
712 UserRequest *ur = NULL;
713 TcorePending *pending = NULL;
714 char *cmd_str = NULL;
715 TcoreATRequest *req = NULL;
716 gboolean ret = FALSE;
720 err("Core Object is NULL");
721 return TCORE_RETURN_FAILURE;
724 /* Create new User Request */
725 ur = tcore_user_request_new(NULL, NULL);
728 cmd_str = g_strdup("AT+CLCC");
730 /* Create new Pending Request */
731 pending = tcore_pending_new(o, 0);
732 req = tcore_at_request_new(cmd_str, "+CLCC", TCORE_AT_MULTILINE);
734 tcore_pending_free(pending);
737 tcore_user_request_free(ur);
740 return TCORE_RETURN_FAILURE;
744 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
746 tcore_pending_set_request_data(pending, 0, req);
748 ret = _call_request_message(pending, o, ur, on_response_call_list_get, event_flag);
750 err("AT request (%s) sending failed", req->cmd);
751 /* free only UserRequest. */
753 tcore_user_request_free(ur);
756 return TCORE_RETURN_FAILURE;
759 dbg("AT request sent success");
760 return TCORE_RETURN_SUCCESS;
764 static void on_confirmation_call_message_send(TcorePending *p, gboolean result, void *user_data)
768 if (result == FALSE) { /* Fail */
778 static void call_prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback)
780 TcoreATRequest *req = NULL;
781 TcoreHal *hal = NULL;
782 TcorePending *pending = NULL;
785 hal = tcore_object_get_hal(co);
788 pending = tcore_pending_new(co, 0);
791 req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
793 tcore_pending_free(pending);
796 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
798 tcore_pending_set_request_data(pending, 0, req);
799 tcore_pending_set_response_callback(pending, callback, NULL);
800 tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL);
801 ret = tcore_hal_send_request(hal, pending);
802 if (ret != TCORE_RETURN_SUCCESS)
803 err("Failed to process request");
806 static void on_confirmation_call_outgoing(TcorePending *p, int data_len, const void *data, void *user_data)
808 UserRequest *ur = NULL;
809 GSList *tokens = NULL;
810 const char *line = NULL;
811 const TcoreATResponse *response = data;
812 struct tresp_call_dial resp;
813 enum telephony_call_error error;
816 ur = tcore_pending_ref_user_request(p);
818 if (response->success > 0) {
820 resp.err = CALL_ERROR_NONE;
822 dbg("RESPONSE NOT OK");
824 line = (const char *) response->final_response;
825 tokens = tcore_at_tok_new(line);
827 if (g_slist_length(tokens) < 1) {
828 err("Unspecified error cause OR string corrupted");
829 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
831 error = atoi(g_slist_nth_data(tokens, 0));
832 err("Error: [%d]", error);
833 /* TODO: CMEE error mapping is required. */
834 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
838 tcore_at_tok_free(tokens);
841 /* Send Response to TAPI */
842 tcore_user_request_send_response(ur, TRESP_CALL_DIAL, sizeof(struct tresp_call_dial), &resp);
844 err("User Request is NULL");
851 static void on_confirmation_call_accept(TcorePending *p, int data_len, const void *data, void *user_data)
853 UserRequest *ur = NULL;
854 GSList *tokens = NULL;
855 const char *line = NULL;
856 const TcoreATResponse *response = data;
857 struct tresp_call_answer resp;
858 enum telephony_call_error error;
861 ur = tcore_pending_ref_user_request(p);
863 if (response->success > 0) {
865 resp.err = CALL_ERROR_NONE;
867 dbg("RESPONSE NOT OK");
869 line = (const char *) response->final_response;
870 tokens = tcore_at_tok_new(line);
872 if (g_slist_length(tokens) < 1) {
873 err("Unspecified error cause OR string corrupted");
874 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
876 error = atoi(g_slist_nth_data(tokens, 0));
877 err("Error: [%d]", error);
878 /* TODO: CMEE error mapping is required. */
879 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
883 tcore_at_tok_free(tokens);
886 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
888 /* Send Response to TAPI */
889 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
891 err("User Request is NULL");
899 static void on_confirmation_call_reject(TcorePending *p, int data_len, const void *data, void *user_data)
901 UserRequest *ur = NULL;
902 GSList *tokens = NULL;
903 const char *line = NULL;
904 const TcoreATResponse *response = data;
905 struct tresp_call_answer resp;
906 enum telephony_call_error error;
910 ur = tcore_pending_ref_user_request(p);
912 if (response->success > 0) {
914 resp.err = CALL_ERROR_NONE;
916 dbg("RESPONSE NOT OK");
917 line = (const char *) response->final_response;
918 tokens = tcore_at_tok_new(line);
920 if (g_slist_length(tokens) < 1) {
921 err("Unspecified error cause OR string corrupted");
922 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
924 error = atoi(g_slist_nth_data(tokens, 0));
925 err("Error: [%d]", error);
926 /* TODO: CMEE error mapping is required. */
927 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
931 tcore_at_tok_free(tokens);
934 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
936 /* Send Response to TAPI */
937 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
939 err("User Request is NULL");
946 static void on_confirmation_call_replace(TcorePending *p, int data_len, const void *data, void *user_data)
948 UserRequest *ur = NULL;
949 GSList *tokens = NULL;
950 const char *line = NULL;
951 const TcoreATResponse *response = data;
952 struct tresp_call_answer resp;
953 enum telephony_call_error error;
956 ur = tcore_pending_ref_user_request(p);
958 if (response->success > 0) {
960 resp.err = CALL_ERROR_NONE;
962 dbg("RESPONSE NOT OK");
963 line = (const char *) response->final_response;
964 tokens = tcore_at_tok_new(line);
966 if (g_slist_length(tokens) < 1) {
967 err("Unspecified error cause OR string corrupted");
968 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
970 error = atoi(g_slist_nth_data(tokens, 0));
971 err("Error: [%d]", error);
972 /* TODO: CMEE error mapping is required. */
973 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
977 tcore_at_tok_free(tokens);
979 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
981 /* Send Response to TAPI */
982 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
984 dbg("User Request is NULL");
991 static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data)
993 CoreObject *o = NULL;
994 UserRequest *ur = NULL;
995 GSList *tokens = NULL;
996 const char *line = NULL;
997 const TcoreATResponse *response = data;
998 struct tresp_call_answer resp;
999 enum telephony_call_error error;
1003 o = tcore_pending_ref_core_object(p);
1004 ur = tcore_pending_ref_user_request(p);
1005 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1008 if (response->success > 0) {
1010 resp.err = CALL_ERROR_NONE;
1012 err("RESPONSE NOT OK");
1013 line = (const char *) response->final_response;
1014 tokens = tcore_at_tok_new(line);
1016 if (g_slist_length(tokens) < 1) {
1017 err("Unspecified error cause OR string corrupted");
1018 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1020 error = atoi(g_slist_nth_data(tokens, 0));
1021 err("Error: [%d]", error);
1022 /* TODO: CMEE error mapping is required. */
1023 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1027 tcore_at_tok_free(tokens);
1030 /* Send response to TAPI */
1031 tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp);
1034 CallObject *co = NULL;
1037 list = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_ACTIVE);
1039 err("Can't find active Call");
1043 co = (CallObject *) list->data;
1045 err("Can't get active Call object");
1049 /* Set Call Status */
1050 tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD);
1051 dbg("Call status is set to HELD");
1054 err("User Request is NULL");
1061 static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type)
1063 UserRequest *ur = NULL;
1064 struct tresp_call_end resp;
1065 GSList *tokens = NULL;
1066 const char *line = NULL;
1067 enum telephony_call_error error;
1068 const TcoreATResponse *response = data;
1071 ur = tcore_pending_ref_user_request(p);
1073 if (response->success > 0) {
1075 resp.err = CALL_ERROR_NONE;
1077 err("RESPONSE NOT OK");
1079 line = (const char *) response->final_response;
1080 tokens = tcore_at_tok_new(line);
1082 if (g_slist_length(tokens) < 1) {
1083 err("Unspecified error cause OR string corrupted");
1084 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1086 error = atoi(g_slist_nth_data(tokens, 0));
1087 err("Error: [%d]", error);
1088 /* TODO: CMEE error mapping is required. */
1089 resp.err = CALL_ERROR_SERVICE_UNAVAIL;
1091 tcore_at_tok_free(tokens);
1095 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1096 dbg("resp.type = %d resp.handle= %d", resp.type, resp.handle);
1098 /* Send reponse to TAPI */
1099 tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
1101 err("User Request is NULL");
1109 static void on_confirmation_call_endall(TcorePending *p, int data_len, const void *data, void *user_data)
1111 /* skip response handling - actual result will be handled in on_confirmation_call_release_all */
1112 const TcoreATResponse *response = data;
1116 if (response->success > 0)
1119 err("RESPONSE NOT OK");
1126 static void on_confirmation_call_release_all(TcorePending *p, int data_len, const void *data, void *user_data)
1129 _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ALL);
1135 static void on_confirmation_call_release_specific(TcorePending *p, int data_len, const void *data, void *user_data)
1138 _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_DEFAULT);
1143 static void on_confirmation_call_release_all_active(TcorePending *p, int data_len, const void *data, void *user_data)
1146 _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ACTIVE_ALL);
1151 static void on_confirmation_call_release_all_held(TcorePending *p, int data_len, const void *data, void *user_data)
1154 _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_HOLD_ALL);
1159 static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type)
1161 UserRequest *ur = NULL;
1162 GSList *tokens = NULL;
1163 const char *line = NULL;
1164 const TcoreATResponse *response = NULL;
1165 enum telephony_call_error error;
1168 ur = tcore_pending_ref_user_request(p);
1169 response = (TcoreATResponse *) data;
1170 if (response->success > 0) {
1172 error = CALL_ERROR_NONE;
1174 err("RESPONSE NOT OK");
1176 line = (const char *) response->final_response;
1177 tokens = tcore_at_tok_new(line);
1179 if (g_slist_length(tokens) < 1) {
1180 err("Unspecified error cause OR string corrupted");
1181 error = CALL_ERROR_SERVICE_UNAVAIL;
1183 error = atoi(g_slist_nth_data(tokens, 0));
1185 /* TODO: CMEE error mapping is required. */
1186 error = CALL_ERROR_SERVICE_UNAVAIL;
1190 tcore_at_tok_free(tokens);
1193 dbg("Response Call type -%d", type);
1195 case TRESP_CALL_HOLD:
1197 struct tresp_call_hold resp;
1200 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1201 dbg("call hold response");
1202 /* Send reponse to TAPI */
1203 tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp);
1207 case TRESP_CALL_ACTIVE:
1209 struct tresp_call_active resp;
1212 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1213 dbg("call active response");
1214 /* Send reponse to TAPI */
1215 tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp);
1219 case TRESP_CALL_JOIN:
1221 struct tresp_call_join resp;
1224 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1225 dbg("call join response");
1227 /* Send reponse to TAPI */
1228 tcore_user_request_send_response(ur, TRESP_CALL_JOIN, sizeof(struct tresp_call_join), &resp);
1232 case TRESP_CALL_SPLIT:
1234 struct tresp_call_split resp;
1237 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1238 dbg("call split response");
1239 /* Send reponse to TAPI */
1240 tcore_user_request_send_response(ur, TRESP_CALL_SPLIT, sizeof(struct tresp_call_split), &resp);
1244 case TRESP_CALL_SWAP:
1246 struct tresp_call_swap resp;
1249 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1250 dbg("call swap response");
1251 /* Send reponse to TAPI */
1252 tcore_user_request_send_response(ur, TRESP_CALL_SWAP, sizeof(struct tresp_call_swap), &resp);
1256 case TRESP_CALL_DEFLECT:
1258 struct tresp_call_deflect resp;
1261 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1262 dbg("call deflect response");
1263 /* Send reponse to TAPI */
1264 tcore_user_request_send_response(ur, TRESP_CALL_DEFLECT, sizeof(struct tresp_call_deflect), &resp);
1269 case TRESP_CALL_TRANSFER:
1271 struct tresp_call_transfer resp;
1274 resp.handle = tcore_call_object_get_handle((CallObject *) user_data);
1275 dbg("call transfer response");
1276 /* Send reponse to TAPI */
1277 tcore_user_request_send_response(ur, TRESP_CALL_TRANSFER, sizeof(struct tresp_call_transfer), &resp);
1281 case TRESP_CALL_START_CONT_DTMF:
1283 struct tresp_call_dtmf resp;
1286 dbg("call start cont dtmf response");
1287 /* Send reponse to TAPI */
1288 tcore_user_request_send_response(ur, TRESP_CALL_START_CONT_DTMF, sizeof(struct tresp_call_dtmf), &resp);
1292 case TRESP_CALL_STOP_CONT_DTMF:
1294 struct tresp_call_dtmf resp;
1297 dbg("call stop cont dtmf response");
1298 /* Send reponse to TAPI */
1299 tcore_user_request_send_response(ur, TRESP_CALL_START_CONT_DTMF, sizeof(struct tresp_call_dtmf), &resp);
1305 dbg("type not supported");
1310 if ((type == TRESP_CALL_HOLD) || (type == TRESP_CALL_ACTIVE) || (type == TRESP_CALL_JOIN)
1311 || (type == TRESP_CALL_SPLIT) || (type == TRESP_CALL_SWAP)) {
1313 CoreObject *core_obj = NULL;
1314 gboolean *eflag = g_new0(gboolean, 1);
1316 core_obj = tcore_pending_ref_core_object(p);
1319 dbg("Calling _call_list_get");
1320 _call_list_get(core_obj, eflag);
1328 static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data)
1331 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_HOLD);
1336 static void on_confirmation_call_active(TcorePending *p, int data_len, const void *data, void *user_data)
1339 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_ACTIVE);
1344 static void on_confirmation_call_join(TcorePending *p, int data_len, const void *data, void *user_data)
1347 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_JOIN);
1352 static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data)
1355 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_SPLIT);
1360 static void on_confirmation_call_deflect(TcorePending *p, int data_len, const void *data, void *user_data)
1363 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_DEFLECT);
1368 static void on_confirmation_call_transfer(TcorePending *p, int data_len, const void *data, void *user_data)
1371 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_TRANSFER);
1376 static void on_confirmation_call_start_cont_dtmf(TcorePending *p, int data_len, const void *data, void *user_data)
1379 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_START_CONT_DTMF);
1384 static void on_confirmation_call_stop_cont_dtmf(TcorePending *p, int data_len, const void *data, void *user_data)
1387 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_STOP_CONT_DTMF);
1393 static void _on_confirmation_dtmf_tone_duration(TcorePending *p, int data_len, const void *data, void *user_data)
1395 GSList *tokens = NULL;
1396 const char *line = NULL;
1397 const TcoreATResponse *response = data;
1398 enum telephony_call_error error;
1402 if (response->success > 0) {
1404 error = CALL_ERROR_NONE;
1406 err("RESPONSE NOT OK");
1407 line = (const char *) response->final_response;
1408 tokens = tcore_at_tok_new(line);
1409 if (g_slist_length(tokens) < 1) {
1410 err("err cause not specified or string corrupted");
1411 error = CALL_ERROR_SERVICE_UNAVAIL;
1413 error = atoi(g_slist_nth_data(tokens, 0));
1414 /* TODO: CMEE error mapping is required. */
1418 tcore_at_tok_free(tokens);
1421 dbg("Set dtmf tone duration response - %d", error);
1426 static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data)
1429 _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_SWAP);
1434 static void on_confirmation_set_sound_path(TcorePending *p, int data_len,
1438 const TcoreATResponse *resp = data;
1439 struct tnoti_call_sound_path *snd_path = user_data;
1440 struct tresp_call_set_sound_path resp_set_sound_path;
1441 UserRequest *ur = tcore_pending_ref_user_request(p);
1442 TcorePlugin *plugin = tcore_pending_ref_plugin(p);
1443 CoreObject *co_call;
1446 err("User Request is NULL");
1451 if (resp->success <= 0) {
1453 dbg("RESPONSE NOT OK");
1454 resp_set_sound_path.err = TRUE;
1460 resp_set_sound_path.err = FALSE;
1462 co_call = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL);
1464 /* Notify control plugin about sound path */
1465 tcore_server_send_notification(tcore_plugin_ref_server(plugin),
1466 co_call, TNOTI_CALL_SOUND_PATH,
1467 sizeof(struct tnoti_call_sound_path),
1471 /* Answer TAPI request */
1472 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH,
1473 sizeof(resp_set_sound_path),
1474 &resp_set_sound_path);
1479 static void on_confirmation_call_set_source_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1481 UserRequest *ur = NULL;
1482 GSList *tokens = NULL;
1483 const char *line = NULL;
1484 const TcoreATResponse *response = data;
1485 char *resp_str = NULL;
1486 struct tresp_call_set_sound_path resp;
1490 ur = tcore_pending_ref_user_request(p);
1492 /* +XDRV: <group_id>, <function_id>, <xdrv_result>[, <response_n>]
\ 3 */
1494 err("Input data is NULL");
1498 if (response->success > 0) {
1501 line = (const char *) (((GSList *) response->lines)->data);
1502 tokens = tcore_at_tok_new(line);
1504 resp_str = g_slist_nth_data(tokens, 0);
1505 if (!g_slist_nth_data(tokens, 0)) {
1506 err("group_id is missing");
1511 if (!g_slist_nth_data(tokens, 1)) {
1512 err(" function_id is missing");
1517 resp_str = g_slist_nth_data(tokens, 2);
1520 error = atoi(resp_str);
1522 dbg("Response is Success");
1530 tcore_at_tok_free(tokens);
1532 dbg("RESPONSE NOT OK");
1534 line = (const char *) response->final_response;
1535 tokens = tcore_at_tok_new(line);
1537 if (g_slist_length(tokens) < 1) {
1538 err("err cause not specified or string corrupted");
1541 error = atoi(g_slist_nth_data(tokens, 0));
1543 /* TODO: CMEE error mapping is required. */
1548 tcore_at_tok_free(tokens);
1552 if (resp.err) { /* Send only failed notification . success notification send when destination device is set. */
1553 /* Send notification to TAPI */
1554 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_set_sound_path), &resp);
1555 setsoundpath = TRUE;
1558 err("User Request is NULL");
1565 static void on_confirmation_call_set_destination_sound_path(TcorePending *p, int data_len, const void *data, void *user_data)
1567 UserRequest *ur = NULL;
1568 GSList *tokens = NULL;
1569 const char *line = NULL;
1570 char *resp_str = NULL;
1571 struct tresp_call_set_sound_path resp;
1572 const TcoreATResponse *response = data;
1577 ur = tcore_pending_ref_user_request(p);
1578 /* +XDRV: <group_id>, <function_id>, <xdrv_result>[, <response_n>] */
1581 err("Input data is NULL");
1586 if (response->success > 0) {
1589 line = (const char *) (((GSList *) response->lines)->data);
1590 tokens = tcore_at_tok_new(line);
1592 resp_str = g_slist_nth_data(tokens, 0);
1593 if (!g_slist_nth_data(tokens, 0)) {
1594 dbg("group_id is missing");
1599 if (!g_slist_nth_data(tokens, 1)) {
1600 dbg("function_id is missing");
1605 resp_str = g_slist_nth_data(tokens, 2);
1607 error = atoi(resp_str);
1609 dbg("Response is Success");
1618 tcore_at_tok_free(tokens);
1620 dbg("RESPONSE NOT OK");
1622 line = (const char *) response->final_response;
1623 tokens = tcore_at_tok_new(line);
1625 if (g_slist_length(tokens) < 1) {
1626 err("err cause not specified or string corrupted");
1629 error = atoi(g_slist_nth_data(tokens, 0));
1630 /* TODO: CMEE error mapping is required. */
1635 tcore_at_tok_free(tokens);
1638 if (setsoundpath == TRUE) {
1639 setsoundpath = FALSE;
1641 /* Send response to TAPI */
1642 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_set_sound_path), &resp);
1645 dbg("User Request is NULL");
1652 static void on_confirmation_call_set_source_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data)
1654 UserRequest *ur = NULL;
1655 GSList *tokens = NULL;
1656 const char *line = NULL;
1657 const TcoreATResponse *response = data;
1658 char *resp_str = NULL;
1659 struct tresp_call_set_sound_volume_level resp;
1662 ur = tcore_pending_ref_user_request(p);
1664 /* +XDRV: <group_id>, <function_id>, <xdrv_result>[, <response_n>]
\ 3 */
1666 err("Input data is NULL");
1670 if (response->success > 0) {
1673 line = (const char *) (((GSList *) response->lines)->data);
1674 tokens = tcore_at_tok_new(line);
1676 resp_str = g_slist_nth_data(tokens, 0);
1677 if (!g_slist_nth_data(tokens, 0)) {
1678 err("group_id is missing");
1683 if (!g_slist_nth_data(tokens, 1)) {
1684 err("function_id is missing");
1689 resp_str = g_slist_nth_data(tokens, 2);
1691 error = atoi(resp_str);
1694 dbg("Response is Success ");
1703 tcore_at_tok_free(tokens);
1705 dbg("RESPONSE NOT OK");
1707 line = (const char *) response->final_response;
1708 tokens = tcore_at_tok_new(line);
1710 if (g_slist_length(tokens) < 1) {
1711 err("err cause not specified or string corrupted");
1714 error = atoi(g_slist_nth_data(tokens, 0));
1716 /* TODO: CMEE error mapping is required. */
1721 tcore_at_tok_free(tokens);
1725 if (resp.err && soundvolume == FALSE) { /* Send only failed notification . success notification send when destination device is set. */
1726 /* Send reposne to TAPI */
1727 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_set_sound_volume_level), &resp);
1731 err("User Request is NULL");
1739 static void on_confirmation_call_set_destination_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data)
1741 UserRequest *ur = NULL;
1742 GSList *tokens = NULL;
1743 const char *line = NULL;
1744 char *resp_str = NULL;
1745 const TcoreATResponse *response = data;
1746 struct tresp_call_set_sound_volume_level resp;
1751 ur = tcore_pending_ref_user_request(p);
1753 /* +XDRV: <group_id>, <function_id>, <xdrv_result>[, <response_n>]
\ 3 */
1755 err("Input data is NULL");
1760 if (response->success > 0) {
1762 line = (const char *) (((GSList *) response->lines)->data);
1763 tokens = tcore_at_tok_new(line);
1764 resp_str = g_slist_nth_data(tokens, 0);
1766 if (!g_slist_nth_data(tokens, 0)) {
1767 err("group_id is missing");
1772 if (!g_slist_nth_data(tokens, 1)) {
1773 err("function_id is missing");
1778 resp_str = g_slist_nth_data(tokens, 2);
1781 error = atoi(resp_str);
1784 dbg("Response is Success");
1793 tcore_at_tok_free(tokens);
1795 dbg("RESPONSE NOT OK");
1797 line = (const char *) response->final_response;
1798 tokens = tcore_at_tok_new(line);
1800 if (g_slist_length(tokens) < 1) {
1801 err("err cause not specified or string corrupted");
1804 error = atoi(g_slist_nth_data(tokens, 0));
1806 /* TODO: CMEE error mapping is required. */
1810 tcore_at_tok_free(tokens);
1813 if (soundvolume == TRUE) {
1814 soundvolume = FALSE;
1816 /* Send reposne to TAPI */
1817 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_set_sound_volume_level), &resp);
1820 err("User Request is NULL");
1828 static void on_confirmation_call_set_sound_mute_status(TcorePending *p, int data_len, const void *data, void *user_data)
1830 UserRequest *ur = NULL;
1831 GSList *tokens = NULL;
1832 const char *line = NULL;
1833 char *resp_str = NULL;
1834 struct tresp_call_set_sound_mute_status resp;
1835 const TcoreATResponse *response = data;
1840 ur = tcore_pending_ref_user_request(p);
1843 err("Input data is NULL");
1847 if (response->success > 0) {
1850 line = (const char *) (((GSList *) response->lines)->data);
1851 tokens = tcore_at_tok_new(line);
1852 resp_str = g_slist_nth_data(tokens, 0);
1854 if (!g_slist_nth_data(tokens, 0)) {
1855 err("group_id is missing");
1860 if (!g_slist_nth_data(tokens, 1)) {
1861 err(" function_id is missing");
1866 resp_str = g_slist_nth_data(tokens, 2);
1869 error = atoi(resp_str);
1871 dbg("Response is Success");
1879 tcore_at_tok_free(tokens);
1881 dbg("RESPONSE NOT OK");
1883 line = (const char *) response->final_response;
1884 tokens = tcore_at_tok_new(line);
1886 if (g_slist_length(tokens) < 1) {
1887 err("err cause not specified or string corrupted");
1890 error = atoi(g_slist_nth_data(tokens, 0));
1892 /* TODO: CMEE error mapping is required. */
1897 tcore_at_tok_free(tokens);
1901 tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_MUTE_STATUS, sizeof(struct tresp_call_set_sound_mute_status), &resp);
1903 err("User Request is NULL");
1910 static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data)
1912 TcorePlugin *plugin = NULL;
1913 CoreObject *core_obj = NULL;
1914 CallObject *co = NULL;
1915 struct clcc_call_t *call_list = NULL;
1916 gboolean *event_flag = (gboolean *) user_data;
1917 const TcoreATResponse *response = data;
1918 GSList *resp_data = NULL;
1921 int cllc_info = 0, countCalls = 0, countValidCalls = 0;
1926 plugin = tcore_pending_ref_plugin(p);
1927 core_obj = tcore_pending_ref_core_object(p);
1929 if (response->success > 0) {
1931 if (response->lines) {
1932 resp_data = (GSList *) response->lines;
1933 countCalls = g_slist_length(resp_data);
1934 dbg("Total records : %d", countCalls);
1937 if (0 == countCalls) {
1938 err("Call count is zero");
1946 call_list = g_new0(struct clcc_call_t, countCalls);
1948 for (countValidCalls = 0; resp_data != NULL; resp_data = resp_data->next, countValidCalls++, cllc_info++) {
1949 line = (char *) (resp_data->data);
1951 error = _callFromCLCCLine(line, call_list + countValidCalls);
1955 co = tcore_call_object_find_by_id(core_obj, call_list[cllc_info].info.id);
1957 co = tcore_call_object_new(core_obj);
1959 err("[ error ] co is NULL");
1964 /* Call set parameters */
1965 tcore_call_object_set_type(co, call_type(call_list[cllc_info].info.type));
1966 tcore_call_object_set_direction(co, call_list[cllc_info].info.direction);
1967 tcore_call_object_set_multiparty_state(co, _call_is_in_mpty(call_list[cllc_info].info.mpty));
1968 tcore_call_object_set_cli_info(co, CALL_CLI_MODE_DEFAULT, 0, call_list[cllc_info].number, strlen(call_list[cllc_info].number));
1969 tcore_call_object_set_active_line(co, 0);
1972 dbg("Call status before calling _call_branch_by_status() : (%d)", call_list[cllc_info].info.status);
1973 _call_branch_by_status(plugin, co, call_list[cllc_info].info.status);
1976 tcore_call_object_set_status(co, call_list[cllc_info].info.status);
1978 dbg("Call id : (%d)", call_list[cllc_info].info.id);
1979 dbg("Call direction : (%d)", call_list[cllc_info].info.direction);
1980 dbg("Call type : (%d)", call_list[cllc_info].info.type);
1981 dbg("Call mpty : (%d)", call_list[cllc_info].info.mpty);
1982 dbg("Call number : (%s)", call_list[cllc_info].number);
1983 dbg("Call status : (%d)", call_list[cllc_info].info.status);
1987 /* Free Call list */
1991 /* Free User data */
2001 static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data)
2003 TcorePlugin *plugin = NULL;
2004 CoreObject *core_obj = NULL;
2005 CallObject *co = (CallObject *) user_data;
2006 const TcoreATResponse *response = data;
2007 const char *line = NULL;
2008 struct tnoti_call_status_idle call_status;
2009 GSList *tokens = NULL;
2014 plugin = tcore_pending_ref_plugin(p);
2015 core_obj = tcore_pending_ref_core_object(p);
2017 if (response->success > 0) {
2019 line = (const char *) (((GSList *) response->lines)->data);
2020 tokens = tcore_at_tok_new(line);
2021 resp_str = g_slist_nth_data(tokens, 0);
2023 err("call end cause - report value missing");
2025 resp_str = g_slist_nth_data(tokens, 1);
2027 err("call end cause value missing");
2029 error = atoi(resp_str);
2030 dbg("call end cause - %d", error);
2031 call_status.cause = _compare_call_end_cause(error);
2032 dbg("TAPI call end cause - %d", call_status.cause);
2036 tcore_at_tok_free(tokens);
2038 err("RESPONSE NOT OK");
2039 line = (char *) response->final_response;
2040 tokens = tcore_at_tok_new(line);
2041 if (g_slist_length(tokens) < 1)
2042 err("err cause not specified or string corrupted");
2044 err(" err cause value: %d", atoi(g_slist_nth_data(tokens, 0)));
2046 call_status.cause = CC_CAUSE_NORMAL_CALL_CLEARING;
2048 tcore_at_tok_free(tokens);
2051 call_status.type = tcore_call_object_get_type(co);
2052 dbg("data.type : [%d]", call_status.type);
2054 call_status.handle = tcore_call_object_get_handle(co);
2055 dbg("data.handle : [%d]", call_status.handle);
2058 tcore_call_object_set_status(co, TCORE_CALL_STATUS_IDLE);
2060 /* Send Notification to TAPI */
2061 tcore_server_send_notification(tcore_plugin_ref_server(plugin),
2063 TNOTI_CALL_STATUS_IDLE,
2064 sizeof(struct tnoti_call_status_idle),
2065 (void *) &call_status);
2067 /* Free Call object */
2068 tcore_call_object_free(core_obj, co);
2071 static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call)
2073 /* +CLCC: 1, 0, 2, 0, 0, "18005551212", 145 */
2074 /* [+CLCC: <id1>, <dir>, <stat>, <mode>, <mpty>[, <number>, <type>[, <alpha>[, <priority>]]] */
2079 unsigned int num_type;
2080 GSList *tokens = NULL;
2085 tokens = tcore_at_tok_new(line);
2087 resp = g_slist_nth_data(tokens, 0);
2092 p_call->info.id = atoi(resp);
2093 dbg("id : [%d]\n", p_call->info.id);
2096 resp = g_slist_nth_data(tokens, 1);
2103 p_call->info.direction = TCORE_CALL_DIRECTION_OUTGOING;
2105 p_call->info.direction = TCORE_CALL_DIRECTION_INCOMING;
2107 dbg("Direction : [ %d ]\n", p_call->info.direction);
2110 resp = g_slist_nth_data(tokens, 2);
2112 err("InValid Stat");
2116 dbg("Call state : %d", state);
2118 case 0: /* active */
2119 p_call->info.status = TCORE_CALL_STATUS_ACTIVE;
2123 p_call->info.status = TCORE_CALL_STATUS_HELD;
2127 p_call->info.status = TCORE_CALL_STATUS_DIALING;
2131 p_call->info.status = TCORE_CALL_STATUS_ALERT;
2135 p_call->info.status = TCORE_CALL_STATUS_INCOMING;
2139 p_call->info.status = TCORE_CALL_STATUS_WAITING;
2142 dbg("Status : [%d]\n", p_call->info.status);
2145 resp = g_slist_nth_data(tokens, 3);
2147 err("InValid Mode");
2153 p_call->info.type = TCORE_CALL_TYPE_VOICE;
2157 p_call->info.type = TCORE_CALL_TYPE_VIDEO;
2160 default: /* only Voice/VT call is supported in CS. treat other unknown calls as error */
2161 dbg("invalid type : [%d]\n", mode);
2164 dbg("Call type : [%d]\n", p_call->info.type);
2167 resp = g_slist_nth_data(tokens, 4);
2169 err("InValid Mpty");
2173 p_call->info.mpty = atoi(resp);
2174 dbg("Mpty : [ %d ]\n", p_call->info.mpty);
2177 resp = g_slist_nth_data(tokens, 5);
2178 dbg("Incoming number - %s and its len - %d", resp, strlen(resp));
2180 /* tolerate null here */
2182 err("Number is NULL");
2185 /* Strike off double quotes */
2186 num = tcore_at_tok_extract(resp);
2188 err("number after removing quotes is NULL");
2190 dbg("num after removing quotes - %s", num);
2192 p_call->info.num_len = strlen(resp);
2193 dbg("num_len : [0x%x]\n", p_call->info.num_len);
2195 /* parse <num type> */
2196 resp = g_slist_nth_data(tokens, 6);
2198 dbg("InValid Num type");
2201 p_call->info.num_type = atoi(resp);
2202 dbg("BCD num type: [0x%x]\n", p_call->info.num_type);
2204 /* check number is international or national. */
2205 num_type = ((p_call->info.num_type) >> 4) & 0x07;
2206 dbg("called party's type of number : [0x%x]\n", num_type);
2209 if (num_type == 1 && num[0] != '+') {
2210 /* international number */
2211 p_call->number[0] = '+';
2212 memcpy(&(p_call->number[1]), num, strlen(num));
2214 memcpy(&(p_call->number), num, strlen(num));
2216 dbg("incoming number - %s", p_call->number);
2221 tcore_at_tok_free(tokens);
2227 err("Invalid CLCC line");
2232 tcore_at_tok_free(tokens);
2238 static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data)
2240 GSList *tokens = NULL;
2241 const char *line = NULL;
2245 GSList *pList = NULL;
2246 CallObject *co = NULL, *dupco = NULL;
2248 dbg("function entrance");
2249 /* check call with waiting status already exist */
2250 pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_WAITING);
2252 if (pList != NULL) {
2253 dbg("[error]Waiting call already exist. skip");
2256 /* check call with incoming status already exist */
2257 pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
2259 if (pList != NULL) {
2260 dbg("[error]incoming call already exist. skip");
2263 line = (char *) data;
2264 tokens = tcore_at_tok_new(line);
2266 pId = g_slist_nth_data(tokens, 0);
2268 dbg("[error]:Call id is missing from +XCALLSTAT indication");
2269 tcore_at_tok_free(tokens);
2273 call_id = atoi(pId);
2274 dupco = tcore_call_object_find_by_id(o, call_id);
2275 if (dupco != NULL) {
2276 dbg("co with same id already exist. skip");
2277 tcore_at_tok_free(tokens);
2280 co = tcore_call_object_new(o);
2282 err("[ error ] co is NULL");
2283 tcore_at_tok_free(tokens);
2286 tcore_call_object_set_id(co, call_id);
2288 tcore_at_tok_free(tokens);
2290 eflag = g_new0(gboolean, 1);
2292 dbg("calling _call_list_get");
2293 _call_list_get(o, eflag);
2296 static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data)
2298 GSList *tokens = NULL;
2299 const char *line = NULL;
2303 GSList *pList = NULL;
2304 CallObject *co = NULL, *dupco = NULL;
2306 dbg("function entrance");
2307 /* check call with incoming status already exist */
2308 pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING);
2310 if (pList != NULL) {
2311 dbg("incoming call already exist. skip");
2315 line = (char *) data;
2316 tokens = tcore_at_tok_new(line);
2318 pId = g_slist_nth_data(tokens, 0);
2320 dbg("Error:Call id is missing from %XCALLSTAT indication");
2321 tcore_at_tok_free(tokens);
2325 call_id = atoi(pId);
2327 dupco = tcore_call_object_find_by_id(o, call_id);
2328 if (dupco != NULL) {
2329 dbg("co with same id already exist. skip");
2330 tcore_at_tok_free(tokens);
2334 co = tcore_call_object_new(o);
2336 dbg("[ error ] co is NULL");
2337 tcore_at_tok_free(tokens);
2340 tcore_call_object_set_id(co, call_id);
2342 dbg("freeing at token");
2343 tcore_at_tok_free(tokens);
2345 eflag = g_new0(gboolean, 1);
2348 dbg("calling _call_list_get");
2349 _call_list_get(o, eflag);
2352 static void on_notification_call_status(CoreObject *o, const void *data, void *user_data)
2355 TcorePlugin *plugin = NULL;
2356 CallObject *co = NULL;
2361 char *pCallId = NULL;
2362 GSList *tokens = NULL;
2363 gboolean *eflag = NULL;
2364 enum tcore_call_status co_status;
2366 dbg("function entrance");
2367 plugin = tcore_object_ref_plugin(o);
2368 cmd = (char *) data;
2369 tokens = tcore_at_tok_new(cmd);
2371 /* parse <Call Id> */
2372 pCallId = g_slist_nth_data(tokens, 0);
2374 dbg("CallId is missing from %XCALLSTAT indication");
2375 tcore_at_tok_free(tokens);
2379 dbg("call id = %d", id);
2381 if ((stat = g_slist_nth_data(tokens, 1)))
2382 status = atoi(stat);
2383 dbg("call status = %d", status);
2386 tcore_at_tok_free(tokens);
2387 co_status = _call_status(status);
2389 dbg("co_status = %d", co_status);
2390 switch (co_status) {
2391 case CALL_STATUS_ACTIVE:
2394 dbg("call(%d) status : [ ACTIVE ]", id);
2396 co = tcore_call_object_find_by_id(o, id);
2402 * Activie / Held status notification will be handled in call_list_get().
2403 * Because of timing issue, we should not notifity this event before updating call info.
2404 * One exception is that we will send this event when active status is receviced during dialing or incoming.
2406 prev_status = tcore_call_object_get_status(co);
2407 if ((prev_status == TCORE_CALL_STATUS_DIALING)
2408 || (prev_status == TCORE_CALL_STATUS_ALERT)
2409 || (prev_status == TCORE_CALL_STATUS_INCOMING)
2410 || (prev_status == TCORE_CALL_STATUS_WAITING)) {
2411 _call_status_active(plugin, co);
2416 case CALL_STATUS_HELD:
2418 dbg("call(%d) status : [ held ]", id);
2420 * Activie / Held status notification will be handled in call_list_get().
2421 * Because of timing issue, we should not notifity this event before updating call info.
2424 co = tcore_call_object_find_by_id(o, id);
2429 _call_status_held(plugin, co);
2434 case CALL_STATUS_DIALING:
2436 dbg("call(%d) status : [ dialing ]", id);
2437 co = tcore_call_object_find_by_id(o, id);
2439 co = tcore_call_object_new(o);
2441 dbg("error : tcore_call_object_new [ id : %d ]", id);
2444 tcore_call_object_set_id(co, id);
2447 tcore_call_object_set_type(co, call_type(type));
2448 tcore_call_object_set_direction(co, TCORE_CALL_DIRECTION_OUTGOING);
2449 _call_status_dialing(plugin, co);
2453 case CALL_STATUS_ALERT:
2455 dbg("call(%d) status : [ alert ]", id);
2456 co = tcore_call_object_find_by_id(o, id);
2461 /* Store dialed number information into Call object. */
2462 eflag = g_new0(gboolean, 1);
2464 dbg("calling _call_list_get");
2465 _call_list_get(o, eflag);
2469 case CALL_STATUS_INCOMING:
2470 case CALL_STATUS_WAITING:
2471 dbg("call(%d) status : [ incoming ]", id);
2474 case CALL_STATUS_IDLE:
2476 dbg("call(%d) status : [ release ]", id);
2478 co = tcore_call_object_find_by_id(o, id);
2484 plugin = tcore_object_ref_plugin(o);
2486 dbg("plugin is NULL");
2489 _call_status_idle(plugin, co);
2494 dbg("invalid call status", id);
2499 static TReturn imc_call_outgoing(CoreObject *o, UserRequest *ur)
2501 struct treq_call_dial *data = 0;
2503 const char *clir, *num;
2504 TcorePending *pending;
2505 TcoreATRequest *req;
2510 data = (struct treq_call_dial *) tcore_user_request_ref_data(ur, 0);
2511 if (data->type == CALL_TYPE_VIDEO) {
2512 dbg("invalid call type");
2513 return TCORE_RETURN_FAILURE;
2516 if (!strncmp(data->number, "*31#", 4)) {
2517 dbg("clir suppression");
2519 num = data->number + 4;
2520 } else if (!strncmp(data->number, "#31#", 4)) {
2521 dbg("clir invocation");
2523 num = data->number + 4;
2527 dbg("no clir string in number");
2529 vconf_get_int("db/ciss/show_my_number", &cli);
2532 dbg("clir invocation from setting application");
2535 dbg("set clir state to default");
2541 dbg("data->number = %s", num);
2543 cmd_str = g_strdup_printf("ATD%s%s;", num, clir);
2545 dbg("request command : %s", cmd_str);
2547 pending = tcore_pending_new(o, 0);
2548 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2550 tcore_pending_free(pending);
2552 return TCORE_RETURN_FAILURE;
2554 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2556 tcore_pending_set_request_data(pending, 0, req);
2557 ret = _call_request_message(pending, o, ur, on_confirmation_call_outgoing, NULL);
2562 dbg("AT request(%s) sent failed", req->cmd);
2563 return TCORE_RETURN_FAILURE;
2566 dbg("AT request(%s) sent success", req->cmd);
2570 return TCORE_RETURN_SUCCESS;
2573 static TReturn imc_call_answer(CoreObject *o, UserRequest *ur)
2575 char *cmd_str = NULL;
2576 CallObject *co = NULL;
2577 struct treq_call_answer *data = 0;
2578 TcorePending *pending = NULL;
2579 TcoreATRequest *req;
2580 gboolean ret = FALSE;
2582 dbg("function entrance");
2584 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2585 dbg("cp not ready/n");
2586 return TCORE_RETURN_ENOSYS;
2589 data = (struct treq_call_answer *) tcore_user_request_ref_data(ur, 0);
2590 co = tcore_call_object_find_by_handle(o, data->handle);
2591 if (data->type == CALL_ANSWER_TYPE_ACCEPT) {
2592 dbg(" request type CALL_ANSWER_TYPE_ACCEPT");
2594 cmd_str = g_strdup_printf("%s", "ATA");
2595 pending = tcore_pending_new(o, 0);
2596 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2598 tcore_pending_free(pending);
2600 return TCORE_RETURN_FAILURE;
2602 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2604 tcore_pending_set_request_data(pending, 0, req);
2605 ret = _call_request_message(pending, o, ur, on_confirmation_call_accept, co);
2609 dbg("AT request(%s) sent failed", req->cmd);
2610 return TCORE_RETURN_FAILURE;
2613 switch (data->type) {
2614 case CALL_ANSWER_TYPE_REJECT:
2616 dbg("call answer reject");
2617 tcore_call_control_answer_reject(o, ur, on_confirmation_call_reject, co);
2621 case CALL_ANSWER_TYPE_REPLACE:
2623 dbg("call answer replace");
2624 tcore_call_control_answer_replace(o, ur, on_confirmation_call_replace, co);
2628 case CALL_ANSWER_TYPE_HOLD_ACCEPT:
2630 dbg("call answer hold and accept");
2631 tcore_call_control_answer_hold_and_accept(o, ur, on_confirmation_call_hold_and_accept, co);
2636 dbg("[ error ] wrong answer type [ %d ]", data->type);
2637 return TCORE_RETURN_FAILURE;
2641 return TCORE_RETURN_SUCCESS;
2644 static TReturn imc_call_release(CoreObject *o, UserRequest *ur)
2646 CallObject *co = NULL;
2647 struct treq_call_end *data = 0;
2648 UserRequest *ur_dup = NULL;
2649 char *chld0_cmd = NULL;
2650 char *chld1_cmd = NULL;
2651 TcorePending *pending = NULL, *pending1 = NULL;
2652 TcoreATRequest *req, *req1;
2653 gboolean ret = FALSE;
2655 dbg("function entrance");
2656 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2657 dbg("cp not ready/n");
2658 return TCORE_RETURN_ENOSYS;
2660 data = (struct treq_call_end *) tcore_user_request_ref_data(ur, 0);
2661 co = tcore_call_object_find_by_handle(o, data->handle);
2663 dbg("type of release call = %d", data->type);
2665 if (data->type == CALL_END_TYPE_ALL) {
2666 /* releaseAll do not exist on legacy request. send CHLD=0, CHLD=1 in sequence */
2667 chld0_cmd = g_strdup("AT+CHLD=0");
2668 chld1_cmd = g_strdup("AT+CHLD=1");
2670 pending = tcore_pending_new(o, 0);
2671 req = tcore_at_request_new(chld0_cmd, NULL, TCORE_AT_NO_RESULT);
2673 tcore_pending_free(pending);
2676 return TCORE_RETURN_FAILURE;
2678 dbg("input command is %s", chld0_cmd);
2679 dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2681 tcore_pending_set_request_data(pending, 0, req);
2682 ur_dup = tcore_user_request_new(NULL, NULL);
2683 ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_endall, NULL);
2687 dbg("AT request %s has failed ", req->cmd);
2689 tcore_user_request_free(ur_dup);
2693 return TCORE_RETURN_FAILURE;
2696 pending1 = tcore_pending_new(o, 0);
2697 req1 = tcore_at_request_new(chld1_cmd, NULL, TCORE_AT_NO_RESULT);
2699 tcore_pending_free(pending1);
2701 return TCORE_RETURN_FAILURE;
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 handle : [ %d ]", hold->handle);
2764 co = tcore_call_object_find_by_handle(o, hold->handle);
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 handle : [ %d ]", active->handle);
2783 co = tcore_call_object_find_by_handle(o, active->handle);
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 handle : [ %d ]", swap->handle);
2802 co = tcore_call_object_find_by_handle(o, swap->handle);
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 handle : [ %d ]", join->handle);
2821 co = tcore_call_object_find_by_handle(o, join->handle);
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;
2833 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2834 dbg("cp not ready/n");
2835 return TCORE_RETURN_ENOSYS;
2838 split = (struct treq_call_split *) tcore_user_request_ref_data(ur, 0);
2839 co = tcore_call_object_find_by_handle(o, split->handle);
2841 id = tcore_call_object_get_id(co);
2842 dbg("call ID : [ %d ]", id);
2844 tcore_call_control_split(o, ur, id, on_confirmation_call_split, co);
2846 return TCORE_RETURN_SUCCESS;
2849 static TReturn imc_call_deflect(CoreObject *o, UserRequest *ur)
2851 struct treq_call_deflect *deflect = 0;
2852 CallObject *co = NULL;
2854 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2855 dbg("cp not ready/n");
2856 return TCORE_RETURN_ENOSYS;
2859 deflect = (struct treq_call_deflect *) tcore_user_request_ref_data(ur, 0);
2860 co = tcore_call_object_find_by_number(o, deflect->number);
2861 dbg("deflect number: [ %s ]", deflect->number);
2863 tcore_call_control_deflect(o, ur, deflect->number, on_confirmation_call_deflect, co);
2865 return TCORE_RETURN_SUCCESS;
2868 static TReturn imc_call_transfer(CoreObject *o, UserRequest *ur)
2870 struct treq_call_transfer *transfer = 0;
2871 CallObject *co = NULL;
2873 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2874 dbg("cp not ready/n");
2875 return TCORE_RETURN_ENOSYS;
2878 transfer = (struct treq_call_transfer *) tcore_user_request_ref_data(ur, 0);
2879 dbg("call handle : [ %d ]", transfer->handle);
2881 co = tcore_call_object_find_by_handle(o, transfer->handle);
2882 tcore_call_control_transfer(o, ur, on_confirmation_call_transfer, co);
2884 return TCORE_RETURN_SUCCESS;
2887 static TReturn imc_call_start_cont_dtmf(CoreObject *o, UserRequest *ur)
2889 char *cmd_str = NULL;
2890 gboolean ret = FALSE;
2891 TcoreATRequest *req;
2892 struct treq_call_start_cont_dtmf *dtmf = 0;
2893 TcorePending *pending = NULL;
2895 dbg("Function enter");
2897 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2898 dbg("cp not ready/n");
2899 return TCORE_RETURN_ENOSYS;
2901 dtmf = (struct treq_call_start_cont_dtmf *) tcore_user_request_ref_data(ur, 0);
2903 /* Start Command Syntax: AT+XVTS=<DTMF> */
2904 cmd_str = g_strdup_printf("AT+XVTS=%c", dtmf->dtmf_digit);
2906 pending = tcore_pending_new(o, 0);
2907 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2909 tcore_pending_free(pending);
2911 return TCORE_RETURN_FAILURE;
2914 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2916 tcore_pending_set_request_data(pending, 0, req);
2917 ret = _call_request_message(pending, o, ur, on_confirmation_call_start_cont_dtmf, NULL);
2921 dbg("AT request sent failed");
2922 return TCORE_RETURN_FAILURE;
2925 return TCORE_RETURN_SUCCESS;
2928 static TReturn imc_call_stop_cont_dtmf(CoreObject *o, UserRequest *ur)
2930 char *cmd_str = NULL;
2931 gboolean ret = FALSE;
2932 TcoreATRequest *req;
2933 TcorePending *pending = NULL;
2935 dbg("Function enter");
2937 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2938 dbg("cp not ready/n");
2939 return TCORE_RETURN_ENOSYS;
2942 /* Stop Command Syntax: AT+XVTS= */
2943 cmd_str = g_strdup_printf("AT+XVTS=");
2945 pending = tcore_pending_new(o, 0);
2946 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
2948 tcore_pending_free(pending);
2950 return TCORE_RETURN_FAILURE;
2953 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
2955 tcore_pending_set_request_data(pending, 0, req);
2956 ret = _call_request_message(pending, o, ur, on_confirmation_call_stop_cont_dtmf, NULL);
2960 dbg("AT request sent failed");
2961 return TCORE_RETURN_FAILURE;
2964 return TCORE_RETURN_SUCCESS;
2967 static TReturn imc_call_set_sound_path(CoreObject *o, UserRequest *ur)
2969 UserRequest *ur_dup = NULL;
2970 TcorePending *pending = NULL, *pending1 = NULL;
2971 TcoreATRequest *req, *req1;
2972 char *cmd_str = NULL, *cmd_str1 = NULL;
2973 int device_type = -1;
2974 struct treq_call_set_sound_path *sound_path = 0;
2975 gboolean ret = FALSE;
2976 TcorePlugin *plugin = tcore_object_ref_plugin(o);
2977 const char *cp_name = tcore_server_get_cp_name_by_plugin(plugin);
2979 dbg("function entrance");
2981 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
2982 dbg("cp not ready/n");
2983 return TCORE_RETURN_ENOSYS;
2985 sound_path = (struct treq_call_set_sound_path *) tcore_user_request_ref_data(ur, 0);
2986 if (sound_path == NULL) {
2987 dbg("invaling user request");
2988 return TCORE_RETURN_FAILURE;
2990 dbg("audio device type - 0x%x", sound_path->path);
2991 switch (sound_path->path) {
2992 case CALL_SOUND_PATH_HANDSET:
2996 case CALL_SOUND_PATH_HEADSET:
3000 case CALL_SOUND_PATH_HEADSET_3_5PI:
3004 case CALL_SOUND_PATH_SPEAKER:
3008 case CALL_SOUND_PATH_HANDFREE:
3012 case CALL_SOUND_PATH_HEADSET_HAC:
3016 case CALL_SOUND_PATH_BLUETOOTH:
3017 case CALL_SOUND_PATH_STEREO_BLUETOOTH:
3021 case CALL_SOUND_PATH_BT_NSEC_OFF:
3022 case CALL_SOUND_PATH_MIC1:
3023 case CALL_SOUND_PATH_MIC2:
3025 dbg("unsupported device type");
3026 return TCORE_RETURN_FAILURE;
3029 if (g_str_has_prefix(cp_name, "mfld_blackbay") == TRUE) {
3030 struct tnoti_call_sound_path *tnoti_snd_path;
3032 tnoti_snd_path = g_try_new0(struct tnoti_call_sound_path, 1);
3033 if (!tnoti_snd_path)
3034 return TCORE_RETURN_ENOMEM;
3036 tnoti_snd_path->path = sound_path->path;
3038 /* Configure modem I2S1 to 8khz, mono, PCM if routing to bluetooth */
3039 if (sound_path->path == CALL_SOUND_PATH_BLUETOOTH || sound_path->path == CALL_SOUND_PATH_STEREO_BLUETOOTH) {
3040 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 4, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 21", NULL, TCORE_AT_NO_RESULT, NULL);
3041 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 5, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 22", NULL, TCORE_AT_NO_RESULT, NULL);
3043 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 4, 3, 0, 1, 0, 8, 0, 1, 0, 2, 0, 21", NULL, TCORE_AT_NO_RESULT, NULL);
3044 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 5, 2, 0, 1, 0, 8, 0, 1, 0, 2, 0, 22", NULL, TCORE_AT_NO_RESULT, NULL);
3047 /* Configure modem I2S2 and do the modem routing */
3048 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 4, 4, 0, 0, 0, 8, 0, 1, 0, 2, 0, 21", NULL, TCORE_AT_NO_RESULT, NULL);
3049 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 5, 3, 0, 0, 0, 8, 0, 1, 0, 2, 0, 22", NULL, TCORE_AT_NO_RESULT, NULL);
3050 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 6, 0, 4", NULL, TCORE_AT_NO_RESULT, NULL);
3051 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 6, 3, 0", NULL, TCORE_AT_NO_RESULT, NULL);
3052 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 6, 4, 2", NULL, TCORE_AT_NO_RESULT, NULL);
3053 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 6, 5, 2", NULL, TCORE_AT_NO_RESULT, NULL);
3056 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 2, 4", NULL, TCORE_AT_NO_RESULT, NULL); /* AMC_I2S2_RX */
3057 call_prepare_and_send_pending_request(o, "AT+XDRV=40, 2, 3", NULL, TCORE_AT_NO_RESULT, NULL); /* AMC_I2S1_RX */
3058 /* amc route: AMC_RADIO_RX => AMC_I2S1_TX */
3060 pending = tcore_pending_new(o, 0);
3061 req = tcore_at_request_new("AT+XDRV=40, 6, 0, 2", "+XDRV", TCORE_AT_SINGLELINE);
3063 tcore_pending_free(pending);
3064 return TCORE_RETURN_FAILURE;
3066 dbg("XDRV req-cmd for source type : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3067 tcore_pending_set_request_data(pending, 0, req);
3068 ur_dup = tcore_user_request_ref(ur);
3069 ret = _call_request_message(pending, o, ur_dup, on_confirmation_set_sound_path, tnoti_snd_path);
3073 cmd_str = g_strdup_printf("AT+XDRV=40, 4, 3, 0, 0, 0, 0, 0, 1, 0, 1, 0, %d", device_type); /* source type. */
3074 pending = tcore_pending_new(o, 0);
3075 req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3077 tcore_pending_free(pending);
3079 return TCORE_RETURN_FAILURE;
3081 dbg("XDRV req-cmd for source type : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
3082 tcore_pending_set_request_data(pending, 0, req);
3083 ur_dup = tcore_user_request_ref(ur);
3084 ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_set_source_sound_path, NULL);
3088 dbg("At request(%s) sent failed", req->cmd);
3089 return TCORE_RETURN_FAILURE;
3092 cmd_str1 = g_strdup_printf("AT+XDRV=40, 5, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0, %d", device_type); /* destination type */
3093 pending1 = tcore_pending_new(o, 0);
3094 req1 = tcore_at_request_new(cmd_str1, "+XDRV", TCORE_AT_SINGLELINE);
3096 tcore_pending_free(pending1);
3098 return TCORE_RETURN_FAILURE;
3100 dbg("XDRV req-cmd for destination type : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd));
3101 tcore_pending_set_request_data(pending1, 0, req1);
3102 ret = _call_request_message(pending1, o, ur, on_confirmation_call_set_destination_sound_path, NULL);
3106 dbg("AT request %s has failed ", req1->cmd);
3107 return TCORE_RETURN_FAILURE;
3111 return TCORE_RETURN_SUCCESS;
3114 static TReturn imc_call_set_sound_volume_level(CoreObject *o, UserRequest *ur)
3116 UserRequest *src_ur = NULL;
3117 UserRequest *dest_ur = NULL;
3118 TcorePending *src_pending = NULL;
3119 TcorePending *dest_pending = NULL;
3120 TcoreATRequest *src_req = NULL;
3121 TcoreATRequest *dest_req = NULL;
3122 char *cmd_str = NULL, *volume_level = NULL;
3123 gboolean ret = FALSE;
3124 struct treq_call_set_sound_volume_level *data = NULL;
3128 if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) {
3129 dbg("cp not ready/n");
3130 return TCORE_RETURN_ENOSYS;
3133 data = (struct treq_call_set_sound_volume_level *) tcore_user_request_ref_data(ur, 0);
3135 /* Hard-coded values for MIC & Speakers */
3137 dbg("Set Source volume");
3139 cmd_str = g_strdup_printf("%s", "AT+XDRV=40, 7, 3, 88"); /* Source type */
3140 dbg("Request command string: %s", cmd_str);
3142 /* Create new Pending request */
3143 src_pending = tcore_pending_new(o, 0);
3145 /* Create new AT-Command request */
3146 src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3147 if (src_req == NULL) {
3148 tcore_pending_free(src_pending);
3150 return TCORE_RETURN_FAILURE;
3152 dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd));
3154 /* Free Command string */
3157 tcore_pending_set_request_data(src_pending, 0, src_req);
3158 src_ur = tcore_user_request_ref(ur);
3161 ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3163 err("Failed to send AT-Command request");
3164 return TCORE_RETURN_FAILURE;
3167 cmd_str = g_strdup_printf("%s", "AT+XDRV=40, 7, 0, 88"); /* Destination type */
3168 dbg("Request command string: %s", cmd_str);
3170 /* Create new Pending request */
3171 src_pending = tcore_pending_new(o, 0);
3173 /* Create new AT-Command request */
3174 src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3175 if (src_req == NULL) {
3176 tcore_pending_free(src_pending);
3178 return TCORE_RETURN_FAILURE;
3180 dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd));
3182 /* Free Command string */
3185 tcore_pending_set_request_data(src_pending, 0, src_req);
3187 src_ur = tcore_user_request_ref(ur);
3190 ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3192 err("Failed to send AT-Command request");
3193 return TCORE_RETURN_FAILURE;
3196 /* Destination volume */
3197 dbg("Set Source volume");
3199 cmd_str = g_strdup_printf("%s", "AT+XDRV=40, 8, 0, 88"); /* Source type */
3200 dbg("Request command string: %s", cmd_str);
3202 /* Create new Pending request */
3203 dest_pending = tcore_pending_new(o, 0);
3205 /* Create new AT-Command request */
3206 dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3207 if (dest_req == NULL) {
3208 tcore_pending_free(dest_pending);
3210 return TCORE_RETURN_FAILURE;
3212 dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd));
3214 /* Free Command string */
3217 tcore_pending_set_request_data(dest_pending, 0, dest_req);
3218 dest_ur = tcore_user_request_ref(ur);
3221 ret = _call_request_message(dest_pending, o, dest_ur, on_confirmation_call_set_source_sound_volume_level, NULL);
3223 err("Failed to send AT-Command request");
3224 return TCORE_RETURN_FAILURE;
3227 dbg("Input volume level - %d", data->volume);
3228 switch (data->volume) {
3229 case CALL_SOUND_MUTE:
3233 case CALL_SOUND_VOLUME_LEVEL_1:
3234 volume_level = "40";
3237 case CALL_SOUND_VOLUME_LEVEL_2:
3238 volume_level = "46";
3241 case CALL_SOUND_VOLUME_LEVEL_3:
3242 volume_level = "52";
3245 case CALL_SOUND_VOLUME_LEVEL_4:
3246 volume_level = "58";
3249 case CALL_SOUND_VOLUME_LEVEL_5:
3250 volume_level = "64";
3253 case CALL_SOUND_VOLUME_LEVEL_6:
3254 volume_level = "70";
3257 case CALL_SOUND_VOLUME_LEVEL_7:
3258 volume_level = "76";
3261 case CALL_SOUND_VOLUME_LEVEL_8:
3262 volume_level = "82";
3265 case CALL_SOUND_VOLUME_LEVEL_9:
3267 volume_level = "88";
3270 cmd_str = g_strdup_printf("%s%s", "AT+XDRV=40, 8, 2, ", volume_level); /* Destination type */
3271 dbg("Request command string: %s", cmd_str);
3273 /* Create new Pending request */
3274 dest_pending = tcore_pending_new(o, 0);
3276 /* Create new AT-Command request */
3277 dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3278 if (dest_req == NULL) {
3279 tcore_pending_free(dest_pending);
3281 return TCORE_RETURN_FAILURE;
3283 dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd));
3285 /* Free Command string */
3288 tcore_pending_set_request_data(dest_pending, 0, dest_req);
3291 ret = _call_request_message(dest_pending, o, ur, on_confirmation_call_set_destination_sound_volume_level, NULL);
3293 err("Failed to send AT-Command request");
3294 return TCORE_RETURN_FAILURE;
3297 return TCORE_RETURN_SUCCESS;
3300 static TReturn imc_call_set_sound_mute_status(CoreObject *o, UserRequest *ur)
3302 struct treq_call_set_sound_mute_status *data = NULL;
3303 char *cmd_str = NULL;
3305 TcorePending *pending = NULL;
3306 TcoreATRequest *req = NULL;
3308 dbg("function entrance");
3310 data = (struct treq_call_set_sound_mute_status *) tcore_user_request_ref_data(ur, 0);
3312 if (data->status == CALL_SOUND_MUTE_STATUS_ON)
3313 cmd_str = g_strdup_printf("%s", "AT+XDRV=40, 8, 0, 0, 0");
3314 else if (data->status == CALL_SOUND_MUTE_STATUS_OFF)
3315 cmd_str = g_strdup_printf("%s", "AT+XDRV=40, 8, 0, 0, 88");
3317 dbg("Request command : [%s]", cmd_str);
3319 pending = tcore_pending_new(o, 0);
3321 req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE);
3323 tcore_pending_free(pending);
3325 return TCORE_RETURN_FAILURE;
3327 dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3331 /* Set request data (AT command) to Pending request */
3332 tcore_pending_set_request_data(pending, 0, req);
3335 ret = _call_request_message(pending, o, ur, on_confirmation_call_set_sound_mute_status, NULL);
3337 err("Failed to send AT-Command request");
3338 return TCORE_RETURN_FAILURE;
3342 return TCORE_RETURN_SUCCESS;
3345 static TReturn imc_call_set_preferred_voice_subscription(CoreObject *o, UserRequest *ur)
3347 struct treq_call_set_preferred_voice_subscription *req_data = NULL;
3349 Storage *strg = NULL;
3350 TReturn ret = TCORE_RETURN_FAILURE;
3354 server = tcore_plugin_ref_server(tcore_object_ref_plugin(o));
3355 strg = tcore_server_find_storage(server, "vconf");
3357 req_data = (struct treq_call_set_preferred_voice_subscription *) tcore_user_request_ref_data(ur, NULL);
3358 dbg("Preferred Subscription: [%d]", req_data->preferred_subs);
3360 /* Update VCONF through Storage - req_data->preferred_subs is aligned to VCONFKEY values */
3361 if (tcore_storage_set_int(strg, STORAGE_KEY_TELEPHONY_PREFERRED_VOICE_SUBSCRIPTION, req_data->preferred_subs)) {
3362 struct tresp_call_set_preferred_voice_subscription resp_data = {0, };
3365 resp_data.err = CALL_ERROR_NONE;
3366 ret = tcore_user_request_send_response(ur,
3367 TRESP_CALL_SET_PREFERRED_VOICE_SUBSCRIPTION,
3368 sizeof(struct tresp_call_set_preferred_voice_subscription), &resp_data);
3371 dbg("ret: [0x%x]", ret);
3375 static TReturn imc_call_get_preferred_voice_subscription(CoreObject *o, UserRequest *ur)
3377 struct tresp_call_get_preferred_voice_subscription resp_data = {0, };
3378 TReturn ret = TCORE_RETURN_FAILURE;
3380 Storage *strg = NULL;
3384 server = tcore_plugin_ref_server(tcore_object_ref_plugin(o));
3385 strg = tcore_server_find_storage(server, "vconf");
3387 /* VCONFKEY is aligned to resp_data->preferred_subs type */
3388 resp_data.preferred_subs = tcore_storage_get_int(strg, STORAGE_KEY_TELEPHONY_PREFERRED_VOICE_SUBSCRIPTION);
3389 dbg("Preferred Subscription: [%d]", resp_data.preferred_subs);
3391 resp_data.err = CALL_ERROR_NONE;
3393 ret = tcore_user_request_send_response(ur,
3394 TRESP_CALL_GET_PREFERRED_VOICE_SUBSCRIPTION,
3395 sizeof(struct tresp_call_get_preferred_voice_subscription), &resp_data);
3397 dbg("ret: [0x%x]", ret);
3402 static TReturn _set_dtmf_tone_duration(CoreObject *o, UserRequest *ur)
3404 char *cmd_str = NULL;
3405 TcorePending *pending = NULL;
3406 TcoreATRequest *req = NULL;
3407 gboolean ret = FALSE;
3411 cmd_str = g_strdup_printf("%s", "AT+VTD=3"); /* ~300 mili secs. +VTD= n, where n = (0 - 255) * 1/10 secs. */
3412 dbg("Request command string: %s", cmd_str);
3414 /* Create new Pending request */
3415 pending = tcore_pending_new(o, 0);
3417 /* Create new AT-Command request */
3418 req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
3419 dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd));
3421 /* Free command string */
3424 /* Set request data (AT command) to Pending request */
3425 tcore_pending_set_request_data(pending, 0, req);
3428 ret = _call_request_message(pending, o, ur, _on_confirmation_dtmf_tone_duration, NULL);
3430 err("Failed to send AT-Command request");
3432 tcore_user_request_free(ur);
3435 return TCORE_RETURN_FAILURE;
3439 return TCORE_RETURN_SUCCESS;
3443 /* Call Operations */
3444 static struct tcore_call_operations call_ops = {
3445 .dial = imc_call_outgoing,
3446 .answer = imc_call_answer,
3447 .end = imc_call_release,
3448 .hold = imc_call_hold,
3449 .active = imc_call_active,
3450 .swap = imc_call_swap,
3451 .join = imc_call_join,
3452 .split = imc_call_split,
3453 .deflect = imc_call_deflect,
3454 .transfer = imc_call_transfer,
3455 .start_cont_dtmf = imc_call_start_cont_dtmf,
3456 .stop_cont_dtmf = imc_call_stop_cont_dtmf,
3457 .send_burst_dtmf = NULL,
3458 .set_sound_path = imc_call_set_sound_path,
3459 .set_sound_volume_level = imc_call_set_sound_volume_level,
3460 .get_sound_volume_level = NULL,
3461 .set_sound_mute_status = imc_call_set_sound_mute_status,
3462 .get_sound_mute_status = NULL,
3463 .set_sound_equalization = NULL,
3464 .set_sound_noise_reduction = NULL,
3465 .set_preferred_voice_subscription = imc_call_set_preferred_voice_subscription,
3466 .get_preferred_voice_subscription = imc_call_get_preferred_voice_subscription,
3469 gboolean imc_call_init(TcorePlugin *cp, CoreObject *co_call)
3473 /* Set operations */
3474 tcore_call_set_ops(co_call, &call_ops, TCORE_OPS_TYPE_CP);
3477 tcore_object_add_callback(co_call, "+XCALLSTAT", on_notification_call_info, NULL);
3478 tcore_object_add_callback(co_call, "+CLIP", on_notification_call_clip_info, NULL);
3485 void imc_call_exit(TcorePlugin *cp, CoreObject *co_call)