diff options
Diffstat (limited to 'src/voicecall.c')
-rw-r--r-- | src/voicecall.c | 80 |
1 files changed, 45 insertions, 35 deletions
diff --git a/src/voicecall.c b/src/voicecall.c index f6d15ff7..241b38ea 100644 --- a/src/voicecall.c +++ b/src/voicecall.c @@ -48,15 +48,9 @@ GSList *g_drivers = NULL; -struct multi_release { - ofono_voicecall_cb_t cb; - void *data; -}; - struct ofono_voicecall { GSList *call_list; GSList *release_list; - struct multi_release multi_release; GSList *multiparty_list; GHashTable *en_list; /* emergency number list */ GSList *sim_en_list; /* Emergency numbers already read from SIM */ @@ -77,6 +71,7 @@ struct ofono_voicecall { unsigned int hfp_watch; GKeyFile *settings; char *imsi; + ofono_voicecall_cb_t release_queue_done_cb; struct ofono_emulator *pending_em; unsigned int pending_id; char *em_atd_number; @@ -1219,7 +1214,8 @@ static void voicecalls_emit_call_added(struct ofono_voicecall *vc, g_dbus_send_message(ofono_dbus_get_connection(), signal); } -static void voicecalls_release_queue(struct ofono_voicecall *vc, GSList *calls) +static void voicecalls_release_queue(struct ofono_voicecall *vc, GSList *calls, + ofono_voicecall_cb_t cb) { GSList *l; struct voicecall *call; @@ -1235,6 +1231,8 @@ static void voicecalls_release_queue(struct ofono_voicecall *vc, GSList *calls) vc->release_list = g_slist_prepend(vc->release_list, l->data); } + + vc->release_queue_done_cb = cb; } static void voicecalls_release_next(struct ofono_voicecall *vc) @@ -1696,9 +1694,8 @@ static DBusMessage *manager_hangup_all(DBusConnection *conn, vc->pending = dbus_message_ref(msg); if (vc->driver->hangup_all == NULL) { - voicecalls_release_queue(vc, vc->call_list); - vc->multi_release.cb = voicecalls_release_done; - vc->multi_release.data = vc; + voicecalls_release_queue(vc, vc->call_list, + voicecalls_release_done); voicecalls_release_next(vc); } else vc->driver->hangup_all(vc, generic_callback, vc); @@ -1950,9 +1947,8 @@ static DBusMessage *multiparty_hangup(DBusConnection *conn, } /* Fall back to the old-fashioned way */ - voicecalls_release_queue(vc, vc->multiparty_list); - vc->multi_release.cb = voicecalls_release_done; - vc->multi_release.data = vc; + voicecalls_release_queue(vc, vc->multiparty_list, + voicecalls_release_done); voicecalls_release_next(vc); out: @@ -2263,7 +2259,7 @@ static void multirelease_callback(const struct ofono_error *error, void *data) return; } - vc->multi_release.cb(error, vc->multi_release.data); + vc->release_queue_done_cb(error, vc); } static void emit_en_list_changed(struct ofono_voicecall *vc) @@ -2706,9 +2702,10 @@ static void sim_watch(struct ofono_atom *atom, static void emulator_generic_cb(const struct ofono_error *error, void *data) { - struct ofono_emulator *em = data; + struct ofono_voicecall *vc = data; - ofono_emulator_send_final(em, error); + ofono_emulator_send_final(vc->pending_em, error); + vc->pending_em = NULL; } static void emulator_mpty_join_cb(const struct ofono_error *error, void *data) @@ -2781,8 +2778,16 @@ static void emulator_mpty_private_chat_cb(const struct ofono_error *error, g_slist_free(old); } +#define CHECK_BUSY(vc, em, result) \ + if (vc->pending || vc->dial_req || vc->pending_em) { \ + result.error = 126; \ + result.type = OFONO_ERROR_TYPE_CME; \ + ofono_emulator_send_final(em, &result); \ + } \ + static void emulator_ata_cb(struct ofono_emulator *em, - struct ofono_emulator_request *req, void *userdata) + struct ofono_emulator_request *req, + void *userdata) { struct ofono_voicecall *vc = userdata; struct ofono_error result; @@ -2791,13 +2796,16 @@ static void emulator_ata_cb(struct ofono_emulator *em, switch (ofono_emulator_request_get_type(req)) { case OFONO_EMULATOR_REQUEST_TYPE_COMMAND_ONLY: + CHECK_BUSY(vc, em, result) + if (!voicecalls_have_incoming(vc)) goto fail; if (vc->driver->answer == NULL) goto fail; - vc->driver->answer(vc, emulator_generic_cb, em); + vc->pending_em = em; + vc->driver->answer(vc, emulator_generic_cb, vc); break; default: @@ -2819,7 +2827,7 @@ static void emulator_chup_cb(struct ofono_emulator *em, switch (ofono_emulator_request_get_type(req)) { case OFONO_EMULATOR_REQUEST_TYPE_COMMAND_ONLY: - if (vc->release_list) + if (vc->pending || vc->pending_em) goto fail; if (vc->driver->release_specific == NULL && @@ -2827,7 +2835,8 @@ static void emulator_chup_cb(struct ofono_emulator *em, goto fail; if (vc->driver->hangup_active) { - vc->driver->hangup_active(vc, emulator_generic_cb, em); + vc->pending_em = em; + vc->driver->hangup_active(vc, emulator_generic_cb, vc); goto done; } @@ -2845,8 +2854,8 @@ static void emulator_chup_cb(struct ofono_emulator *em, if (vc->release_list == NULL) goto fail; - vc->multi_release.cb = emulator_generic_cb; - vc->multi_release.data = em; + vc->pending_em = em; + vc->release_queue_done_cb = emulator_generic_cb; voicecalls_release_next(vc); done: @@ -2939,6 +2948,8 @@ static void emulator_chld_cb(struct ofono_emulator *em, if (!ofono_emulator_request_next_number(req, &chld)) goto fail; + CHECK_BUSY(vc, em, result) + switch (chld) { case 0: if (vc->driver->set_udub == NULL) @@ -2947,42 +2958,42 @@ static void emulator_chld_cb(struct ofono_emulator *em, if (vc->driver->release_all_held == NULL) goto fail; + vc->pending_em = em; + if (voicecalls_have_waiting(vc)) { vc->driver->set_udub(vc, - emulator_generic_cb, em); + emulator_generic_cb, vc); return; } vc->driver->release_all_held(vc, - emulator_generic_cb, em); + emulator_generic_cb, vc); return; case 1: if (vc->driver->release_all_active == NULL) goto fail; + vc->pending_em = em; vc->driver->release_all_active(vc, - emulator_generic_cb, em); + emulator_generic_cb, vc); return; case 2: if (vc->driver->hold_all_active == NULL) goto fail; + vc->pending_em = em; vc->driver->hold_all_active(vc, - emulator_generic_cb, em); + emulator_generic_cb, vc); return; case 3: if (vc->driver->create_multiparty == NULL) goto fail; - if (vc->pending_em || vc->pending || vc->dial_req) - goto fail; - if (!voicecalls_have_held(vc) || !voicecalls_have_active(vc)) goto fail; vc->pending_em = em; - vc->driver->create_multiparty(vc, emulator_mpty_join_cb, vc); return; @@ -2990,8 +3001,9 @@ static void emulator_chld_cb(struct ofono_emulator *em, if (vc->driver->transfer == NULL) goto fail; + vc->pending_em = em; vc->driver->transfer(vc, - emulator_generic_cb, em); + emulator_generic_cb, vc); return; default: break; @@ -3001,8 +3013,9 @@ static void emulator_chld_cb(struct ofono_emulator *em, if (vc->driver->release_specific == NULL) goto fail; + vc->pending_em = em; vc->driver->release_specific(vc, chld - 10, - emulator_generic_cb, em); + emulator_generic_cb, vc); return; } @@ -3013,9 +3026,6 @@ static void emulator_chld_cb(struct ofono_emulator *em, if (vc->driver->private_chat == NULL) goto fail; - if (vc->pending_em || vc->pending || vc->dial_req) - goto fail; - for (l = vc->multiparty_list; l; l = l->next) { struct voicecall *v = l->data; if (v->call->id == id) |