diff options
author | Pekka Pessi <Pekka.Pessi@nokia.com> | 2011-02-02 00:22:09 +0200 |
---|---|---|
committer | Aki Niemi <aki.niemi@nokia.com> | 2011-02-03 14:59:53 +0200 |
commit | 1715ce85cb6b5a6b775fb33d388103a813ab9db7 (patch) | |
tree | 121c484473e80ae7ee81a38bc225288920b8a6bc /drivers/isimodem/voicecall.c | |
parent | 457b051928da7a831f7361b9bd156d494593ce04 (diff) | |
download | ofono-1715ce85cb6b5a6b775fb33d388103a813ab9db7.tar.bz2 |
isimodem: fix problems in call state reporting
Do not report early incoming calls.
Report "disconnected" state separately.
Call ofono_voicecall_disconnected() only after call id is released.
Diffstat (limited to 'drivers/isimodem/voicecall.c')
-rw-r--r-- | drivers/isimodem/voicecall.c | 84 |
1 files changed, 60 insertions, 24 deletions
diff --git a/drivers/isimodem/voicecall.c b/drivers/isimodem/voicecall.c index 8267f1c3..0a32f279 100644 --- a/drivers/isimodem/voicecall.c +++ b/drivers/isimodem/voicecall.c @@ -363,10 +363,13 @@ static int isi_call_status_to_clcc(const struct isi_call *call) case CALL_STATUS_WAITING: return 5; - case CALL_STATUS_ANSWERED: - case CALL_STATUS_ACTIVE: case CALL_STATUS_MO_RELEASE: case CALL_STATUS_MT_RELEASE: + case CALL_STATUS_TERMINATED: + return 6; + + case CALL_STATUS_ANSWERED: + case CALL_STATUS_ACTIVE: case CALL_STATUS_HOLD_INITIATED: return 0; @@ -375,11 +378,10 @@ static int isi_call_status_to_clcc(const struct isi_call *call) return 1; case CALL_STATUS_RECONNECT_PENDING: - case CALL_STATUS_TERMINATED: case CALL_STATUS_SWAP_INITIATED: + default: return 0; } - return 0; } static struct ofono_call isi_call_as_ofono_call(const struct isi_call *call) @@ -433,13 +435,27 @@ static struct isi_call *isi_call_set_idle(struct isi_call *call) return call; } -static void isi_call_release(struct ofono_voicecall *ovc, struct isi_call *call) +static void isi_call_disconnected(struct ofono_voicecall *ovc, + struct isi_call *call) { struct ofono_error error = { OFONO_ERROR_TYPE_NO_ERROR, 0 }; + + DBG("disconnected id=%u reason=%u", call->id, call->reason); + + ofono_voicecall_disconnected(ovc, call->id, call->reason, &error); + + isi_call_set_idle(call); +} + +static void isi_call_set_disconnect_reason(struct isi_call *call) +{ enum ofono_disconnect_reason reason; + if (call->reason != OFONO_DISCONNECT_REASON_UNKNOWN) + return; + switch (call->status) { case CALL_STATUS_IDLE: reason = OFONO_DISCONNECT_REASON_UNKNOWN; @@ -456,17 +472,9 @@ static void isi_call_release(struct ofono_voicecall *ovc, struct isi_call *call) case CALL_STATUS_TERMINATED: default: reason = OFONO_DISCONNECT_REASON_ERROR; - break; - } - - if (!call->reason) { - call->reason = reason; - DBG("disconnected id=%u reason=%u", call->id, reason); - ofono_voicecall_disconnected(ovc, call->id, reason, &error); } - if (!reason) - isi_call_set_idle(call); + call->reason = reason; } static void isi_call_notify(struct ofono_voicecall *ovc, struct isi_call *call) @@ -487,11 +495,20 @@ static void isi_call_notify(struct ofono_voicecall *ovc, struct isi_call *call) switch (call->status) { case CALL_STATUS_IDLE: + isi_call_disconnected(ovc, call); + return; + + case CALL_STATUS_COMING: + case CALL_STATUS_PROCEEDING: + if ((call->mode_info & CALL_MODE_ORIGINATOR)) + /* Do not notify early MT calls */ + return; + break; + case CALL_STATUS_MO_RELEASE: case CALL_STATUS_MT_RELEASE: case CALL_STATUS_TERMINATED: - isi_call_release(ovc, call); - return; + isi_call_set_disconnect_reason(call); } ocall = isi_call_as_ofono_call(call); @@ -615,17 +632,33 @@ static void isi_call_status_ind_cb(const GIsiMessage *msg, void *data) } } - if (old_status != call->status) { + if (old_status == call->status) + return; - if (call->status == CALL_STATUS_IDLE) { - call->status = CALL_STATUS_TERMINATED; + isi_call_notify(ovc, call); +} - isi_call_notify(ovc, call); - isi_call_set_idle(call); - return; - } - } +static void isi_call_terminated_ind_cb(const GIsiMessage *msg, void *data) +{ + struct ofono_voicecall *ovc = data; + struct isi_voicecall *ivc = ofono_voicecall_get_data(ovc); + struct isi_call *call; + uint8_t call_id; + uint8_t old_status; + + if (ivc == NULL || g_isi_msg_id(msg) != CALL_TERMINATED_IND || + !g_isi_msg_data_get_byte(msg, 0, &call_id) || + (call_id & 7) == 0) + return; + + call = &ivc->calls[call_id & 7]; + old_status = call->status; + + if (old_status == CALL_STATUS_IDLE) + return; + + call->status = CALL_STATUS_TERMINATED; isi_call_notify(ovc, call); } @@ -1255,6 +1288,9 @@ static void isi_call_verify_cb(const GIsiMessage *msg, void *data) g_isi_client_ind_subscribe(ivc->client, CALL_STATUS_IND, isi_call_status_ind_cb, ovc); + g_isi_client_ind_subscribe(ivc->client, CALL_TERMINATED_IND, + isi_call_terminated_ind_cb, ovc); + if (!isi_call_status_req(ovc, CALL_ID_ALL, CALL_STATUS_MODE_ADDR_AND_ORIGIN, NULL, NULL)) |