* [fix-isi-voicecall PATCHv5 0/4] Call state fixes @ 2010-12-03 8:30 Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 1/4] isi/voicecall: fix status reporting Pekka.Pessi 2010-12-03 12:59 ` [fix-isi-voicecall PATCHv5 0/4] Call state fixes Aki Niemi 0 siblings, 2 replies; 6+ messages in thread From: Pekka.Pessi @ 2010-12-03 8:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 96 bytes --] Hi all, Here are the isi voicecall patches again, rebased with the NULL fixes. --Pekka ^ permalink raw reply [flat|nested] 6+ messages in thread
* [fix-isi-voicecall PATCHv5 1/4] isi/voicecall: fix status reporting 2010-12-03 8:30 [fix-isi-voicecall PATCHv5 0/4] Call state fixes Pekka.Pessi @ 2010-12-03 8:30 ` Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 2/4] isi/voicecall: add call id to queued requests Pekka.Pessi 2010-12-03 12:59 ` [fix-isi-voicecall PATCHv5 0/4] Call state fixes Aki Niemi 1 sibling, 1 reply; 6+ messages in thread From: Pekka.Pessi @ 2010-12-03 8:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 13003 bytes --] From: Pekka Pessi <Pekka.Pessi@nokia.com> Do not report incoming calls to the oFono core until they can be answered. Report MT_RELEASED or MO_RELEASED via ofono_voicecall_notify(), TERMINATED calls via ofono_voicecall_disconnected(). --- drivers/isimodem/voicecall.c | 387 ++++++++++++++++++++--------------------- 1 files changed, 189 insertions(+), 198 deletions(-) diff --git a/drivers/isimodem/voicecall.c b/drivers/isimodem/voicecall.c index 84b77d1..b89cbb3 100644 --- a/drivers/isimodem/voicecall.c +++ b/drivers/isimodem/voicecall.c @@ -62,13 +62,6 @@ struct isi_voicecall { /* ------------------------------------------------------------------------- */ -static void isi_call_notify(struct ofono_voicecall *ovc, - struct isi_call *call); -static void isi_call_release(struct ofono_voicecall *, struct isi_call *); -static struct ofono_call isi_call_as_ofono_call(struct isi_call const *); -static int isi_call_status_to_clcc(struct isi_call const *call); -static struct isi_call *isi_call_set_idle(struct isi_call *call); - typedef void GIsiIndication(GIsiClient *client, const void *restrict data, size_t len, uint16_t object, void *opaque); @@ -80,9 +73,6 @@ typedef gboolean GIsiResponse(GIsiClient *client, void const *restrict data, size_t len, uint16_t object, void *opaque); -static GIsiVerify isi_call_verify_cb; -static gboolean isi_call_register(gpointer); - enum { ISI_CALL_TIMEOUT = 1000, }; @@ -205,6 +195,159 @@ static gboolean isi_ctx_return_success(struct isi_call_req_context *irc) } /* ------------------------------------------------------------------------- */ +/* Notify */ + +enum clcc_status { + CLCC_STATUS_EARLY = -1, + CLCC_STATUS_ACTIVE = 0, + CLCC_STATUS_HOLD = 1, + CLCC_STATUS_DIALING = 2, + CLCC_STATUS_ALERTING = 3, + CLCC_STATUS_INCOMING = 4, + CLCC_STATUS_WAITING = 5, + CLCC_STATUS_DISCONNECTED = 6, +}; + +/** Get +CLCC status */ +static int isi_call_status_to_clcc(struct isi_voicecall const *ivc, + struct isi_call const *call) +{ + switch (call->status) { + case CALL_STATUS_CREATE: + return CLCC_STATUS_DIALING; + + case CALL_STATUS_COMING: + return CLCC_STATUS_EARLY; + + case CALL_STATUS_PROCEEDING: + if ((call->mode_info & CALL_MODE_ORIGINATOR)) + return CLCC_STATUS_EARLY; /* MT */ + else + return CLCC_STATUS_DIALING; /* MO */ + + case CALL_STATUS_MO_ALERTING: + return CLCC_STATUS_ALERTING; + + case CALL_STATUS_MT_ALERTING: + return CLCC_STATUS_INCOMING; + + case CALL_STATUS_WAITING: + return CLCC_STATUS_WAITING; + + case CALL_STATUS_ANSWERED: + case CALL_STATUS_ACTIVE: + case CALL_STATUS_HOLD_INITIATED: + case CALL_STATUS_RECONNECT_PENDING: + case CALL_STATUS_SWAP_INITIATED: + return CLCC_STATUS_ACTIVE; + + case CALL_STATUS_HOLD: + case CALL_STATUS_RETRIEVE_INITIATED: + return CLCC_STATUS_HOLD; + + case CALL_STATUS_MO_RELEASE: + case CALL_STATUS_MT_RELEASE: + case CALL_STATUS_TERMINATED: + case CALL_STATUS_IDLE: + return CLCC_STATUS_DISCONNECTED; + } + + return CLCC_STATUS_ACTIVE; +} + +static struct ofono_call isi_call_as_ofono_call(struct isi_voicecall const *ivc, + struct isi_call const *call) +{ + struct ofono_call ocall = { call->id }; + struct ofono_phone_number *number = &ocall.phone_number; + + ocall.type = 0; /* Voice call */ + ocall.direction = call->mode_info & CALL_MODE_ORIGINATOR; + ocall.status = isi_call_status_to_clcc(ivc, call); + memcpy(number->number, call->address, sizeof(number->number)); + number->type = 0x80 | call->addr_type; + ocall.clip_validity = call->presentation & 3; + + if (ocall.clip_validity == 0 && strlen(number->number) == 0) + ocall.clip_validity = 2; + + return ocall; +} + +static struct isi_call *isi_call_set_idle(struct isi_call *call) +{ + uint8_t id; + + id = call->id; + memset(call, 0, sizeof(*call)); + call->id = id; + + return call; +} + +static void isi_call_disconnected(struct ofono_voicecall *ovc, + struct isi_call *call) +{ + struct ofono_error error = { OFONO_ERROR_TYPE_NO_ERROR, 0 }; + enum ofono_disconnect_reason reason = call->reason; + + if (!reason) + reason = OFONO_DISCONNECT_REASON_ERROR; + + DBG("disconnected id=%u reason=%u", call->id, reason); + ofono_voicecall_disconnected(ovc, call->id, reason, &error); + isi_call_set_idle(call); +} + +static void isi_call_notify(struct ofono_voicecall *ovc, + struct isi_call *call) +{ + struct isi_voicecall *ivc = ofono_voicecall_get_data(ovc); + struct isi_call_req_context *irc, **queue; + struct ofono_call ocall; + + DBG("called with status=%s (0x%02X)", + call_status_name(call->status), call->status); + + for (queue = &ivc->queue; (irc = *queue);) { + irc->step(irc, call->status); + + if (*queue == irc) + queue = &irc->next; + } + + ocall = isi_call_as_ofono_call(ivc, call); + + DBG("id=%u,\"%s\",%u,\"%s\",%u,%u", + ocall.id, + ocall.direction ? "mt" : "mo", + ocall.status, + ocall.phone_number.number, + ocall.phone_number.type, + ocall.clip_validity); + + if (ocall.status == CLCC_STATUS_EARLY) + return; + + ofono_voicecall_notify(ovc, &ocall); + + switch (call->status) { + case CALL_STATUS_MO_RELEASE: + call->reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP; + break; + + case CALL_STATUS_MT_RELEASE: + call->reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP; + break; + + case CALL_STATUS_IDLE: + case CALL_STATUS_TERMINATED: + isi_call_disconnected(ovc, call); + break; + } +} + +/* ------------------------------------------------------------------------- */ /* Decoding subblocks */ static void isi_call_any_address_sb_proc(struct isi_voicecall *ivc, @@ -491,16 +634,8 @@ static void isi_call_status_ind_cb(GIsiClient *client, } } - if (old != call->status) { - if (call->status == CALL_STATUS_IDLE) { - call->status = CALL_STATUS_TERMINATED; - isi_call_notify(ovc, call); - isi_call_set_idle(call); - return; - } - } - - isi_call_notify(ovc, call); + if (old != call->status) + isi_call_notify(ovc, call); } static struct isi_call_req_context * @@ -801,150 +936,6 @@ static gboolean isi_call_dtmf_send_resp(GIsiClient *client, return isi_ctx_return_failure(irc); } - -/* ------------------------------------------------------------------------- */ -/* Notify */ - -static void isi_call_notify(struct ofono_voicecall *ovc, - struct isi_call *call) -{ - struct isi_voicecall *ivc = ofono_voicecall_get_data(ovc); - struct isi_call_req_context *irc, **queue; - struct ofono_call ocall; - - DBG("called with status=%s (0x%02X)", - call_status_name(call->status), call->status); - - for (queue = &ivc->queue; (irc = *queue);) { - irc->step(irc, call->status); - if (*queue == irc) - queue = &irc->next; - } - - switch (call->status) { - case CALL_STATUS_IDLE: - case CALL_STATUS_MO_RELEASE: - case CALL_STATUS_MT_RELEASE: - case CALL_STATUS_TERMINATED: - isi_call_release(ovc, call); - return; - } - - ocall = isi_call_as_ofono_call(call); - - DBG("id=%u,%s,%u,\"%s\",%u,%u", - ocall.id, - ocall.direction ? "terminated" : "originated", - ocall.status, - ocall.phone_number.number, - ocall.phone_number.type, - ocall.clip_validity); - - ofono_voicecall_notify(ovc, &ocall); -} - -static void isi_call_release(struct ofono_voicecall *ovc, - struct isi_call *call) -{ - struct ofono_error error = { OFONO_ERROR_TYPE_NO_ERROR, 0 }; - enum ofono_disconnect_reason reason; - - switch (call->status) { - case CALL_STATUS_IDLE: - reason = OFONO_DISCONNECT_REASON_UNKNOWN; - break; - case CALL_STATUS_MO_RELEASE: - reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP; - break; - case CALL_STATUS_MT_RELEASE: - reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP; - break; - 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); -} - -static struct ofono_call isi_call_as_ofono_call(struct isi_call const *call) -{ - struct ofono_call ocall = { call->id }; - struct ofono_phone_number *number = &ocall.phone_number; - - ocall.type = 0; /* Voice call */ - ocall.direction = call->mode_info & CALL_MODE_ORIGINATOR; - ocall.status = isi_call_status_to_clcc(call); - memcpy(number->number, call->address, sizeof number->number); - number->type = 0x80 | call->addr_type; - ocall.clip_validity = call->presentation & 3; - if (ocall.clip_validity == 0 && strlen(number->number) == 0) - ocall.clip_validity = 2; - - return ocall; -} - -/** Get +CLCC status */ -static int isi_call_status_to_clcc(struct isi_call const *call) -{ - switch (call->status) { - case CALL_STATUS_CREATE: - return 2; - case CALL_STATUS_COMING: - return 4; - case CALL_STATUS_PROCEEDING: - if ((call->mode_info & CALL_MODE_ORIGINATOR)) - return 4; /* MT */ - else - return 2; /* MO */ - case CALL_STATUS_MO_ALERTING: - return 3; - case CALL_STATUS_MT_ALERTING: - return 4; - 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_HOLD_INITIATED: - return 0; - - case CALL_STATUS_HOLD: - case CALL_STATUS_RETRIEVE_INITIATED: - return 1; - - case CALL_STATUS_RECONNECT_PENDING: - case CALL_STATUS_TERMINATED: - case CALL_STATUS_SWAP_INITIATED: - return 0; - } - - return 0; -} - -static struct isi_call *isi_call_set_idle(struct isi_call *call) -{ - uint8_t id; - - if (call) { - id = call->id; - memset(call, 0, sizeof *call); - call->id = id; - } - - return call; -} - /* ---------------------------------------------------------------------- */ static void isi_dial(struct ofono_voicecall *ovc, @@ -1245,31 +1236,27 @@ static void isi_send_tones(struct ofono_voicecall *ovc, const char *tones, isi_call_dtmf_send_req(ovc, CALL_ID_ALL, tones, cb, data);; } -static int isi_voicecall_probe(struct ofono_voicecall *ovc, - unsigned int vendor, void *user) +static gboolean isi_call_register(gpointer _ovc) { - GIsiModem *idx = user; - struct isi_voicecall *ivc = g_try_new0(struct isi_voicecall, 1); - int id; - - if (ivc == NULL) - return -ENOMEM; + struct ofono_voicecall *ovc = _ovc; + struct isi_voicecall *ivc = ofono_voicecall_get_data(ovc); + const char *debug = getenv("OFONO_ISI_DEBUG"); - for (id = 0; id <= 7; id++) - ivc->calls[id].id = id; + if (debug != NULL && (!strcmp(debug, "all") || !strcmp(debug, "call"))) + g_isi_client_set_debug(ivc->client, call_debug, NULL); - ivc->client = g_isi_client_create(idx, PN_CALL); - if (ivc->client == NULL) { - g_free(ivc); - return -ENOMEM; - } + g_isi_subscribe(ivc->client, + CALL_STATUS_IND, isi_call_status_ind_cb, + ovc); - ofono_voicecall_set_data(ovc, ivc); + if (isi_call_status_req(ovc, CALL_ID_ALL, + CALL_STATUS_MODE_ADDR_AND_ORIGIN, + NULL, NULL) == NULL) + DBG("Failed to request call status"); - if (!g_isi_verify(ivc->client, isi_call_verify_cb, ovc)) - DBG("Unable to verify reachability"); + ofono_voicecall_register(ovc); - return 0; + return FALSE; } static void isi_call_verify_cb(GIsiClient *client, @@ -1288,28 +1275,32 @@ static void isi_call_verify_cb(GIsiClient *client, g_idle_add(isi_call_register, ovc); } -static gboolean isi_call_register(gpointer _ovc) +static int isi_voicecall_probe(struct ofono_voicecall *ovc, + unsigned int vendor, void *user) { - struct ofono_voicecall *ovc = _ovc; - struct isi_voicecall *ivc = ofono_voicecall_get_data(ovc); + GIsiModem *idx = user; + struct isi_voicecall *ivc; + int id; - const char *debug = getenv("OFONO_ISI_DEBUG"); + ivc = g_try_new0(struct isi_voicecall, 1); + if (ivc == NULL) + return -ENOMEM; - if (debug && (strcmp(debug, "all") == 0 || strcmp(debug, "call") == 0)) - g_isi_client_set_debug(ivc->client, call_debug, NULL); + for (id = 1; id <= 7; id++) + ivc->calls[id].id = id; - g_isi_subscribe(ivc->client, - CALL_STATUS_IND, isi_call_status_ind_cb, - ovc); + ivc->client = g_isi_client_create(idx, PN_CALL); + if (ivc->client == NULL) { + g_free(ivc); + return -ENOMEM; + } - if (isi_call_status_req(ovc, CALL_ID_ALL, - CALL_STATUS_MODE_ADDR_AND_ORIGIN, - NULL, NULL) == NULL) - DBG("Failed to request call status"); + ofono_voicecall_set_data(ovc, ivc); - ofono_voicecall_register(ovc); + if (g_isi_verify(ivc->client, isi_call_verify_cb, ovc) == NULL) + DBG("Unable to verify reachability"); - return FALSE; + return 0; } static void isi_voicecall_remove(struct ofono_voicecall *call) -- 1.7.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [fix-isi-voicecall PATCHv5 2/4] isi/voicecall: add call id to queued requests 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 1/4] isi/voicecall: fix status reporting Pekka.Pessi @ 2010-12-03 8:30 ` Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 3/4] isi/voicecall: avoid side-effects of release Pekka.Pessi 0 siblings, 1 reply; 6+ messages in thread From: Pekka.Pessi @ 2010-12-03 8:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 4781 bytes --] From: Pekka Pessi <Pekka.Pessi@nokia.com> --- drivers/isimodem/voicecall.c | 89 +++++++++++++++++++++++++++--------------- 1 files changed, 57 insertions(+), 32 deletions(-) diff --git a/drivers/isimodem/voicecall.c b/drivers/isimodem/voicecall.c index b89cbb3..e7126a8 100644 --- a/drivers/isimodem/voicecall.c +++ b/drivers/isimodem/voicecall.c @@ -80,41 +80,62 @@ enum { /* ------------------------------------------------------------------------- */ /* Request context for voicecall cb */ -struct isi_call_req_context; - -typedef void isi_call_req_step(struct isi_call_req_context *, int reason); +typedef void isi_call_req_step(struct isi_call_req_context *, + int id, int status); struct isi_call_req_context { - struct isi_call_req_context *next, **prev; + struct isi_call_req_context *next; + struct isi_call_req_context **prev; isi_call_req_step *step; + int id; struct ofono_voicecall *ovc; ofono_voicecall_cb_t cb; void *data; }; -static struct isi_call_req_context * -isi_call_req(struct ofono_voicecall *ovc, - void const *restrict req, - size_t len, - GIsiResponse *handler, - ofono_voicecall_cb_t cb, void *data) +static struct isi_call_req_context *isi_call_req_new( + struct ofono_voicecall *ovc, + ofono_voicecall_cb_t cb, + void *data) { - struct isi_voicecall *ivc; struct isi_call_req_context *irc; - ivc = ofono_voicecall_get_data(ovc); - irc = g_try_new0(struct isi_call_req_context, 1); + if (irc == NULL) + goto failed; - if (irc) { - irc->ovc = ovc; - irc->cb = cb; - irc->data = data; + irc->ovc = ovc; + irc->cb = cb; + irc->data = data; - if (g_isi_request_make(ivc->client, req, len, - ISI_CALL_TIMEOUT, handler, irc)) - return irc; - } + return irc; + +failed: + if (cb) + CALLBACK_WITH_FAILURE(cb, data); + + return NULL; +} + +static struct isi_call_req_context *isi_call_req(struct ofono_voicecall *ovc, + void const *restrict req, + size_t len, + GIsiResponse *handler, + ofono_voicecall_cb_t cb, + void *data) +{ + struct isi_voicecall *ivc; + struct isi_call_req_context *irc; + + irc = isi_call_req_new(ovc, cb, data); + if (irc == NULL) + return NULL; + + ivc = ofono_voicecall_get_data(ovc); + + if (g_isi_send(ivc->client, req, len, + ISI_CALL_TIMEOUT, handler, irc, NULL)) + return irc; g_free(irc); @@ -125,7 +146,8 @@ isi_call_req(struct ofono_voicecall *ovc, } static void isi_ctx_queue(struct isi_call_req_context *irc, - isi_call_req_step *next) + isi_call_req_step *next, + int id) { if (irc->prev == NULL) { struct isi_voicecall *ivc = ofono_voicecall_get_data(irc->ovc); @@ -139,6 +161,7 @@ static void isi_ctx_queue(struct isi_call_req_context *irc, } irc->step = next; + irc->id = id; } static void isi_ctx_remove(struct isi_call_req_context *irc) @@ -187,7 +210,7 @@ static gboolean isi_ctx_return_failure(struct isi_call_req_context *irc) static gboolean isi_ctx_return_success(struct isi_call_req_context *irc) { if (irc && irc->step) { - irc->step(irc, 0); + irc->step(irc, 0, 0); return TRUE; } @@ -310,7 +333,7 @@ static void isi_call_notify(struct ofono_voicecall *ovc, call_status_name(call->status), call->status); for (queue = &ivc->queue; (irc = *queue);) { - irc->step(irc, call->status); + irc->step(irc, call->id, call->status); if (*queue == irc) queue = &irc->next; @@ -1063,18 +1086,19 @@ static void isi_release_all_active(struct ofono_voicecall *ovc, if (irc == NULL) ; else if (waiting) - isi_ctx_queue(irc, isi_wait_and_answer); + isi_ctx_queue(irc, isi_wait_and_answer, 0); else if (hold) - isi_ctx_queue(irc, isi_wait_and_retrieve); + isi_ctx_queue(irc, isi_wait_and_retrieve, 0); } else CALLBACK_WITH_FAILURE(cb, data); } static void isi_wait_and_answer(struct isi_call_req_context *irc, - int event) + int id, int status) { - DBG("irc=%p event=%u", (void *)irc, event); - switch (event) { + DBG("irc=%p id=%d status=%d", (void *)irc, id, status); + + switch (status) { case CALL_STATUS_TERMINATED: isi_answer(irc->ovc, irc->cb, irc->data); isi_ctx_free(irc); @@ -1083,10 +1107,11 @@ static void isi_wait_and_answer(struct isi_call_req_context *irc, } static void isi_wait_and_retrieve(struct isi_call_req_context *irc, - int event) + int id, int status) { - DBG("irc=%p event=%u", (void *)irc, event); - switch (event) { + DBG("irc=%p id=%u status=%u", (void *)irc, id, status); + + switch (status) { case CALL_STATUS_TERMINATED: isi_retrieve(irc->ovc, irc->cb, irc->data); isi_ctx_free(irc); -- 1.7.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [fix-isi-voicecall PATCHv5 3/4] isi/voicecall: avoid side-effects of release 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 2/4] isi/voicecall: add call id to queued requests Pekka.Pessi @ 2010-12-03 8:30 ` Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 4/4] isi/voicecall: fix handling of waiting calls Pekka.Pessi 0 siblings, 1 reply; 6+ messages in thread From: Pekka.Pessi @ 2010-12-03 8:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 3661 bytes --] From: Pekka Pessi <Pekka.Pessi@nokia.com> If a call was held automatically when an another call was dialed or answered, it gets retrieved when the other call is released unless auto change features is explicitly disabled. Drop cause_type parameter because it is never used. Use cause code for busy when releasing incoming or waiting calls. --- drivers/isimodem/voicecall.c | 32 ++++++++++++++++---------------- 1 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/isimodem/voicecall.c b/drivers/isimodem/voicecall.c index e7126a8..9c1bec7 100644 --- a/drivers/isimodem/voicecall.c +++ b/drivers/isimodem/voicecall.c @@ -699,12 +699,13 @@ static gboolean isi_call_answer_resp(GIsiClient *client, static struct isi_call_req_context * isi_call_release_req(struct ofono_voicecall *ovc, - uint8_t call_id, enum call_cause_type cause_type, - uint8_t cause, ofono_voicecall_cb_t cb, void *data) + uint8_t call_id, uint8_t cause, + ofono_voicecall_cb_t cb, void *data) { uint8_t const req[] = { - CALL_RELEASE_REQ, call_id, 1, - CALL_CAUSE, 4, cause_type, cause, + CALL_RELEASE_REQ, call_id, 2, + CALL_CAUSE, 4, CALL_CAUSE_TYPE_CLIENT, cause, + CALL_STATE_AUTO_CHANGE, 4, 0, 0 }; size_t rlen = sizeof req; @@ -1008,7 +1009,8 @@ static void isi_hangup_current(struct ofono_voicecall *ovc, * active calls or calls in progress. */ struct isi_voicecall *ivc = ofono_voicecall_get_data(ovc); - int id = 0; + int id; + uint8_t cause = CALL_CAUSE_RELEASE_BY_USER; for (id = 1; id <= 7; id++) { if (ivc->calls[id].call_id & CALL_ID_WAITING) @@ -1018,11 +1020,14 @@ static void isi_hangup_current(struct ofono_voicecall *ovc, switch (ivc->calls[id].status) { case CALL_STATUS_CREATE: + case CALL_STATUS_MT_ALERTING: + case CALL_STATUS_ANSWERED: + goto release_by_id; + case CALL_STATUS_COMING: case CALL_STATUS_PROCEEDING: case CALL_STATUS_MO_ALERTING: - case CALL_STATUS_MT_ALERTING: - case CALL_STATUS_ANSWERED: + cause = CALL_CAUSE_BUSY_USER_REQUEST; goto release_by_id; } } @@ -1030,15 +1035,14 @@ static void isi_hangup_current(struct ofono_voicecall *ovc, id = CALL_ID_ACTIVE; release_by_id: - isi_call_release_req(ovc, id, CALL_CAUSE_TYPE_CLIENT, - CALL_CAUSE_RELEASE_BY_USER, cb, data); + isi_call_release_req(ovc, id, cause, cb, data); } static void isi_release_all_held(struct ofono_voicecall *ovc, ofono_voicecall_cb_t cb, void *data) { /* AT+CHLD=0 (w/out incoming calls) */ - isi_call_release_req(ovc, CALL_ID_HOLD, CALL_CAUSE_TYPE_CLIENT, + isi_call_release_req(ovc, CALL_ID_HOLD, CALL_CAUSE_RELEASE_BY_USER, cb, data); } @@ -1047,8 +1051,7 @@ static void isi_set_udub(struct ofono_voicecall *ovc, { /* Release waiting calls */ isi_call_release_req(ovc, CALL_ID_WAITING, - CALL_CAUSE_TYPE_CLIENT, CALL_CAUSE_BUSY_USER_REQUEST, - cb, data); + CALL_CAUSE_BUSY_USER_REQUEST, cb, data); } static void isi_retrieve(struct ofono_voicecall *ovc, @@ -1079,7 +1082,6 @@ static void isi_release_all_active(struct ofono_voicecall *ovc, struct isi_call_req_context *irc; irc = isi_call_release_req(ovc, CALL_ID_ACTIVE, - CALL_CAUSE_TYPE_CLIENT, CALL_CAUSE_RELEASE_BY_USER, cb, data); @@ -1176,9 +1178,7 @@ static void isi_release_specific(struct ofono_voicecall *ovc, int id, break; } - isi_call_release_req(ovc, id, - CALL_CAUSE_TYPE_CLIENT, cause, - cb, data); + isi_call_release_req(ovc, id, cause, cb, data); } else CALLBACK_WITH_FAILURE(cb, data); } -- 1.7.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [fix-isi-voicecall PATCHv5 4/4] isi/voicecall: fix handling of waiting calls 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 3/4] isi/voicecall: avoid side-effects of release Pekka.Pessi @ 2010-12-03 8:30 ` Pekka.Pessi 0 siblings, 0 replies; 6+ messages in thread From: Pekka.Pessi @ 2010-12-03 8:30 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 4524 bytes --] From: Pekka Pessi <Pekka.Pessi@nokia.com> Also, do not retrieve calls after isi_release_all_active() because retrieving is now only an unwanted side-effect . --- drivers/isimodem/voicecall.c | 114 ++++++++++++++++++++--------------------- 1 files changed, 56 insertions(+), 58 deletions(-) diff --git a/drivers/isimodem/voicecall.c b/drivers/isimodem/voicecall.c index 9c1bec7..f2fd53a 100644 --- a/drivers/isimodem/voicecall.c +++ b/drivers/isimodem/voicecall.c @@ -1060,65 +1060,59 @@ static void isi_retrieve(struct ofono_voicecall *ovc, isi_call_control_req(ovc, CALL_ID_HOLD, CALL_OP_RETRIEVE, 0, cb, data); } -static isi_call_req_step isi_wait_and_answer, isi_wait_and_retrieve; +static void isi_wait_and_answer(struct isi_call_req_context *irc, + int id, int status) +{ + DBG("irc=%p id=%d status=%d", (void *)irc, id, status); + + if (id != irc->id) + return; + + switch (status) { + case CALL_STATUS_MT_ALERTING: + isi_call_answer_req(irc->ovc, irc->id, irc->cb, irc->data); + isi_ctx_free(irc); + break; + + default: + isi_ctx_return_failure(irc); + break; + } +} static void isi_release_all_active(struct ofono_voicecall *ovc, ofono_voicecall_cb_t cb, void *data) { /* AT+CHLD=1 */ struct isi_voicecall *ivc = ofono_voicecall_get_data(ovc); - int id = 0, waiting = 0, active = 0, hold = 0; + struct isi_call_req_context *irc; + int id; + int waiting_id = 0; + int active = 0; for (id = 1; id <= 7; id++) { if (ivc->calls[id].call_id & CALL_ID_WAITING) - waiting++; - if (ivc->calls[id].call_id & CALL_ID_HOLD) - hold++; + waiting_id = id; + if (ivc->calls[id].call_id & CALL_ID_ACTIVE) active++; } - if (active) { - struct isi_call_req_context *irc; - - irc = isi_call_release_req(ovc, CALL_ID_ACTIVE, - CALL_CAUSE_RELEASE_BY_USER, - cb, data); - - if (irc == NULL) - ; - else if (waiting) - isi_ctx_queue(irc, isi_wait_and_answer, 0); - else if (hold) - isi_ctx_queue(irc, isi_wait_and_retrieve, 0); - } else + if (!active) { CALLBACK_WITH_FAILURE(cb, data); -} - -static void isi_wait_and_answer(struct isi_call_req_context *irc, - int id, int status) -{ - DBG("irc=%p id=%d status=%d", (void *)irc, id, status); - - switch (status) { - case CALL_STATUS_TERMINATED: - isi_answer(irc->ovc, irc->cb, irc->data); - isi_ctx_free(irc); - break; + return; } -} -static void isi_wait_and_retrieve(struct isi_call_req_context *irc, - int id, int status) -{ - DBG("irc=%p id=%u status=%u", (void *)irc, id, status); + irc = isi_call_release_req(ovc, CALL_ID_ACTIVE, + CALL_CAUSE_RELEASE_BY_USER, + cb, data); + if (irc == NULL) + return; - switch (status) { - case CALL_STATUS_TERMINATED: - isi_retrieve(irc->ovc, irc->cb, irc->data); - isi_ctx_free(irc); - break; - } + if (waiting_id) + isi_ctx_queue(irc, isi_wait_and_answer, waiting_id); + + /* Retrieving held calls is currently a unwanted side-effect */ } static void isi_hold_all_active(struct ofono_voicecall *ovc, @@ -1126,34 +1120,38 @@ static void isi_hold_all_active(struct ofono_voicecall *ovc, { /* AT+CHLD=2 */ struct isi_voicecall *ivc = ofono_voicecall_get_data(ovc); - int id = 0, op = 0, waiting = 0, active = 0, hold = 0; + int id; + int waiting = 0; + int active = 0; + int hold = 0; + int op; for (id = 1; id <= 7; id++) { if (ivc->calls[id].call_id & CALL_ID_WAITING) waiting++; - if (ivc->calls[id].call_id & CALL_ID_HOLD) + else if (ivc->calls[id].call_id & CALL_ID_HOLD) hold++; - if (ivc->calls[id].call_id & CALL_ID_ACTIVE) + else if (ivc->calls[id].call_id & CALL_ID_ACTIVE) active++; } if (waiting) { isi_call_answer_req(ovc, CALL_ID_WAITING, cb, data); - } else if (hold) { - if (active) { + return; + } + + if (active) { + if (hold) op = CALL_OP_SWAP; - id = CALL_ID_ACTIVE; - } else { - op = CALL_OP_RETRIEVE; - id = CALL_ID_HOLD; - } - isi_call_control_req(ovc, id, op, 0, cb, data); - } else if (active) { - id = CALL_ID_ACTIVE, op = CALL_OP_HOLD; - isi_call_control_req(ovc, id, op, 0, cb, data); - } else { + else + op = CALL_OP_HOLD; + + isi_call_control_req(ovc, CALL_ID_ACTIVE, op, 0, cb, data); + + } else if (hold) + isi_retrieve(ovc, cb, data); + else CALLBACK_WITH_FAILURE(cb, data); - } } static void isi_release_specific(struct ofono_voicecall *ovc, int id, -- 1.7.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [fix-isi-voicecall PATCHv5 0/4] Call state fixes 2010-12-03 8:30 [fix-isi-voicecall PATCHv5 0/4] Call state fixes Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 1/4] isi/voicecall: fix status reporting Pekka.Pessi @ 2010-12-03 12:59 ` Aki Niemi 1 sibling, 0 replies; 6+ messages in thread From: Aki Niemi @ 2010-12-03 12:59 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 265 bytes --] On Fri, 2010-12-03 at 10:30 +0200, ext Pekka.Pessi(a)nokia.com wrote: > Hi all, > > Here are the isi voicecall patches again, rebased with the NULL fixes. Pushed the lot, thanks. Are these fixes now also in the refactored gisi tree? ;) Cheers, Aki ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-12-03 12:59 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-12-03 8:30 [fix-isi-voicecall PATCHv5 0/4] Call state fixes Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 1/4] isi/voicecall: fix status reporting Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 2/4] isi/voicecall: add call id to queued requests Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 3/4] isi/voicecall: avoid side-effects of release Pekka.Pessi 2010-12-03 8:30 ` [fix-isi-voicecall PATCHv5 4/4] isi/voicecall: fix handling of waiting calls Pekka.Pessi 2010-12-03 12:59 ` [fix-isi-voicecall PATCHv5 0/4] Call state fixes Aki Niemi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox