temp/ofono: implement DTMF in qmimodem driver (MR 1922)
The TLVs are documented in GobiAPI. I pass 0xff for the call ID, as the stock RIL appears to always do. I would guess it means "current foreground call." The call ID is returned in TLV 0x10, but I didn't implement parsing of that. Co-authored-by: Joey Hewitt <joey@joeyhewitt.com> Acked-by: Alexey Andreyev <aa13q@ya.ru>
This commit is contained in:
parent
55503f0e52
commit
f7f7716efa
2 changed files with 250 additions and 1 deletions
247
temp/ofono/0007-qmimodem-implement-dtmf.patch
Normal file
247
temp/ofono/0007-qmimodem-implement-dtmf.patch
Normal file
|
@ -0,0 +1,247 @@
|
|||
From 306a3a6f19546b7b9b6b8df973d75710ce21bc3c Mon Sep 17 00:00:00 2001
|
||||
From: Joey Hewitt <joey@joeyhewitt.com>
|
||||
Date: Mon, 4 Sep 2017 23:51:07 -0700
|
||||
Subject: [PATCH] qmimodem: implement DTMF
|
||||
|
||||
The TLVs are documented in GobiAPI. I pass 0xff for the call ID, as the
|
||||
stock RIL appears to always do. I would guess it means "current foreground
|
||||
call."
|
||||
|
||||
The call ID is returned in TLV 0x10, but I didn't implement parsing of
|
||||
that.
|
||||
|
||||
Acked-by: Alexey Andreyev <aa13q@ya.ru>
|
||||
|
||||
diff --git a/drivers/qmimodem/voice_generated.c b/drivers/qmimodem/voice_generated.c
|
||||
index aef79c4..b579043 100644
|
||||
--- a/drivers/qmimodem/voice_generated.c
|
||||
+++ b/drivers/qmimodem/voice_generated.c
|
||||
@@ -216,3 +216,72 @@ enum parse_error qmi_voice_call_status(
|
||||
|
||||
return err;
|
||||
}
|
||||
+
|
||||
+int qmi_voice_start_cont_dtmf(
|
||||
+ struct qmi_voice_start_cont_dtmf_arg *arg,
|
||||
+ struct qmi_service *service,
|
||||
+ qmi_result_func_t func,
|
||||
+ void *user_data,
|
||||
+ qmi_destroy_func_t destroy)
|
||||
+{
|
||||
+ struct qmi_param *param = NULL;
|
||||
+ uint8_t param_body[2];
|
||||
+
|
||||
+ param = qmi_param_new();
|
||||
+ if (!param)
|
||||
+ goto error;
|
||||
+
|
||||
+ param_body[0] = arg->call_id;
|
||||
+ param_body[1] = arg->dtmf_char;
|
||||
+
|
||||
+ if (!qmi_param_append(
|
||||
+ param,
|
||||
+ 0x1,
|
||||
+ sizeof(param_body),
|
||||
+ param_body))
|
||||
+ goto error;
|
||||
+
|
||||
+ if (qmi_service_send(service,
|
||||
+ 0x29,
|
||||
+ param,
|
||||
+ func,
|
||||
+ user_data,
|
||||
+ destroy) > 0)
|
||||
+ return 0;
|
||||
+
|
||||
+error:
|
||||
+ g_free(param);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int qmi_voice_stop_cont_dtmf(
|
||||
+ struct qmi_voice_stop_cont_dtmf_arg *arg,
|
||||
+ struct qmi_service *service,
|
||||
+ qmi_result_func_t func,
|
||||
+ void *user_data,
|
||||
+ qmi_destroy_func_t destroy)
|
||||
+{
|
||||
+ struct qmi_param *param = NULL;
|
||||
+
|
||||
+ param = qmi_param_new();
|
||||
+ if (!param)
|
||||
+ goto error;
|
||||
+
|
||||
+ if (!qmi_param_append_uint8(
|
||||
+ param,
|
||||
+ 0x1,
|
||||
+ arg->call_id))
|
||||
+ goto error;
|
||||
+
|
||||
+ if (qmi_service_send(service,
|
||||
+ 0x2a,
|
||||
+ param,
|
||||
+ func,
|
||||
+ user_data,
|
||||
+ destroy) > 0)
|
||||
+ return 0;
|
||||
+
|
||||
+error:
|
||||
+ g_free(param);
|
||||
+ return 1;
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/drivers/qmimodem/voice_generated.h b/drivers/qmimodem/voice_generated.h
|
||||
index dc238ef..c627fe1 100644
|
||||
--- a/drivers/qmimodem/voice_generated.h
|
||||
+++ b/drivers/qmimodem/voice_generated.h
|
||||
@@ -110,4 +110,27 @@ enum parse_error qmi_voice_call_status(
|
||||
struct qmi_result *qmi_result,
|
||||
struct qmi_voice_all_call_status_ind *result);
|
||||
|
||||
+struct qmi_voice_start_cont_dtmf_arg {
|
||||
+ uint8_t call_id;
|
||||
+ uint8_t dtmf_char;
|
||||
+};
|
||||
+
|
||||
+int qmi_voice_start_cont_dtmf(
|
||||
+ struct qmi_voice_start_cont_dtmf_arg *arg,
|
||||
+ struct qmi_service *service,
|
||||
+ qmi_result_func_t func,
|
||||
+ void *user_data,
|
||||
+ qmi_destroy_func_t destroy);
|
||||
+
|
||||
+struct qmi_voice_stop_cont_dtmf_arg {
|
||||
+ uint8_t call_id;
|
||||
+};
|
||||
+
|
||||
+int qmi_voice_stop_cont_dtmf(
|
||||
+ struct qmi_voice_stop_cont_dtmf_arg *arg,
|
||||
+ struct qmi_service *service,
|
||||
+ qmi_result_func_t func,
|
||||
+ void *user_data,
|
||||
+ qmi_destroy_func_t destroy);
|
||||
+
|
||||
#endif /* __OFONO_QMI_VOICE_GENERATED_H */
|
||||
diff --git a/drivers/qmimodem/voicecall.c b/drivers/qmimodem/voicecall.c
|
||||
index bc8ac2b..5d8d35f 100644
|
||||
--- a/drivers/qmimodem/voicecall.c
|
||||
+++ b/drivers/qmimodem/voicecall.c
|
||||
@@ -413,6 +413,110 @@ static void hangup_active(struct ofono_voicecall *vc,
|
||||
release_specific(vc, call->id, cb, data);
|
||||
}
|
||||
|
||||
+static void stop_cont_dtmf_cb(struct qmi_result *result, void *user_data)
|
||||
+{
|
||||
+ struct cb_data *cbd = user_data;
|
||||
+ ofono_voicecall_cb_t cb = cbd->cb;
|
||||
+
|
||||
+ uint16_t error;
|
||||
+
|
||||
+ if (qmi_result_set_error(result, &error)) {
|
||||
+ DBG("QMI Error %d", error);
|
||||
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
+}
|
||||
+
|
||||
+static void start_cont_dtmf_cb(struct qmi_result *result, void *user_data)
|
||||
+{
|
||||
+ struct cb_data *cbd = user_data;
|
||||
+ ofono_voicecall_cb_t cb = cbd->cb;
|
||||
+ struct ofono_voicecall *vc = cbd->user;
|
||||
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
|
||||
+ struct qmi_voice_stop_cont_dtmf_arg arg;
|
||||
+ uint16_t error;
|
||||
+
|
||||
+ if (qmi_result_set_error(result, &error)) {
|
||||
+ DBG("QMI Error %d", error);
|
||||
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ arg.call_id = 0xff;
|
||||
+
|
||||
+ if (!qmi_voice_stop_cont_dtmf(&arg,
|
||||
+ vd->voice,
|
||||
+ stop_cont_dtmf_cb,
|
||||
+ cbd,
|
||||
+ g_free))
|
||||
+ return;
|
||||
+
|
||||
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
+}
|
||||
+
|
||||
+static void send_one_dtmf(struct ofono_voicecall *vc, const char dtmf,
|
||||
+ ofono_voicecall_cb_t cb, void *data) {
|
||||
+ struct qmi_voice_start_cont_dtmf_arg arg;
|
||||
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
|
||||
+
|
||||
+ arg.call_id = 0xff;
|
||||
+ arg.dtmf_char = (uint8_t) dtmf;
|
||||
+
|
||||
+ struct cb_data *cbd = cb_data_new(cb, data);
|
||||
+ cbd->user = vc;
|
||||
+
|
||||
+ if (!qmi_voice_start_cont_dtmf(&arg,
|
||||
+ vd->voice,
|
||||
+ start_cont_dtmf_cb,
|
||||
+ cbd,
|
||||
+ NULL))
|
||||
+ return;
|
||||
+
|
||||
+ CALLBACK_WITH_FAILURE(cb, data);
|
||||
+ g_free(cbd);
|
||||
+}
|
||||
+
|
||||
+struct send_one_dtmf_cb_data {
|
||||
+ const char *full_dtmf;
|
||||
+ const char *next_dtmf;
|
||||
+ struct ofono_voicecall *vc;
|
||||
+};
|
||||
+
|
||||
+static void send_one_dtmf_cb(const struct ofono_error *error, void *data) {
|
||||
+ struct cb_data *cbd = data;
|
||||
+ ofono_voicecall_cb_t cb = cbd->cb;
|
||||
+ struct send_one_dtmf_cb_data *send_one_dtmf_cb_data = cbd->user;
|
||||
+
|
||||
+ if (error->type != OFONO_ERROR_TYPE_NO_ERROR || *send_one_dtmf_cb_data->next_dtmf == 0) {
|
||||
+ if (error->type == OFONO_ERROR_TYPE_NO_ERROR) {
|
||||
+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
|
||||
+ } else {
|
||||
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
|
||||
+ }
|
||||
+ g_free((gpointer)send_one_dtmf_cb_data->full_dtmf);
|
||||
+ g_free(send_one_dtmf_cb_data);
|
||||
+ g_free(cbd);
|
||||
+ } else {
|
||||
+ send_one_dtmf(send_one_dtmf_cb_data->vc, *(send_one_dtmf_cb_data->next_dtmf++), send_one_dtmf_cb, data);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
|
||||
+ ofono_voicecall_cb_t cb, void *data)
|
||||
+{
|
||||
+ struct cb_data *cbd = cb_data_new(cb, data);
|
||||
+ struct send_one_dtmf_cb_data *send_one_dtmf_cb_data = g_new(struct send_one_dtmf_cb_data, 1);
|
||||
+
|
||||
+ send_one_dtmf_cb_data->full_dtmf = g_strdup(dtmf);
|
||||
+ send_one_dtmf_cb_data->next_dtmf = &send_one_dtmf_cb_data->full_dtmf[1];
|
||||
+ send_one_dtmf_cb_data->vc = vc;
|
||||
+ cbd->user = send_one_dtmf_cb_data;
|
||||
+
|
||||
+ send_one_dtmf(vc, *dtmf, send_one_dtmf_cb, cbd);
|
||||
+}
|
||||
+
|
||||
static const struct ofono_voicecall_driver driver = {
|
||||
.name = "qmimodem",
|
||||
.probe = qmi_voicecall_probe,
|
||||
@@ -421,6 +525,7 @@ static const struct ofono_voicecall_driver driver = {
|
||||
.answer = answer,
|
||||
.hangup_active = hangup_active,
|
||||
.release_specific = release_specific,
|
||||
+ .send_tones = send_dtmf,
|
||||
};
|
||||
|
||||
void qmi_voicecall_init(void)
|
|
@ -3,7 +3,7 @@
|
|||
pkgname=ofono
|
||||
pkgver=9999
|
||||
_pkgver=1.31
|
||||
pkgrel=7
|
||||
pkgrel=8
|
||||
pkgdesc="Infrastructure for building mobile telephony (GSM/UMTS) applications [$_pkgver]"
|
||||
url="https://01.org/ofono"
|
||||
arch="armhf armv7 aarch64"
|
||||
|
@ -24,6 +24,7 @@ source="https://www.kernel.org/pub/linux/network/ofono/ofono-$_pkgver.tar.xz
|
|||
0004-add-call-list-helper-to-manage-voice-call-lists.patch
|
||||
0005-qmimodem-implement-voice-calls.patch
|
||||
0006-qmimodem-Fix-dialing-to-an-international-number.patch
|
||||
0007-qmimodem-implement-dtmf.patch
|
||||
$pkgname.initd
|
||||
$pkgname-auto-enable.initd
|
||||
udev.rules
|
||||
|
@ -83,6 +84,7 @@ ad25dcc34bf710287c9a03fdcd61f2f2fd675691f55be30dbe7c8421753aa857906dd23b2d4f7f75
|
|||
3e0dce12bcb65d3c6db15cfd50058e793bf1f1ae6e330bf804565afde54614227746a8d4316ccd36093f22e2cc4f62e3a32e46276ab81a7b1f3a61f56984ed78 0004-add-call-list-helper-to-manage-voice-call-lists.patch
|
||||
72d0f63c091d4b1fc5b405ec67e73f377887ee3dffd4791272122462bf4feaeec207de9b177632756e1f973a7bf7bde119c6ec6556568a6307287ba43998b7a0 0005-qmimodem-implement-voice-calls.patch
|
||||
6dd4d5f829d66b5b9a13aed6d5a991a2cd3dee6db04a122bcc1d87d0eddc37637468bec58f9fe6027c89eac3b14411201d324150e6be4b103622340da6a599fe 0006-qmimodem-Fix-dialing-to-an-international-number.patch
|
||||
7d28bcec2dc8b13003c05d74202aced9c86efe35447fbcb0f444fb04447fab8e80a47fa20a662aa0148d42c25333b3261e3cd570991deee9cdfd76effd24af7e 0007-qmimodem-implement-dtmf.patch
|
||||
bc76c404a7de626210dbd78f659444567a95b6e6d8db0661d5d67ea361e2941ad55242d43a5957995817145d4d5323476fbc42d1830b20608a5e90a7a4ba1194 ofono.initd
|
||||
54a2cb55547e77c22a98c4260f2e94d9327d5d98e1b604f9413a7380ae4489247a97561cc2ab39476bc6e6fb5e673dca8053218b18ac4626addb51ecb29f0167 ofono-auto-enable.initd
|
||||
28ba914e171ba7f0dcc4be24f2bd078a8db6b2c0fdbb29845b2702f00f9cf64d0e9ecb277e5d7f8113ef450eb9044e542e7093129ecd67bef1c9e9328756391c udev.rules
|
||||
|
|
Loading…
Reference in a new issue