diff options
| author | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-28 12:22:29 +0000 | 
|---|---|---|
| committer | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-28 12:22:29 +0000 | 
| commit | d1fb0b25a9882016de70f102408f10101b348e57 (patch) | |
| tree | e9a28f98b63eec38c78e8df150198d63635a50de | |
| parent | 10abd63aeb3665b2dcade32b6397a485579638ec (diff) | |
Fix unix client disconnects before headset has been successfully connected
| -rw-r--r-- | audio/a2dp.c | 2 | ||||
| -rw-r--r-- | audio/a2dp.h | 2 | ||||
| -rw-r--r-- | audio/headset.c | 42 | ||||
| -rw-r--r-- | audio/headset.h | 1 | ||||
| -rw-r--r-- | audio/unix.c | 9 | 
5 files changed, 49 insertions, 7 deletions
| diff --git a/audio/a2dp.c b/audio/a2dp.c index fad9bd25..5e08b25b 100644 --- a/audio/a2dp.c +++ b/audio/a2dp.c @@ -880,7 +880,7 @@ static void discovery_complete(struct avdtp *session, GSList *seps, int err,  	sink_new_stream(setup->dev, session, setup->stream);  } -gboolean a2dp_source_cancel_stream(int id) +gboolean a2dp_source_cancel_stream(struct device *dev, unsigned int id)  {  	struct a2dp_stream_cb *cb_data;  	GSList *l; diff --git a/audio/a2dp.h b/audio/a2dp.h index 4804c5f1..7358473e 100644 --- a/audio/a2dp.h +++ b/audio/a2dp.h @@ -72,7 +72,7 @@ unsigned int a2dp_source_request_stream(struct avdtp *session,  					gboolean start, a2dp_stream_cb_t cb,  					void *user_data,  					struct a2dp_sep **sep); -gboolean a2dp_source_cancel_stream(int id); +gboolean a2dp_source_cancel_stream(struct device *dev, unsigned int id);  gboolean a2dp_source_lock(struct device *dev, struct avdtp *session);  gboolean a2dp_source_unlock(struct device *dev, struct avdtp *session); diff --git a/audio/headset.c b/audio/headset.c index 0ccd9d2e..5a626c17 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -68,6 +68,7 @@ static char *str_state[] = {"DISCONNECTED", "CONNECTING", "CONNECTED",  struct pending_connect {  	DBusMessage *msg; +	DBusPendingCall *call;  	GIOChannel *io;  	guint io_id;  	int sock; @@ -114,6 +115,11 @@ static void pending_connect_free(struct pending_connect *c)  	}  	if (c->msg)  		dbus_message_unref(c->msg); +	if (c->call) { +		dbus_pending_call_cancel(c->call); +		dbus_pending_call_unref(c->call); +	} +  	g_free(c);  } @@ -780,7 +786,7 @@ failed:  	headset_set_state(device, HEADSET_STATE_DISCONNECTED);  } -static int get_handles(struct device *device) +static int get_handles(struct device *device, struct pending_connect *c)  {  	DBusPendingCall *pending;  	struct headset *hs = device->headset; @@ -816,7 +822,10 @@ static int get_handles(struct device *device)  	}  	dbus_pending_call_set_notify(pending, get_handles_reply, device, NULL); -	dbus_pending_call_unref(pending); +	if (c) +		c->call = pending; +	else +		dbus_pending_call_unref(pending);  	dbus_message_unref(msg);  	return 0; @@ -836,7 +845,7 @@ static int rfcomm_connect(struct device *device, struct pending_connect *c)  		hs->type = hs->hfp_handle ? SVC_HANDSFREE : SVC_HEADSET;  		if (hs->state == HEADSET_STATE_DISCONNECTED) -			return get_handles(device); +			return get_handles(device, c);  		else  			return 0;  	} @@ -1399,6 +1408,33 @@ void headset_free(struct device *dev)  	dev->headset = NULL;  } +gboolean headset_cancel_stream(struct device *dev, unsigned int id) +{ +	struct headset *hs = dev->headset; +	GSList *l; +	struct pending_connect *pending = NULL; + +	for (l = hs->pending; l != NULL; l = l->next) { +		struct pending_connect *tmp = l->data; + +		if (tmp->id == id) { +			pending = tmp; +			break; +		} +	} + +	if (!pending) +		return FALSE; + +	hs->pending = g_slist_remove(hs->pending, pending); +	pending_connect_free(pending); + +	if (!hs->pending) +		headset_set_state(dev, HEADSET_STATE_DISCONNECTED); + +	return TRUE; +} +  unsigned int headset_request_stream(struct device *dev, headset_stream_cb_t cb,  					void *user_data)  { diff --git a/audio/headset.h b/audio/headset.h index 31486834..3f762815 100644 --- a/audio/headset.h +++ b/audio/headset.h @@ -57,6 +57,7 @@ void headset_update(struct device *dev, sdp_record_t *record, uint16_t svc);  unsigned int headset_request_stream(struct device *dev, headset_stream_cb_t cb,  					void *user_data); +gboolean headset_cancel_stream(struct device *dev, unsigned int id);  headset_type_t headset_get_type(struct device *dev);  void headset_set_type(struct device *dev, headset_type_t type); diff --git a/audio/unix.c b/audio/unix.c index 1d1a0b6a..71bb480c 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -79,6 +79,7 @@ struct unix_client {  	notify_cb_t disconnect;  	notify_cb_t suspend;  	notify_cb_t play; +	gboolean (*cancel_stream) (struct device *dev, unsigned int id);  };  static GSList *clients = NULL; @@ -248,6 +249,8 @@ static void headset_setup_complete(struct device *dev, void *user_data)  		return;  	} +	headset_lock(dev, NULL); +  	memset(&cfg, 0, sizeof(cfg));  	cfg.fd_opt = CFG_FD_OPT_READWRITE; @@ -401,10 +404,12 @@ static void create_stream(struct device *dev, struct unix_client *client)  		id = a2dp_source_request_stream(a2dp->session, dev,  						TRUE, a2dp_setup_complete,  						client, &a2dp->sep); +		client->cancel_stream = a2dp_source_cancel_stream;  		break;  	case TYPE_HEADSET:  		id = headset_request_stream(dev, headset_setup_complete,  						client); +		client->cancel_stream = headset_cancel_stream;  		break;  	default:  		error("No known services for device"); @@ -525,8 +530,8 @@ static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data)  			goto failed;  		if (client->disconnect)  			client->disconnect(client->dev, cb_data); -		if (client->type == TYPE_SINK && client->req_id > 0) -			a2dp_source_cancel_stream(client->req_id); +		if (client->cancel_stream && client->req_id > 0) +			client->cancel_stream(client->dev, client->req_id);  		goto failed;  	} | 
