isi/voicecall: fix handling of waiting calls

Also, do not retrieve calls after isi_release_all_active() because
retrieving is now only an unwanted side-effect .
This commit is contained in:
Pekka Pessi 2010-12-03 10:30:50 +02:00 committed by Aki Niemi
parent be2778cb99
commit a67c5cf4c5
1 changed files with 57 additions and 59 deletions

View File

@ -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) {
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 {
CALLBACK_WITH_FAILURE(cb, data);
return;
}
if (active) {
if (hold)
op = CALL_OP_SWAP;
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,