voicecall: Add support for function hangup_all

This patch fixes problem for modems that cannot terminate
DIALING/ALERTING calls with CHUP=1X. The main change is that
voicecall driver's hangup function is split into the functions
hangup_all and hangup_active.

Changes:
- In cases where hangup previously was used, hangup_all is used
  if implemented otherwise hangup_active is used.
- Call in state DIALING/ALERTING is released with hangup_active if
  implemented.
- manager_hangup_all will simply call hangup_all if implemented.
- manager_hangup_all will release calls in state
  ALERTING/DIALING/INCOMING using hangup_active otherwise
  release_specific.
This commit is contained in:
Sjur Brændeland 2010-08-09 23:18:38 +02:00 committed by Denis Kenzior
parent dde0a4ccb5
commit 9a24ece0fb
2 changed files with 45 additions and 13 deletions

View File

@ -69,6 +69,8 @@ struct ofono_voicecall_driver {
ofono_voicecall_cb_t cb, void *data);
void (*hangup_active)(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void (*hangup_all)(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void (*hold_all_active)(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data);
void (*release_all_held)(struct ofono_voicecall *vc,

View File

@ -261,15 +261,18 @@ static DBusMessage *voicecall_hangup(DBusConnection *conn,
if (vc->pending)
return __ofono_error_busy(msg);
/* According to various specs, other than 27.007, +CHUP is used
* to reject an incoming call
*/
if (call->status == CALL_STATUS_INCOMING) {
if (vc->driver->hangup == NULL)
if (vc->driver->hangup_all == NULL &&
vc->driver->hangup_active == NULL)
return __ofono_error_not_implemented(msg);
vc->pending = dbus_message_ref(msg);
vc->driver->hangup(vc, generic_callback, vc);
if (vc->driver->hangup_all)
vc->driver->hangup_all(vc, generic_callback, vc);
else
vc->driver->hangup_active(vc, generic_callback, vc);
return NULL;
}
@ -286,12 +289,18 @@ static DBusMessage *voicecall_hangup(DBusConnection *conn,
num_calls = g_slist_length(vc->call_list);
if (num_calls == 1 && vc->driver->hangup &&
if (num_calls == 1 &&
(call->status == CALL_STATUS_ACTIVE ||
call->status == CALL_STATUS_DIALING ||
call->status == CALL_STATUS_ALERTING)) {
call->status == CALL_STATUS_ALERTING) &&
(vc->driver->hangup_all != NULL ||
vc->driver->hangup_active != NULL)) {
vc->pending = dbus_message_ref(msg);
vc->driver->hangup(vc, generic_callback, vc);
if (vc->driver->hangup_all)
vc->driver->hangup_all(vc, generic_callback, vc);
else
vc->driver->hangup_active(vc, generic_callback, vc);
return NULL;
}
@ -304,6 +313,15 @@ static DBusMessage *voicecall_hangup(DBusConnection *conn,
return NULL;
}
if (vc->driver->hangup_active != NULL &&
(call->status == CALL_STATUS_ALERTING ||
call->status == CALL_STATUS_DIALING)) {
vc->pending = dbus_message_ref(msg);
vc->driver->hangup_active(vc, generic_callback, vc);
return NULL;
}
if (vc->driver->release_specific == NULL)
return __ofono_error_not_implemented(msg);
@ -762,7 +780,14 @@ static void voicecalls_release_next(struct ofono_voicecall *vc)
vc->release_list = g_slist_remove(vc->release_list, call);
vc->driver->release_specific(vc, call->call->id,
if (vc->driver->hangup_active != NULL &&
(call->call->status == CALL_STATUS_ALERTING ||
call->call->status == CALL_STATUS_DIALING ||
call->call->status == CALL_STATUS_INCOMING))
vc->driver->hangup_active(vc, multirelease_callback, vc);
else
vc->driver->release_specific(vc, call->call->id,
multirelease_callback, vc);
}
@ -1119,7 +1144,9 @@ static DBusMessage *manager_hangup_all(DBusConnection *conn,
if (vc->pending)
return __ofono_error_busy(msg);
if (!vc->driver->release_specific)
if (vc->driver->hangup_all == NULL &&
(vc->driver->release_specific == NULL ||
vc->driver->hangup_active == NULL))
return __ofono_error_not_implemented(msg);
if (vc->call_list == NULL) {
@ -1131,9 +1158,12 @@ static DBusMessage *manager_hangup_all(DBusConnection *conn,
vc->pending = dbus_message_ref(msg);
voicecalls_release_queue(vc, vc->call_list);
voicecalls_release_next(vc);
if (vc->driver->hangup_all != NULL)
vc->driver->hangup_all(vc, generic_callback, vc);
else {
voicecalls_release_queue(vc, vc->call_list);
voicecalls_release_next(vc);
}
return NULL;
}