4 * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
28 #include <core_object.h>
37 #include "imc_common.h"
40 #define STATUS_INCOMING 4
41 #define STATUS_WAITING 5
42 #define STATUS_CONNECTED 7
44 #define find_call_object(co, call_id, call_obj) \
46 call_obj = tcore_call_object_find_by_id(co, call_id); \
48 err("unable to find call object"); \
53 struct imc_set_volume_info {
58 static gchar *xdrv_set_volume[] = {
66 /*Forward Declarations*/
67 static void on_response_imc_call_default(TcorePending *p,
68 guint data_len, const void *data, void *user_data);
70 static TelReturn __call_list_get(CoreObject *co, gboolean flag);
72 static TelCallType __call_type(int type)
78 return TEL_CALL_TYPE_VOICE;
81 return TEL_CALL_TYPE_VIDEO;
84 err("invalid call type, returning default call type as voice");
85 return TEL_CALL_TYPE_VOICE;
89 static TelCallState __call_state(int state)
95 return TEL_CALL_STATE_ACTIVE;
98 return TEL_CALL_STATE_HELD;
101 return TEL_CALL_STATE_DIALING;
104 return TEL_CALL_STATE_ALERT;
108 return TEL_CALL_STATE_INCOMING;
111 return TEL_CALL_STATE_IDLE;
115 static void __call_branch_by_status(CoreObject *co, CallObject *call_obj,
116 TelCallState call_state)
118 unsigned int call_id;
119 TelCallType call_type;
121 TcoreNotification command = TCORE_NOTIFICATION_UNKNOWN;
122 dbg("Call State[%d]", call_state);
124 if (tcore_call_object_get_state(call_obj, &state) == FALSE) {
125 err("unable to get call status");
129 if (call_state == state) {
130 dbg("current call state and existing call state are same");
134 if (tcore_call_object_get_call_type(call_obj, &call_type) == FALSE) {
135 err("unable to get call type");
139 if (tcore_call_object_get_id(call_obj, &call_id) == FALSE) {
140 err("unable to get call id");
145 tcore_call_object_set_state(call_obj, call_state);
147 if (call_type == TEL_CALL_TYPE_VOICE) {
148 /* voice call notification */
149 switch (call_state) {
150 case TEL_CALL_STATE_ACTIVE:
151 command = TCORE_NOTIFICATION_CALL_STATUS_ACTIVE;
154 case TEL_CALL_STATE_HELD:
155 command = TCORE_NOTIFICATION_CALL_STATUS_HELD;
158 case TEL_CALL_STATE_DIALING:
159 command = TCORE_NOTIFICATION_CALL_STATUS_DIALING;
162 case TEL_CALL_STATE_ALERT:
163 command = TCORE_NOTIFICATION_CALL_STATUS_ALERT;
166 case TEL_CALL_STATE_INCOMING:
167 case TEL_CALL_STATE_WAITING: {
168 TelCallIncomingInfo incoming = {0,};
169 command = TCORE_NOTIFICATION_CALL_STATUS_INCOMING;
170 incoming.call_id = call_id;
171 tcore_call_object_get_cli_validity(call_obj, &incoming.cli_validity);
172 tcore_call_object_get_number(call_obj, incoming.number);
173 tcore_call_object_get_cni_validity(call_obj, &incoming.cni_validity);
174 tcore_call_object_get_name(call_obj, incoming.name);
175 tcore_call_object_get_mt_forward(call_obj, &incoming.forward);
176 tcore_call_object_get_active_line(call_obj, &incoming.active_line);
178 /* Send notification */
179 tcore_object_send_notification(co, command,
180 sizeof(TelCallIncomingInfo), &incoming);
184 case TEL_CALL_STATE_IDLE: {
185 TelCallStatusIdleNoti idle;
186 command = TCORE_NOTIFICATION_CALL_STATUS_IDLE;
187 idle.call_id = call_id;
189 /* TODO - get proper call end cause. */
190 idle.cause = TEL_CALL_END_CAUSE_NONE;
192 /* Send notification */
193 tcore_object_send_notification(co, command,
194 sizeof(TelCallStatusIdleNoti), &idle);
196 /* Free Call object */
197 tcore_call_object_free(co, call_obj);
203 else if (call_type == TEL_CALL_TYPE_VIDEO) {
204 /* video call notification */
205 switch (call_state) {
206 case TEL_CALL_STATE_ACTIVE:
207 command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_ACTIVE;
210 case TEL_CALL_STATE_HELD:
211 err("invalid state");
214 case TEL_CALL_STATE_DIALING:
215 command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_DIALING;
218 case TEL_CALL_STATE_ALERT:
219 command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_ALERT;
222 case TEL_CALL_STATE_INCOMING:
223 case TEL_CALL_STATE_WAITING:
224 command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_INCOMING;
227 case TEL_CALL_STATE_IDLE: {
228 TelCallStatusIdleNoti idle;
229 command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_IDLE;
230 idle.call_id = call_id;
232 /* TODO - get proper call end cause. */
233 idle.cause = TEL_CALL_END_CAUSE_NONE;
235 /* Send notification */
236 tcore_object_send_notification(co, command,
237 sizeof(TelCallStatusIdleNoti), &idle);
239 /* Free Call object */
240 tcore_call_object_free(co, call_obj);
246 err("Unknown Call type: [%d]", call_type);
249 if (command != TCORE_NOTIFICATION_UNKNOWN)
250 tcore_object_send_notification(co, command, sizeof(call_id), &call_id);
253 static void __handle_call_list_get(CoreObject *co, gboolean flag, void *data)
261 GSList *tokens = NULL;
266 char number[TEL_CALL_CALLING_NUMBER_LEN_MAX +1] = {0,};
267 GSList *lines = data;
268 CallObject *call_obj = NULL;
270 while (lines != NULL) {
271 line = (char *)lines->data;
272 /* point to next node */
274 /* free previous tokens*/
275 tcore_at_tok_free(tokens);
277 tokens = tcore_at_tok_new(line);
280 resp = g_slist_nth_data(tokens, 0);
282 err("Invalid call_id");
285 call_id = atoi(resp);
288 resp = g_slist_nth_data(tokens, 1);
290 err("Invalid direction");
293 direction = (atoi(resp) == 0) ? 1 : 0;
296 resp = g_slist_nth_data(tokens, 2);
298 err("Invalid state");
301 state = __call_state(atoi(resp));
304 resp = g_slist_nth_data(tokens, 3);
306 err("Invalid call_type");
309 call_type = __call_type(atoi(resp));
312 resp = g_slist_nth_data(tokens, 4);
320 resp = g_slist_nth_data(tokens, 5);
322 err("Number is NULL");
324 /* Strike off double quotes */
325 num = tcore_at_tok_extract(resp);
326 dbg("Number: [%s]", num);
329 resp = g_slist_nth_data(tokens, 6);
331 err("Invalid num type");
333 num_type = atoi(resp);
334 /* check number is international or national. */
335 ton = ((num_type) >> 4) & 0x07;
336 if (ton == 1 && num[0] != '+') {
337 /* international number */
339 memcpy(&number[1], num, strlen(num));
341 memcpy(number, num, strlen(num));
347 dbg("Call ID: [%d] Direction: [%s] Call Type: [%d] Multi-party: [%s] "
348 "Number: [%s] TON: [%d] State: [%d]",
349 call_id, (direction ? "Outgoing" : "Incoming"), call_type,
350 (mpty ? "YES" : "NO"), number, ton, state);
352 call_obj = tcore_call_object_find_by_id(co, call_id);
353 if (NULL == call_obj) {
354 call_obj = tcore_call_object_new(co, call_id);
355 if (NULL == call_obj) {
356 err("unable to create call object");
361 /* Set Call parameters */
362 tcore_call_object_set_type(call_obj, call_type);
363 tcore_call_object_set_direction(call_obj, direction);
364 tcore_call_object_set_multiparty_state(call_obj, mpty);
365 tcore_call_object_set_cli_info(call_obj, TEL_CALL_CLI_VALIDITY_VALID, number);
366 tcore_call_object_set_active_line(call_obj, TEL_CALL_ACTIVE_LINE1);
368 __call_branch_by_status(co, call_obj, state);
370 tcore_call_object_set_state(call_obj, state);
374 /* internal notification operation */
375 static void __on_notification_imc_call_incoming(CoreObject *co, unsigned int call_id,
379 CallObject *call_obj = NULL;
382 /* check call with incoming status already exist */
383 list = tcore_call_object_find_by_status(co, TEL_CALL_STATE_INCOMING);
385 err("Incoming call already exist! Skip...");
390 call_obj = tcore_call_object_find_by_id(co, call_id);
391 if (call_obj != NULL) {
392 err("Call object for Call ID [%d] already exist! Skip...", call_id);
396 /* Create new Call object */
397 call_obj = tcore_call_object_new(co, (unsigned int)call_id);
398 if (NULL == call_obj) {
399 err("Failed to create Call object");
403 /* Make request to get current Call list */
404 __call_list_get(co, TRUE);
407 static void __on_notification_imc_call_status(CoreObject *co, unsigned int call_id,
408 unsigned int call_state, void *user_data)
410 CallObject *call_obj = NULL;
413 state = __call_state(call_state);
414 dbg("state [%d]", state);
417 case TEL_CALL_STATE_ACTIVE: {
418 find_call_object(co, call_id, call_obj);
419 /* Send notification to application */
420 __call_branch_by_status(co, call_obj, state);
424 case TEL_CALL_STATE_HELD: {
425 find_call_object(co, call_id, call_obj);
426 /* Send notification to application */
427 __call_branch_by_status(co, call_obj, state);
431 case TEL_CALL_STATE_DIALING: {
432 call_obj = tcore_call_object_find_by_id(co, call_id);
434 call_obj = tcore_call_object_new(co, call_id);
436 err("unable to create call object");
440 /* Make request to get current call list.Update CallObject with <number>
441 * and send notification to application */
442 __call_list_get(co, TRUE);
446 case TEL_CALL_STATE_ALERT: {
447 find_call_object(co, call_id, call_obj);
448 /* Send notification to application */
449 __call_branch_by_status(co, call_obj, TEL_CALL_STATE_ALERT);
453 case TEL_CALL_STATE_IDLE: {
454 find_call_object(co, call_id, call_obj);
455 /* Send notification to application */
456 __call_branch_by_status(co, call_obj, state);
461 err("invalid call status");
466 /*internal response operation */
467 static void __on_response_imc_call_list_get(TcorePending *p, guint data_len, const void *data,
470 const TcoreAtResponse *at_resp = data;
471 CoreObject *co = tcore_pending_ref_core_object(p);
472 ImcRespCbData *resp_cb_data = user_data;
473 GSList *lines = NULL;
474 TelCallResult result = TEL_CALL_RESULT_FAILURE; //TODO - CME error mapping required
475 gboolean *flag = IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
479 tcore_check_return_assert(co != NULL);
480 tcore_check_return_assert(resp_cb_data != NULL);
482 if (at_resp && at_resp->success) {
483 if (NULL == at_resp->lines) {
484 err("invalid response received");
488 lines = (GSList *) at_resp->lines;
489 count = g_slist_length(lines);
490 dbg("Total records : %d", count);
492 err("Call count is zero");
495 result = TEL_CALL_RESULT_SUCCESS;
498 /* parse +CLCC notification parameter */
499 __handle_call_list_get(co, *flag, lines);
506 /*internal request operation */
507 static TelReturn __send_call_request(CoreObject *co, TcoreObjectResponseCallback cb,
508 void *cb_data, gchar *at_cmd, gchar *func_name)
510 ImcRespCbData *resp_cb_data;
513 /* Response callback data */
514 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, func_name,
515 strlen(func_name) + 1);
517 /* Send Request to modem */
518 ret = tcore_at_prepare_and_send_request(co,
520 TCORE_AT_COMMAND_TYPE_NO_RESULT,
522 on_response_imc_call_default, resp_cb_data,
523 on_send_imc_request, NULL);
524 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, func_name);
532 * Operation - Get current call list.
535 * AT-Command: AT+CLCC
539 *[+CLCC: <id1>, <dir>, <stat>, <mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>]]]
543 * +CME ERROR: <error>
545 static TelReturn __call_list_get(CoreObject *co, gboolean flag)
547 ImcRespCbData *resp_cb_data;
548 TelReturn ret = TEL_RETURN_FAILURE;
552 err("Core Object is NULL");
556 /* Response callback data */
557 resp_cb_data = imc_create_resp_cb_data(NULL, NULL, &flag, sizeof(gboolean));
559 /* Send Request to modem */
560 ret = tcore_at_prepare_and_send_request(co,
562 TCORE_AT_COMMAND_TYPE_MULTILINE,
564 __on_response_imc_call_list_get, resp_cb_data,
565 on_send_imc_request, NULL);
566 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get current call list");
574 * Operation - call status notification from network.
575 * notification message format:
576 * +XCALLSTAT: <call_id><stat>
579 * indicates the call identification (GSM02.30 4.5.5.1)
583 * 2 dialling (MO call)
584 * 3 alerting (MO call; ringing for the remote party)
585 * 4 ringing (MT call)
586 * 5 waiting (MT call)
588 * 7 connected (indicates the completion of a call setup first time for MT and MO calls
589 * this is reported in addition to state active)
591 static gboolean on_notification_imc_call_status(CoreObject *co, const void *data,
594 GSList *tokens = NULL;
595 GSList *lines = NULL;
596 const char *line = NULL;
597 char *state = NULL, *call_handle = NULL;
598 unsigned int status, call_id;
602 lines = (GSList *) data;
604 err("Invalid response received");
607 line = (char *) (lines->data);
608 tokens = tcore_at_tok_new(line);
610 call_handle = g_slist_nth_data(tokens, 0);
611 if (NULL == call_handle) {
612 err("call id missing from %XCALLSTAT indication");
615 call_id = atoi(call_handle);
616 state = g_slist_nth_data(tokens, 1);
618 err("call state is missing from %XCALLSTAT indication");
621 status = atoi(state);
622 dbg("call id[%d], status[%d]", call_id, status);
625 case STATUS_INCOMING:
627 __on_notification_imc_call_incoming(co, call_id, user_data);
630 case STATUS_CONNECTED: /* ignore Connected state. */
631 dbg("ignore connected state");
635 __on_notification_imc_call_status(co, call_id, status, user_data);
640 tcore_at_tok_free(tokens);
645 * Operation - SS network initiated notification.
647 * notification message format:
648 * +CSSU: <code2>[<index> [,<number>,<type>]]
650 * (it is manufacturer specific, which of these codes are supported):
651 * 0 this is a forwarded call (MT call setup)
652 * 1 this is a CUG call (<index> present) (MT call setup)
653 * 2 call has been put on hold (during a voice call)
654 * 3 call has been retrieved (during a voice call)
655 * 4 multiparty call entered (during a voice call)
656 * 5 Call has been released - not a SS notification (during a voice call)
657 * 6 forward check SS message received (can be received whenever)
658 * 7 call is being connected (alerting) with the remote party in alerting state
659 * in explicit call transfer operation
660 * (during a voice call)
661 * 8 call has been connected with the other remote party in explicit call transfer
662 * operation (during a voice call or MT call setup)
663 * 9 this is a deflected call (MT call setup)
664 * 10 additional incoming call forwarded
666 * refer Closed user group +CCUG
668 * string type phone of format specified by <type>
670 * type of address octet in integer format.
672 static gboolean on_notification_imc_call_ss_cssu_info(CoreObject *co, const void *event_data,
675 GSList *tokens = NULL;
676 TcoreNotification command = TCORE_NOTIFICATION_UNKNOWN;
685 if (1 != g_slist_length((GSList *) event_data)) {
686 err("unsolicited msg but multiple line");
690 cmd = (char *) ((GSList *) event_data)->data;
691 dbg("ss notification message[%s]", cmd);
693 tokens = tcore_at_tok_new(cmd);
696 resp = g_slist_nth_data(tokens, 0);
698 err("Code2 is missing from +CSSU indication");
699 tcore_at_tok_free(tokens);
705 /* parse [ <index>, <number> <type>] */
706 if ((resp = g_slist_nth_data(tokens, 1)))
709 if ((resp = g_slist_nth_data(tokens, 2))) {
710 /* Strike off double quotes */
711 number = tcore_at_tok_extract(resp);
714 dbg("+CSSU: <code2> = %d <index> = %d <number> = %s ", code2, index, number);
716 /* <code2> - other values will be ignored */
719 command = TCORE_NOTIFICATION_CALL_INFO_MT_FORWARDED;
722 command = TCORE_NOTIFICATION_CALL_INFO_HELD;
725 command = TCORE_NOTIFICATION_CALL_INFO_ACTIVE;
728 command = TCORE_NOTIFICATION_CALL_INFO_JOINED;
732 command = TCORE_NOTIFICATION_CALL_INFO_TRANSFERED;
735 command = TCORE_NOTIFICATION_CALL_INFO_MT_DEFLECTED;
738 dbg("Unsupported +CSSU notification : %d", code2);
742 if (command != TCORE_NOTIFICATION_UNKNOWN)
743 tcore_object_send_notification(co, command, 0, NULL);
744 tcore_at_tok_free(tokens);
751 * Operation - SS network initiated notification.
752 * notification message format:
753 * +CSSI : <code1>[,<index>]
756 * 0 unconditional call forwarding is active
757 * 1 some of the conditional call forwarding are active
758 * 2 call has been forwarded
760 * 4 this is a CUG call (also <index> present)
761 * 5 outgoing calls are barred
762 * 6 incoming calls are barred
763 * 7 CLIR suppression rejected
764 * 8 call has been deflected
767 * refer Closed user group +CCUG.
769 static gboolean on_notification_imc_call_ss_cssi_info(CoreObject *co, const void *event_data,
772 GSList *tokens = NULL;
773 TcoreNotification command = TCORE_NOTIFICATION_UNKNOWN;
781 if (1 != g_slist_length((GSList *) event_data)) {
782 err("unsolicited msg but multiple line");
785 cmd = (char *) ((GSList *) event_data)->data;
786 dbg("ss notification message[%s]", cmd);
788 tokens = tcore_at_tok_new(cmd);
790 resp = g_slist_nth_data(tokens, 0);
792 err("<code1> is missing from %CSSI indication");
793 tcore_at_tok_free(tokens);
799 /* parse [ <index>] */
800 if ((resp = g_slist_nth_data(tokens, 1)))
803 dbg("+CSSI: <code1> = %d <index> = %d ", code1, index);
805 /* <code1> - other values will be ignored */
808 command = TCORE_NOTIFICATION_CALL_INFO_MO_FORWARD_UNCONDITIONAL;
811 command = TCORE_NOTIFICATION_CALL_INFO_MO_FORWARD_CONDITIONAL;
814 command = TCORE_NOTIFICATION_CALL_INFO_MO_FORWARDED;
817 command = TCORE_NOTIFICATION_CALL_INFO_MO_WAITING;
820 command = TCORE_NOTIFICATION_CALL_INFO_MO_BARRED_OUTGOING;
823 command = TCORE_NOTIFICATION_CALL_INFO_MO_BARRED_INCOMING;
826 command = TCORE_NOTIFICATION_CALL_INFO_MO_DEFLECTED;
829 dbg("Unsupported +CSSI notification : %d", code1);
833 if (command != TCORE_NOTIFICATION_UNKNOWN)
834 tcore_object_send_notification(co, command, 0, NULL);
835 tcore_at_tok_free(tokens);
840 static gboolean on_notification_imc_call_clip_info(CoreObject *co, const void *data,
844 /* TODO - handle +CLIP notification*/
849 static void on_response_imc_call_default(TcorePending *p,
850 guint data_len, const void *data, void *user_data)
852 const TcoreAtResponse *at_resp = data;
853 CoreObject *co = tcore_pending_ref_core_object(p);
854 ImcRespCbData *resp_cb_data = user_data;
856 TelCallResult result = TEL_CALL_RESULT_FAILURE;
859 tcore_check_return_assert(co != NULL);
860 tcore_check_return_assert(resp_cb_data != NULL);
862 if (at_resp && at_resp->success) {
863 result = TEL_CALL_RESULT_SUCCESS;
865 err("ERROR[%s] CME error[%s]",at_resp->final_response,
866 at_resp->lines->data);
868 * TODO - need to map CME error and final
869 * response error to TelCallResult
873 dbg("%s: [%s]", IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data),
874 (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
876 /* Invoke callback */
877 if (resp_cb_data->cb)
878 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
880 /* Free callback data */
881 imc_destroy_resp_cb_data(resp_cb_data);
884 static void on_response_imc_call_set_volume_info(TcorePending *p,
885 guint data_len, const void *data, void *user_data)
887 const TcoreAtResponse *at_resp = data;
888 CoreObject *co = tcore_pending_ref_core_object(p);
889 ImcRespCbData *resp_cb_data = user_data;
890 GSList *tokens = NULL;
892 char *resp_str = NULL;
895 /* TODO: XDRV error mapping required */
896 TelCallResult result = TEL_CALL_RESULT_FAILURE;
899 tcore_check_return_assert(co != NULL);
900 tcore_check_return_assert(resp_cb_data != NULL);
902 if (at_resp && at_resp->success) {
903 line = at_resp->lines;
904 tokens = tcore_at_tok_new(line->data);
906 if (!g_slist_nth_data(tokens, 0)) {
907 err("group_id missing");
911 if (!g_slist_nth_data(tokens, 1)) {
912 err(" function_id missing");
916 resp_str = g_slist_nth_data(tokens, 2);
918 err("xdrv result missing");
921 struct imc_set_volume_info *volume_info;
926 error = atoi(resp_str);
932 /* Fetch volume_info from resp_cb_data */
933 volume_info = (struct imc_set_volume_info *)
934 IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
935 dbg("volume info index[%d]", volume_info->next_index);
937 if (xdrv_set_volume[volume_info->next_index] == NULL) {
938 /*Processing of xdrv commands completed */
940 result = TEL_CALL_RESULT_SUCCESS;
942 } else if (volume_info->next_index == 3) {
943 switch ((volume_info->volume) / 10) {
977 at_cmd = g_strdup_printf("%s%s",
978 xdrv_set_volume[volume_info->next_index], vol);
980 /* Increment index to point to next xdrv command */
981 volume_info->next_index += 1;
983 /* Send Request to modem */
984 ret = tcore_at_prepare_and_send_request(co,
986 TCORE_AT_COMMAND_TYPE_SINGLELINE,
988 on_response_imc_call_set_volume_info,
989 resp_cb_data, on_send_imc_request, NULL);
990 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_call_set_volume_info");
998 dbg("Set Volume Info: [%s]",
999 (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1001 /* Invoke callback */
1002 if (resp_cb_data->cb)
1003 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1005 imc_destroy_resp_cb_data(resp_cb_data);
1006 tcore_at_tok_free(tokens);
1009 static void on_response_imc_call_set_sound_path(TcorePending *p,
1010 guint data_len, const void *data, void *user_data)
1012 const TcoreAtResponse *at_resp = data;
1013 CoreObject *co = tcore_pending_ref_core_object(p);
1014 ImcRespCbData *resp_cb_data = user_data;
1015 GSList *tokens = NULL;
1016 GSList *line = NULL;
1017 char *resp_str = NULL;
1019 gint xdrv_func_id = -1;
1021 TelCallResult result = TEL_CALL_RESULT_FAILURE; // TODO: XDRV error mapping is required
1024 tcore_check_return_assert(co != NULL);
1025 tcore_check_return_assert(resp_cb_data != NULL);
1027 if (at_resp && at_resp->success) {
1028 line = at_resp->lines;
1029 tokens = tcore_at_tok_new(line->data);
1030 if (!g_slist_nth_data(tokens, 0)) {
1031 err("group_id missing");
1035 if (!(resp_str = g_slist_nth_data(tokens, 1))) {
1036 err("function_id missing");
1039 xdrv_func_id = atoi(resp_str);
1041 if (!(resp_str = g_slist_nth_data(tokens, 2))) {
1042 err("RESPONSE NOK");
1045 error = atoi(resp_str);
1047 err("RESPONSE NOK");
1051 if (xdrv_func_id == 4) {
1052 /* Send next command to configure destination device type */
1055 gint *device_type = IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
1057 at_cmd = g_strdup_printf("AT+XDRV=40,5,2,0,0,0,0,0,1,0,1,0,%d",
1060 ret = tcore_at_prepare_and_send_request(co,
1062 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1064 on_response_imc_call_set_sound_path, resp_cb_data,
1065 on_send_imc_request, NULL);
1066 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_call_set_sound_path");
1072 result = TEL_CALL_RESULT_SUCCESS;
1076 dbg("Set Sound Path: [%s]",
1077 (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1079 tcore_at_tok_free(tokens);
1081 /* Invoke callback */
1082 if (resp_cb_data->cb)
1083 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1085 imc_destroy_resp_cb_data(resp_cb_data);
1088 static void on_response_set_sound_path(TcorePending *p, guint data_len,
1089 const void *data, void *user_data)
1091 const TcoreAtResponse *at_resp = data;
1092 ImcRespCbData *resp_cb_data = user_data;
1093 TelCallResult result = TEL_CALL_RESULT_FAILURE;
1094 CoreObject *co_call = tcore_pending_ref_core_object(p);
1096 if (at_resp && at_resp->success)
1097 result = TEL_CALL_RESULT_SUCCESS;
1099 if(resp_cb_data->cb)
1100 resp_cb_data->cb(co_call, (gint)result, NULL, resp_cb_data->cb_data);
1102 imc_destroy_resp_cb_data(resp_cb_data);
1105 static void on_response_imc_call_set_mute(TcorePending *p, guint data_len,
1106 const void *data, void *user_data)
1108 const TcoreAtResponse *at_resp = data;
1109 CoreObject *co = tcore_pending_ref_core_object(p);
1110 ImcRespCbData *resp_cb_data = user_data;
1111 GSList *tokens = NULL;
1112 const char *line = NULL;
1113 char *resp_str = NULL;
1116 TelCallResult result = TEL_CALL_RESULT_FAILURE; // TODO: XDRV error mapping is required
1119 tcore_check_return_assert(co != NULL);
1120 tcore_check_return_assert(resp_cb_data != NULL);
1122 if (at_resp && at_resp->success) {
1123 line = (((GSList *)at_resp->lines)->data);
1124 tokens = tcore_at_tok_new(line);
1126 resp_str = g_slist_nth_data(tokens, 0);
1127 if (!g_slist_nth_data(tokens, 0)) {
1128 err("group_id missing");
1132 if (!g_slist_nth_data(tokens, 1)) {
1133 err("function_id missing");
1137 resp_str = g_slist_nth_data(tokens, 2);
1138 if (!(resp_str = g_slist_nth_data(tokens, 1))) {
1139 err("xdrv_result missing");
1142 error = atoi(resp_str);
1144 err(" RESPONSE NOK [%d]", error);
1147 result = TEL_CALL_RESULT_SUCCESS;
1151 dbg("Set Mute: [%s]",
1152 (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
1153 tcore_at_tok_free(tokens);
1155 /* Invoke callback */
1156 if (resp_cb_data->cb)
1157 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
1159 imc_destroy_resp_cb_data(resp_cb_data);
1168 * AT-Command: ATD <num> [I] [G] [;]
1169 * <num> - dialed number
1170 * [I][i] - CLI presentation(supression or invocation)
1171 * [G] - control the CUG supplementary service information for this call.
1182 * +CME ERROR: <error>
1184 static TelReturn imc_call_dial(CoreObject *co, const TelCallDial *dial_info,
1185 TcoreObjectResponseCallback cb, void *cb_data)
1193 if (dial_info->call_type == TEL_CALL_TYPE_VIDEO) {
1194 err("Video call is not supported in imc modem");
1195 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1198 if (!strncmp(dial_info->number, "*31#", 4)) {
1199 dbg("clir suppression");
1201 num = (gchar *)&(dial_info->number[4]);
1202 } else if (!strncmp(dial_info->number, "#31#", 4)) {
1203 dbg("clir invocation");
1205 num = (gchar *)&(dial_info->number[4]);
1209 dbg("no clir string in number");
1211 /* it will be removed when setting application use tapi_ss_set_cli()
1212 * instead of his own vconfkey. (0 : By network, 1 : Show, 2 : Hide)
1214 vconf_get_int("db/ciss/show_my_number", &cli);
1216 dbg("clir invocation from setting application");
1219 dbg("set clir state to default");
1222 num = (gchar *)dial_info->number;
1226 at_cmd = g_strdup_printf("ATD%s%s;", num, clir);
1227 dbg(" at command : %s", at_cmd);
1229 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_dial");
1233 * Operation - Answer/Reject/Replace/hold(current call) & accept incoming call.
1237 * 1. AT-Command: ATA
1242 * +CME ERROR: <error>
1244 * 2. AT-Command: AT+CHLD=[<n>]
1246 * 0 - (deafult)release all held calls or set User Determined User Busy for a waiting/incoming
1247 * call; if both exists then only the waiting call will be rejected.
1248 * 1 - release all active calls and accepts the other (held or waiting)
1249 * Note: In the scenario: An active call, a waiting call and held call, when the active call is
1250 * terminated, we will make the Waiting call as active.
1251 * 2 - place all active calls (if exist) on hold and accepts the other call (held or waiting/in-coming).
1252 * If only one call exists which is active, place it on hold and if only held call exists make it active call.
1257 * +CME ERROR: <error>
1258 * For more informatiion refer 3GPP TS 27.007.
1260 static TelReturn imc_call_answer(CoreObject *co, TelCallAnswerType ans_type,
1261 TcoreObjectResponseCallback cb, void *cb_data)
1266 if (ans_type == TEL_CALL_ANSWER_ACCEPT) {
1268 at_cmd = g_strdup_printf("%s", "ATA");
1269 }else if (ans_type == TEL_CALL_ANSWER_REJECT) {
1271 at_cmd = g_strdup_printf("%s", "AT+CHLD=0");
1272 } else if (ans_type == TEL_CALL_ANSWER_REPLACE) {
1274 at_cmd = g_strdup_printf("%s", "AT+CHLD=1");
1275 } else if (ans_type == TEL_CALL_ANSWER_HOLD_AND_ACCEPT) {
1277 at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
1279 err("Unsupported call answer type");
1280 return TEL_RETURN_FAILURE;
1283 dbg("at command : %s", at_cmd);
1285 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_answer");
1289 * Operation - release all calls/release specific call/release all active
1290 * call/release all held calls.
1293 * 1. AT-Command: AT+CHLD=[<n>]
1295 * 0 - (defualt)release all held calls or set User Determined User -
1296 * Busy for a waiting/incoming.
1297 * call; if both exists then only the waiting call will be rejected.
1298 * 1 - release all active calls and accepts the other (held or waiting).
1299 * 1x - release a specific call (x specific call number as indicated by call id).
1300 * 8 - release all calls.
1305 * +CME ERROR: <error>
1307 static TelReturn imc_call_end(CoreObject *co, const TelCallEnd *end_info,
1308 TcoreObjectResponseCallback cb, void *cb_data)
1313 if (end_info->end_type == TEL_CALL_END_ALL) {
1315 at_cmd = g_strdup_printf("%s", "AT+CHLD=8");
1316 }else if (end_info->end_type == TEL_CALL_END) {
1318 at_cmd = g_strdup_printf("%s%d", "AT+CHLD=1",end_info->call_id);
1319 } else if (end_info->end_type == TEL_CALL_END_ACTIVE_ALL) {
1321 at_cmd = g_strdup_printf("%s", "AT+CHLD=1");
1322 } else if (end_info->end_type == TEL_CALL_END_HOLD_ALL) {
1324 at_cmd = g_strdup_printf("%s", "AT+CHLD=0");
1326 err("Unsupported call end type");
1327 return TEL_RETURN_FAILURE;
1330 dbg("at command : %s", at_cmd);
1332 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_end");
1336 * Operation - send dtmf.
1339 * 1. AT-Command: AT+VTS=<DTMF>,{<DTMF>,<duration>}.
1342 * is a single ASCII character in the set 0-9, #, *, A-D. Even it will support string DTMF.
1344 * integer in range 0-255, meaning 1/10(10 millisec) seconds multiples. The string parameter
1345 * of the command consists of combinations of the following separated by commas:
1346 * NOTE : There is a limit of 50 dtmf tones can be requested through a single VTS command.
1351 * +CME ERROR: <error>
1353 static TelReturn imc_call_send_dtmf(CoreObject *co, const char *dtmf_str,
1354 TcoreObjectResponseCallback cb, void *cb_data)
1357 char *tmp_dtmf = NULL, *dtmf;
1362 //(void) _set_dtmf_tone_duration(o, dup);
1364 /* DTMF digits + comma for each dtmf digit */
1365 tmp_dtmf = tcore_malloc0((strlen(dtmf_str) * 2) + 1);
1366 tcore_check_return_value_assert(tmp_dtmf != NULL, TEL_RETURN_FAILURE);
1367 /* Save initial pointer */
1370 for (count = 0; count < strlen(dtmf_str); count++) {
1371 *tmp_dtmf = dtmf_str[count];
1378 /* last digit is having COMMA , overwrite it with '\0'*/
1379 *(--tmp_dtmf) = '\0';
1381 /* (AT+VTS = <d1>,<d2>,<d3>,<d4>,<d5>,<d6>, ..... <d32> */
1382 at_cmd = g_strdup_printf("AT+VTS=%s", dtmf);
1383 dbg("at command : %s", at_cmd);
1387 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_send_dtmf");
1391 * Operation - call hold.
1394 * 1. AT-Command: AT+CHLD=[<n>]
1397 * 2 - place all active calls (if exist) on hold and accepts the other call (held or waiting/incoming).
1398 * If only one call exists which is active, place it on hold and if only held call exists
1399 * make it active call
1404 * +CME ERROR: <error>
1406 static TelReturn imc_call_hold(CoreObject *co, TcoreObjectResponseCallback cb,
1413 at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
1414 dbg("at command : %s", at_cmd);
1416 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_hold");
1420 * Operation - call active.
1423 * 1. AT-Command: AT+CHLD=[<n>]
1426 * 2 - place all active calls (if exist) on hold and accepts the other call (held or waiting/incoming).
1427 * If only one call exists which is active, place it on hold and if only held call exists
1428 * make it active call
1433 * +CME ERROR: <error>
1435 static TelReturn imc_call_active(CoreObject *co, TcoreObjectResponseCallback cb,
1441 at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
1442 dbg("at command : %s", at_cmd);
1444 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_active");
1448 * Operation - call swap.
1451 * 1. AT-Command: AT+CHLD=[<n>]
1454 * 2 - place all active calls (if exist) on hold and accepts the other call (held or waiting/incoming).
1455 * If only one call exists which is active, place it on hold and if only held call exists
1456 * make it active call
1461 * +CME ERROR: <error>
1463 static TelReturn imc_call_swap(CoreObject *co, TcoreObjectResponseCallback cb,
1469 at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
1470 dbg("at command : %s", at_cmd);
1472 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_swap");
1476 * Operation - call join.
1479 * 1. AT-Command: AT+CHLD=[<n>]
1482 * 3 - adds a held call to the conversation
1487 * +CME ERROR: <error>
1489 static TelReturn imc_call_join(CoreObject *co, TcoreObjectResponseCallback cb,
1495 at_cmd = g_strdup_printf("%s", "AT+CHLD=3");
1496 dbg("at command : %s", at_cmd);
1498 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_join");
1502 * Operation - call split.
1505 * 1. AT-Command: AT+CHLD=[<n>]
1508 * 2x - place all active calls on hold except call x with which communication is supported
1513 * +CME ERROR: <error>
1515 static TelReturn imc_call_split(CoreObject *co, unsigned int call_id,
1516 TcoreObjectResponseCallback cb, void *cb_data)
1521 at_cmd = g_strdup_printf("%s%d", "AT+CHLD=2", call_id);
1522 dbg("at command : %s", at_cmd);
1524 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_split");
1528 * Operation - call transfer.
1531 * 1. AT-Command: AT+CHLD=[<n>]
1534 * 4 connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer)
1539 * +CME ERROR: <error>
1541 static TelReturn imc_call_transfer(CoreObject *co, TcoreObjectResponseCallback cb,
1547 at_cmd = g_strdup_printf("%s", "AT+CHLD=4");
1548 dbg("at command : %s", at_cmd);
1550 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_transfer");
1554 * Operation - call deflect.
1557 * 1. AT-Command: AT+CTFR= <number>[,<type>]
1560 * string type phone number
1562 * type of address octet in integer format. It is optional parameter.
1568 * +CME ERROR: <error>
1570 static TelReturn imc_call_deflect(CoreObject *co, const char *deflect_to,
1571 TcoreObjectResponseCallback cb, void *cb_data)
1576 at_cmd = g_strdup_printf("AT+CTFR=%s", deflect_to);
1577 dbg("at command : %s", at_cmd);
1579 return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_deflect");
1582 static TelReturn imc_call_set_active_line(CoreObject *co, TelCallActiveLine active_line,
1583 TcoreObjectResponseCallback cb, void *cb_data)
1588 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1591 static TelReturn imc_call_get_active_line(CoreObject *co, TcoreObjectResponseCallback cb,
1597 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1601 * Operation - Set voule info.
1604 * AT-Command: AT+XDRV=<group_id>,<function_id>[,<param_n>]
1605 * The first command parameter defines the involved driver group.
1606 * The second command parameter defines a certain function in the selected driver group.
1607 * Other parameters are dependent on the first two parameters.
1608 * Nearly all parameters are integer values, also if they are represented by literals.
1609 * Only very few are strings or
1613 * +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]
1614 * The first response parameter defines the involved driver group.
1615 * The second response parameter defines the current function in the selected driver group.
1616 * The third response parameter defines the xdrv_result of the operation.
1617 * Additional response parameters dependent on the first two parameters.
1619 static TelReturn imc_call_set_volume_info(CoreObject *co, const TelCallVolumeInfo *volume_info,
1620 TcoreObjectResponseCallback cb, void *cb_data)
1622 ImcRespCbData *resp_cb_data = NULL;
1625 struct imc_set_volume_info cb_volume_info;
1629 cb_volume_info.next_index = 1;
1630 cb_volume_info.volume = volume_info->volume;
1632 /* Response callback data */
1633 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
1634 &cb_volume_info, sizeof(struct imc_set_volume_info));
1636 at_cmd = g_strdup_printf("%s", xdrv_set_volume[0]);
1638 /* Send Request to modem */
1639 ret = tcore_at_prepare_and_send_request(co,
1641 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1643 on_response_imc_call_set_volume_info, resp_cb_data,
1644 on_send_imc_request, NULL);
1645 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_call_set_volume_info");
1652 static TelReturn imc_call_get_volume_info(CoreObject *co, TelCallSoundDevice sound_device,
1653 TcoreObjectResponseCallback cb, void *cb_data)
1658 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1662 * Operation - Set sound path.
1665 * AT-Command: AT+XDRV=<group_id>,<function_id>[,<param_n>]
1666 * The first command parameter defines the involved driver group.
1667 * The second command parameter defines a certain function in the selected driver group.
1668 * Other parameters are dependent on the first two parameters.
1669 * Nearly all parameters are integer values, also if they are represented by literals.
1670 * Only very few are strings or
1674 * +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]
1675 * The first response parameter defines the involved driver group.
1676 * The second response parameter defines the current function in the selected driver group.
1677 * The third response parameter defines the xdrv_result of the operation.
1678 * Additional response parameters dependent on the first two parameters.
1681 static TelReturn imc_call_set_sound_path(CoreObject *co, const TelCallSoundPathInfo *sound_path_info,
1682 TcoreObjectResponseCallback cb, void *cb_data)
1684 ImcRespCbData *resp_cb_data = NULL;
1687 gint device_type = -1;
1688 TcorePlugin *plugin = tcore_object_ref_plugin(co);
1689 const char *cp_name = tcore_server_get_cp_name_by_plugin(plugin);
1691 dbg("audio device type - 0x%x", sound_path_info->path);
1693 switch (sound_path_info->path) {
1694 case TEL_SOUND_PATH_HANDSET:
1697 case TEL_SOUND_PATH_HEADSET:
1700 case TEL_SOUND_PATH_HEADSET_3_5PI:
1703 case TEL_SOUND_PATH_SPK_PHONE:
1706 case TEL_SOUND_PATH_HANDSFREE:
1709 case TEL_SOUND_PATH_HEADSET_HAC:
1712 case TEL_SOUND_PATH_BLUETOOTH:
1713 case TEL_SOUND_PATH_STEREO_BLUETOOTH:
1716 case TEL_SOUND_PATH_BT_NSEC_OFF:
1717 case TEL_SOUND_PATH_MIC1:
1718 case TEL_SOUND_PATH_MIC2:
1720 dbg("unsupported device type");
1721 return TEL_RETURN_INVALID_PARAMETER;
1724 if (g_str_has_prefix(cp_name, "imcmodem")) {
1725 /* Response callback data */
1726 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &device_type, sizeof(gint));
1728 at_cmd = g_strdup_printf("AT+XDRV=40,4,3,0,0,0,0,0,1,0,1,0,%d", device_type);
1730 ret = tcore_at_prepare_and_send_request(co,
1732 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1734 on_response_imc_call_set_sound_path, resp_cb_data,
1735 on_send_imc_request, NULL);
1736 IMC_CHECK_REQUEST_RET(ret, NULL, "imc_call_set_sound_path");
1739 /* Response callback data */
1740 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1742 /* Configure modem I2S1 to 8khz, mono, PCM if routing to bluetooth */
1743 if (sound_path_info->path == TEL_SOUND_PATH_BLUETOOTH ||
1744 sound_path_info->path == TEL_SOUND_PATH_STEREO_BLUETOOTH) {
1745 tcore_at_prepare_and_send_request(co,
1746 "AT+XDRV=40,4,3,0,1,0,0,0,0,0,0,0,21",
1747 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1748 NULL, NULL, NULL, NULL, NULL);
1750 tcore_at_prepare_and_send_request(co,
1751 "AT+XDRV=40,5,2,0,1,0,0,0,0,0,0,0,22",
1752 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1753 NULL, NULL, NULL, NULL, NULL);
1755 tcore_at_prepare_and_send_request(co,
1756 "AT+XDRV=40,4,3,0,1,0,8,0,1,0,2,0,21",
1757 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1758 NULL, NULL, NULL, NULL, NULL);
1760 tcore_at_prepare_and_send_request(co,
1761 "AT+XDRV=40,5,2,0,1,0,8,0,1,0,2,0,22",
1762 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1763 NULL, NULL, NULL, NULL, NULL);
1766 /* Configure modem I2S2 and do the modem routing */
1767 tcore_at_prepare_and_send_request(co,
1768 "AT+XDRV=40,4,4,0,0,0,8,0,1,0,2,0,21",
1769 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1770 NULL, NULL, NULL, NULL, NULL);
1772 tcore_at_prepare_and_send_request(co,
1773 "AT+XDRV=40,5,3,0,0,0,8,0,1,0,2,0,22",
1774 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1775 NULL, NULL, NULL, NULL, NULL);
1777 tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,0,4",
1778 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1779 NULL, NULL, NULL, NULL, NULL);
1781 tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,3,0",
1782 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1783 NULL, NULL, NULL, NULL, NULL);
1785 tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,4,2",
1786 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1787 NULL, NULL, NULL, NULL, NULL);
1789 tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,5,2",
1790 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1791 NULL, NULL, NULL, NULL, NULL);
1794 tcore_at_prepare_and_send_request(co, "AT+XDRV=40,2,4",
1795 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1796 NULL, NULL, NULL, NULL, NULL);
1798 tcore_at_prepare_and_send_request(co, "AT+XDRV=40,2,3",
1799 NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT,
1800 NULL, NULL, NULL, NULL, NULL);
1802 /* amc route: AMC_RADIO_RX => AMC_I2S1_TX */
1803 ret = tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,0,2",
1804 "+XDRV", TCORE_AT_COMMAND_TYPE_SINGLELINE, NULL,
1805 on_response_set_sound_path, resp_cb_data, NULL, NULL);
1807 IMC_CHECK_REQUEST_RET(ret, NULL, "imc_call_set_sound_path");
1814 * Operation - Set/Unset mute status.
1817 * AT-Command: AT+XDRV=<group_id>,<function_id>[,<param_n>]
1818 * The first command parameter defines the involved driver group.
1819 * The second command parameter defines a certain function in the selected driver group.
1820 * Other parameters are dependent on the first two parameters.
1821 * Nearly all parameters are integer values, also if they are represented by literals.
1822 * Only very few are strings or
1826 * +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>]
1827 * The first response parameter defines the involved driver group.
1828 * The second response parameter defines the current function in the selected driver group.
1829 * The third response parameter defines the xdrv_result of the operation.
1830 * Additional response parameters dependent on the first two parameters.
1832 static TelReturn imc_call_set_mute(CoreObject *co, gboolean mute, TcoreObjectResponseCallback cb,
1835 ImcRespCbData *resp_cb_data = NULL;
1841 /* Response callback data */
1842 resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0);
1846 at_cmd = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,0"); /*MUTE*/
1848 at_cmd = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,88"); /*UNMUTE*/
1850 /* Send Request to modem */
1851 ret = tcore_at_prepare_and_send_request(co,
1853 TCORE_AT_COMMAND_TYPE_SINGLELINE,
1855 on_response_imc_call_set_mute, resp_cb_data,
1856 on_send_imc_request, NULL);
1857 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_call_set_mute");
1864 static TelReturn imc_call_get_mute_status(CoreObject *co, TcoreObjectResponseCallback cb,
1870 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1874 static TelReturn imc_call_set_sound_recording(CoreObject *co, TelCallSoundRecording sound_rec,
1875 TcoreObjectResponseCallback cb, void *cb_data)
1880 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1883 static TelReturn imc_call_set_sound_equalization(CoreObject *co, const TelCallSoundEqualization *sound_eq,
1884 TcoreObjectResponseCallback cb, void *cb_data)
1889 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
1892 /* Call Operations */
1893 static TcoreCallOps imc_call_ops = {
1894 .dial = imc_call_dial,
1895 .answer = imc_call_answer,
1896 .end = imc_call_end,
1897 .send_dtmf = imc_call_send_dtmf,
1898 .hold = imc_call_hold,
1899 .active = imc_call_active,
1900 .swap = imc_call_swap,
1901 .join = imc_call_join,
1902 .split = imc_call_split,
1903 .transfer = imc_call_transfer,
1904 .deflect = imc_call_deflect,
1905 .set_active_line = imc_call_set_active_line,
1906 .get_active_line = imc_call_get_active_line,
1907 .set_volume_info = imc_call_set_volume_info,
1908 .get_volume_info = imc_call_get_volume_info,
1909 .set_sound_path = imc_call_set_sound_path,
1910 .set_mute = imc_call_set_mute,
1911 .get_mute_status = imc_call_get_mute_status,
1912 .set_sound_recording = imc_call_set_sound_recording,
1913 .set_sound_equalization = imc_call_set_sound_equalization,
1916 gboolean imc_call_init(TcorePlugin *p, CoreObject *co)
1920 /* Set operations */
1921 tcore_call_set_ops(co, &imc_call_ops);
1924 tcore_object_add_callback(co, "+XCALLSTAT", on_notification_imc_call_status, NULL);
1925 tcore_object_add_callback(co, "+CLIP", on_notification_imc_call_clip_info, NULL);
1926 tcore_object_add_callback(co, "+CSSU", on_notification_imc_call_ss_cssu_info, NULL);
1927 tcore_object_add_callback(co, "+CSSI", on_notification_imc_call_ss_cssi_info, NULL);
1932 void imc_call_exit(TcorePlugin *p, CoreObject *co)