Diff between 731aec9cae63d5901d6226be885be3dee540786f and 08eec685c63f1799fb168434e9418b41bd76f75e

Changed Files

File Additions Deletions Status
audio/avctp.c +28 -0 modified
audio/avctp.h +1 -0 modified
audio/avrcp.c +11 -1 modified

Full Patch

diff --git a/audio/avctp.c b/audio/avctp.c
index 37b6664..6fd5491 100644
--- a/audio/avctp.c
+++ b/audio/avctp.c
@@ -1311,6 +1311,34 @@ struct avctp *avctp_connect(const bdaddr_t *src, const bdaddr_t *dst)
 	return session;
 }
 
+int avctp_connect_browsing(struct avctp *session)
+{
+	GError *err = NULL;
+	GIOChannel *io;
+
+	if (session->state != AVCTP_STATE_CONNECTED)
+		return -ENOTCONN;
+
+	if (session->browsing_io != NULL)
+		return 0;
+
+	io = bt_io_connect(avctp_connect_browsing_cb, session, NULL, &err,
+				BT_IO_OPT_SOURCE_BDADDR, &session->server->src,
+				BT_IO_OPT_DEST_BDADDR, &session->dst,
+				BT_IO_OPT_PSM, AVCTP_BROWSING_PSM,
+				BT_IO_OPT_MODE, L2CAP_MODE_ERTM,
+				BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		return -EIO;
+	}
+
+	session->browsing_io = io;
+
+	return 0;
+}
+
 void avctp_disconnect(struct avctp *session)
 {
 	if (!session->control_io)
diff --git a/audio/avctp.h b/audio/avctp.h
index 7293a50..6d39a20 100644
--- a/audio/avctp.h
+++ b/audio/avctp.h
@@ -95,6 +95,7 @@ void avctp_unregister(const bdaddr_t *src);
 
 struct avctp *avctp_connect(const bdaddr_t *src, const bdaddr_t *dst);
 struct avctp *avctp_get(const bdaddr_t *src, const bdaddr_t *dst);
+int avctp_connect_browsing(struct avctp *session);
 void avctp_disconnect(struct avctp *session);
 
 unsigned int avctp_register_pdu_handler(uint8_t opcode, avctp_control_pdu_cb cb,
diff --git a/audio/avrcp.c b/audio/avrcp.c
index 300ecd8..095dafe 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -1322,9 +1322,19 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 
 		desc = list->data;
 
-		if (desc && desc->version >= 0x0104)
+		if (desc && desc->version >= 0x0104) {
+			int feat;
+			int ret;
+
 			register_volume_notification(player);
 
+			ret = sdp_get_int_attr(rec,
+						SDP_ATTR_SUPPORTED_FEATURES,
+						&feat);
+			if (ret == 0 && (feat & AVRCP_FEATURE_BROWSING))
+				avctp_connect_browsing(player->session);
+		}
+
 		sdp_list_free(list, free);
 	default:
 		return;