aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Pigg <adam@piggz.co.uk>2024-04-21 20:49:05 +0100
committerDenis Kenzior <denkenz@gmail.com>2024-04-22 16:04:08 -0500
commit752d286a5ce3efc28a6b8a4c4dffb44d23d8d15b (patch)
tree2421da11951dd4daf7bfdd848899a4c86e969283
parent3680df68459353dff4bd39dd47b222685e5713b3 (diff)
downloadofono-752d286a5ce3efc28a6b8a4c4dffb44d23d8d15b.tar.gz
qmimodem: voicecall: Implement active call hangup
hangup_active iterates the current list of calls, looking for the first active call and then calls release_specific. This then sets up the parameters for a call to QMI_VOICE_END_CALL, with the only parameters being the call-id. end_call_cb will then be called and will parse out the call-id and check for success.
-rw-r--r--drivers/qmimodem/voice.h1
-rw-r--r--drivers/qmimodem/voicecall.c82
2 files changed, 83 insertions, 0 deletions
diff --git a/drivers/qmimodem/voice.h b/drivers/qmimodem/voice.h
index a524cf987..caedb079b 100644
--- a/drivers/qmimodem/voice.h
+++ b/drivers/qmimodem/voice.h
@@ -51,6 +51,7 @@ enum voice_commands {
QMI_VOICE_DIAL_CALL = 0x20,
QMI_VOICE_ALL_CALL_STATUS_IND = 0x2e,
QMI_VOICE_GET_ALL_CALL_INFO = 0x2f,
+ QMI_VOICE_END_CALL = 0x21,
QMI_VOICE_ANSWER_CALL = 0x22,
QMI_VOICE_SUPS_NOTIFICATION_IND = 0x32,
QMI_VOICE_SET_SUPS_SERVICE = 0x33,
diff --git a/drivers/qmimodem/voicecall.c b/drivers/qmimodem/voicecall.c
index d65fb59b2..24c4f3f17 100644
--- a/drivers/qmimodem/voicecall.c
+++ b/drivers/qmimodem/voicecall.c
@@ -527,6 +527,86 @@ error:
l_free(param);
}
+static void end_call_cb(struct qmi_result *result, void *user_data)
+{
+ struct cb_data *cbd = user_data;
+ ofono_voicecall_cb_t cb = cbd->cb;
+ uint16_t error;
+ uint8_t call_id;
+
+ static const uint8_t RESULT_CALL_ID = 0x10;
+
+ if (qmi_result_set_error(result, &error)) {
+ DBG("QMI Error %d", error);
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
+ }
+
+ if (qmi_result_get_uint8(result, RESULT_CALL_ID, &call_id))
+ DBG("Received end call result with call id %d", call_id);
+
+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
+static void release_specific(struct ofono_voicecall *vc, int id,
+ ofono_voicecall_cb_t cb, void *data)
+{
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ struct cb_data *cbd;
+ struct qmi_param *param = NULL;
+
+ static const uint8_t PARAM_CALL_ID = 0x01;
+
+ DBG("");
+
+ param = qmi_param_new();
+ cbd = cb_data_new(cb, data);
+ cbd->user = vc;
+
+ if (!qmi_param_append_uint8(param, PARAM_CALL_ID, id))
+ goto error;
+
+ if (qmi_service_send(vd->voice, QMI_VOICE_END_CALL, param, end_call_cb,
+ cbd, l_free) > 0)
+ return;
+
+error:
+ CALLBACK_WITH_FAILURE(cb, data);
+ l_free(cbd);
+ l_free(param);
+}
+
+static void hangup_active(struct ofono_voicecall *vc, ofono_voicecall_cb_t cb,
+ void *data)
+{
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ struct ofono_call *call;
+ enum call_status active[] = {
+ CALL_STATUS_ACTIVE,
+ CALL_STATUS_DIALING,
+ CALL_STATUS_ALERTING,
+ CALL_STATUS_INCOMING,
+ };
+
+ DBG("");
+
+ for (uint32_t i = 0; i < L_ARRAY_SIZE(active); i++) {
+ call = l_queue_find(vd->call_list, ofono_call_match_by_status,
+ L_INT_TO_PTR(active[i]));
+
+ if (call)
+ break;
+ }
+
+ if (call == NULL) {
+ DBG("Can not find a call to hang up");
+ CALLBACK_WITH_FAILURE(cb, data);
+ return;
+ }
+
+ release_specific(vc, call->id, cb, data);
+}
+
static void create_voice_cb(struct qmi_service *service, void *user_data)
{
struct ofono_voicecall *vc = user_data;
@@ -594,6 +674,8 @@ static const struct ofono_voicecall_driver driver = {
.remove = qmi_voicecall_remove,
.dial = dial,
.answer = answer,
+ .hangup_active = hangup_active,
+ .release_specific = release_specific,
};
OFONO_ATOM_DRIVER_BUILTIN(voicecall, qmimodem, &driver)