diff options
| author | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-11 13:02:10 +0000 | 
|---|---|---|
| committer | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-11 13:02:10 +0000 | 
| commit | 37b86c3b3bf4641c7f41c701f531ffbfc5ebe720 (patch) | |
| tree | 697038f5edc0efd4fd24c947ffcf619f35d26535 | |
| parent | 36a07968fcc69442e3248caa46e74de18bacea75 (diff) | |
Implement support for receiving the Close command
| -rw-r--r-- | audio/avdtp.c | 60 | 
1 files changed, 57 insertions, 3 deletions
| diff --git a/audio/avdtp.c b/audio/avdtp.c index cf6060e4..2d71e272 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -171,6 +171,10 @@ struct abort_resp {  	struct avdtp_header header;  } __attribute__ ((packed)); +struct close_resp { +	struct avdtp_header header; +} __attribute__ ((packed)); +  struct stream_pause_resp {  	struct avdtp_header header;  	uint8_t rfa0:2; @@ -309,6 +313,9 @@ static gboolean avdtp_send(struct avdtp *session, void *data, int len)  {  	int ret; +	if (session->sock < 0) +		return FALSE; +  	ret = send(session->sock, data, len, 0);  	if (ret < 0) @@ -332,7 +339,6 @@ static void pending_req_free(struct pending_req *req)  	g_free(req);  } -#if 0  static gboolean stream_close_timeout(gpointer user_data)  {  	struct avdtp_stream *stream = user_data; @@ -341,7 +347,6 @@ static gboolean stream_close_timeout(gpointer user_data)  	return FALSE;  } -#endif  static gboolean disconnect_timeout(gpointer user_data)  { @@ -389,6 +394,8 @@ static void stream_free(struct avdtp_stream *stream)  	stream->lsep->info.inuse = 0;  	stream->lsep->stream = NULL;  	stream->rsep->stream = NULL; +	if (stream->close_timer) +		g_source_remove(stream->close_timer);  	if (stream->caps) {  		g_slist_foreach(stream->caps, (GFunc) g_free, NULL);  		g_slist_free(stream->caps); @@ -717,7 +724,54 @@ static gboolean avdtp_start_cmd(struct avdtp *session, struct seid_req *req,  static gboolean avdtp_close_cmd(struct avdtp *session, struct seid_req *req,  				int size)  { -	return avdtp_unknown_cmd(session, (void *) req, size); +	struct avdtp_local_sep *sep; +	struct avdtp_stream *stream; +	struct close_resp *rsp = (struct close_resp *) session->buf; +	struct seid_rej rej; +	uint8_t err; +	gboolean ret; + +	if (size < sizeof(struct seid_req)) { +		error("Too short abort request"); +		return FALSE; +	} + +	sep = find_local_sep_by_seid(req->acp_seid); +	if (!sep || !sep->stream) { +		err = AVDTP_BAD_ACP_SEID; +		goto failed; +	} + +	if (sep->state != AVDTP_STATE_OPEN && +			sep->state != AVDTP_STATE_STREAMING) { +		err = AVDTP_BAD_STATE; +		goto failed; +	} + +	stream = sep->stream; + +	if (sep->ind && sep->ind->close) { +		if (!sep->ind->close(sep, stream, &err)) +			goto failed; +	} + +	avdtp_sep_set_state(session, sep, AVDTP_STATE_CLOSING); + +	init_response(&rsp->header, &req->header, TRUE); + +	ret = avdtp_send(session, rsp, sizeof(struct close_resp)); +	if (ret == TRUE) { +		stream->close_timer = g_timeout_add(REQ_TIMEOUT, +							stream_close_timeout, +							stream); +	} + +	return ret; + +failed: +	init_response(&rej.header, &req->header, FALSE); +	rej.error = err; +	return avdtp_send(session, &rej, sizeof(rej));  }  static gboolean avdtp_suspend_cmd(struct avdtp *session, struct seid_req *req, | 
