3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include <ofono/log.h>
35 #include <ofono/modem.h>
36 #include <ofono/voicecall.h>
39 #include "gatresult.h"
44 static const char *none_prefix[] = { NULL };
45 static const char *xlema_prefix[] = { "+XLEMA:", NULL };
47 struct voicecall_data {
49 unsigned int local_release;
54 struct release_id_req {
55 struct ofono_voicecall *vc;
56 ofono_voicecall_cb_t cb;
61 struct change_state_req {
62 struct ofono_voicecall *vc;
63 ofono_voicecall_cb_t cb;
68 static int class_to_call_type(int cls)
82 static struct ofono_call *create_call(struct ofono_voicecall *vc, int type,
83 int direction, int status,
84 const char *num, int num_type,
87 struct voicecall_data *d = ofono_voicecall_get_data(vc);
88 struct ofono_call *call;
90 /* Generate a call structure for the waiting call */
91 call = g_try_new(struct ofono_call, 1);
95 ofono_call_init(call);
99 call->direction = direction;
100 call->status = status;
103 strncpy(call->phone_number.number, num,
104 OFONO_MAX_PHONE_NUMBER_LENGTH);
105 call->phone_number.type = num_type;
108 call->clip_validity = clip;
110 d->calls = g_slist_insert_sorted(d->calls, call, at_util_call_compare);
115 static void xcallstat_notify(GAtResult *result, gpointer user_data)
117 struct ofono_voicecall *vc = user_data;
118 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
123 struct ofono_call *new_call;
124 struct ofono_call *existing_call = NULL;
126 g_at_result_iter_init(&iter, result);
128 if (g_at_result_iter_next(&iter, "+XCALLSTAT:") == FALSE)
131 if (g_at_result_iter_next_number(&iter, &id) == FALSE)
134 if (g_at_result_iter_next_number(&iter, &status) == FALSE)
137 l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(id),
138 at_util_call_compare_by_id);
140 if (l == NULL && status != CALL_STATUS_DIALING &&
141 status != CALL_STATUS_INCOMING &&
142 status != CALL_STATUS_WAITING) {
143 ofono_error("Received XCALLSTAT for an untracked"
144 " call, this indicates a bug!");
149 existing_call = l->data;
152 case CALL_STATUS_DISCONNECTED:
154 enum ofono_disconnect_reason reason;
156 existing_call->status = status;
158 if (vd->local_release & (1 << existing_call->id))
159 reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
161 reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
163 ofono_voicecall_disconnected(vc, existing_call->id,
166 vd->local_release &= ~(1 << existing_call->id);
167 vd->calls = g_slist_remove(vd->calls, l->data);
168 g_free(existing_call);
171 case CALL_STATUS_DIALING:
172 case CALL_STATUS_WAITING:
173 case CALL_STATUS_INCOMING:
177 /* Handle the following situation:
178 * Active Call + Waiting Call. Active Call is Released.
179 * The Waiting call becomes Incoming. In this case, no
180 * need to create a new call. Call status change will be
181 * triggered from clip_notify.
184 existing_call->status = status;
188 if (status == CALL_STATUS_DIALING)
189 direction = CALL_DIRECTION_MOBILE_ORIGINATED;
191 direction = CALL_DIRECTION_MOBILE_TERMINATED;
193 new_call = create_call(vc, 0, direction, status,
195 CLIP_VALIDITY_NOT_AVAILABLE, id);
196 if (new_call == NULL) {
197 ofono_error("Unable to malloc. "
198 "Call management is fubar");
205 case CALL_STATUS_ALERTING:
206 case CALL_STATUS_ACTIVE:
207 case CALL_STATUS_HELD:
209 /* For connected status, simply reset back to active */
211 status = CALL_STATUS_ACTIVE;
213 existing_call->status = status;
214 ofono_voicecall_notify(vc, existing_call);
219 static void xem_notify(GAtResult *result, gpointer user_data)
221 //struct ofono_voicecall *vc = user_data;
222 //struct voicecall_data *vd = ofono_voicecall_get_data(vc);
226 g_at_result_iter_init(&iter, result);
228 if (g_at_result_iter_next(&iter, "+XEM:") == FALSE)
231 if (g_at_result_iter_next_number(&iter, &state) == FALSE)
234 DBG("state %d", state);
238 ofono_info("Emergency call is finished");
241 ofono_info("Emergency call is entered");
246 static void generic_cb(gboolean ok, GAtResult *result, gpointer user_data)
248 struct change_state_req *req = user_data;
249 struct voicecall_data *vd = ofono_voicecall_get_data(req->vc);
250 struct ofono_error error;
252 decode_at_error(&error, g_at_result_final_response(result));
254 if (ok && req->affected_types) {
256 struct ofono_call *call;
258 for (l = vd->calls; l; l = l->next) {
261 if (req->affected_types & (1 << call->status))
262 vd->local_release |= (1 << call->id);
266 req->cb(&error, req->data);
269 static void release_id_cb(gboolean ok, GAtResult *result,
272 struct release_id_req *req = user_data;
273 struct voicecall_data *vd = ofono_voicecall_get_data(req->vc);
274 struct ofono_error error;
276 decode_at_error(&error, g_at_result_final_response(result));
279 vd->local_release |= 1 << req->id;
281 req->cb(&error, req->data);
284 static void atd_cb(gboolean ok, GAtResult *result, gpointer user_data)
286 struct cb_data *cbd = user_data;
287 ofono_voicecall_cb_t cb = cbd->cb;
288 struct ofono_error error;
290 decode_at_error(&error, g_at_result_final_response(result));
292 /* Let oFono core will generate a call with the dialed number
293 * inside its dial callback.
295 cb(&error, cbd->data);
298 static void ifx_dial(struct ofono_voicecall *vc,
299 const struct ofono_phone_number *ph,
300 enum ofono_clir_option clir, ofono_voicecall_cb_t cb,
303 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
304 struct cb_data *cbd = cb_data_new(cb, data);
310 snprintf(buf, sizeof(buf), "ATD+%s", ph->number);
312 snprintf(buf, sizeof(buf), "ATD%s", ph->number);
315 case OFONO_CLIR_OPTION_INVOCATION:
318 case OFONO_CLIR_OPTION_SUPPRESSION:
327 if (g_at_chat_send(vd->chat, buf, none_prefix,
328 atd_cb, cbd, g_free) > 0)
333 CALLBACK_WITH_FAILURE(cb, data);
336 static void ifx_template(const char *cmd, struct ofono_voicecall *vc,
337 GAtResultFunc result_cb, unsigned int affected_types,
338 ofono_voicecall_cb_t cb, void *data)
340 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
341 struct change_state_req *req = g_try_new0(struct change_state_req, 1);
349 req->affected_types = affected_types;
351 if (g_at_chat_send(vd->chat, cmd, none_prefix,
352 result_cb, req, g_free) > 0)
358 CALLBACK_WITH_FAILURE(cb, data);
361 static void ifx_answer(struct ofono_voicecall *vc,
362 ofono_voicecall_cb_t cb, void *data)
364 ifx_template("ATA", vc, generic_cb, 0, cb, data);
367 static void ifx_ath(struct ofono_voicecall *vc,
368 ofono_voicecall_cb_t cb, void *data)
370 /* Hangup active + held call, but not waiting */
371 ifx_template("ATH", vc, generic_cb, 0x1f, cb, data);
374 static void ifx_chup(struct ofono_voicecall *vc,
375 ofono_voicecall_cb_t cb, void *data)
377 /* Hangup active + but not held or waiting */
378 ifx_template("AT+CHUP", vc, generic_cb, 0x1d, cb, data);
381 static void ifx_hold_all_active(struct ofono_voicecall *vc,
382 ofono_voicecall_cb_t cb, void *data)
384 ifx_template("AT+CHLD=2", vc, generic_cb, 0, cb, data);
387 static void ifx_release_all_held(struct ofono_voicecall *vc,
388 ofono_voicecall_cb_t cb, void *data)
390 unsigned int held_status = 1 << CALL_STATUS_HELD;
391 ifx_template("AT+CHLD=0", vc, generic_cb, held_status, cb, data);
394 static void ifx_set_udub(struct ofono_voicecall *vc,
395 ofono_voicecall_cb_t cb, void *data)
397 unsigned int incoming_or_waiting =
398 (1 << CALL_STATUS_INCOMING) | (1 << CALL_STATUS_WAITING);
400 ifx_template("AT+CHLD=0", vc, generic_cb, incoming_or_waiting,
404 static void ifx_release_all_active(struct ofono_voicecall *vc,
405 ofono_voicecall_cb_t cb, void *data)
407 ifx_template("AT+CHLD=1", vc, generic_cb, 0x1, cb, data);
410 static void ifx_release_specific(struct ofono_voicecall *vc, int id,
411 ofono_voicecall_cb_t cb, void *data)
413 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
414 struct release_id_req *req = g_try_new0(struct release_id_req, 1);
425 snprintf(buf, sizeof(buf), "AT+CHLD=1%d", id);
427 if (g_at_chat_send(vd->chat, buf, none_prefix,
428 release_id_cb, req, g_free) > 0)
434 CALLBACK_WITH_FAILURE(cb, data);
437 static void ifx_private_chat(struct ofono_voicecall *vc, int id,
438 ofono_voicecall_cb_t cb, void *data)
442 snprintf(buf, sizeof(buf), "AT+CHLD=2%d", id);
443 ifx_template(buf, vc, generic_cb, 0, cb, data);
446 static void ifx_create_multiparty(struct ofono_voicecall *vc,
447 ofono_voicecall_cb_t cb, void *data)
449 ifx_template("AT+CHLD=3", vc, generic_cb, 0, cb, data);
452 static void ifx_transfer(struct ofono_voicecall *vc,
453 ofono_voicecall_cb_t cb, void *data)
456 unsigned int transfer = 0x1 | 0x2;
458 /* Transfer can puts held & active calls together and disconnects
459 * from both. However, some networks support transferring of
460 * dialing/ringing calls as well.
462 transfer |= 0x4 | 0x8;
464 ifx_template("AT+CHLD=4", vc, generic_cb, transfer, cb, data);
467 static void ifx_deflect(struct ofono_voicecall *vc,
468 const struct ofono_phone_number *ph,
469 ofono_voicecall_cb_t cb, void *data)
472 unsigned int incoming_or_waiting =
473 (1 << CALL_STATUS_INCOMING) | (1 << CALL_STATUS_WAITING);
475 snprintf(buf, sizeof(buf), "AT+CTFR=%s,%d", ph->number, ph->type);
476 ifx_template(buf, vc, generic_cb, incoming_or_waiting, cb, data);
479 static void ifx_swap_without_accept(struct ofono_voicecall *vc,
480 ofono_voicecall_cb_t cb, void *data)
482 ifx_template("AT+CHLD=6", vc, generic_cb, 0, cb, data);
485 static void vts_cb(gboolean ok, GAtResult *result, gpointer user_data)
487 struct cb_data *cbd = user_data;
488 ofono_voicecall_cb_t cb = cbd->cb;
489 struct ofono_error error;
491 decode_at_error(&error, g_at_result_final_response(result));
492 cb(&error, cbd->data);
495 static void ifx_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
496 ofono_voicecall_cb_t cb, void *data)
498 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
499 struct cb_data *cbd = cb_data_new(cb, data);
500 int len = strlen(dtmf);
505 /* strlen("+VTS=T\;") = 7 + initial AT + null */
506 buf = g_try_new(char, len * 7 + 3);
510 s = sprintf(buf, "AT+VTS=%c", dtmf[0]);
512 for (i = 1; i < len; i++)
513 s += sprintf(buf + s, ";+VTS=%c", dtmf[i]);
515 s = g_at_chat_send(vd->chat, buf, none_prefix,
516 vts_cb, cbd, g_free);
526 CALLBACK_WITH_FAILURE(cb, data);
529 static void cring_notify(GAtResult *result, gpointer user_data)
531 struct ofono_voicecall *vc = user_data;
532 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
536 struct ofono_call *call;
538 /* Handle the following situation:
539 * Active Call + Waiting Call. Active Call is Released. The Waiting
540 * call becomes Incoming and CRING indications are signaled.
541 * Sometimes these arrive before the actual state change notification.
542 * If this happens, simply ignore the CRING when a waiting call
543 * exists (cannot have waiting + incoming in GSM)
545 if (g_slist_find_custom(vd->calls,
546 GINT_TO_POINTER(CALL_STATUS_WAITING),
547 at_util_call_compare_by_status))
550 l = g_slist_find_custom(vd->calls,
551 GINT_TO_POINTER(CALL_STATUS_INCOMING),
552 at_util_call_compare_by_status);
554 ofono_error("CRING received before XCALLSTAT!!!");
558 g_at_result_iter_init(&iter, result);
560 if (!g_at_result_iter_next(&iter, "+CRING:"))
563 line = g_at_result_iter_raw_line(&iter);
569 /* Ignore everything that is not voice for now */
570 if (!strcasecmp(line, "VOICE"))
575 /* Assume the CLIP always arrives, and we signal the call there */
579 static void clip_notify(GAtResult *result, gpointer user_data)
581 struct ofono_voicecall *vc = user_data;
582 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
587 struct ofono_call *call;
589 l = g_slist_find_custom(vd->calls,
590 GINT_TO_POINTER(CALL_STATUS_INCOMING),
591 at_util_call_compare_by_status);
593 ofono_error("CLIP for unknown call");
597 g_at_result_iter_init(&iter, result);
599 if (!g_at_result_iter_next(&iter, "+CLIP:"))
602 if (!g_at_result_iter_next_string(&iter, &num))
605 if (!g_at_result_iter_next_number(&iter, &type))
613 /* Skip subaddr, satype and alpha */
614 g_at_result_iter_skip_next(&iter);
615 g_at_result_iter_skip_next(&iter);
616 g_at_result_iter_skip_next(&iter);
618 /* If we have CLI validity field, override our guessed value */
619 g_at_result_iter_next_number(&iter, &validity);
621 DBG("clip_notify: %s %d %d", num, type, validity);
625 strncpy(call->phone_number.number, num,
626 OFONO_MAX_PHONE_NUMBER_LENGTH);
627 call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
628 call->phone_number.type = type;
629 call->clip_validity = validity;
632 ofono_voicecall_notify(vc, call);
635 static void cnap_notify(GAtResult *result, gpointer user_data)
637 struct ofono_voicecall *vc = user_data;
638 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
643 struct ofono_call *call;
646 * Currently, its not clear which URC will contain the
647 * calling party name for the waiting call.
649 l = g_slist_find_custom(vd->calls,
650 GINT_TO_POINTER(CALL_STATUS_INCOMING),
651 at_util_call_compare_by_status);
653 ofono_error("CNAP for unknown call");
657 g_at_result_iter_init(&iter, result);
659 if (!g_at_result_iter_next(&iter, "+CNAP:"))
662 if (!g_at_result_iter_next_string(&iter, &name))
665 if (strlen(name) > 0)
666 validity = CNAP_VALIDITY_VALID;
668 validity = CNAP_VALIDITY_NOT_AVAILABLE;
670 /* If we have CNI validity field, override our guessed value */
671 g_at_result_iter_next_number(&iter, &validity);
673 DBG("%s %d", name, validity);
677 strncpy(call->name, name, OFONO_MAX_CALLER_NAME_LENGTH);
678 call->name[OFONO_MAX_CALLER_NAME_LENGTH] = '\0';
679 call->cnap_validity = validity;
682 ofono_voicecall_notify(vc, call);
685 static void ccwa_notify(GAtResult *result, gpointer user_data)
687 struct ofono_voicecall *vc = user_data;
688 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
691 int num_type, validity, cls;
693 struct ofono_call *call;
695 l = g_slist_find_custom(vd->calls,
696 GINT_TO_POINTER(CALL_STATUS_WAITING),
697 at_util_call_compare_by_status);
699 ofono_error("CCWA received before XCALLSTAT!!!");
703 g_at_result_iter_init(&iter, result);
705 if (!g_at_result_iter_next(&iter, "+CCWA:"))
708 if (!g_at_result_iter_next_string(&iter, &num))
711 if (!g_at_result_iter_next_number(&iter, &num_type))
714 if (!g_at_result_iter_next_number(&iter, &cls))
717 /* Skip alpha field */
718 g_at_result_iter_skip_next(&iter);
725 /* If we have CLI validity field, override our guessed value */
726 g_at_result_iter_next_number(&iter, &validity);
728 DBG("ccwa_notify: %s %d %d %d", num, num_type, cls, validity);
732 call->type = class_to_call_type(cls);
733 strncpy(call->phone_number.number, num, OFONO_MAX_PHONE_NUMBER_LENGTH);
734 call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
735 call->phone_number.type = num_type;
736 call->clip_validity = validity;
738 if (call->type == 0) /* Only notify voice calls */
739 ofono_voicecall_notify(vc, call);
742 static void xcolp_notify(GAtResult *result, gpointer user_data)
744 struct ofono_voicecall *vc = user_data;
745 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
750 struct ofono_call *call;
752 g_at_result_iter_init(&iter, result);
754 if (!g_at_result_iter_next(&iter, "+XCOLP:"))
757 if (!g_at_result_iter_next_number(&iter, &call_id))
760 if (!g_at_result_iter_next_string(&iter, &num))
763 if (!g_at_result_iter_next_number(&iter, &type))
766 if (strlen(num) == 0) {
767 ofono_error("XCOLP received with invalid number!!!");
771 DBG("xcolp_notify: %d %s %d", call_id, num, type);
773 l = g_slist_find_custom(vd->calls,
774 GINT_TO_POINTER(call_id),
775 at_util_call_compare_by_id);
777 ofono_error("XCOLP for unknown call");
783 strncpy(call->phone_number.number, num, OFONO_MAX_PHONE_NUMBER_LENGTH);
784 call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
785 call->phone_number.type = type;
786 call->clip_validity = CLIP_VALIDITY_VALID;
788 ofono_voicecall_notify(vc, call);
791 static void xlema_notify(GAtResult *result, gpointer user_data)
793 struct ofono_voicecall *vc = user_data;
794 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
796 int index, total_cnt;
799 int count = (vd->en_list == NULL) ? 0 : g_strv_length(vd->en_list);
801 g_at_result_iter_init(&iter, result);
803 if (!g_at_result_iter_next(&iter, "+XLEMA:"))
806 if (!g_at_result_iter_next_number(&iter, &index))
809 if (!g_at_result_iter_next_number(&iter, &total_cnt))
812 if (!g_at_result_iter_next_string(&iter, &number))
816 if (g_at_result_iter_skip_next(&iter) == FALSE)
820 if (g_at_result_iter_skip_next(&iter) == FALSE)
823 /* If we succeed here, then the number is from NVM or NITZ */
824 if (g_at_result_iter_skip_next(&iter) == FALSE)
827 if (vd->en_list == NULL)
828 vd->en_list = g_new0(char *, total_cnt + 1);
830 len = strspn(number, "0123456789");
831 vd->en_list[count] = g_strndup(number, len);
833 if (number[len] != '\0')
834 ofono_warn("Malformed emergency number: %.*s", len, number);
837 if (index != total_cnt)
841 ofono_voicecall_en_list_notify(vc, vd->en_list);
843 g_strfreev(vd->en_list);
848 static void xlema_read(gboolean ok, GAtResult *result, gpointer user_data)
850 struct ofono_voicecall *vc = user_data;
851 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
854 int index, total_cnt;
859 DBG("Emergency number list read failed");
863 g_at_result_iter_init(&iter, result);
865 while (g_at_result_iter_next(&iter, "+XLEMA:"))
868 vd->en_list = g_new0(char *, num + 1);
871 g_at_result_iter_init(&iter, result);
873 while (g_at_result_iter_next(&iter, "+XLEMA:")) {
874 if (!g_at_result_iter_next_number(&iter, &index))
877 if (!g_at_result_iter_next_number(&iter, &total_cnt))
880 if (!g_at_result_iter_next_string(&iter, &number))
883 len = strspn(number, "0123456789");
884 vd->en_list[num++] = g_strndup(number, len);
886 if (number[len] != '\0')
887 ofono_warn("Malformed emergency number: %.*s",
891 ofono_voicecall_en_list_notify(vc, vd->en_list);
893 g_strfreev(vd->en_list);
897 static void cssi_notify(GAtResult *result, gpointer user_data)
899 struct ofono_voicecall *vc = user_data;
903 g_at_result_iter_init(&iter, result);
905 if (!g_at_result_iter_next(&iter, "+CSSI:"))
908 if (!g_at_result_iter_next_number(&iter, &code))
911 if (!g_at_result_iter_next_number(&iter, &index))
914 ofono_voicecall_ssn_mo_notify(vc, 0, code, index);
917 static void cssu_notify(GAtResult *result, gpointer user_data)
919 struct ofono_voicecall *vc = user_data;
924 struct ofono_phone_number ph;
929 g_at_result_iter_init(&iter, result);
931 if (!g_at_result_iter_next(&iter, "+CSSU:"))
934 if (!g_at_result_iter_next_number(&iter, &code))
937 if (!g_at_result_iter_next_number_default(&iter, -1, &index))
940 if (!g_at_result_iter_next_string(&iter, &num))
943 strncpy(ph.number, num, OFONO_MAX_PHONE_NUMBER_LENGTH);
945 if (!g_at_result_iter_next_number(&iter, &ph.type))
949 ofono_voicecall_ssn_mt_notify(vc, 0, code, index, &ph);
952 static void ifx_voicecall_initialized(gboolean ok, GAtResult *result,
955 struct ofono_voicecall *vc = user_data;
956 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
958 DBG("voicecall_init: registering to notifications");
960 g_at_chat_register(vd->chat, "+CRING:", cring_notify, FALSE, vc, NULL);
961 g_at_chat_register(vd->chat, "+CLIP:", clip_notify, FALSE, vc, NULL);
962 g_at_chat_register(vd->chat, "+CNAP:", cnap_notify, FALSE, vc, NULL);
963 g_at_chat_register(vd->chat, "+CCWA:", ccwa_notify, FALSE, vc, NULL);
964 g_at_chat_register(vd->chat, "+XEM:", xem_notify, FALSE, vc, NULL);
965 g_at_chat_register(vd->chat, "+XCALLSTAT:", xcallstat_notify,
967 g_at_chat_register(vd->chat, "+XCOLP:", xcolp_notify, FALSE, vc, NULL);
968 g_at_chat_register(vd->chat, "+XLEMA:", xlema_notify, FALSE, vc, NULL);
969 g_at_chat_register(vd->chat, "+CSSI:", cssi_notify, FALSE, vc, NULL);
970 g_at_chat_register(vd->chat, "+CSSU:", cssu_notify, FALSE, vc, NULL);
971 /* Enable emergency number list notification */
972 g_at_chat_send(vd->chat, "AT+XLEMA=1", xlema_prefix, xlema_read, vc,
975 ofono_voicecall_register(vc);
978 static int ifx_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
981 GAtChat *chat = data;
982 struct voicecall_data *vd;
984 vd = g_try_new0(struct voicecall_data, 1);
988 vd->chat = g_at_chat_clone(chat);
990 ofono_voicecall_set_data(vc, vd);
992 g_at_chat_send(vd->chat, "AT+XCALLSTAT=1", none_prefix, NULL, NULL,
994 g_at_chat_send(vd->chat, "AT+XEMC=1", none_prefix, NULL, NULL, NULL);
995 g_at_chat_send(vd->chat, "AT+XCOLP=1", none_prefix, NULL, NULL, NULL);
997 g_at_chat_send(vd->chat, "AT+CRC=1", none_prefix, NULL, NULL, NULL);
998 g_at_chat_send(vd->chat, "AT+CLIP=1", none_prefix, NULL, NULL, NULL);
999 g_at_chat_send(vd->chat, "AT+CNAP=1", none_prefix, NULL, NULL, NULL);
1000 g_at_chat_send(vd->chat, "AT+CSSN=1,1", none_prefix, NULL, NULL, NULL);
1001 g_at_chat_send(vd->chat, "AT+CCWA=1", none_prefix,
1002 ifx_voicecall_initialized, vc, NULL);
1007 static void ifx_voicecall_remove(struct ofono_voicecall *vc)
1009 struct voicecall_data *vd = ofono_voicecall_get_data(vc);
1011 g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
1012 g_slist_free(vd->calls);
1014 g_strfreev(vd->en_list);
1016 ofono_voicecall_set_data(vc, NULL);
1018 g_at_chat_unref(vd->chat);
1022 static struct ofono_voicecall_driver driver = {
1024 .probe = ifx_voicecall_probe,
1025 .remove = ifx_voicecall_remove,
1027 .answer = ifx_answer,
1028 .hangup_all = ifx_ath,
1029 .hangup_active = ifx_chup,
1030 .hold_all_active = ifx_hold_all_active,
1031 .release_all_held = ifx_release_all_held,
1032 .set_udub = ifx_set_udub,
1033 .release_all_active = ifx_release_all_active,
1034 .release_specific = ifx_release_specific,
1035 .private_chat = ifx_private_chat,
1036 .create_multiparty = ifx_create_multiparty,
1037 .transfer = ifx_transfer,
1038 .deflect = ifx_deflect,
1039 .swap_without_accept = ifx_swap_without_accept,
1040 .send_tones = ifx_send_dtmf
1043 void ifx_voicecall_init(void)
1045 ofono_voicecall_driver_register(&driver);
1048 void ifx_voicecall_exit(void)
1050 ofono_voicecall_driver_unregister(&driver);