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: | 
