Skip to content

Commit

Permalink
qmimodem: reimplement release_specific()
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
scintill committed Sep 15, 2017
1 parent ae8ea8c commit 979fce8
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 26 deletions.
26 changes: 15 additions & 11 deletions drivers/qmimodem/voice_generated.c
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -89,17 +95,15 @@ int qmi_voice_end_call(
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;
}


Expand Down
17 changes: 9 additions & 8 deletions drivers/qmimodem/voice_generated.h
Expand Up @@ -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;
Expand Down
46 changes: 39 additions & 7 deletions drivers/qmimodem/voicecall.c
Expand Up @@ -336,13 +336,13 @@ static void answer(struct ofono_voicecall *vc, ofono_voicecall_cb_t cb, void *da
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)) {
Expand All @@ -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;
Expand All @@ -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[] = {
Expand Down

0 comments on commit 979fce8

Please sign in to comment.