diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-31 11:51:43 +0000 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-31 11:51:43 +0000 |
commit | ec384afacde8614306abe32cf40c55b795783f0e (patch) | |
tree | 64becc3deee3b735acddd15157fa428ccfbf2b22 /audio/unix.c | |
parent | fc0d501d82773718d0f2d040f786136332c39813 (diff) |
Implement proper locking for headsets
Diffstat (limited to 'audio/unix.c')
-rw-r--r-- | audio/unix.c | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/audio/unix.c b/audio/unix.c index 3e8c7469..2cb0d804 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -64,6 +64,10 @@ struct a2dp_data { struct a2dp_sep *sep; }; +struct headset_data { + headset_lock_t lock; +}; + struct unix_client { struct device *dev; struct avdtp_service_capability *media_codec; @@ -71,9 +75,10 @@ struct unix_client { char *interface; union { struct a2dp_data a2dp; - void *data; + struct headset_data hs; } d; int sock; + int fd_opt; unsigned int req_id; unsigned int cb_id; gboolean (*cancel_stream) (struct device *dev, unsigned int id); @@ -245,6 +250,7 @@ static void headset_setup_complete(struct device *dev, void *user_data) { struct unix_client *client = user_data; struct ipc_data_cfg cfg; + struct headset_data *hs = &client->d.hs; int fd; client->req_id = 0; @@ -255,11 +261,31 @@ static void headset_setup_complete(struct device *dev, void *user_data) return; } - headset_lock(dev); + switch (client->fd_opt) { + case CFG_FD_OPT_READ: + hs->lock = HEADSET_LOCK_READ; + break; + case CFG_FD_OPT_WRITE: + hs->lock = HEADSET_LOCK_WRITE; + break; + case CFG_FD_OPT_READWRITE: + hs->lock = HEADSET_LOCK_READ | HEADSET_LOCK_WRITE; + break; + default: + hs->lock = 0; + break; + } + + if (!headset_lock(dev, hs->lock)) { + error("Unable to lock headset"); + unix_send_cfg(client->sock, NULL, -1); + client->dev = NULL; + return; + } memset(&cfg, 0, sizeof(cfg)); - cfg.fd_opt = CFG_FD_OPT_READWRITE; + cfg.fd_opt = client->fd_opt; cfg.codec = CFG_CODEC_SCO; cfg.mode = CFG_MODE_MONO; cfg.pkt_len = 48; @@ -551,6 +577,8 @@ static void cfg_event(struct unix_client *client, struct ipc_packet *pkt, int le str2ba(pkt->device, &bdaddr); + client->fd_opt = cfg->fd_opt; + if (client->interface) { g_free(client->interface); client->interface = NULL; @@ -618,6 +646,7 @@ static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data) struct unix_client *client = data; int len, len_check; struct a2dp_data *a2dp = &client->d.a2dp; + struct headset_data *hs = &client->d.hs; if (cond & G_IO_NVAL) return FALSE; @@ -627,7 +656,7 @@ static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data) switch (client->type) { case TYPE_HEADSET: if (client->dev) - headset_unlock(client->dev); + headset_unlock(client->dev, hs->lock); break; case TYPE_SOURCE: case TYPE_SINK: |