Updates after review:
Use at_util_call_compare.
So far, we have only done the trivial changes to voice call driver.
We agree on moving more of the state logic to core,
but this is complex and we need more time to discuss and look into this,
particularly regarding call release.
---
drivers/stemodem/voicecall.c | 648 ++
1 files changed, 648 insertions(+), 0 deletions(-)
create mode 100644 drivers/stemodem/voicecall.c
diff --git a/drivers/stemodem/voicecall.c b/drivers/stemodem/voicecall.c
new file mode 100644
index 000..36b9c5c
--- /dev/null
+++ b/drivers/stemodem/voicecall.c
@@ -0,0 +1,648 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2008-2009 Intel Corporation. All rights reserved.
+ * Copyright (C) 2010 ST-Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#define _GNU_SOURCE
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+#include "gatchat.h"
+#include "gatresult.h"
+#include "common.h"
+
+#include "stemodem.h"
+
+enum call_status_ste {
+ STE_CALL_STATUS_IDLE = 0,
+ STE_CALL_STATUS_CALLING = 1,
+ STE_CALL_STATUS_CONNECTING = 2,
+ STE_CALL_STATUS_ACTIVE = 3,
+ STE_CALL_STATUS_HOLD = 4,
+ STE_CALL_STATUS_WAITING = 5,
+ STE_CALL_STATUS_ALERTING = 6,
+ STE_CALL_STATUS_BUSY = 7
+};
+
+static const char *none_prefix[] = { NULL };
+
+struct voicecall_data {
+ GSList *calls;
+ unsigned int local_release;
+ GAtChat *chat;
+};
+
+struct release_id_req {
+ struct ofono_voicecall *vc;
+ ofono_voicecall_cb_t cb;
+ void *data;
+ int id;
+};
+
+struct change_state_req {
+ struct ofono_voicecall *vc;
+ ofono_voicecall_cb_t cb;
+ void *data;
+ int affected_types;
+};
+
+/* Translate from the ECAV-based STE-status to CLCC based status */
+static int call_status_ste_to_ofono(int status)
+{
+ switch (status) {
+ case STE_CALL_STATUS_IDLE:
+ return CALL_STATUS_DISCONNECTED;
+ case STE_CALL_STATUS_CALLING:
+ return CALL_STATUS_DIALING;
+ case STE_CALL_STATUS_CONNECTING:
+ return CALL_STATUS_ALERTING;
+ case STE_CALL_STATUS_ACTIVE:
+ return CALL_STATUS_ACTIVE;
+ case STE_CALL_STATUS_HOLD:
+ return CALL_STATUS_HELD;
+ case STE_CALL_STATUS_WAITING:
+ return CALL_STATUS_WAITING;
+ case STE_CALL_STATUS_ALERTING:
+ return CALL_STATUS_INCOMING;
+ case STE_CALL_STATUS_BUSY:
+ return CALL_STATUS_DISCONNECTED;
+ default:
+ return CALL_STATUS_DISCONNECTED;
+ }
+}
+
+static struct ofono_call *create_call(struct ofono_voicecall *vc, int type,
+ int direction, int status,
+ const char *num, int num_type, int clip)
+{
+ struct voicecall_data *d = ofono_voicecall_get_data(vc);
+ struct ofono_call *call;
+
+ /* Generate a call structure for the waiting call */
+ call = g_try_new0(struct ofono_call, 1);
+ if (!call)
+ return NULL;
+
+ call->type = type;
+ call->direction = direction;
+ call->status = status;
+
+ if (clip != 2) {
+ strncpy(call->phone_number.number, num,
+ OFONO_MAX_PHONE_NUMBER_LENGTH);
+ call->phone_number.type = num_type;
+ }
+
+ call->clip_validity = clip;
+
+ d->calls = g_slist_insert_sorted(d->calls, call, at_util_call_compare);
+
+ return call;
+}
+
+static void ste_generic_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct change_state_req *req = user_data;
+ struct voicecall_data *vd = ofono_voicecall_get_data(req->vc);
+ struct ofono_error error;
+
+ dump_response("ste_generic_cb", ok, result);
+ decode_at_error(&error, g_at_result_final_response(result));
+
+ if (ok && req->affected_types) {
+ GSList *l;
+ struct ofono_call *call;
+
+ for (l = vd->calls; l; l = l->next) {
+ call = l->data;
+
+ if (req->affected_types & (0x1 << call->status))
+ vd->lo