modem/ofono: Patches for the getting the voice call working (#1512)

This patchset is based on the branch on the sysmocom.de git,

https://git.sysmocom.de/ofono/log/?h=lynxis/voicecall

The original branch was based on old ofono so this patches are manually
merged to ofono 1.21 and tested on debian initially.
This commit is contained in:
Bhushan Shah 2018-05-26 11:45:19 +05:30 committed by Oliver Smith
parent 4efdfa9700
commit e15476311e
No known key found for this signature in database
GPG Key ID: 5AE7F5513E0885CB
12 changed files with 2449 additions and 3 deletions

View File

@ -0,0 +1,25 @@
From 20653ec096bd0e15c09926f8dfc7771bf2036b9a Mon Sep 17 00:00:00 2001
From: Jonny Lamb <jonny@debian.org>
Date: Mon, 29 Nov 2010 18:04:01 +0000
Subject: [PATCH] doc/ofonod.8: escape minus sign
I'm a sucker for lintian-cleanliness!
Signed-off-by: Jonny Lamb <jonny@debian.org>
---
doc/ofonod.8 | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
Index: ofono-1.21/doc/ofonod.8
===================================================================
--- ofono-1.21.orig/doc/ofonod.8
+++ ofono-1.21/doc/ofonod.8
@@ -18,7 +18,7 @@ is used to manage \fID-Bus\fP permission
.SH OPTIONS
.TP
.B --debug, -d
-Enable debug information output. Note multiple arguments to -d can be
+Enable debug information output. Note multiple arguments to \-d can be
specified, colon, comma or space separated. The arguments are relative
source code filenames for which debugging output should be enabled;
output shell-style globs are accepted (e.g.: "plugins/*:src/main.c").

View File

@ -0,0 +1,205 @@
From c97a48fd4b94d4e6785dd713abe2a06da5e0d623 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Wed, 12 Jul 2017 21:00:00 +0200
Subject: [PATCH 02/17] common: create GList helper ofono_call_compare
replaces at_util_call_compare (atmodem) and
call_compare (rild).
---
drivers/atmodem/atutil.c | 17 ++---------------
drivers/atmodem/atutil.h | 1 -
drivers/atmodem/voicecall.c | 2 +-
drivers/hfpmodem/voicecall.c | 2 +-
drivers/huaweimodem/voicecall.c | 2 +-
drivers/ifxmodem/voicecall.c | 2 +-
drivers/rilmodem/voicecall.c | 16 +---------------
drivers/stemodem/voicecall.c | 2 +-
src/common.c | 14 ++++++++++++++
src/common.h | 2 ++
10 files changed, 24 insertions(+), 36 deletions(-)
Index: ofono-1.21/drivers/atmodem/atutil.c
===================================================================
--- ofono-1.21.orig/drivers/atmodem/atutil.c
+++ ofono-1.21/drivers/atmodem/atutil.c
@@ -32,6 +32,7 @@
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/log.h>
#include <ofono/types.h>
+#include "../src/common.h"
#include "atutil.h"
#include "vendor.h"
@@ -102,20 +103,6 @@ gint at_util_call_compare_by_id(gconstpo
return 0;
}
-gint at_util_call_compare(gconstpointer a, gconstpointer b)
-{
- const struct ofono_call *ca = a;
- const struct ofono_call *cb = b;
-
- if (ca->id < cb->id)
- return -1;
-
- if (ca->id > cb->id)
- return 1;
-
- return 0;
-}
-
GSList *at_util_parse_clcc(GAtResult *result, unsigned int *ret_mpty_ids)
{
GAtResultIter iter;
@@ -174,7 +161,7 @@ GSList *at_util_parse_clcc(GAtResult *re
else
call->clip_validity = 2;
- l = g_slist_insert_sorted(l, call, at_util_call_compare);
+ l = g_slist_insert_sorted(l, call, ofono_call_compare);
if (mpty)
mpty_ids |= 1 << id;
Index: ofono-1.21/drivers/atmodem/atutil.h
===================================================================
--- ofono-1.21.orig/drivers/atmodem/atutil.h
+++ ofono-1.21/drivers/atmodem/atutil.h
@@ -54,7 +54,6 @@ void decode_at_error(struct ofono_error
gint at_util_call_compare_by_status(gconstpointer a, gconstpointer b);
gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
gint at_util_call_compare_by_id(gconstpointer a, gconstpointer b);
-gint at_util_call_compare(gconstpointer a, gconstpointer b);
GSList *at_util_parse_clcc(GAtResult *result, unsigned int *mpty_ids);
gboolean at_util_parse_reg(GAtResult *result, const char *prefix,
int *mode, int *status,
Index: ofono-1.21/drivers/atmodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/atmodem/voicecall.c
+++ ofono-1.21/drivers/atmodem/voicecall.c
@@ -132,7 +132,7 @@ static struct ofono_call *create_call(st
call->clip_validity = clip;
call->cnap_validity = CNAP_VALIDITY_NOT_AVAILABLE;
- d->calls = g_slist_insert_sorted(d->calls, call, at_util_call_compare);
+ d->calls = g_slist_insert_sorted(d->calls, call, ofono_call_compare);
return call;
}
Index: ofono-1.21/drivers/hfpmodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/hfpmodem/voicecall.c
+++ ofono-1.21/drivers/hfpmodem/voicecall.c
@@ -128,7 +128,7 @@ static struct ofono_call *create_call(st
call->phone_number.type = num_type;
}
- d->calls = g_slist_insert_sorted(d->calls, call, at_util_call_compare);
+ d->calls = g_slist_insert_sorted(d->calls, call, ofono_call_compare);
call->clip_validity = clip;
Index: ofono-1.21/drivers/huaweimodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/huaweimodem/voicecall.c
+++ ofono-1.21/drivers/huaweimodem/voicecall.c
@@ -76,7 +76,7 @@ static struct ofono_call *create_call(st
call->clip_validity = clip;
- d->calls = g_slist_insert_sorted(d->calls, call, at_util_call_compare);
+ d->calls = g_slist_insert_sorted(d->calls, call, ofono_call_compare);
return call;
}
Index: ofono-1.21/drivers/ifxmodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/ifxmodem/voicecall.c
+++ ofono-1.21/drivers/ifxmodem/voicecall.c
@@ -107,7 +107,7 @@ static struct ofono_call *create_call(st
call->clip_validity = clip;
- d->calls = g_slist_insert_sorted(d->calls, call, at_util_call_compare);
+ d->calls = g_slist_insert_sorted(d->calls, call, ofono_call_compare);
return call;
}
Index: ofono-1.21/drivers/rilmodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/rilmodem/voicecall.c
+++ ofono-1.21/drivers/rilmodem/voicecall.c
@@ -117,20 +117,6 @@ done:
ofono_voicecall_disconnected(vc, reqdata->id, reason, NULL);
}
-static int call_compare(gconstpointer a, gconstpointer b)
-{
- const struct ofono_call *ca = a;
- const struct ofono_call *cb = b;
-
- if (ca->id < cb->id)
- return -1;
-
- if (ca->id > cb->id)
- return 1;
-
- return 0;
-}
-
static void clcc_poll_cb(struct ril_msg *message, gpointer user_data)
{
struct ofono_voicecall *vc = user_data;
@@ -209,7 +195,7 @@ static void clcc_poll_cb(struct ril_msg
call->id, call->status, call->type,
call->phone_number.number, call->name);
- calls = g_slist_insert_sorted(calls, call, call_compare);
+ calls = g_slist_insert_sorted(calls, call, ofono_call_compare);
}
no_calls:
Index: ofono-1.21/drivers/stemodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/stemodem/voicecall.c
+++ ofono-1.21/drivers/stemodem/voicecall.c
@@ -128,7 +128,7 @@ static struct ofono_call *create_call(st
call->clip_validity = clip;
- d->calls = g_slist_insert_sorted(d->calls, call, at_util_call_compare);
+ d->calls = g_slist_insert_sorted(d->calls, call, ofono_call_compare);
return call;
}
Index: ofono-1.21/src/common.c
===================================================================
--- ofono-1.21.orig/src/common.c
+++ ofono-1.21/src/common.c
@@ -765,3 +765,17 @@ const char *call_status_to_string(enum c
return "unknown";
}
+
+gint ofono_call_compare(gconstpointer a, gconstpointer b)
+{
+ const struct ofono_call *ca = a;
+ const struct ofono_call *cb = b;
+
+ if (ca->id < cb->id)
+ return -1;
+
+ if (ca->id > cb->id)
+ return 1;
+
+ return 0;
+}
Index: ofono-1.21/src/common.h
===================================================================
--- ofono-1.21.orig/src/common.h
+++ ofono-1.21/src/common.h
@@ -184,4 +184,5 @@ const char *registration_tech_to_string(
const char *packet_bearer_to_string(int bearer);
gboolean is_valid_apn(const char *apn);
+gint ofono_call_compare(gconstpointer a, gconstpointer b);
const char *call_status_to_string(enum call_status status);

View File

@ -0,0 +1,54 @@
From 99767e9da1b956afdd08c359785721a293931295 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Tue, 25 Jul 2017 11:34:36 +0200
Subject: [PATCH 03/17] voicecall,common: promote call_status_to_string()
public
call_status_to_string() is useful for debug output.
Change signature to contain enum call_status
Replace default case to get compiler warning when new enums added
---
src/common.c | 21 +++++++++++++++++++++
src/common.h | 1 +
src/voicecall.c | 24 ++----------------------
3 files changed, 24 insertions(+), 22 deletions(-)
Index: ofono-1.21/src/common.c
===================================================================
--- ofono-1.21.orig/src/common.c
+++ ofono-1.21/src/common.c
@@ -779,3 +779,24 @@ gint ofono_call_compare(gconstpointer a,
return 0;
}
+
+const char *ofono_call_status_to_string(enum call_status status)
+{
+ switch (status) {
+ case CALL_STATUS_ACTIVE:
+ return "active";
+ case CALL_STATUS_HELD:
+ return "held";
+ case CALL_STATUS_DIALING:
+ return "dialing";
+ case CALL_STATUS_ALERTING:
+ return "alerting";
+ case CALL_STATUS_INCOMING:
+ return "incoming";
+ case CALL_STATUS_WAITING:
+ return "waiting";
+ case CALL_STATUS_DISCONNECTED:
+ return "disconnected";
+ }
+ return "unknown";
+}
Index: ofono-1.21/src/common.h
===================================================================
--- ofono-1.21.orig/src/common.h
+++ ofono-1.21/src/common.h
@@ -185,4 +185,4 @@ const char *packet_bearer_to_string(int
gboolean is_valid_apn(const char *apn);
gint ofono_call_compare(gconstpointer a, gconstpointer b);
-const char *call_status_to_string(enum call_status status);
+const char *ofono_call_status_to_string(enum call_status status);

View File

@ -0,0 +1,467 @@
From 2ae2366c262a15e4f3269afd9c80ddf06c1b9b46 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Tue, 25 Jul 2017 12:42:29 +0200
Subject: [PATCH 06/17] add call-list helper to manage voice call lists
Many drivers asks the modem for a complete call list of current calls.
These list of calls can be feeded into call-list which parse the
list and notify ofono for new calls.
---
Makefile.am | 13 ++-
include/call-list.h | 38 ++++++++
src/call-list.c | 114 ++++++++++++++++++++++++
unit/test-call-list.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 399 insertions(+), 3 deletions(-)
create mode 100644 include/call-list.h
create mode 100644 src/call-list.c
create mode 100644 unit/test-call-list.c
Index: ofono-1.21/Makefile.am
===================================================================
--- ofono-1.21.orig/Makefile.am
+++ ofono-1.21/Makefile.am
@@ -22,7 +22,7 @@ pkginclude_HEADERS = include/log.h inclu
include/private-network.h include/cdma-netreg.h \
include/cdma-provision.h include/handsfree.h \
include/handsfree-audio.h include/siri.h \
- include/netmon.h include/lte.h
+ include/netmon.h include/lte.h include/call-list.h
nodist_pkginclude_HEADERS = include/version.h
@@ -630,7 +630,7 @@ src_ofonod_SOURCES = $(builtin_sources)
src/cdma-provision.c src/handsfree.c \
src/handsfree-audio.c src/bluetooth.h \
src/hfp.h src/siri.c \
- src/netmon.c src/lte.c \
+ src/netmon.c src/lte.c src/call-list.c \
src/netmonagent.c src/netmonagent.h
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@@ -807,7 +807,8 @@ unit_tests = unit/test-common unit/test-
unit/test-rilmodem-cs \
unit/test-rilmodem-sms \
unit/test-rilmodem-cb \
- unit/test-rilmodem-gprs
+ unit/test-rilmodem-gprs \
+ unit/test-call-list
noinst_PROGRAMS = $(unit_tests) \
unit/test-sms-root unit/test-mux unit/test-caif
@@ -849,6 +850,12 @@ unit_test_sms_root_SOURCES = unit/test-s
unit_test_sms_root_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_sms_root_OBJECTS)
+unit_test_call_list_SOURCES = \
+ src/common.c src/util.c src/log.c \
+ src/call-list.c unit/test-call-list.c
+unit_test_call_list_LDADD = @GLIB_LIBS@ -ldl
+unit_objects += $(unit_test_call_list_OBJECTS)
+
unit_test_mux_SOURCES = unit/test-mux.c $(gatchat_sources)
unit_test_mux_LDADD = @GLIB_LIBS@
unit_objects += $(unit_test_mux_OBJECTS)
Index: ofono-1.21/include/call-list.h
===================================================================
--- /dev/null
+++ ofono-1.21/include/call-list.h
@@ -0,0 +1,38 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2017 Alexander Couzens <lynxis@fe80.eu>
+ *
+ * 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.
+ *
+ */
+
+#include <glib.h>
+
+struct ofono_voicecall;
+struct ofono_phone_number;
+
+/*
+ * Can be called by the driver in the dialing callback,
+ * when the new call id already known
+ */
+void ofono_call_list_dial_callback(struct ofono_voicecall *vc,
+ GSList **call_list,
+ const struct ofono_phone_number *ph,
+ int call_id);
+
+/*
+ * Called with a list of known calls e.g. clcc.
+ * Call list will take ownership of all ofono call within the calls.
+ */
+void ofono_call_list_notify(struct ofono_voicecall *vc,
+ GSList **call_list,
+ GSList *calls);
Index: ofono-1.21/src/call-list.c
===================================================================
--- /dev/null
+++ ofono-1.21/src/call-list.c
@@ -0,0 +1,114 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2017 Alexander Couzens <lynxis@fe80.eu>
+ *
+ * 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.
+ *
+ */
+
+#include <glib.h>
+
+#include "common.h"
+
+#include <ofono/types.h>
+#include <ofono/log.h>
+#include <ofono/voicecall.h>
+#include <ofono/call-list.h>
+
+#include <string.h>
+
+void ofono_call_list_dial_callback(struct ofono_voicecall *vc,
+ GSList **call_list,
+ const struct ofono_phone_number *ph,
+ int call_id)
+{
+ GSList *list;
+ struct ofono_call *call;
+
+ /* list_notify could be triggered before this call back is handled */
+ list = g_slist_find_custom(*call_list,
+ GINT_TO_POINTER(call_id),
+ ofono_call_compare_by_id);
+
+ if (list && list->data) {
+ call = list->data;
+ DBG("Call id %d already known. In state %s(%d)",
+ call_id, ofono_call_status_to_string(call->status),
+ call->status);
+ return;
+ }
+
+ call = g_new0(struct ofono_call, 1);
+ call->id = call_id;
+
+ memcpy(&call->called_number, ph, sizeof(*ph));
+ call->direction = CALL_DIRECTION_MOBILE_ORIGINATED;
+ call->status = CALL_STATUS_DIALING;
+ call->type = 0; /* voice */
+
+ *call_list = g_slist_insert_sorted(*call_list,
+ call,
+ ofono_call_compare);
+ ofono_voicecall_notify(vc, call);
+}
+
+void ofono_call_list_notify(struct ofono_voicecall *vc,
+ GSList **call_list,
+ GSList *calls)
+{
+ GSList *old_calls = *call_list;
+ GSList *new_calls = calls;
+ struct ofono_call *new_call, *old_call;
+
+ while (old_calls || new_calls) {
+ old_call = old_calls ? old_calls->data : NULL;
+ new_call = new_calls ? new_calls->data : NULL;
+
+ /* we drop disconnected calls and treat them as not existent */
+ if (new_call && new_call->status == CALL_STATUS_DISCONNECTED) {
+ new_calls = new_calls->next;
+ calls = g_slist_remove(calls, new_call);
+ g_free(new_call);
+ continue;
+ }
+
+ if (old_call &&
+ (new_call == NULL ||
+ (new_call->id > old_call->id))) {
+ ofono_voicecall_disconnected(
+ vc,
+ old_call->id,
+ OFONO_DISCONNECT_REASON_UNKNOWN,
+ NULL);
+ old_calls = old_calls->next;
+ } else if (new_call &&
+ (old_call == NULL ||
+ (new_call->id < old_call->id))) {
+
+ /* new call, signal it */
+ if (new_call->type == 0)
+ ofono_voicecall_notify(vc, new_call);
+
+ new_calls = new_calls->next;
+ } else {
+ if (memcmp(new_call, old_call, sizeof(*new_call))
+ && new_call->type == 0)
+ ofono_voicecall_notify(vc, new_call);
+
+ new_calls = new_calls->next;
+ old_calls = old_calls->next;
+ }
+ }
+
+ g_slist_free_full(*call_list, g_free);
+ *call_list = calls;
+}
Index: ofono-1.21/unit/test-call-list.c
===================================================================
--- /dev/null
+++ ofono-1.21/unit/test-call-list.c
@@ -0,0 +1,237 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2017 Alexander Couzens <lynxis@fe80.eu>
+ *
+ * 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.
+ *
+ */
+
+
+#include <glib.h>
+#include <string.h>
+
+
+#include "../src/common.h"
+#include <ofono/types.h>
+#include <ofono/call-list.h>
+
+struct voicecall {
+};
+
+struct notified {
+ unsigned int id;
+ enum call_status status;
+};
+
+static struct notified notified_list[32];
+static int notified_idx;
+static int notified_check;
+
+void reset_notified(void)
+{
+ notified_idx = 0;
+ notified_check = 0;
+ memset(&notified_list, 0, sizeof(notified_list));
+}
+
+void ofono_voicecall_notify(struct ofono_voicecall *vc,
+ struct ofono_call *call)
+{
+ notified_list[notified_idx].id = call->id;
+ notified_list[notified_idx].status = call->status;
+ notified_idx++;
+}
+
+void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
+ enum ofono_disconnect_reason reason,
+ const struct ofono_error *error)
+{
+ notified_list[notified_idx].id = id;
+ notified_list[notified_idx].status = CALL_STATUS_DISCONNECTED;
+ notified_idx++;
+}
+
+static GSList *create_call(
+ GSList *calls,
+ unsigned int id,
+ enum call_status status,
+ enum call_direction direction)
+{
+ struct ofono_call *call = g_new0(struct ofono_call, 1);
+
+ call->id = id;
+ call->status = status;
+ call->direction = direction;
+
+ calls = g_slist_insert_sorted(calls, call, ofono_call_compare);
+
+ return calls;
+}
+
+static void assert_notified(unsigned int call_id, int call_status)
+{
+ g_assert(notified_idx >= notified_check);
+ g_assert(notified_list[notified_check].id == call_id);
+ g_assert(notified_list[notified_check].status == call_status);
+
+ notified_check++;
+}
+
+static void test_notify_disconnected(void)
+{
+ struct ofono_voicecall *vc = NULL;
+ struct ofono_phone_number ph;
+ GSList *call_list;
+ GSList *calls;
+
+ strcpy(ph.number, "004888123456");
+ ph.type = 0;
+
+ /* reset test */
+ reset_notified();
+ call_list = NULL;
+
+ /* fill disconnected call*/
+ calls = create_call(NULL, 1, CALL_STATUS_DISCONNECTED,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ ofono_call_list_notify(vc, &call_list, calls);
+
+ /* incoming call */
+ calls = create_call(NULL, 1, CALL_STATUS_DISCONNECTED,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ calls = create_call(calls, 1, CALL_STATUS_ALERTING,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ ofono_call_list_notify(vc, &call_list, calls);
+
+ /* answer call */
+ calls = create_call(NULL, 1, CALL_STATUS_ACTIVE,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ calls = create_call(calls, 1, CALL_STATUS_DISCONNECTED,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ ofono_call_list_notify(vc, &call_list, calls);
+
+ /* another call waiting */
+ calls = create_call(NULL, 1, CALL_STATUS_DISCONNECTED,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ calls = create_call(calls, 1, CALL_STATUS_ACTIVE,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ calls = create_call(calls, 2, CALL_STATUS_DISCONNECTED,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ calls = create_call(calls, 2, CALL_STATUS_WAITING,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ calls = create_call(calls, 2, CALL_STATUS_DISCONNECTED,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ ofono_call_list_notify(vc, &call_list, calls);
+
+ /* end all calls */
+ ofono_call_list_notify(vc, &call_list, NULL);
+
+ /* verify call history */
+ assert_notified(1, CALL_STATUS_ALERTING);
+ assert_notified(1, CALL_STATUS_ACTIVE);
+ assert_notified(2, CALL_STATUS_WAITING);
+ assert_notified(1, CALL_STATUS_DISCONNECTED);
+ assert_notified(2, CALL_STATUS_DISCONNECTED);
+
+ g_assert(notified_check == notified_idx);
+ g_slist_free_full(call_list, g_free);
+}
+
+static void test_notify(void)
+{
+ struct ofono_voicecall *vc = NULL;
+ struct ofono_phone_number ph;
+ GSList *call_list;
+ GSList *calls;
+
+ strcpy(ph.number, "004888123456");
+ ph.type = 0;
+
+ /* reset test */
+ reset_notified();
+ call_list = NULL;
+
+ /* incoming call */
+ calls = create_call(NULL, 1, CALL_STATUS_ALERTING,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ ofono_call_list_notify(vc, &call_list, calls);
+
+ /* answer call */
+ calls = create_call(NULL, 1, CALL_STATUS_ACTIVE,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ ofono_call_list_notify(vc, &call_list, calls);
+
+ /* another call waiting */
+ calls = create_call(NULL, 1, CALL_STATUS_ACTIVE,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ calls = create_call(calls, 2, CALL_STATUS_WAITING,
+ CALL_DIRECTION_MOBILE_TERMINATED);
+ ofono_call_list_notify(vc, &call_list, calls);
+
+ /* end all calls */
+ ofono_call_list_notify(vc, &call_list, NULL);
+
+ /* verify call history */
+ assert_notified(1, CALL_STATUS_ALERTING);
+ assert_notified(1, CALL_STATUS_ACTIVE);
+ assert_notified(2, CALL_STATUS_WAITING);
+ assert_notified(1, CALL_STATUS_DISCONNECTED);
+ assert_notified(2, CALL_STATUS_DISCONNECTED);
+
+ g_assert(notified_check == notified_idx);
+ g_slist_free_full(call_list, g_free);
+}
+
+static void test_dial_callback(void)
+{
+ struct ofono_voicecall *vc = NULL;
+ struct ofono_phone_number ph;
+ struct ofono_call *call;
+ GSList *call_list, *calls;
+
+ /* reset test */
+ reset_notified();
+ call_list = NULL;
+
+ strcpy(ph.number, "0099301234567890");
+ ph.type = 0;
+
+ /* check if a call gets added to the call_list */
+ ofono_call_list_dial_callback(vc, &call_list, &ph, 33);
+
+ call = call_list->data;
+ g_assert(strcmp(call->called_number.number, ph.number) == 0);
+ g_slist_free_full(call_list, g_free);
+
+ /* check when notify is faster than dial_callback */
+ call_list = NULL;
+ calls = create_call(NULL, 1, CALL_STATUS_DIALING,
+ CALL_DIRECTION_MOBILE_ORIGINATED);
+ ofono_call_list_notify(vc, &call_list, calls);
+ ofono_call_list_dial_callback(vc, &call_list, &ph, 1);
+ call = call_list->data;
+ g_assert(call_list->next == NULL);
+ g_slist_free_full(call_list, g_free);
+
+ call_list = NULL;
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/test-call-list/test_notify", test_notify);
+ g_test_add_func("/test-call-list/test_notify_disconnected",
+ test_notify_disconnected);
+ g_test_add_func("/test-call-list/dial_callback", test_dial_callback);
+ return g_test_run();
+}

View File

@ -0,0 +1,313 @@
From 4c71f0ca71c74987523c68764df28840ccd3882e Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Tue, 25 Jul 2017 15:35:51 +0200
Subject: [PATCH 07/17] common,atmodem: rename & move
at_util_call_compare_by_status to common.c
at_util_call_compare_by_status is used by several modem drivers.
---
drivers/atmodem/atutil.c | 11 -----------
drivers/atmodem/atutil.h | 2 +-
drivers/atmodem/voicecall.c | 16 ++++++++--------
drivers/hfpmodem/voicecall.c | 20 ++++++++++----------
drivers/huaweimodem/voicecall.c | 4 ++--
drivers/ifxmodem/voicecall.c | 10 +++++-----
src/common.c | 11 +++++++++++
src/common.h | 1 +
8 files changed, 38 insertions(+), 37 deletions(-)
Index: ofono-1.21/drivers/atmodem/atutil.c
===================================================================
--- ofono-1.21.orig/drivers/atmodem/atutil.c
+++ ofono-1.21/drivers/atmodem/atutil.c
@@ -69,17 +69,6 @@ void decode_at_error(struct ofono_error
}
}
-gint at_util_call_compare_by_status(gconstpointer a, gconstpointer b)
-{
- const struct ofono_call *call = a;
- int status = GPOINTER_TO_INT(b);
-
- if (status != call->status)
- return 1;
-
- return 0;
-}
-
gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b)
{
const struct ofono_call *call = a;
Index: ofono-1.21/drivers/atmodem/atutil.h
===================================================================
--- ofono-1.21.orig/drivers/atmodem/atutil.h
+++ ofono-1.21/drivers/atmodem/atutil.h
@@ -51,7 +51,7 @@ enum at_util_charset {
typedef void (*at_util_sim_inserted_cb_t)(gboolean present, void *userdata);
void decode_at_error(struct ofono_error *error, const char *final);
-gint at_util_call_compare_by_status(gconstpointer a, gconstpointer b);
+gint ofono_call_compare_by_status(gconstpointer a, gconstpointer b);
gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
gint at_util_call_compare_by_id(gconstpointer a, gconstpointer b);
GSList *at_util_parse_clcc(GAtResult *result, unsigned int *mpty_ids);
Index: ofono-1.21/drivers/atmodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/atmodem/voicecall.c
+++ ofono-1.21/drivers/atmodem/voicecall.c
@@ -660,13 +660,13 @@ static void ring_notify(GAtResult *resul
/* See comment in CRING */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
/* RING can repeat, ignore if we already have an incoming call */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
/* Generate an incoming call of unknown type */
@@ -698,13 +698,13 @@ static void cring_notify(GAtResult *resu
*/
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
/* CRING can repeat, ignore if we already have an incoming call */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
g_at_result_iter_init(&iter, result);
@@ -748,7 +748,7 @@ static void clip_notify(GAtResult *resul
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CLIP for unknown call");
return;
@@ -810,7 +810,7 @@ static void cdip_notify(GAtResult *resul
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CDIP for unknown call");
return;
@@ -859,7 +859,7 @@ static void cnap_notify(GAtResult *resul
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CNAP for unknown call");
return;
@@ -913,7 +913,7 @@ static void ccwa_notify(GAtResult *resul
/* Some modems resend CCWA, ignore it the second time around */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
g_at_result_iter_init(&iter, result);
Index: ofono-1.21/drivers/hfpmodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/hfpmodem/voicecall.c
+++ ofono-1.21/drivers/hfpmodem/voicecall.c
@@ -85,12 +85,12 @@ static GSList *find_dialing(GSList *call
GSList *c;
c = g_slist_find_custom(calls, GINT_TO_POINTER(CALL_STATUS_DIALING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (c == NULL)
c = g_slist_find_custom(calls,
GINT_TO_POINTER(CALL_STATUS_ALERTING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
return c;
}
@@ -720,7 +720,7 @@ static void ccwa_notify(GAtResult *resul
/* CCWA can repeat, ignore if we already have an waiting call */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
/* some phones may send extra CCWA after active call is ended
@@ -729,7 +729,7 @@ static void ccwa_notify(GAtResult *resul
*/
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
@@ -772,7 +772,7 @@ static gboolean clip_timeout(gpointer us
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL)
return FALSE;
@@ -801,12 +801,12 @@ static void ring_notify(GAtResult *resul
/* RING can repeat, ignore if we already have an incoming call */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
waiting = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
/* If we started receiving RINGS but have a waiting call, most
* likely all other calls were dropped and we just didn't get
@@ -851,7 +851,7 @@ static void clip_notify(GAtResult *resul
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CLIP for unknown call");
@@ -967,7 +967,7 @@ static void ciev_callsetup_notify(struct
waiting = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
/* This is a truly bizarre case not covered at all by the specification
* (yes, they are complete idiots). Here we assume the other side is
@@ -1046,7 +1046,7 @@ static void ciev_callsetup_notify(struct
{
GSList *o = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_DIALING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (o) {
struct ofono_call *call = o->data;
Index: ofono-1.21/drivers/huaweimodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/huaweimodem/voicecall.c
+++ ofono-1.21/drivers/huaweimodem/voicecall.c
@@ -179,7 +179,7 @@ static void cring_notify(GAtResult *resu
/* CRING can repeat, ignore if we already have an incoming call */
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
g_at_result_iter_init(&iter, result);
@@ -218,7 +218,7 @@ static void clip_notify(GAtResult *resul
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CLIP for unknown call");
return;
Index: ofono-1.21/drivers/ifxmodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/ifxmodem/voicecall.c
+++ ofono-1.21/drivers/ifxmodem/voicecall.c
@@ -545,12 +545,12 @@ static void cring_notify(GAtResult *resu
*/
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
- at_util_call_compare_by_status))
+ ofono_call_compare_by_status))
return;
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CRING received before XCALLSTAT!!!");
return;
@@ -589,7 +589,7 @@ static void clip_notify(GAtResult *resul
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CLIP for unknown call");
return;
@@ -649,7 +649,7 @@ static void cnap_notify(GAtResult *resul
*/
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CNAP for unknown call");
return;
@@ -695,7 +695,7 @@ static void ccwa_notify(GAtResult *resul
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING),
- at_util_call_compare_by_status);
+ ofono_call_compare_by_status);
if (l == NULL) {
ofono_error("CCWA received before XCALLSTAT!!!");
return;
Index: ofono-1.21/src/common.c
===================================================================
--- ofono-1.21.orig/src/common.c
+++ ofono-1.21/src/common.c
@@ -780,6 +780,17 @@ gint ofono_call_compare(gconstpointer a,
return 0;
}
+gint ofono_call_compare_by_status(gconstpointer a, gconstpointer b)
+{
+ const struct ofono_call *call = a;
+ int status = GPOINTER_TO_INT(b);
+
+ if (status != call->status)
+ return 1;
+
+ return 0;
+}
+
const char *ofono_call_status_to_string(enum call_status status)
{
switch (status) {
Index: ofono-1.21/src/common.h
===================================================================
--- ofono-1.21.orig/src/common.h
+++ ofono-1.21/src/common.h
@@ -185,4 +185,5 @@ const char *packet_bearer_to_string(int
gboolean is_valid_apn(const char *apn);
gint ofono_call_compare(gconstpointer a, gconstpointer b);
+gint ofono_call_compare_by_status(gconstpointer a, gconstpointer b);
const char *ofono_call_status_to_string(enum call_status status);

View File

@ -0,0 +1,156 @@
From 3bba30fd23705dc8817b2eb0f28c9be03b8f7892 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Tue, 25 Jul 2017 15:39:36 +0200
Subject: [PATCH 08/17] common,atmodem: rename & move
at_util_call_compare_by_id to common.c
at_util_call_compare_by_id is used by several modem drivers.
---
drivers/atmodem/atutil.c | 14 --------------
drivers/atmodem/atutil.h | 2 +-
drivers/huaweimodem/voicecall.c | 6 +++---
drivers/ifxmodem/voicecall.c | 4 ++--
drivers/stemodem/voicecall.c | 2 +-
src/common.c | 14 ++++++++++++++
src/common.h | 1 +
7 files changed, 22 insertions(+), 21 deletions(-)
Index: ofono-1.21/drivers/atmodem/atutil.c
===================================================================
--- ofono-1.21.orig/drivers/atmodem/atutil.c
+++ ofono-1.21/drivers/atmodem/atutil.c
@@ -78,20 +78,6 @@ gint at_util_call_compare_by_phone_numbe
sizeof(struct ofono_phone_number));
}
-gint at_util_call_compare_by_id(gconstpointer a, gconstpointer b)
-{
- const struct ofono_call *call = a;
- unsigned int id = GPOINTER_TO_UINT(b);
-
- if (id < call->id)
- return -1;
-
- if (id > call->id)
- return 1;
-
- return 0;
-}
-
GSList *at_util_parse_clcc(GAtResult *result, unsigned int *ret_mpty_ids)
{
GAtResultIter iter;
Index: ofono-1.21/drivers/atmodem/atutil.h
===================================================================
--- ofono-1.21.orig/drivers/atmodem/atutil.h
+++ ofono-1.21/drivers/atmodem/atutil.h
@@ -53,7 +53,7 @@ typedef void (*at_util_sim_inserted_cb_t
void decode_at_error(struct ofono_error *error, const char *final);
gint ofono_call_compare_by_status(gconstpointer a, gconstpointer b);
gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
-gint at_util_call_compare_by_id(gconstpointer a, gconstpointer b);
+gint ofono_call_compare_by_id(gconstpointer a, gconstpointer b);
GSList *at_util_parse_clcc(GAtResult *result, unsigned int *mpty_ids);
gboolean at_util_parse_reg(GAtResult *result, const char *prefix,
int *mode, int *status,
Index: ofono-1.21/drivers/huaweimodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/huaweimodem/voicecall.c
+++ ofono-1.21/drivers/huaweimodem/voicecall.c
@@ -347,7 +347,7 @@ static void conf_notify(GAtResult *resul
ofono_info("Call setup: id %d", call_id);
l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(call_id),
- at_util_call_compare_by_id);
+ ofono_call_compare_by_id);
if (l == NULL) {
ofono_error("Received CONF for untracked call");
return;
@@ -384,7 +384,7 @@ static void conn_notify(GAtResult *resul
ofono_info("Call connect: id %d type %d", call_id, call_type);
l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(call_id),
- at_util_call_compare_by_id);
+ ofono_call_compare_by_id);
if (l == NULL) {
ofono_error("Received CONN for untracked call");
return;
@@ -428,7 +428,7 @@ static void cend_notify(GAtResult *resul
call_id, duration, end_status);
l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(call_id),
- at_util_call_compare_by_id);
+ ofono_call_compare_by_id);
if (l == NULL) {
ofono_error("Received CEND for untracked call");
return;
Index: ofono-1.21/drivers/ifxmodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/ifxmodem/voicecall.c
+++ ofono-1.21/drivers/ifxmodem/voicecall.c
@@ -135,7 +135,7 @@ static void xcallstat_notify(GAtResult *
return;
l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(id),
- at_util_call_compare_by_id);
+ ofono_call_compare_by_id);
if (l == NULL && status != CALL_STATUS_DIALING &&
status != CALL_STATUS_INCOMING &&
@@ -773,7 +773,7 @@ static void xcolp_notify(GAtResult *resu
l = g_slist_find_custom(vd->calls,
GINT_TO_POINTER(call_id),
- at_util_call_compare_by_id);
+ ofono_call_compare_by_id);
if (l == NULL) {
ofono_error("XCOLP for unknown call");
return;
Index: ofono-1.21/drivers/stemodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/stemodem/voicecall.c
+++ ofono-1.21/drivers/stemodem/voicecall.c
@@ -462,7 +462,7 @@ static void ecav_notify(GAtResult *resul
* If it doesn't exists we make a new one
*/
l = g_slist_find_custom(vd->calls, GUINT_TO_POINTER(id),
- at_util_call_compare_by_id);
+ ofono_call_compare_by_id);
if (l)
existing_call = l->data;
Index: ofono-1.21/src/common.c
===================================================================
--- ofono-1.21.orig/src/common.c
+++ ofono-1.21/src/common.c
@@ -791,6 +791,20 @@ gint ofono_call_compare_by_status(gconst
return 0;
}
+gint ofono_call_compare_by_id(gconstpointer a, gconstpointer b)
+{
+ const struct ofono_call *call = a;
+ unsigned int id = GPOINTER_TO_UINT(b);
+
+ if (id < call->id)
+ return -1;
+
+ if (id > call->id)
+ return 1;
+
+ return 0;
+}
+
const char *ofono_call_status_to_string(enum call_status status)
{
switch (status) {
Index: ofono-1.21/src/common.h
===================================================================
--- ofono-1.21.orig/src/common.h
+++ ofono-1.21/src/common.h
@@ -186,4 +186,5 @@ const char *packet_bearer_to_string(int
gboolean is_valid_apn(const char *apn);
gint ofono_call_compare(gconstpointer a, gconstpointer b);
gint ofono_call_compare_by_status(gconstpointer a, gconstpointer b);
+gint ofono_call_compare_by_id(gconstpointer a, gconstpointer b);
const char *ofono_call_status_to_string(enum call_status status);

View File

@ -0,0 +1,123 @@
From 32dac2f67735efa1bbfcd7c5563d5cbc980c6770 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Tue, 25 Jul 2017 20:36:00 +0200
Subject: [PATCH 11/17] qmimodem: sync the modem on enable
The qmi sync call release all previous resources.
---
drivers/qmimodem/qmi.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/qmimodem/qmi.h | 5 ++++-
plugins/gobi.c | 12 +++++++++++-
3 files changed, 62 insertions(+), 2 deletions(-)
Index: ofono-1.21/drivers/qmimodem/qmi.c
===================================================================
--- ofono-1.21.orig/drivers/qmimodem/qmi.c
+++ ofono-1.21/drivers/qmimodem/qmi.c
@@ -1323,6 +1323,53 @@ bool qmi_device_shutdown(struct qmi_devi
return true;
}
+struct sync_data {
+ qmi_sync_func_t func;
+ void *user_data;
+};
+
+static void qmi_device_sync_callback(uint16_t message, uint16_t length,
+ const void *buffer, void *user_data)
+{
+ struct sync_data *data = user_data;
+
+ if(data->func)
+ data->func(data->user_data);
+
+ g_free(data);
+}
+
+/* sync will release all previous clients */
+bool qmi_device_sync(struct qmi_device *device,
+ qmi_sync_func_t func, void *user_data)
+{
+ struct qmi_request *req;
+ struct qmi_control_hdr *hdr;
+ struct sync_data *func_data;
+
+ if (!device)
+ return false;
+
+ func_data = g_new0(struct sync_data, 1);
+ func_data->func = func;
+ func_data->user_data = user_data;
+
+ req = __request_alloc(QMI_SERVICE_CONTROL, 0x00,
+ QMI_CTL_SYNC, QMI_CONTROL_HDR_SIZE,
+ NULL, 0,
+ qmi_device_sync_callback, func_data, (void **) &hdr);
+
+ if (device->next_control_tid < 1)
+ device->next_control_tid = 1;
+
+ hdr->type = 0x00;
+ hdr->transaction = device->next_control_tid++;
+
+ __request_submit(device, req, hdr->transaction);
+
+ return true;
+}
+
static bool get_device_file_name(struct qmi_device *device,
char *file_name, int size)
{
Index: ofono-1.21/drivers/qmimodem/qmi.h
===================================================================
--- ofono-1.21.orig/drivers/qmimodem/qmi.h
+++ ofono-1.21/drivers/qmimodem/qmi.h
@@ -76,7 +76,7 @@ typedef void (*qmi_destroy_func_t)(void
struct qmi_device;
typedef void (*qmi_debug_func_t)(const char *str, void *user_data);
-
+typedef void (*qmi_sync_func_t)(void *user_data);
typedef void (*qmi_shutdown_func_t)(void *user_data);
typedef void (*qmi_discover_func_t)(uint8_t count,
const struct qmi_version *list, void *user_data);
@@ -96,6 +96,9 @@ bool qmi_device_discover(struct qmi_devi
bool qmi_device_shutdown(struct qmi_device *device, qmi_shutdown_func_t func,
void *user_data, qmi_destroy_func_t destroy);
+bool qmi_device_sync(struct qmi_device *device,
+ qmi_sync_func_t func, void *user_data);
+
enum qmi_device_expected_data_format qmi_device_get_expected_data_format(
struct qmi_device *device);
bool qmi_device_set_expected_data_format(struct qmi_device *device,
Index: ofono-1.21/plugins/gobi.c
===================================================================
--- ofono-1.21.orig/plugins/gobi.c
+++ ofono-1.21/plugins/gobi.c
@@ -320,6 +320,16 @@ static void discover_cb(uint8_t count, c
create_dms_cb, modem, NULL);
}
+static void sync_cb(void *user_data)
+{
+ struct ofono_modem *modem = user_data;
+ struct gobi_data *data = ofono_modem_get_data(modem);
+
+ DBG("modem in sync");
+
+ qmi_device_discover(data->device, discover_cb, modem, NULL);
+}
+
static int gobi_enable(struct ofono_modem *modem)
{
struct gobi_data *data = ofono_modem_get_data(modem);
@@ -347,7 +357,7 @@ static int gobi_enable(struct ofono_mode
qmi_device_set_close_on_unref(data->device, true);
- qmi_device_discover(data->device, discover_cb, modem, NULL);
+ qmi_device_sync(data->device, sync_cb, modem);
return -EINPROGRESS;
}

View File

@ -0,0 +1,26 @@
From e3d6b09ab785af7e0eab4628592a8bb8239ef7a3 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Wed, 26 Jul 2017 02:11:23 +0200
Subject: [PATCH 14/17] network/ofono_netreg_status_notify: debug output lac
and ci
The location are code and cell id is updated at the same time.
---
src/network.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: ofono-1.21/src/network.c
===================================================================
--- ofono-1.21.orig/src/network.c
+++ ofono-1.21/src/network.c
@@ -1351,8 +1351,8 @@ void ofono_netreg_status_notify(struct o
if (netreg == NULL)
return;
- DBG("%s status %d tech %d", __ofono_atom_get_path(netreg->atom),
- status, tech);
+ DBG("%s status %d tech %d lac %d ci %d",
+ __ofono_atom_get_path(netreg->atom), status, tech, lac, ci);
if (netreg->status != status) {
struct ofono_modem *modem;

View File

@ -0,0 +1,25 @@
From 8f00ef8b3b9be29ad6f58769234a30c6c5ae0d27 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Wed, 26 Jul 2017 02:12:16 +0200
Subject: [PATCH 15/17] network: debug output the network time if updated
---
src/network.c | 5 +++++
1 file changed, 5 insertions(+)
Index: ofono-1.21/src/network.c
===================================================================
--- ofono-1.21.orig/src/network.c
+++ ofono-1.21/src/network.c
@@ -1407,6 +1407,11 @@ void ofono_netreg_time_notify(struct ofo
if (info == NULL)
return;
+ DBG("net time %d-%02d-%02d %02d:%02d:%02d utcoff %d dst %d",
+ info->year, info->mon, info->mday,
+ info->hour, info->min, info->sec,
+ info->utcoff, info->dst);
+
__ofono_nettime_info_received(modem, info);
}

View File

@ -0,0 +1,53 @@
From d43fde3c5e6165b8a977c8917c11e4d1a55eac3f Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Tue, 25 Jul 2017 16:43:03 +0200
Subject: [PATCH 16/17] voicecall: prefer release_specific() over
hang_up_active/hangup_all
release_specific() has the call_id as parameter in difference to the more unspecific
calls hangup_all and hangup_active.
---
src/voicecall.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
Index: ofono-1.21/src/voicecall.c
===================================================================
--- ofono-1.21.orig/src/voicecall.c
+++ ofono-1.21/src/voicecall.c
@@ -542,10 +542,18 @@ static DBusMessage *voicecall_hangup(DBu
if (vc->dial_req && vc->dial_req->call != v)
return __ofono_error_busy(msg);
- switch (call->status) {
- case CALL_STATUS_DISCONNECTED:
+ if (call->status == CALL_STATUS_DISCONNECTED)
return __ofono_error_failed(msg);
+ if (vc->driver->release_specific) {
+ vc->pending = dbus_message_ref(msg);
+ vc->driver->release_specific(vc, call->id,
+ generic_callback, vc);
+
+ return NULL;
+ }
+
+ switch (call->status) {
case CALL_STATUS_INCOMING:
if (vc->driver->hangup_all == NULL &&
vc->driver->hangup_active == NULL)
@@ -615,14 +623,7 @@ static DBusMessage *voicecall_hangup(DBu
break;
}
- if (vc->driver->release_specific == NULL)
- return __ofono_error_not_implemented(msg);
-
- vc->pending = dbus_message_ref(msg);
- vc->driver->release_specific(vc, call->id,
- generic_callback, vc);
-
- return NULL;
+ return __ofono_error_not_implemented(msg);
}
static DBusMessage *voicecall_answer(DBusConnection *conn,

View File

@ -0,0 +1,976 @@
From df3b0c1cd8be029ff2c98c2ba7ba1110385a17f6 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Tue, 25 Jul 2017 15:31:48 +0200
Subject: [PATCH 17/17] [RFC] qmimodem: implement voice calls
The voice_generated.* files is an RFC how files should look like.
They aren't yet generated.
---
Makefile.am | 5 +-
drivers/qmimodem/qmi.h | 13 ++
drivers/qmimodem/voice.c | 86 ++++++++++
drivers/qmimodem/voice.h | 84 ++++++++++
drivers/qmimodem/voice_generated.c | 210 +++++++++++++++++++++++
drivers/qmimodem/voice_generated.h | 113 +++++++++++++
drivers/qmimodem/voicecall.c | 332 ++++++++++++++++++++++++++++++++++++-
7 files changed, 840 insertions(+), 3 deletions(-)
create mode 100644 drivers/qmimodem/voice.c
create mode 100644 drivers/qmimodem/voice.h
create mode 100644 drivers/qmimodem/voice_generated.c
create mode 100644 drivers/qmimodem/voice_generated.h
Index: ofono-1.21/Makefile.am
===================================================================
--- ofono-1.21.orig/Makefile.am
+++ ofono-1.21/Makefile.am
@@ -216,7 +216,9 @@ qmi_sources = drivers/qmimodem/qmi.h dri
drivers/qmimodem/wds.h \
drivers/qmimodem/pds.h \
drivers/qmimodem/common.h \
- drivers/qmimodem/wda.h
+ drivers/qmimodem/wda.h \
+ drivers/qmimodem/voice.h \
+ drivers/qmimodem/voice.c
builtin_modules += qmimodem
builtin_sources += $(qmi_sources) \
@@ -225,6 +227,7 @@ builtin_sources += $(qmi_sources) \
drivers/qmimodem/qmimodem.c \
drivers/qmimodem/devinfo.c \
drivers/qmimodem/voicecall.c \
+ drivers/qmimodem/voice_generated.c \
drivers/qmimodem/network-registration.c \
drivers/qmimodem/sim-legacy.c \
drivers/qmimodem/sim.c \
Index: ofono-1.21/drivers/qmimodem/qmi.h
===================================================================
--- ofono-1.21.orig/drivers/qmimodem/qmi.h
+++ ofono-1.21/drivers/qmimodem/qmi.h
@@ -19,6 +19,9 @@
*
*/
+#ifndef __OFONO_QMI_QMI_H
+#define __OFONO_QMI_QMI_H
+
#include <stdbool.h>
#include <stdint.h>
@@ -175,3 +178,13 @@ uint16_t qmi_service_register(struct qmi
void *user_data, qmi_destroy_func_t destroy);
bool qmi_service_unregister(struct qmi_service *service, uint16_t id);
bool qmi_service_unregister_all(struct qmi_service *service);
+
+
+/* FIXME: find a place for parse_error */
+enum parse_error {
+ NONE = 0,
+ MISSING_MANDATORY = 1,
+ INVALID_LENGTH = 2,
+};
+
+#endif /* __OFONO_QMI_QMI_H */
Index: ofono-1.21/drivers/qmimodem/voice.c
===================================================================
--- /dev/null
+++ ofono-1.21/drivers/qmimodem/voice.c
@@ -0,0 +1,86 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2017 Alexander Couzens <lynxis@fe80.eu>
+ *
+ * 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.
+ *
+ */
+
+#include <stdint.h>
+
+#include "voice.h"
+#include "../../src/common.h"
+
+#define _(X) case X: return #X
+
+const char *qmi_voice_call_state_name(enum qmi_voice_call_state value)
+{
+ switch (value) {
+ _(QMI_CALL_STATE_IDLE);
+ _(QMI_CALL_STATE_ORIG);
+ _(QMI_CALL_STATE_INCOMING);
+ _(QMI_CALL_STATE_CONV);
+ _(QMI_CALL_STATE_CC_IN_PROG);
+ _(QMI_CALL_STATE_ALERTING);
+ _(QMI_CALL_STATE_HOLD);
+ _(QMI_CALL_STATE_WAITING);
+ _(QMI_CALL_STATE_DISCONNECTING);
+ _(QMI_CALL_STATE_END);
+ _(QMI_CALL_STATE_SETUP);
+ }
+ return "QMI_CALL_STATE_<UNKNOWN>";
+}
+
+int qmi_to_ofono_status(uint8_t status, int *ret) {
+ int err = 0;
+ switch (status) {
+ case QMI_CALL_STATE_IDLE:
+ case QMI_CALL_STATE_END:
+ case QMI_CALL_STATE_DISCONNECTING:
+ *ret = CALL_STATUS_DISCONNECTED;
+ break;
+ case QMI_CALL_STATE_HOLD:
+ *ret = CALL_STATUS_HELD;
+ break;
+ case QMI_CALL_STATE_WAITING:
+ *ret = CALL_STATUS_WAITING;
+ break;
+ case QMI_CALL_STATE_ORIG:
+ *ret = CALL_STATUS_DIALING;
+ break;
+ case QMI_CALL_STATE_INCOMING:
+ *ret = CALL_STATUS_INCOMING;
+ break;
+ case QMI_CALL_STATE_CONV:
+ *ret = CALL_STATUS_ACTIVE;
+ break;
+ case QMI_CALL_STATE_CC_IN_PROG:
+ case QMI_CALL_STATE_SETUP:
+ /* FIXME: unsure if _SETUP is dialing or not */
+ *ret = CALL_STATUS_DIALING;
+ break;
+ case QMI_CALL_STATE_ALERTING:
+ *ret = CALL_STATUS_ALERTING;
+ break;
+ default:
+ err = 1;
+ }
+ return err;
+}
+
+uint8_t ofono_to_qmi_direction(enum call_direction ofono_direction) {
+ return ofono_direction + 1;
+}
+enum call_direction qmi_to_ofono_direction(uint8_t qmi_direction) {
+ return qmi_direction - 1;
+}
+
Index: ofono-1.21/drivers/qmimodem/voice.h
===================================================================
--- /dev/null
+++ ofono-1.21/drivers/qmimodem/voice.h
@@ -0,0 +1,84 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2017 Alexander Couzens <lynxis@fe80.eu>
+ *
+ * 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.
+ *
+ */
+
+enum call_direction;
+
+enum ussd_dcs {
+ USS_DCS_ASCII = 0x1,
+ USS_DCS_8BIT,
+ USS_DCS_UCS2,
+};
+
+enum ussd_user_required {
+ NO_USER_ACTION_REQUIRED = 0x1,
+ USER_ACTION_REQUIRED = 0x2,
+};
+
+struct qmi_ussd_data {
+ uint8_t dcs;
+ uint8_t length;
+ uint8_t data[0];
+} __attribute__((__packed__));
+
+enum voice_commands {
+ QMI_VOICE_CANCEL_USSD = 0x3c,
+ QMI_VOICE_USSD_RELEASE_IND = 0x3d,
+ QMI_VOICE_USSD_IND = 0x3e,
+ QMI_VOICE_SUPS_IND = 0x42,
+ QMI_VOICE_ASYNC_ORIG_USSD = 0x43,
+};
+
+enum qmi_voice_call_state {
+ QMI_CALL_STATE_IDLE = 0x0,
+ QMI_CALL_STATE_ORIG,
+ QMI_CALL_STATE_INCOMING,
+ QMI_CALL_STATE_CONV,
+ QMI_CALL_STATE_CC_IN_PROG,
+ QMI_CALL_STATE_ALERTING,
+ QMI_CALL_STATE_HOLD,
+ QMI_CALL_STATE_WAITING,
+ QMI_CALL_STATE_DISCONNECTING,
+ QMI_CALL_STATE_END,
+ QMI_CALL_STATE_SETUP
+};
+
+enum qmi_voice_call_type {
+ QMI_CALL_TYPE_VOICE = 0x0,
+ QMI_CALL_TYPE_VOICE_FORCE,
+};
+
+const char *qmi_voice_call_state_name(enum qmi_voice_call_state value);
+uint8_t ofono_to_qmi_direction(enum call_direction ofono_direction);
+enum call_direction qmi_to_ofono_direction(uint8_t qmi_direction);
+int qmi_to_ofono_status(uint8_t status, int *ret);
+
+#define QMI_VOICE_IND_ALL_STATUS 0x2e
+
+#define QMI_VOICE_PARAM_USS_DATA 0x01
+
+#define QMI_VOICE_PARAM_ASYNC_USSD_ERROR 0x10
+#define QMI_VOICE_PARAM_ASYNC_USSD_FAILURE_CASE 0x11
+#define QMI_VOICE_PARAM_ASYNC_USSD_DATA 0x12
+
+#define QMI_VOICE_PARAM_USSD_IND_USER_ACTION 0x01
+#define QMI_VOICE_PARAM_USSD_IND_DATA 0x10
+#define QMI_VOICE_PARAM_USSD_IND_UCS2 0x11
+
+/* according to GSM TS 23.038 */
+#define USSD_DCS_8BIT 0xf4
+#define USSD_DCS_UCS2 0x48
+#define USSD_DCS_UNSPECIFIC 0x0f
Index: ofono-1.21/drivers/qmimodem/voice_generated.c
===================================================================
--- /dev/null
+++ ofono-1.21/drivers/qmimodem/voice_generated.c
@@ -0,0 +1,210 @@
+
+#include <stdint.h>
+#include <string.h>
+#include <glib.h>
+
+#include "voice_generated.h"
+
+int qmi_voice_dial_call(
+ struct qmi_voice_dial_call_arg *arg,
+ struct qmi_service *service,
+ qmi_result_func_t func,
+ void *user_data,
+ qmi_destroy_func_t destroy)
+{
+ struct qmi_param *param = NULL;
+
+ param = qmi_param_new();
+ if (!param)
+ goto error;
+
+ if (arg->calling_number_set) {
+ if (!qmi_param_append(param,
+ 0x1,
+ strlen(arg->calling_number),
+ arg->calling_number))
+ goto error;
+ }
+
+ if (arg->call_type_set)
+ qmi_param_append_uint8(param, 0x10, arg->call_type);
+
+ if (qmi_service_send(service,
+ 0x20,
+ param,
+ func,
+ user_data,
+ destroy) > 0)
+ return 0;
+error:
+ g_free(param);
+ return 1;
+}
+
+enum parse_error qmi_voice_dial_call_parse(
+ struct qmi_result *qmi_result,
+ struct qmi_voice_dial_call_result *result)
+{
+ int err = NONE;
+
+ /* mandatory */
+ if (qmi_result_get_uint8(qmi_result, 0x10, &result->call_id))
+ result->call_id_set = 1;
+ else
+ err = MISSING_MANDATORY;
+
+ return err;
+}
+
+int qmi_voice_end_call(
+ struct qmi_voice_end_call_arg *arg,
+ struct qmi_service *service,
+ qmi_result_func_t func,
+ void *user_data,
+ qmi_destroy_func_t destroy)
+{
+ struct qmi_param *param = NULL;
+
+ param = qmi_param_new();
+ if (!param)
+ goto error;
+
+ if (arg->call_id_set) {
+ if (!qmi_param_append_uint8(
+ param,
+ 0x1,
+ arg->call_id))
+ goto error;
+ }
+
+ if (qmi_service_send(service,
+ 0x21,
+ param,
+ func,
+ user_data,
+ destroy) > 0)
+ return 0;
+error:
+ g_free(param);
+ return 1;
+}
+
+enum parse_error qmi_voice_end_call_parse(
+ struct qmi_result *qmi_result,
+ struct qmi_voice_end_call_result *result)
+{
+ int err = NONE;
+
+ /* optional */
+ if (qmi_result_get_uint8(qmi_result, 0x10, &result->call_id))
+ result->call_id_set = 1;
+
+ return err;
+}
+
+
+int qmi_voice_answer_call(
+ struct qmi_voice_answer_call_arg *arg,
+ struct qmi_service *service,
+ qmi_result_func_t func,
+ void *user_data,
+ qmi_destroy_func_t destroy)
+{
+ struct qmi_param *param = NULL;
+
+ param = qmi_param_new();
+ if (!param)
+ goto error;
+
+ if (arg->call_id_set) {
+ if (!qmi_param_append_uint8(
+ param,
+ 0x1,
+ arg->call_id))
+ goto error;
+ }
+
+ if (qmi_service_send(service,
+ 0x22,
+ param,
+ func,
+ user_data,
+ destroy) > 0)
+ return 0;
+error:
+ g_free(param);
+ return 1;
+}
+
+
+enum parse_error qmi_voice_answer_call_parse(
+ struct qmi_result *qmi_result,
+ struct qmi_voice_answer_call_result *result)
+{
+ int err = NONE;
+
+ /* optional */
+ if (qmi_result_get_uint8(qmi_result, 0x10, &result->call_id))
+ result->call_id_set = 1;
+
+ return err;
+}
+
+enum parse_error qmi_voice_ind_call_status(
+ struct qmi_result *qmi_result,
+ struct qmi_voice_all_call_status_ind *result)
+{
+ int err = NONE;
+ int offset;
+ uint16_t len;
+ const struct qmi_voice_remote_party_number *remote_party_number;
+ const struct qmi_voice_call_information *call_information;
+
+ /* mandatory */
+ call_information = qmi_result_get(qmi_result, 0x01, &len);
+ if (call_information)
+ {
+ int instance_size = sizeof(struct qmi_voice_call_information_instance);
+ /* verify the length */
+ if (len < sizeof(call_information->size))
+ return INVALID_LENGTH;
+
+ if (len != call_information->size * sizeof(struct qmi_voice_call_information_instance)
+ + sizeof(call_information->size))
+ return INVALID_LENGTH;
+ result->call_information_set = 1;
+ result->call_information = call_information;
+ } else
+ return MISSING_MANDATORY;
+
+ /* mandatory */
+ remote_party_number = qmi_result_get(qmi_result, 0x10, &len);
+ if (remote_party_number) {
+ const struct qmi_voice_remote_party_number_instance *instance;
+ int instance_size = sizeof(struct qmi_voice_remote_party_number_instance);
+ int i;
+
+ /* verify the length */
+ if (len < sizeof(remote_party_number->size))
+ return INVALID_LENGTH;
+
+ for (i = 0, offset = sizeof(remote_party_number->size);
+ offset <= len && i < 16 && i < remote_party_number->size; i++)
+ {
+ if (offset == len) {
+ break;
+ } else if (offset + instance_size > len) {
+ return INVALID_LENGTH;
+ }
+
+ instance = (void *)remote_party_number + offset;
+ result->remote_party_number[i] = instance;
+ offset += sizeof(struct qmi_voice_remote_party_number_instance) + instance->number_size;
+ }
+ result->remote_party_number_set = 1;
+ result->remote_party_number_size = remote_party_number->size;
+ } else
+ return MISSING_MANDATORY;
+
+ return err;
+}
Index: ofono-1.21/drivers/qmimodem/voice_generated.h
===================================================================
--- /dev/null
+++ ofono-1.21/drivers/qmimodem/voice_generated.h
@@ -0,0 +1,113 @@
+
+#ifndef __OFONO_QMI_VOICE_GENERATED_H
+#define __OFONO_QMI_VOICE_GENERATED_H
+
+#include "qmi.h"
+
+struct qmi_voice_remote_party_number_instance {
+ uint8_t call_id;
+ uint8_t presentation_indicator;
+ uint8_t number_size;
+ char number[0];
+} __attribute__((__packed__));
+
+struct qmi_voice_remote_party_number {
+ uint8_t size;
+ struct qmi_voice_remote_party_number_instance instance[0];
+} __attribute__((__packed__));
+
+/* generator / parser */
+
+struct qmi_voice_dial_call_arg {
+ bool calling_number_set;
+ const char *calling_number;
+ bool call_type_set;
+ uint8_t call_type;
+};
+
+int qmi_voice_dial_call(
+ struct qmi_voice_dial_call_arg *arg,
+ struct qmi_service *service,
+ qmi_result_func_t func,
+ void *user_data,
+ qmi_destroy_func_t destroy);
+
+struct qmi_voice_dial_call_result {
+ bool call_id_set;
+ uint8_t call_id;
+};
+
+enum parse_error qmi_voice_dial_call_parse(
+ struct qmi_result *qmi_result,
+ struct qmi_voice_dial_call_result *result);
+
+struct qmi_voice_end_call_arg {
+ bool call_id_set;
+ uint8_t call_id;
+};
+
+int qmi_voice_end_call(
+ struct qmi_voice_end_call_arg *arg,
+ struct qmi_service *service,
+ qmi_result_func_t func,
+ void *user_data,
+ qmi_destroy_func_t destroy);
+
+struct qmi_voice_end_call_result {
+ bool call_id_set;
+ uint8_t call_id;
+};
+
+enum parse_error qmi_voice_end_call_parse(
+ struct qmi_result *qmi_result,
+ struct qmi_voice_end_call_result *result);
+
+struct qmi_voice_answer_call_arg {
+ bool call_id_set;
+ uint8_t call_id;
+};
+
+int qmi_voice_answer_call(
+ struct qmi_voice_answer_call_arg *arg,
+ struct qmi_service *service,
+ qmi_result_func_t func,
+ void *user_data,
+ qmi_destroy_func_t destroy);
+
+struct qmi_voice_answer_call_result {
+ bool call_id_set;
+ uint8_t call_id;
+};
+
+enum parse_error qmi_voice_answer_call_parse(
+ struct qmi_result *qmi_result,
+ struct qmi_voice_answer_call_result *result);
+
+struct qmi_voice_call_information_instance {
+ uint8_t id;
+ uint8_t state;
+ uint8_t type;
+ uint8_t direction;
+ uint8_t mode;
+ uint8_t multipart_indicator;
+ uint8_t als;
+} __attribute__((__packed__));
+
+struct qmi_voice_call_information {
+ uint8_t size;
+ struct qmi_voice_call_information_instance instance[0];
+} __attribute__((__packed__)) ;
+
+struct qmi_voice_all_call_status_ind {
+ bool call_information_set;
+ const struct qmi_voice_call_information *call_information;
+ bool remote_party_number_set;
+ uint8_t remote_party_number_size;
+ const struct qmi_voice_remote_party_number_instance *remote_party_number[16];
+};
+
+enum parse_error qmi_voice_ind_call_status(
+ struct qmi_result *qmi_result,
+ struct qmi_voice_all_call_status_ind *result);
+
+#endif /* __OFONO_QMI_VOICE_GENERATED_H */
Index: ofono-1.21/drivers/qmimodem/voicecall.c
===================================================================
--- ofono-1.21.orig/drivers/qmimodem/voicecall.c
+++ ofono-1.21/drivers/qmimodem/voicecall.c
@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2011-2012 Intel Corporation. All rights reserved.
+ * Copyright (C) 2017 Alexander Couzens <lynxis@fe80.eu>
*
* 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
@@ -23,20 +24,113 @@
#include <config.h>
#endif
+#include <string.h>
+
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/voicecall.h>
+#include <ofono/call-list.h>
-#include "qmi.h"
+#include "../src/common.h"
+#include "qmi.h"
#include "qmimodem.h"
+#include "voice.h"
+#include "voice_generated.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+
+/* qmi protocol */
+
+
+/* end of qmi */
struct voicecall_data {
struct qmi_service *voice;
uint16_t major;
uint16_t minor;
+ GSList *call_list;
+ struct voicecall_static *vs;
+ struct ofono_phone_number dialed;
};
+static void all_call_status_ind(struct qmi_result *result, void *user_data)
+{
+ struct ofono_voicecall *vc = user_data;
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ GSList *calls = NULL;
+ int i;
+ int size = 0;
+ struct qmi_voice_all_call_status_ind status_ind;
+ GSList *n, *o;
+ struct ofono_call *nc, *oc;
+
+
+ if (qmi_voice_ind_call_status(result, &status_ind) != NONE) {
+ DBG("Parsing of all call status indication failed");
+ return;
+ }
+
+ if (!status_ind.remote_party_number_set || !status_ind.call_information_set) {
+ DBG("Some required fields are not set");
+ return;
+ }
+
+ size = status_ind.call_information->size;
+ if (!size) {
+ DBG("No call informations received!");
+ return;
+ }
+
+ /* expect we have valid fields for every call */
+ if (size != status_ind.remote_party_number_size) {
+ DBG("Not all fields have the same size");
+ return;
+ }
+
+ for (i = 0; i < size; i++) {
+ struct qmi_voice_call_information_instance call_info;
+ struct ofono_call *call;
+ const struct qmi_voice_remote_party_number_instance *remote_party = status_ind.remote_party_number[i];
+ int number_size;
+
+ call_info = status_ind.call_information->instance[i];
+ call = g_new0(struct ofono_call, 1);
+ call->id = call_info.id;
+ call->direction = qmi_to_ofono_direction(call_info.direction);
+
+ if (qmi_to_ofono_status(call_info.state, &call->status)) {
+ DBG("Ignore call id %d, because can not convert QMI state 0x%x to ofono.",
+ call_info.id, call_info.state);
+ continue;
+ }
+ DBG("Call %d in state %s(%d)",
+ call_info.id,
+ qmi_voice_call_state_name(call_info.state),
+ call_info.state);
+
+ call->type = 0; /* always voice */
+ number_size = remote_party->number_size;
+ if (number_size > OFONO_MAX_PHONE_NUMBER_LENGTH)
+ OFONO_MAX_PHONE_NUMBER_LENGTH;
+ strncpy(call->phone_number.number, remote_party->number,
+ number_size);
+ /* FIXME: set phone_number_type */
+
+ if (strlen(call->phone_number.number) > 0)
+ call->clip_validity = 0;
+ else
+ call->clip_validity = 2;
+
+ calls = g_slist_insert_sorted(calls, call, ofono_call_compare);
+ }
+
+ ofono_call_list_notify(vc, &vd->call_list, calls);
+}
+
static void create_voice_cb(struct qmi_service *service, void *user_data)
{
struct ofono_voicecall *vc = user_data;
@@ -58,6 +152,12 @@ static void create_voice_cb(struct qmi_s
data->voice = qmi_service_ref(service);
+ /* FIXME: we should call indication_register to ensure we get notified on call events.
+ * We rely at the moment on the default value of notifications
+ */
+ qmi_service_register(data->voice, QMI_VOICE_IND_ALL_STATUS,
+ all_call_status_ind, vc, NULL);
+
ofono_voicecall_register(vc);
}
@@ -77,7 +177,6 @@ static int qmi_voicecall_probe(struct of
create_voice_cb, vc, NULL);
return 0;
-
}
static void qmi_voicecall_remove(struct ofono_voicecall *vc)
@@ -92,13 +191,242 @@ static void qmi_voicecall_remove(struct
qmi_service_unref(data->voice);
+ g_slist_free_full(data->call_list, g_free);
+
g_free(data);
}
+
+static struct ofono_call *create_call(struct ofono_voicecall *vc,
+ enum call_direction direction,
+ enum call_status status,
+ const char *num,
+ int num_type,
+ int clip)
+{
+ return NULL;
+}
+
+static void dial_cb(struct qmi_result *result, void *user_data)
+{
+ struct cb_data *cbd = user_data;
+ struct ofono_voicecall *vc = cbd->user;
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ ofono_voicecall_cb_t cb = cbd->cb;
+ uint16_t error;
+ struct qmi_voice_dial_call_result dial_result;
+ struct ofono_call *call;
+
+ if (qmi_result_set_error(result, &error)) {
+ DBG("QMI Error %d", error);
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
+ }
+
+ if (NONE != qmi_voice_dial_call_parse(result, &dial_result)) {
+ DBG("Received invalid Result");
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
+ }
+
+ if (!dial_result.call_id_set) {
+ DBG("Didn't receive a call id");
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
+ }
+
+ DBG("New call QMI id %d", dial_result.call_id);
+ ofono_call_list_dial_callback(vc,
+ &vd->call_list,
+ &vd->dialed,
+ dial_result.call_id);
+
+
+ /* FIXME: create a timeout on this call_id */
+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void dial(struct ofono_voicecall *vc, const struct ofono_phone_number *ph,
+ enum ofono_clir_option clir, ofono_voicecall_cb_t cb,
+ void *data)
+{
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ struct cb_data *cbd = cb_data_new(cb, data);
+ struct qmi_voice_dial_call_arg arg;
+
+ cbd->user = vc;
+ arg.calling_number_set = true;
+ arg.calling_number = ph->number;
+ memcpy(&vd->dialed, ph, sizeof(*ph));
+
+ arg.call_type_set = true;
+ arg.call_type = QMI_CALL_TYPE_VOICE_FORCE;
+
+ if (!qmi_voice_dial_call(
+ &arg,
+ vd->voice,
+ dial_cb,
+ cbd,
+ g_free))
+ return;
+
+ CALLBACK_WITH_FAILURE(cb, data);
+ g_free(cbd);
+}
+
+static void answer_cb(struct qmi_result *result, void *user_data)
+{
+ struct cb_data *cbd = user_data;
+ struct ofono_voicecall *vc = cbd->user;
+ ofono_voicecall_cb_t cb = cbd->cb;
+ uint16_t error;
+ struct qmi_voice_answer_call_result answer_result;
+ struct ofono_call *call;
+
+ if (qmi_result_set_error(result, &error)) {
+ DBG("QMI Error %d", error);
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
+ }
+
+ /* TODO: what happens when calling it with no active call or wrong caller id? */
+ if (NONE != qmi_voice_answer_call_parse(result, &answer_result)) {
+ DBG("Received invalid Result");
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
+ }
+
+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void answer(struct ofono_voicecall *vc, ofono_voicecall_cb_t cb, void *data)
+{
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ struct cb_data *cbd = cb_data_new(cb, data);
+ struct qmi_voice_answer_call_arg arg;
+ struct ofono_call *call;
+ GSList *list;
+
+ DBG("");
+ cbd->user = vc;
+
+ list = g_slist_find_custom(vd->call_list,
+ GINT_TO_POINTER(CALL_STATUS_INCOMING),
+ ofono_call_compare_by_status);
+
+ if (list == NULL) {
+ DBG("Can not find a call to answer");
+ goto err;
+ }
+
+ call = list->data;
+
+ arg.call_id_set = true;
+ arg.call_id = call->id;
+
+ if (!qmi_voice_answer_call(
+ &arg,
+ vd->voice,
+ answer_cb,
+ cbd,
+ g_free))
+ return;
+err:
+ CALLBACK_WITH_FAILURE(cb, data);
+ g_free(cbd);
+}
+
+static void end_cb(struct qmi_result *result, void *user_data)
+{
+ struct cb_data *cbd = user_data;
+ struct ofono_voicecall *vc = cbd->user;
+ ofono_voicecall_cb_t cb = cbd->cb;
+ uint16_t error;
+ struct qmi_voice_end_call_result end_result;
+ struct ofono_call *call;
+
+ if (qmi_result_set_error(result, &error)) {
+ DBG("QMI Error %d", error);
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
+ }
+
+ if (NONE != qmi_voice_end_call_parse(result, &end_result)) {
+ DBG("Received invalid Result");
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
+ }
+
+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void release_specific(struct ofono_voicecall *vc, int id,
+ ofono_voicecall_cb_t cb, void *data)
+{
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ struct cb_data *cbd = cb_data_new(cb, data);
+ struct qmi_voice_end_call_arg arg;
+ int i;
+
+ DBG("");
+ cbd->user = vc;
+
+ arg.call_id_set = true;
+ arg.call_id = id;
+
+ if (!qmi_voice_end_call(&arg,
+ vd->voice,
+ end_cb,
+ cbd,
+ g_free))
+ return;
+
+ CALLBACK_WITH_FAILURE(cb, data);
+ g_free(cbd);
+}
+
+static void hangup_active(struct ofono_voicecall *vc,
+ ofono_voicecall_cb_t cb, void *data)
+{
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ struct qmi_voice_end_call_arg arg;
+ struct ofono_call *call;
+ GSList *list = NULL;
+ enum call_status active[] = {
+ CALL_STATUS_ACTIVE,
+ CALL_STATUS_DIALING,
+ CALL_STATUS_ALERTING
+ };
+ int i;
+
+ DBG("");
+ for (i = 0; i < ARRAY_SIZE(active); i++) {
+ list = g_slist_find_custom(vd->call_list,
+ GINT_TO_POINTER(CALL_STATUS_ACTIVE),
+ ofono_call_compare_by_status);
+
+ if (list)
+ break;
+ }
+
+ if (list == NULL) {
+ DBG("Can not find a call to hang up");
+ CALLBACK_WITH_FAILURE(cb, data);
+ return;
+ }
+
+ call = list->data;
+ release_specific(vc, call->id, cb, data);
+}
+
static struct ofono_voicecall_driver driver = {
.name = "qmimodem",
.probe = qmi_voicecall_probe,
.remove = qmi_voicecall_remove,
+ .dial = dial,
+ .answer = answer,
+ .hangup_active = hangup_active,
+ .release_specific = release_specific,
};
void qmi_voicecall_init(void)

View File

@ -2,13 +2,13 @@
pkgname=ofono
_upstreamver=1.21
pkgver=1.21_p20180307
pkgrel=2
pkgrel=3
pkgdesc="Infrastructure for building mobile telephony (GSM/UMTS) applications"
url="https://01.org/ofono"
arch="all"
license="GPL2"
depends="bluez mobile-broadband-provider-info"
makedepends="glib-dev dbus-dev eudev-dev
makedepends="autoconf automake libtool glib-dev dbus-dev eudev-dev
linux-headers bsd-compat-headers libexecinfo-dev
mobile-broadband-provider-info"
options="!check"
@ -18,12 +18,24 @@ source="https://www.kernel.org/pub/linux/network/$pkgname/$pkgname-$_upstreamver
0001-nokia-gpio-do-not-create-links-to-gpios-in-dev-cmt.patch::https://git.alpinelinux.org/cgit/aports/plain/testing/ofono/0001-nokia-gpio-do-not-create-links-to-gpios-in-dev-cmt.patch?id=014ae282b4a9152a5b64451f2815f34fcb53507c
support-smdpkt.patch
udev.rules
0001-doc-ofonod.8-escape-minus-sign.patch
0002-common-create-GList-helper-ofono_call_compare.patch
0003-voicecall-common-promote-call_status_to_string-publi.patch
0006-add-call-list-helper-to-manage-voice-call-lists.patch
0007-common-atmodem-rename-move-at_util_call_compare_by_s.patch
0008-common-atmodem-rename-move-at_util_call_compare_by_i.patch
0011-qmimodem-sync-the-modem-on-enable.patch
0014-network-ofono_netreg_status_notify-debug-output-lac-.patch
0015-network-debug-output-the-network-time-if-updated.patch
0016-voicecall-prefer-release_specific-over-hang_up_activ.patch
0017-RFC-qmimodem-implement-voice-calls.patch
"
builddir="$srcdir"/$pkgname-$_upstreamver
build() {
cd "$builddir"
autoreconf --install
./configure \
--prefix=/usr \
--sysconfdir=/etc \
@ -45,4 +57,15 @@ sha512sums="bbc7fdb1d05294839eee5f31ec345866315a80feac8ccc2a67e0ca2c1030c55e0fb4
fd0d303ca71df6953155aac0624c847f273030ebc5fb12efe2fa2ae7b8d75380e2885ab08d9c65c80cf756ef952569832ffdc25317e86a99552b4caac322b3ed ofono.initd
a1f66f3f40c1aa4af5f5b66436414408b46f3c90f2a2c88fa12e09ca6a1732334d2f47687478d652a3a176ee93c1905752635246fd01412834565626c021ca64 0001-nokia-gpio-do-not-create-links-to-gpios-in-dev-cmt.patch
b946ac618aa2ab864876f7a81b689a0c3b776ad66657aaac508a52ea803d7031378dab0d7292ee41caba3e35b6e15d7309910c754a5762de7754be813c257b82 support-smdpkt.patch
8f2893dfc291fc210ef217c4bc74d79436a0997001dd2773809625d52dd19d092cc75d3f9aa5ed2f3d4a6248d4a4e17013a7655323f7dad951f744c55b572417 udev.rules"
8f2893dfc291fc210ef217c4bc74d79436a0997001dd2773809625d52dd19d092cc75d3f9aa5ed2f3d4a6248d4a4e17013a7655323f7dad951f744c55b572417 udev.rules
e602504d41a0c28f99db138255eb9f0f020e59c26fcabc99f2bbe9f4e3d3c99b33ffb247a362569c841f55111b7fd8db0b18e98c3497ef04aa9bde467b86475d 0001-doc-ofonod.8-escape-minus-sign.patch
1ffa1c7c0a99aabf5e064f7c99db43727942365c8b76b2d3e6278e4995570a067e73755e1111f8bcf3f1574b4d24d427c48fe2dc474ad89099d5d818b597fcb5 0002-common-create-GList-helper-ofono_call_compare.patch
4658e7dfdb9167f97c279a55fb2b53d5c33eda87c54cd7fcaaaf489e2b6d2d6b2b487b415ee616827d4388e379a842833860809103010d8b1be75b76505cf8c8 0003-voicecall-common-promote-call_status_to_string-publi.patch
0de8030dad134851cacc9564186aef07db94ab72c914c03326a0e8070e764a3fd47cc921a49bbf6c0828692599005e0dd412b808abb9adfd6b7bc49fcd176b93 0006-add-call-list-helper-to-manage-voice-call-lists.patch
1ecf593363e25b51cff36d692afd12886877c82b75fce853d137dd0c5fa2910ece4a3a18744b563e898be7df254826c80861f2bb0a113d9c2d9cde686b2297ac 0007-common-atmodem-rename-move-at_util_call_compare_by_s.patch
a1b04a014e7643105529b6060577555747c1094c0fc770c99e5fc5b8b97843ba3a23577e33ffa7a77379ef02669ebe96dbf1c25271cf2fd5ab11dabb21aeb588 0008-common-atmodem-rename-move-at_util_call_compare_by_i.patch
1664244d301267537423f47d57b67374659c81fc073435507be6845c0a8fec776cc3dd18e3781040e173a92610b6f0cf78a59378414948eb881e8c7cdf9b7322 0011-qmimodem-sync-the-modem-on-enable.patch
1e6bce11888ce11080a6dd07c487836104abc52be3e908c96eac412ce17941aadfd19bab386706cb9491e6ecf9666efac7cb85db98ca50dd920928a3c502157a 0014-network-ofono_netreg_status_notify-debug-output-lac-.patch
61728285a5247e964d71d2f93d6aa62967ba9be978d41f99928829e3a753124830aede022b86eb5b39b04485afba1a1f2bb7595b0cec5a04899b74297f9297ab 0015-network-debug-output-the-network-time-if-updated.patch
6d85d384261af82314d11310150dc37b01bbf89b6cb3c3b5576724a97cdbf96f67a02bf3828560d773a6ff1271202cf290606070f41d52af16bbea320e48f660 0016-voicecall-prefer-release_specific-over-hang_up_activ.patch
25279f9570b4312100c87bb7d17c39bdeea04acce19414503a9274befc3ff07383488433d9900540933e8e409eed3b47996196d50c9a40f9d01e921066701b64 0017-RFC-qmimodem-implement-voice-calls.patch"