summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2007-08-27 11:31:01 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2007-08-27 11:31:01 +0000
commite1bfc91de96a38616100cc31db7bdb69f2cfbea6 (patch)
treef8e2ce652875076f96b0db575a5daabb10156e66
parentca3ff4f6a27ff2d421a7f8fdd3bd5dd67f1f47df (diff)
Convert alsa initiated headset connections to similar callback system that A2DP is already using
-rw-r--r--audio/headset.c98
-rw-r--r--audio/headset.h8
-rw-r--r--audio/main.c1
-rw-r--r--audio/sink.c2
-rw-r--r--audio/unix.c156
-rw-r--r--audio/unix.h2
6 files changed, 145 insertions, 122 deletions
diff --git a/audio/headset.c b/audio/headset.c
index 5c758db0..da224b8a 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -51,11 +51,9 @@
#include "dbus.h"
#include "dbus-helper.h"
#include "logging.h"
-#include "ipc.h"
#include "device.h"
#include "manager.h"
#include "error.h"
-#include "unix.h"
#include "headset.h"
#define RING_INTERVAL 3000
@@ -71,11 +69,12 @@ static char *str_state[] = {"DISCONNECTED", "CONNECTING", "CONNECTED",
struct pending_connect {
DBusMessage *msg;
GIOChannel *io;
- struct ipc_packet *pkt;
- int pkt_len;
guint io_id;
int sock;
int err;
+ unsigned int id;
+ headset_stream_cb_t cb;
+ void *cb_data;
};
struct headset {
@@ -109,8 +108,6 @@ static int rfcomm_connect(struct device *device, struct pending_connect *c);
static void pending_connect_free(struct pending_connect *c)
{
- if (c->pkt)
- g_free(c->pkt);
if (c->io) {
g_io_channel_close(c->io);
g_io_channel_unref(c->io);
@@ -342,6 +339,7 @@ static GIOError headset_send(struct headset *hs, const char *str)
static void pending_connect_ok(struct pending_connect *c, struct device *dev)
{
+ struct headset *hs = dev->headset;
DBusMessage *reply;
if (c->msg) {
@@ -349,29 +347,34 @@ static void pending_connect_ok(struct pending_connect *c, struct device *dev)
if (reply)
send_message_and_unref(dev->conn, reply);
}
- else if (c->pkt) {
- struct ipc_data_cfg *rsp;
- int ret, fd;
-
- ret = headset_get_config(dev, c->sock, c->pkt, c->pkt_len,
- &rsp, &fd);
- if (ret == 0) {
- unix_send_cfg(c->sock, rsp, fd);
- g_free(rsp);
- }
+
+ if (c->cb) {
+ if (hs->rfcomm && hs->sco)
+ c->cb(dev, c->cb_data);
else
- unix_send_cfg(c->sock, NULL, -1);
+ c->cb(NULL, c->cb_data);
}
pending_connect_free(c);
}
+static gboolean finalize_stream_setup(struct device *dev)
+{
+ struct headset *hs = dev->headset;
+
+ g_slist_foreach(hs->pending, (GFunc) pending_connect_ok, dev);
+ g_slist_free(hs->pending);
+ hs->pending = NULL;
+
+ return FALSE;
+}
+
static void pending_connect_failed(struct pending_connect *c, struct device *dev)
{
if (c->msg)
err_connect_failed(dev->conn, c->msg, strerror(c->err));
- if (c->pkt)
- unix_send_cfg(c->sock, NULL, -1);
+ if (c->cb)
+ c->cb(NULL, c->cb_data);
pending_connect_free(c);
}
@@ -537,7 +540,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond,
g_io_add_watch(chan, G_IO_IN | G_IO_ERR | G_IO_HUP| G_IO_NVAL,
(GIOFunc) rfcomm_io_cb, device);
- if (c->pkt) {
+ if (c->cb) {
if (sco_connect(device, c) < 0)
goto failed;
return FALSE;
@@ -1396,50 +1399,38 @@ void headset_free(struct device *dev)
dev->headset = NULL;
}
-int headset_get_config(struct device *dev, int sock, struct ipc_packet *pkt,
- int pkt_len, struct ipc_data_cfg **cfg, int *fd)
+unsigned int headset_request_stream(struct device *dev, headset_stream_cb_t cb,
+ void *user_data)
{
struct headset *hs = dev->headset;
- int err = EINVAL;
struct pending_connect *c;
-
- if (hs->rfcomm && hs->sco)
- goto proceed;
+ static unsigned int cb_id = 0;
+ int err;
c = g_new0(struct pending_connect, 1);
- c->sock = sock;
- c->pkt = g_malloc(pkt_len);
- memcpy(c->pkt, pkt, pkt_len);
+ c->cb = cb;
+ c->cb_data = user_data;
+ c->id = ++cb_id;
+
+ if (hs->rfcomm && hs->sco) {
+ hs->pending = g_slist_append(hs->pending, c);
+ g_idle_add((GSourceFunc) finalize_stream_setup, hs);
+ return c->id;
+ }
if (hs->rfcomm == NULL)
err = rfcomm_connect(dev, c);
else if (hs->sco == NULL)
err = sco_connect(dev, c);
- else
- goto error;
if (err < 0)
goto error;
- return 1;
-
-proceed:
- *cfg = g_new0(struct ipc_data_cfg, 1);
- (*cfg)->fd_opt = CFG_FD_OPT_READWRITE;
- (*cfg)->codec = CFG_CODEC_NONE;
- (*cfg)->channels = 1;
- (*cfg)->channel_mode = CFG_CHANNEL_MODE_MONO;
- (*cfg)->pkt_len = 48;
- (*cfg)->sample_size = 2;
- (*cfg)->rate = 8000;
- *fd = g_io_channel_unix_get_fd(hs->sco);
-
- return 0;
+ return c->id;
error:
- if (c)
- pending_connect_free(c);
- return -err;
+ pending_connect_free(c);
+ return 0;
}
headset_type_t headset_get_type(struct device *dev)
@@ -1607,3 +1598,14 @@ gboolean headset_play(struct device *dev, void *data)
{
return TRUE;
}
+
+int headset_get_sco_fd(struct device *dev)
+{
+ struct headset *hs = dev->headset;
+
+ if (!hs->sco)
+ return -1;
+
+ return g_io_channel_unix_get_fd(hs->sco);
+}
+
diff --git a/audio/headset.h b/audio/headset.h
index 29e2e496..31486834 100644
--- a/audio/headset.h
+++ b/audio/headset.h
@@ -46,6 +46,8 @@ typedef enum {
SVC_HANDSFREE
} headset_type_t;
+typedef void (*headset_stream_cb_t) (struct device *dev, void *user_data);
+
struct headset *headset_init(struct device *dev, sdp_record_t *record,
uint16_t svc);
@@ -53,8 +55,8 @@ void headset_free(struct device *dev);
void headset_update(struct device *dev, sdp_record_t *record, uint16_t svc);
-int headset_get_config(struct device *dev, int sock, struct ipc_packet *pkt,
- int pkt_len, struct ipc_data_cfg **rsp, int *fd);
+unsigned int headset_request_stream(struct device *dev, headset_stream_cb_t cb,
+ void *user_data);
headset_type_t headset_get_type(struct device *dev);
void headset_set_type(struct device *dev, headset_type_t type);
@@ -67,6 +69,8 @@ void headset_set_state(struct device *dev, headset_state_t state);
int headset_get_channel(struct device *dev);
+int headset_get_sco_fd(struct device *dev);
+
gboolean headset_is_active(struct device *dev);
gboolean headset_lock(struct device *dev, void *data);
diff --git a/audio/main.c b/audio/main.c
index bd9cd0c5..3ca2ba40 100644
--- a/audio/main.c
+++ b/audio/main.c
@@ -37,7 +37,6 @@
#include "dbus.h"
#include "logging.h"
-#include "ipc.h"
#include "unix.h"
#include "manager.h"
diff --git a/audio/sink.c b/audio/sink.c
index 0dc12eb3..4bebf738 100644
--- a/audio/sink.c
+++ b/audio/sink.c
@@ -38,11 +38,9 @@
#include "logging.h"
#include "avdtp.h"
-#include "ipc.h"
#include "device.h"
#include "a2dp.h"
#include "error.h"
-#include "unix.h"
#include "sink.h"
struct pending_request {
diff --git a/audio/unix.c b/audio/unix.c
index 246d6813..9fa5fc08 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -185,6 +185,86 @@ static void stream_state_changed(struct avdtp_stream *stream,
}
}
+static int unix_send_cfg(int sock, struct ipc_data_cfg *cfg, int fd)
+{
+ char buf[IPC_MTU];
+ struct ipc_packet *pkt = (void *) buf;
+ int len, codec_len;
+
+ memset(buf, 0, sizeof(buf));
+
+ pkt->type = PKT_TYPE_CFG_RSP;
+
+ if (!cfg) {
+ pkt->error = EINVAL;
+ len = send(sock, pkt, sizeof(struct ipc_packet), 0);
+ if (len < 0)
+ error("send: %s (%d)", strerror(errno), errno);
+ return len;
+ }
+
+ debug("fd=%d, fd_opt=%u, channels=%u, pkt_len=%u,"
+ "sample_size=%u, rate=%u", fd, cfg->fd_opt, cfg->channels,
+ cfg->pkt_len, cfg->sample_size, cfg->rate);
+
+ if (cfg->codec == CFG_CODEC_SBC)
+ codec_len = sizeof(struct ipc_codec_sbc);
+ else
+ codec_len = 0;
+
+ pkt->error = PKT_ERROR_NONE;
+ pkt->length = sizeof(struct ipc_data_cfg) + codec_len;
+ memcpy(pkt->data, cfg, pkt->length);
+
+ len = sizeof(struct ipc_packet) + pkt->length;
+ len = send(sock, pkt, len, 0);
+ if (len < 0)
+ error("Error %s(%d)", strerror(errno), errno);
+
+ debug("%d bytes sent", len);
+
+ if (fd != -1) {
+ len = unix_sendmsg_fd(sock, fd, pkt);
+ if (len < 0)
+ error("Error %s(%d)", strerror(errno), errno);
+ debug("%d bytes sent", len);
+ }
+
+ return 0;
+}
+
+
+static void headset_setup_complete(struct device *dev, void *user_data)
+{
+ struct unix_client *client = user_data;
+ struct ipc_data_cfg cfg;
+ int fd;
+
+ if (!dev) {
+ unix_send_cfg(client->sock, NULL, -1);
+ client->dev = NULL;
+ return;
+ }
+
+ memset(&cfg, 0, sizeof(cfg));
+
+ cfg.fd_opt = CFG_FD_OPT_READWRITE;
+ cfg.codec = CFG_CODEC_NONE;
+ cfg.channels = 1;
+ cfg.channel_mode = CFG_CHANNEL_MODE_MONO;
+ cfg.pkt_len = 48;
+ cfg.sample_size = 2;
+ cfg.rate = 8000;
+
+ fd = headset_get_sco_fd(dev);
+
+ unix_send_cfg(client->sock, &cfg, fd);
+
+ client->disconnect = (notify_cb_t) headset_unlock;
+ client->suspend = (notify_cb_t) headset_suspend;
+ client->play = (notify_cb_t) headset_play;
+}
+
static void a2dp_setup_complete(struct avdtp *session, struct device *dev,
struct avdtp_stream *stream,
void *user_data)
@@ -300,9 +380,7 @@ failed:
static void cfg_event(struct unix_client *client, struct ipc_packet *pkt,
int len)
{
- struct ipc_data_cfg *rsp;
struct device *dev;
- int ret, fd;
unsigned int id;
struct a2dp_data *a2dp;
bdaddr_t bdaddr;
@@ -341,32 +419,24 @@ proceed:
id = a2dp_source_request_stream(a2dp->session, dev,
TRUE, a2dp_setup_complete,
client, &a2dp->sep);
- if (id == 0) {
- error("request_stream failed");
- goto failed;
- }
-
- client->req_id = id;
-
break;
case TYPE_HEADSET:
- if (!headset_lock(dev, client->d.data)) {
- error("Unable to lock headset");
- goto failed;
- }
-
- ret = headset_get_config(dev, client->sock, pkt, len, &rsp,
- &fd);
- client->disconnect = (notify_cb_t) headset_unlock;
- client->suspend = (notify_cb_t) headset_suspend;
- client->play = (notify_cb_t) headset_play;
+ id = headset_request_stream(dev, headset_setup_complete,
+ client);
break;
default:
error("No known services for device");
goto failed;
}
+ if (id == 0) {
+ error("request_stream failed");
+ goto failed;
+ }
+
+ client->req_id = id;
client->dev = dev;
+
return;
failed:
@@ -553,54 +623,6 @@ void unix_exit(void)
unix_sock = -1;
}
-int unix_send_cfg(int sock, struct ipc_data_cfg *cfg, int fd)
-{
- char buf[IPC_MTU];
- struct ipc_packet *pkt = (void *) buf;
- int len, codec_len;
-
- memset(buf, 0, sizeof(buf));
-
- pkt->type = PKT_TYPE_CFG_RSP;
-
- if (!cfg) {
- pkt->error = EINVAL;
- len = send(sock, pkt, sizeof(struct ipc_packet), 0);
- if (len < 0)
- error("send: %s (%d)", strerror(errno), errno);
- return len;
- }
-
- debug("fd=%d, fd_opt=%u, channels=%u, pkt_len=%u,"
- "sample_size=%u, rate=%u", fd, cfg->fd_opt, cfg->channels,
- cfg->pkt_len, cfg->sample_size, cfg->rate);
-
- if (cfg->codec == CFG_CODEC_SBC)
- codec_len = sizeof(struct ipc_codec_sbc);
- else
- codec_len = 0;
-
- pkt->error = PKT_ERROR_NONE;
- pkt->length = sizeof(struct ipc_data_cfg) + codec_len;
- memcpy(pkt->data, cfg, pkt->length);
-
- len = sizeof(struct ipc_packet) + pkt->length;
- len = send(sock, pkt, len, 0);
- if (len < 0)
- error("Error %s(%d)", strerror(errno), errno);
-
- debug("%d bytes sent", len);
-
- if (fd != -1) {
- len = unix_sendmsg_fd(sock, fd, pkt);
- if (len < 0)
- error("Error %s(%d)", strerror(errno), errno);
- debug("%d bytes sent", len);
- }
-
- return 0;
-}
-
#if 0
static int unix_send_state(int sock, struct ipc_packet *pkt)
{
diff --git a/audio/unix.h b/audio/unix.h
index 7f42688c..feea855f 100644
--- a/audio/unix.h
+++ b/audio/unix.h
@@ -23,5 +23,3 @@
int unix_init(void);
void unix_exit(void);
-
-int unix_send_cfg(int sock, struct ipc_data_cfg *cfg, int fd);