tools: Add simple voice routing to Huawei audio utility

This commit is contained in:
Marcel Holtmann 2010-09-26 23:12:53 +09:00
parent dd0ff9310d
commit 83dfa92ac1
1 changed files with 149 additions and 1 deletions

View File

@ -25,9 +25,14 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <gdbus.h>
@ -48,14 +53,131 @@ struct modem_data {
guint call_changed_watch;
gboolean has_callmanager;
gboolean is_huawei;
gint audio_users;
guint audio_watch;
int format;
int channels;
int speed;
int dsp_out;
};
struct call_data {
char *path;
struct modem_data *modem;
};
static GHashTable *modem_list;
static gboolean audio_receive(GIOChannel *channel,
GIOCondition condition, gpointer user_data)
{
struct modem_data *modem = user_data;
char buf[512];
ssize_t rlen, wlen;
int fd;
if (condition & (G_IO_NVAL | G_IO_ERR)) {
modem->audio_watch = 0;
return FALSE;
}
fd = g_io_channel_unix_get_fd(channel);
rlen = read(fd, buf, sizeof(buf));
if (rlen < 0)
return TRUE;
wlen = write(modem->dsp_out, buf, rlen);
return TRUE;
}
static void open_audio(struct modem_data *modem)
{
GIOChannel *channel;
struct termios ti;
int fd;
if (modem->is_huawei == FALSE)
return;
if (modem->audio_users > 0)
return;
g_print("enabling audio\n");
modem->dsp_out = open("/dev/dsp", O_WRONLY, 0);
if (modem->dsp_out < 0) {
g_printerr("Failed to open DSP device\n");
return;
}
if (ioctl(modem->dsp_out, SNDCTL_DSP_SETFMT, &modem->format) < 0)
g_printerr("Failed to set DSP format\n");
if (ioctl(modem->dsp_out, SNDCTL_DSP_CHANNELS, &modem->channels) < 0)
g_printerr("Failed to set DSP channels\n");
if (ioctl(modem->dsp_out, SNDCTL_DSP_SPEED, &modem->speed) < 0)
g_printerr("Failed to set DSP speed\n");
fd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY);
if (fd < 0) {
g_printerr("Failed to open audio port\n");
close(modem->dsp_out);
modem->dsp_out = -1;
return;
}
/* Switch TTY to raw mode */
memset(&ti, 0, sizeof(ti));
cfmakeraw(&ti);
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSANOW, &ti);
channel = g_io_channel_unix_new(fd);
if (channel == NULL) {
g_printerr("Failed to create IO channel\n");
close(modem->dsp_out);
modem->dsp_out = -1;
close(fd);
return;
}
g_io_channel_set_close_on_unref(channel, TRUE);
modem->audio_watch = g_io_add_watch(channel,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
audio_receive, modem);
g_io_channel_unref(channel);
modem->audio_users++;
}
static void close_audio(struct modem_data *modem)
{
if (modem->is_huawei == FALSE)
return;
modem->audio_users--;
if (modem->audio_users > 0)
return;
g_print("disabling audio\n");
if (modem->audio_watch > 0) {
g_source_remove(modem->audio_watch);
modem->audio_watch = 0;
}
close(modem->dsp_out);
}
static void call_set(struct call_data *call, const char *key,
DBusMessageIter *iter)
{
@ -74,6 +196,8 @@ static void destroy_call(gpointer data)
g_print("call removed (%s)\n", call->path);
close_audio(call->modem);
g_free(call->path);
g_free(call);
}
@ -94,6 +218,10 @@ static void create_call(struct modem_data *modem,
g_print("call added (%s)\n", call->path);
call->modem = modem;
open_audio(modem);
dbus_message_iter_recurse(iter, &dict);
while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
@ -110,7 +238,6 @@ static void create_call(struct modem_data *modem,
dbus_message_iter_next(&dict);
}
}
static gboolean call_added(DBusConnection *conn,
@ -277,6 +404,18 @@ static void check_interfaces(struct modem_data *modem, DBusMessageIter *iter)
get_calls(modem);
}
static void check_manufacturer(struct modem_data *modem, DBusMessageIter *iter)
{
const char *manufacturer;
dbus_message_iter_get_basic(iter, &manufacturer);
if (g_str_equal(manufacturer, "huawei") == TRUE) {
g_print("found Huawei modem\n");
modem->is_huawei = TRUE;
}
}
static void destroy_modem(gpointer data)
{
struct modem_data *modem = data;
@ -305,6 +444,11 @@ static void create_modem(DBusConnection *conn,
modem->path = g_strdup(path);
modem->format = AFMT_S16_LE;
modem->channels = 1;
modem->speed = 8000;
modem->dsp_out = -1;
modem->call_list = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL, destroy_call);
@ -338,6 +482,8 @@ static void create_modem(DBusConnection *conn,
if (g_str_equal(key, "Interfaces") == TRUE)
check_interfaces(modem, &value);
else if (g_str_equal(key, "Manufacturer") == TRUE)
check_manufacturer(modem, &value);
dbus_message_iter_next(&dict);
}
@ -401,6 +547,8 @@ static gboolean modem_changed(DBusConnection *conn,
if (g_str_equal(key, "Interfaces") == TRUE)
check_interfaces(modem, &value);
else if (g_str_equal(key, "Manufacturer") == TRUE)
check_manufacturer(modem, &value);
return TRUE;
}