Diff between f39c17a9f63b2b8258685c17f7317a3bfd517ba7 and 826058933c62dec5b20aab8428cd91ad12aa1141

Changed Files

File Additions Deletions Status
profiles/audio/avctp.c +11 -0 modified
profiles/audio/avctp.h +3 -1 modified
profiles/audio/avrcp.c +24 -6 modified
profiles/audio/device.c +4 -0 modified

Full Patch

diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index 02bee2b..61890cc 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -484,6 +484,12 @@ static void avctp_set_state(struct avctp *session, avctp_state_t new_state)
 	case AVCTP_STATE_CONNECTED:
 		DBG("AVCTP Connected");
 		break;
+	case AVCTP_STATE_BROWSING_CONNECTING:
+		DBG("AVCTP Browsing Connecting");
+		break;
+	case AVCTP_STATE_BROWSING_CONNECTED:
+		DBG("AVCTP Browsing Connected");
+		break;
 	default:
 		error("Invalid AVCTP state %d", new_state);
 		return;
@@ -1023,9 +1029,12 @@ static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
 				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 				(GIOFunc) session_browsing_cb, session);
 
+	avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTED);
 	return;
 
 fail:
+	avctp_set_state(session, AVCTP_STATE_CONNECTED);
+
 	if (session->browsing) {
 		avctp_channel_destroy(session->browsing);
 		session->browsing = NULL;
@@ -1788,6 +1797,8 @@ int avctp_connect_browsing(struct avctp *session)
 	if (session->browsing != NULL)
 		return 0;
 
+	avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING);
+
 	io = bt_io_connect(avctp_connect_browsing_cb, session, NULL, &err,
 				BT_IO_OPT_SOURCE_BDADDR,
 				adapter_get_address(session->server->adapter),
diff --git a/profiles/audio/avctp.h b/profiles/audio/avctp.h
index b9107bd..6cbda92 100644
--- a/profiles/audio/avctp.h
+++ b/profiles/audio/avctp.h
@@ -67,7 +67,9 @@ struct avctp;
 typedef enum {
 	AVCTP_STATE_DISCONNECTED = 0,
 	AVCTP_STATE_CONNECTING,
-	AVCTP_STATE_CONNECTED
+	AVCTP_STATE_CONNECTED,
+	AVCTP_STATE_BROWSING_CONNECTING,
+	AVCTP_STATE_BROWSING_CONNECTED
 } avctp_state_t;
 
 typedef void (*avctp_state_cb) (struct audio_device *dev,
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 636d3e4..32062db 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -190,6 +190,7 @@ struct avrcp {
 	gboolean target;
 	uint16_t version;
 	int features;
+	bool initialized;
 
 	void (*init) (struct avrcp *session);
 	void (*destroy) (struct avrcp *sesion);
@@ -2169,6 +2170,8 @@ static void session_tg_init(struct avrcp *session)
 
 	DBG("%p version 0x%04x", session, session->version);
 
+	session->initialized = true;
+
 	player = g_slist_nth_data(server->players, 0);
 	if (player != NULL) {
 		session->player = player;
@@ -2182,12 +2185,9 @@ static void session_tg_init(struct avrcp *session)
 				(1 << AVRCP_EVENT_TRACK_REACHED_END) |
 				(1 << AVRCP_EVENT_SETTINGS_CHANGED);
 
-	if (session->version >= 0x0104) {
+	if (session->version >= 0x0104)
 		avrcp_register_notification(session,
 						AVRCP_EVENT_VOLUME_CHANGED);
-		if (session->features & AVRCP_FEATURE_BROWSING)
-			avctp_connect_browsing(session->conn);
-	}
 
 	session->control_id = avctp_register_pdu_handler(session->conn,
 							AVC_OP_VENDORDEP,
@@ -2212,6 +2212,8 @@ static void session_ct_init(struct avrcp *session)
 
 	DBG("%p version 0x%04x", session, session->version);
 
+	session->initialized = true;
+
 	session->control_id = avctp_register_pdu_handler(session->conn,
 							AVC_OP_VENDORDEP,
 							handle_vendordep_pdu,
@@ -2364,11 +2366,27 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 
 		break;
 	case AVCTP_STATE_CONNECTED:
-		if (session == NULL)
+		if (session == NULL || session->initialized)
 			break;
 
-		session->init(session);
+		/* Initialize session if browsing cannot be used */
+		if (session->version <= 0x0103 ||
+				old_state == AVCTP_STATE_BROWSING_CONNECTING ||
+				!(session->features & AVRCP_FEATURE_BROWSING)) {
+			session->init(session);
+			break;
+		}
+
+		if (avctp_connect_browsing(session->conn) != 0)
+			session->init(session);
 
+		break;
+	case AVCTP_STATE_BROWSING_CONNECTED:
+		if (session == NULL || session->initialized)
+			break;
+
+		session->init(session);
+		break;
 	default:
 		return;
 	}
diff --git a/profiles/audio/device.c b/profiles/audio/device.c
index d4ba6d2..2aa22bb 100644
--- a/profiles/audio/device.c
+++ b/profiles/audio/device.c
@@ -289,6 +289,10 @@ static void device_avctp_cb(struct audio_device *dev,
 		break;
 	case AVCTP_STATE_CONNECTED:
 		break;
+	case AVCTP_STATE_BROWSING_CONNECTING:
+		break;
+	case AVCTP_STATE_BROWSING_CONNECTED:
+		break;
 	}
 }