summaryrefslogtreecommitdiffstats
path: root/audio/avdtp.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2007-08-15 14:13:27 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2007-08-15 14:13:27 +0000
commit931bfd25641a14b82c6c82db20eeb97bc57fafe6 (patch)
treee5f2598294463bb59c52f9b1a8fcce1d70bf8ff5 /audio/avdtp.c
parent74e5259eb027bd0eaef50004ffe62de28d77e77b (diff)
Implement support for incoming suspend commands
Diffstat (limited to 'audio/avdtp.c')
-rw-r--r--audio/avdtp.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/audio/avdtp.c b/audio/avdtp.c
index f35ff5ff..bc9081a4 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -131,6 +131,12 @@ struct start_req {
struct seid other_seids[0];
} __attribute__ ((packed));
+struct suspend_req {
+ struct avdtp_header header;
+ struct seid first_seid;
+ struct seid other_seids[0];
+} __attribute__ ((packed));
+
struct seid_req {
struct avdtp_header header;
uint8_t rfa0:2;
@@ -1013,10 +1019,60 @@ failed:
return avdtp_send(session, &rej, sizeof(rej));
}
-static gboolean avdtp_suspend_cmd(struct avdtp *session, struct seid_req *req,
- int size)
+static gboolean avdtp_suspend_cmd(struct avdtp *session,
+ struct suspend_req *req, int size)
{
- return avdtp_unknown_cmd(session, (void *) req, size);
+ struct avdtp_local_sep *sep;
+ struct avdtp_stream *stream;
+ struct gen_resp *rsp = (struct gen_resp *) session->buf;
+ struct stream_rej rej;
+ struct seid *seid;
+ uint8_t err, failed_seid;
+ int seid_count, i;
+
+ if (size < sizeof(struct suspend_req)) {
+ error("Too short suspend request");
+ return FALSE;
+ }
+
+ seid_count = 1 + (sizeof(struct suspend_req) - size);
+
+ seid = &req->first_seid;
+
+ for (i = 0; i < seid_count; i++, seid++) {
+ failed_seid = seid->seid;
+
+ sep = find_local_sep_by_seid(req->first_seid.seid);
+ if (!sep || !sep->stream) {
+ err = AVDTP_BAD_ACP_SEID;
+ goto failed;
+ }
+
+ stream = sep->stream;
+
+ if (sep->state != AVDTP_STATE_STREAMING) {
+ err = AVDTP_BAD_STATE;
+ goto failed;
+ }
+
+ if (sep->ind && sep->ind->suspend) {
+ if (!sep->ind->suspend(session, sep, stream, &err))
+ goto failed;
+ }
+
+ avdtp_sep_set_state(session, sep, AVDTP_STATE_OPEN);
+ }
+
+ init_response(&rsp->header, &req->header, TRUE);
+
+ return avdtp_send(session, rsp, sizeof(struct gen_resp));
+
+failed:
+ memset(&rej, 0, sizeof(rej));
+ init_response(&rej.header, &req->header, FALSE);
+ rej.acp_seid = failed_seid;
+ rej.error = err;
+ return avdtp_send(session, &rej, sizeof(rej));
}
static gboolean avdtp_abort_cmd(struct avdtp *session, struct seid_req *req,