From patchwork Wed Feb 11 18:32:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Machek X-Patchwork-Id: 5814151 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 530109F30C for ; Wed, 11 Feb 2015 18:35:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 18FA220211 for ; Wed, 11 Feb 2015 18:35:16 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CFA7B200F0 for ; Wed, 11 Feb 2015 18:35:14 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YLc5n-0007Fa-5l; Wed, 11 Feb 2015 18:32:55 +0000 Received: from atrey.karlin.mff.cuni.cz ([195.113.26.193]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YLc5h-00079g-RG for linux-arm-kernel@lists.infradead.org; Wed, 11 Feb 2015 18:32:51 +0000 Received: by atrey.karlin.mff.cuni.cz (Postfix, from userid 512) id A550581E95; Wed, 11 Feb 2015 19:32:28 +0100 (CET) Date: Wed, 11 Feb 2015 19:32:28 +0100 From: Pavel Machek To: Ivaylo Dimitrov Subject: Voice calls working on N900 (*) (was Re: N900 modem support in 3.18-rc1) Message-ID: <20150211183228.GB29636@amd> References: <20141104205117.GA17606@amd> <20141106180335.GA21513@earth.universe> <20141106225005.GA14002@amd> <201411070001.46481@pali> <545C6F14.8050303@gmail.com> <20141113162420.GB8512@xo-6d-61-c0.localdomain> <5465A977.4030605@gmail.com> <20141114172008.GB12250@earth.universe> <54665E02.8050108@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <54665E02.8050108@gmail.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150211_103250_483761_6F2DB738 X-CRM114-Status: GOOD ( 27.24 ) X-Spam-Score: -2.3 (--) Cc: khilman@kernel.org, tony@atomide.com, aaro.koskinen@iki.fi, kernel list , Sebastian Reichel , Sakari Ailus , Pali Roh?r , linux-omap@vger.kernel.org, freemangordon@abv.bg, ian.molton@facebook.com, linux-arm-kernel X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hi! (*) for low values of working. Ok, so I got voice on n900 to work on 3.19-n900 tree.. Quality of incoming voice is reasonable, quality of outgoing voice not so, I was told. So, you need patched kernel (pali's n900 tree) ofono etc, plus I'm using ofone python script to control the modem, plus you need libcmtspeechdata. I have this version: commit 7f8f3ce357513e4849e1bf6d657980a514529c1a Author: Kai Vehmanen Date: Tue Mar 8 13:46:48 2011 +0200 cmtspeech_msgs: fix compiler warning Add parenthesis to make the code more readable and to kill a compiler warning. Signed-off-by: Kai Vehmanen Plus, apply the patch below. I could not get configure (etc) to work for me, so I build it by hand. cmtspeech_ofono_test can then be used to route the voice calls (if you feed it with audio data, see the "run" script). What is missing: * right setup of mixers. (I was actually running audio data to my desktop for some tests). What commandline tools can be used to set up mixers? I'm using "alsamixer", but it has text ui... * passing audio data using pipes is really a hack... and periodically discarding audio data is certainly not a good idea. Good luck, Pavel diff --git a/mkit b/mkit new file mode 100755 index 0000000..6fbd216 --- /dev/null +++ b/mkit @@ -0,0 +1,15 @@ +build_lib () { +for a in test_cmtspeech test_cmtspeech_msgs test_ring; do + echo $a +# gcc cmtspeech_backend_common.c cmtspeech_msgs.c cmtspeech_nokiamodem.c sal_debug.c $a.c -I. -lrt -o $a +done + +for a in cmtspeech_backend_common cmtspeech_msgs cmtspeech_nokiamodem sal_debug; do + gcc -fPIC $a.c -c -I. -o $a.o +done +ar rcs libcmtspeech.a cmtspeech_backend_common.o cmtspeech_msgs.o cmtspeech_nokiamodem.o sal_debug.o +} + +# build_lib +gcc -I . -I /usr/include/dbus-1.0/ -I /usr/lib/arm-linux-gnueabi/dbus-1.0/include/ utils/cmtspeech_ofono_test.c -lpthread -lrt libcmtspeech.a /usr/lib/arm-linux-gnueabi/libdbus-1.a -o cmtspeech_ofono_test + diff --git a/run b/run new file mode 100755 index 0000000..8cb1f9a --- /dev/null +++ b/run @@ -0,0 +1,2 @@ +#!/bin/bash +parec --rate=4000 --latency-msec=100 | ./cmtspeech_ofono_test -a -v | pacat --rate=4000 --latency-msec=100 diff --git a/utils/cmtspeech_ofono_test.c b/utils/cmtspeech_ofono_test.c index 4a6f080..ffb323f 100644 --- a/utils/cmtspeech_ofono_test.c +++ b/utils/cmtspeech_ofono_test.c @@ -48,6 +48,9 @@ #include #include +#include +#include + struct test_ctx { DBusConnection* dbus_conn; int dbus_fd; @@ -55,6 +58,9 @@ struct test_ctx { bool call_server_status; int verbose; cmtspeech_t *cmtspeech; + int source_fd; + int sink_fd; + int data_through; }; #define PREFIX "cmtspeech_ofono_test: " @@ -75,7 +81,7 @@ static dbus_bool_t priv_add_cb(DBusWatch *watch, void *data) ctx->dbus_fd = fd; ctx->dbus_watch = watch; - DEBUG(printf(PREFIX "priv_add_cb: socket %d, watch %p (tracking %p).\n", + DEBUG(fprintf(stderr, PREFIX "priv_add_cb: socket %d, watch %p (tracking %p).\n", fd, watch, ctx->dbus_watch)); return TRUE; @@ -85,7 +91,7 @@ static void priv_remove_cb(DBusWatch *watch, void *data) { struct test_ctx *ctx = (struct test_ctx*)data; - DEBUG(printf(PREFIX "priv_remove_cb: (%p).\n", (void*)watch)); + DEBUG(fprintf(stderr, PREFIX "priv_remove_cb: (%p).\n", (void*)watch)); if (ctx->dbus_watch == watch) { ctx->dbus_watch = NULL; @@ -99,7 +105,7 @@ static void priv_toggled_cb(DBusWatch *watch, void *data) dbus_bool_t enabled = dbus_watch_get_enabled(watch); - DEBUG(printf(PREFIX "priv_toggled_cb: (%p) enabled=%d.\n", (void*)watch, enabled)); + DEBUG(fprintf(stderr, PREFIX "priv_toggled_cb: (%p) enabled=%d.\n", (void*)watch, enabled)); if (ctx->dbus_watch == watch) { if (enabled == TRUE) @@ -132,7 +138,7 @@ DBusConnection *test_dbus_make_connection(struct test_ctx *ctx, DBusBusType dbus conn = dbus_bus_get(dbus_type, &dbus_error); if (dbus_error_is_set(&dbus_error) != TRUE) { - DEBUG(printf(PREFIX "Connection established to DBus (%d).\n", (int)dbus_type)); + DEBUG(fprintf(stderr, PREFIX "Connection established to DBus (%d).\n", (int)dbus_type)); } else { fprintf(stderr, PREFIX "ERROR: unable to connect to DBus\n"); @@ -184,6 +190,24 @@ static void test_dbus_release(struct test_ctx *ctx) } } +static void flush_input(struct test_ctx *ctx) +{ + char scratch[10240]; + int total = 0; + + fprintf(stderr, "Flushing input...\n"); + if (!ctx->sink_fd) + return; + while(1) { + int num; + num = read(ctx->source_fd, scratch, 10240); + if (num == -1) + break; + total += num; + } + fprintf(stderr, "Flushing input (%d)\n", total); +} + static bool test_handle_dbus_ofono(struct test_ctx *ctx, DBusMessage *msg) { const char* property = NULL; @@ -194,7 +218,7 @@ static bool test_handle_dbus_ofono(struct test_ctx *ctx, DBusMessage *msg) dbus_message_get_args(msg, &dbus_error, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID); - DEBUG(printf(PREFIX "received ofono AudioSettings change, params name='%s'\n", + DEBUG(fprintf(stderr, PREFIX "received ofono AudioSettings change, params name='%s'\n", property)); if (strcmp(property, "Active") == 0) { DBusMessageIter i; @@ -213,7 +237,11 @@ static bool test_handle_dbus_ofono(struct test_ctx *ctx, DBusMessage *msg) dbus_message_iter_get_basic(&j, &state); if (state != old_state) { - INFO(printf(PREFIX "org.ofono.AudioSettings.Active to %d.\n", state)); + INFO(fprintf(stderr, PREFIX "org.ofono.AudioSettings.Active to %d.\n", state)); + if (state == 1) { + flush_input(ctx); + } + cmtspeech_state_change_call_status(ctx->cmtspeech, state); ctx->call_server_status = state; } @@ -238,14 +266,14 @@ static int test_handle_dbus_message(struct test_ctx *ctx, DBusMessage *msg) int res = 0; const char* dbusif = dbus_message_get_interface(msg); - DEBUG(printf(PREFIX "got message to if:%s, member:%s.\n", + DEBUG(fprintf(stderr, PREFIX "got message to if:%s, member:%s.\n", dbusif, dbus_message_get_member(msg))); if (strstr(dbusif, "org.ofono.")) { test_handle_dbus_ofono(ctx, msg); } else - INFO(printf(PREFIX "unknown/ignored signal: if=%s, member=%s.\n", + INFO(fprintf(stderr, PREFIX "unknown/ignored signal: if=%s, member=%s.\n", dbusif, dbus_message_get_member(msg))); return res; @@ -280,6 +308,7 @@ static struct option const opt_tbl[] = { {"verbose", 0, NULL, 'v'}, {"help", 0, NULL, 'h'}, + {"audio", 0, NULL, 'a'}, {NULL, 0, NULL, 0} }; @@ -297,13 +326,24 @@ static void priv_parse_options(struct test_ctx *ctx, int argc, char *argv[]) assert(ctx); - while (res = getopt_long(argc, argv, "hv", opt_tbl, &opt_index), res != -1) { + while (res = getopt_long(argc, argv, "hva", opt_tbl, &opt_index), res != -1) { switch (res) { case 'v': ++ctx->verbose; - printf(PREFIX "Increasing verbosity to %d.\n", ctx->verbose); + fprintf(stderr, PREFIX "Increasing verbosity to %d.\n", ctx->verbose); + break; + + case 'a': + fprintf(stderr, "Enabling audio path\n"); + ctx->source_fd = 0; + ctx->sink_fd = 1; + ctx->data_through = 0; + { + int flags = fcntl(ctx->source_fd, F_GETFL, 0); + fcntl(ctx->source_fd, F_SETFL, flags | O_NONBLOCK); + } break; case 'h': @@ -317,16 +357,43 @@ static void priv_parse_options(struct test_ctx *ctx, int argc, char *argv[]) static void test_handle_cmtspeech_data(struct test_ctx *ctx) { cmtspeech_buffer_t *dlbuf, *ulbuf; + char scratch[10240]; int res = cmtspeech_dl_buffer_acquire(ctx->cmtspeech, &dlbuf); if (res == 0) { - DEBUG(printf(PREFIX "Received a DL packet (%u bytes).\n", dlbuf->count)); + DEBUG(fprintf(stderr, PREFIX "Received a DL packet (%u bytes).\n", dlbuf->count)); if (cmtspeech_protocol_state(ctx->cmtspeech) == CMTSPEECH_STATE_ACTIVE_DLUL) { res = cmtspeech_ul_buffer_acquire(ctx->cmtspeech, &ulbuf); if (res == 0) { if (ulbuf->pcount >= dlbuf->pcount) { - DEBUG(printf(PREFIX "Looping DL packet to UL (%u payload bytes).\n", dlbuf->pcount)); - memcpy(ulbuf->payload, dlbuf->payload, dlbuf->pcount); + if (ctx->sink_fd) { + int num; + + memset(ulbuf->payload, 0, ulbuf->pcount); + num = read(ctx->source_fd, ulbuf->payload, ulbuf->pcount); + if (num != dlbuf->pcount) { + fprintf(stderr, "Not enough data on input (%d/%d)\n", num, dlbuf->pcount); + } + ctx->data_through += ulbuf->pcount; + + if (ctx->data_through > 100000) { + ctx->data_through = 0; + fprintf(stderr, "Draining input\n"); + while(1) { + num = read(ctx->source_fd, scratch, 10240); + fprintf(stderr, "Too much data on input (%d)\n", num); + if (num == -1) + break; + if (num < 320) + fprintf(stderr, "Too little to drain (%d)\n", num); + } + } + + write(ctx->sink_fd, dlbuf->payload, dlbuf->pcount); + } else { + DEBUG(fprintf(stderr, PREFIX "Looping DL packet to UL (%u payload bytes).\n", dlbuf->pcount)); + memcpy(ulbuf->payload, dlbuf->payload, dlbuf->pcount); + } } cmtspeech_ul_buffer_release(ctx->cmtspeech, ulbuf); } @@ -341,7 +408,7 @@ static int test_handle_cmtspeech_control(struct test_ctx *ctx) int state_tr = CMTSPEECH_TR_INVALID; cmtspeech_read_event(ctx->cmtspeech, &cmtevent); - DEBUG(printf(PREFIX "read cmtspeech event %d.\n", cmtevent.msg_type)); + DEBUG(fprintf(stderr, PREFIX "read cmtspeech event %d.\n", cmtevent.msg_type)); state_tr = cmtspeech_event_to_state_transition(ctx->cmtspeech, &cmtevent); @@ -399,7 +466,7 @@ static int test_mainloop(struct test_ctx *ctx) pollres = poll(fds, count, -1); - DEBUG(printf("poll returned %d (count:%d, cmt:%02X, dbus:%02X)\n", + DEBUG(fprintf(stderr, "poll returned %d (count:%d, cmt:%02X, dbus:%02X)\n", pollres, count, fds[cmt].revents, fds[dbus].revents)); if (pollres > 0) { @@ -454,6 +521,7 @@ int main(int argc, char *argv[]) struct test_ctx *ctx = &ctx0; int res = 0; + fprintf(stderr, "NFS sucks, version 0.0.1\n"); priv_setup_signals(); ctx->dbus_conn = NULL; @@ -480,14 +548,14 @@ int main(int argc, char *argv[]) return -1; } - INFO(printf(PREFIX "Setup succesful, entering mainloop.\n")); + INFO(fprintf(stderr, PREFIX "Setup succesful, entering mainloop.\n")); res = test_mainloop(ctx); cmtspeech_close(ctx->cmtspeech); test_dbus_release(ctx); - INFO(printf(PREFIX "Completed, exiting (%d).\n", res)); + INFO(fprintf(stderr, PREFIX "Completed, exiting (%d).\n", res)); return res; }