diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-27 11:31:01 +0000 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-27 11:31:01 +0000 |
commit | e1bfc91de96a38616100cc31db7bdb69f2cfbea6 (patch) | |
tree | f8e2ce652875076f96b0db575a5daabb10156e66 | |
parent | ca3ff4f6a27ff2d421a7f8fdd3bd5dd67f1f47df (diff) |
Convert alsa initiated headset connections to similar callback system that A2DP is already using
-rw-r--r-- | audio/headset.c | 98 | ||||
-rw-r--r-- | audio/headset.h | 8 | ||||
-rw-r--r-- | audio/main.c | 1 | ||||
-rw-r--r-- | audio/sink.c | 2 | ||||
-rw-r--r-- | audio/unix.c | 156 | ||||
-rw-r--r-- | audio/unix.h | 2 |
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); |