aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoey Hewitt <joey@joeyhewitt.com>2017-09-14 19:19:43 -0700
committerJoey Hewitt <joey@joeyhewitt.com>2017-09-14 19:19:43 -0700
commit979fce83a1985b8a43f1b8f49ed746710792375f (patch)
tree0c5922c69a49c0b5935df21e39094a09f2a4bc91
parentae8ea8cd07a09236c14232dfe3ed932277ce871e (diff)
downloadandroid_external_ofono-979fce83a1985b8a43f1b8f49ed746710792375f.tar.gz
android_external_ofono-979fce83a1985b8a43f1b8f49ed746710792375f.tar.bz2
android_external_ofono-979fce83a1985b8a43f1b8f49ed746710792375f.zip
qmimodem: reimplement release_specific()
Works better with inactive calls, I think. My testcase is rejecting an incoming call. Without this patch, caller gets abrupt call ended. With it, they get bounced to voicemail (or presumably whatever else the network/callee has configured)
-rw-r--r--drivers/qmimodem/voice_generated.c26
-rw-r--r--drivers/qmimodem/voice_generated.h17
-rw-r--r--drivers/qmimodem/voicecall.c46
3 files changed, 63 insertions, 26 deletions
diff --git a/drivers/qmimodem/voice_generated.c b/drivers/qmimodem/voice_generated.c
index 3440be43..3d26ab23 100644
--- a/drivers/qmimodem/voice_generated.c
+++ b/drivers/qmimodem/voice_generated.c
@@ -56,8 +56,8 @@ enum parse_error qmi_voice_dial_call_parse(
return err;
}
-int qmi_voice_end_call(
- struct qmi_voice_end_call_arg *arg,
+int qmi_voice_manage_call(
+ struct qmi_voice_manage_call_arg *arg,
struct qmi_service *service,
qmi_result_func_t func,
void *user_data,
@@ -69,16 +69,22 @@ int qmi_voice_end_call(
if (!param)
goto error;
+ if (!qmi_param_append_uint8(
+ param,
+ 0x1,
+ arg->ss_call_type))
+ goto error;
+
if (arg->call_id_set) {
if (!qmi_param_append_uint8(
param,
- 0x1,
+ 0x10,
arg->call_id))
goto error;
}
if (qmi_service_send(service,
- 0x21,
+ 0x31,
param,
func,
user_data,
@@ -89,17 +95,15 @@ error:
return 1;
}
-enum parse_error qmi_voice_end_call_parse(
+enum parse_error qmi_voice_manage_call_parse(
struct qmi_result *qmi_result,
- struct qmi_voice_end_call_result *result)
+ struct qmi_voice_manage_call_result *result)
{
- int err = NONE;
-
/* optional */
- if (qmi_result_get_uint8(qmi_result, 0x10, &result->call_id))
- result->call_id_set = 1;
+ if (qmi_result_get_uint16(qmi_result, 0x10, &result->failcause))
+ result->failcause_set = 1;
- return err;
+ return NONE;
}
diff --git a/drivers/qmimodem/voice_generated.h b/drivers/qmimodem/voice_generated.h
index 471b52ea..aa751b71 100644
--- a/drivers/qmimodem/voice_generated.h
+++ b/drivers/qmimodem/voice_generated.h
@@ -41,26 +41,27 @@ 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 {
+struct qmi_voice_manage_call_arg {
+ uint8_t ss_call_type;
bool call_id_set;
uint8_t call_id;
};
-int qmi_voice_end_call(
- struct qmi_voice_end_call_arg *arg,
+int qmi_voice_manage_call(
+ struct qmi_voice_manage_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;
+struct qmi_voice_manage_call_result {
+ bool failcause_set;
+ uint16_t failcause;
};
-enum parse_error qmi_voice_end_call_parse(
+enum parse_error qmi_voice_manage_call_parse(
struct qmi_result *qmi_result,
- struct qmi_voice_end_call_result *result);
+ struct qmi_voice_manage_call_result *result);
struct qmi_voice_answer_call_arg {
bool call_id_set;
diff --git a/drivers/qmimodem/voicecall.c b/drivers/qmimodem/voicecall.c
index 6b3caba4..d16613f3 100644
--- a/drivers/qmimodem/voicecall.c
+++ b/drivers/qmimodem/voicecall.c
@@ -336,13 +336,13 @@ err:
g_free(cbd);
}
-static void end_cb(struct qmi_result *result, void *user_data)
+static void manage_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 qmi_voice_manage_call_result end_result;
struct ofono_call *call;
if (qmi_result_set_error(result, &error)) {
@@ -351,7 +351,7 @@ static void end_cb(struct qmi_result *result, void *user_data)
return;
}
- if (NONE != qmi_voice_end_call_parse(result, &end_result)) {
+ if (NONE != qmi_voice_manage_call_parse(result, &end_result)) {
DBG("Received invalid Result");
CALLBACK_WITH_FAILURE(cb, cbd->data);
return;
@@ -365,31 +365,63 @@ static void release_specific(struct ofono_voicecall *vc, int id,
{
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;
+ struct qmi_voice_manage_call_arg arg;
int i;
+ GSList *l;
+ struct ofono_call *call;
DBG("");
cbd->user = vc;
+ l = g_slist_find_custom(vd->call_list, GINT_TO_POINTER(id),
+ ofono_call_compare_by_id);
+ if (l == NULL) {
+ ofono_error("invalid call id %d", id);
+ goto error;
+ }
+
+ call = l->data;
+
arg.call_id_set = true;
arg.call_id = id;
+ switch (call->status) {
+ case CALL_STATUS_ACTIVE:
+ case CALL_STATUS_DIALING:
+ case CALL_STATUS_ALERTING:
+ arg.ss_call_type = 9; // release specified call
+ break;
+ case CALL_STATUS_HELD:
+ case CALL_STATUS_INCOMING:
+ case CALL_STATUS_WAITING:
+ arg.ss_call_type = 1; // release held or waiting
+ break;
+ case CALL_STATUS_DISCONNECTED:
+ goto success;
+ }
- if (!qmi_voice_end_call(&arg,
+ if (!qmi_voice_manage_call(&arg,
vd->voice,
- end_cb,
+ manage_cb,
cbd,
g_free))
return;
+error:
CALLBACK_WITH_FAILURE(cb, data);
g_free(cbd);
+ return;
+
+success:
+ CALLBACK_WITH_SUCCESS(cb, data);
+ g_free(cbd);
+ return;
}
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 qmi_voice_manage_call_arg arg;
struct ofono_call *call;
GSList *list = NULL;
enum call_status active[] = {