voicecall: Add support for function hangup_all
authorSjur Brændeland <sjur.brandeland@stericsson.com>
Mon, 9 Aug 2010 21:18:38 +0000 (23:18 +0200)
committerDenis Kenzior <denkenz@gmail.com>
Thu, 12 Aug 2010 16:32:12 +0000 (11:32 -0500)
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.

include/voicecall.h
src/voicecall.c

index 998c02d..2356fcf 100644 (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,
index a30aaa5..49b9c79 100644 (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;
 }