diff options
Diffstat (limited to 'profiles/audio/avctp.c')
-rw-r--r-- | profiles/audio/avctp.c | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c index 197373a7..34b01830 100644 --- a/profiles/audio/avctp.c +++ b/profiles/audio/avctp.c @@ -580,7 +580,8 @@ static void avctp_disconnected(struct avctp *session) g_free(session); } -static void avctp_set_state(struct avctp *session, avctp_state_t new_state) +static void avctp_set_state(struct avctp *session, avctp_state_t new_state, + int err) { GSList *l; avctp_state_t old_state = session->state; @@ -593,7 +594,8 @@ static void avctp_set_state(struct avctp *session, avctp_state_t new_state) if (cb->dev && cb->dev != session->device) continue; - cb->cb(session->device, old_state, new_state, cb->user_data); + cb->cb(session->device, old_state, new_state, err, + cb->user_data); } switch (new_state) { @@ -947,7 +949,7 @@ send: failed: DBG("AVCTP Browsing: disconnected"); - avctp_set_state(session, AVCTP_STATE_CONNECTED); + avctp_set_state(session, AVCTP_STATE_CONNECTED, 0); if (session->browsing) { avctp_channel_destroy(session->browsing); @@ -1043,7 +1045,7 @@ done: failed: DBG("AVCTP session %p got disconnected", session); - avctp_set_state(session, AVCTP_STATE_DISCONNECTED); + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EIO); return FALSE; } @@ -1200,7 +1202,7 @@ 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); + avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTED, 0); /* Process any request that was pending the connection to complete */ if (browsing->process_id == 0 && !g_queue_is_empty(browsing->queue)) @@ -1209,7 +1211,7 @@ static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err, return; fail: - avctp_set_state(session, AVCTP_STATE_CONNECTED); + avctp_set_state(session, AVCTP_STATE_CONNECTED, 0); if (session->browsing) { avctp_channel_destroy(session->browsing); @@ -1225,7 +1227,7 @@ static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data) GError *gerr = NULL; if (err) { - avctp_set_state(session, AVCTP_STATE_DISCONNECTED); + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EIO); error("%s", err->message); return; } @@ -1236,7 +1238,7 @@ static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data) BT_IO_OPT_IMTU, &omtu, BT_IO_OPT_INVALID); if (gerr) { - avctp_set_state(session, AVCTP_STATE_DISCONNECTED); + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EIO); error("%s", gerr->message); g_error_free(gerr); return; @@ -1269,7 +1271,7 @@ static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data) init_uinput(session); - avctp_set_state(session, AVCTP_STATE_CONNECTED); + avctp_set_state(session, AVCTP_STATE_CONNECTED, 0); } static void auth_cb(DBusError *derr, void *user_data) @@ -1286,7 +1288,7 @@ static void auth_cb(DBusError *derr, void *user_data) if (derr && dbus_error_is_set(derr)) { error("Access denied: %s", derr->message); - avctp_set_state(session, AVCTP_STATE_DISCONNECTED); + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EIO); return; } @@ -1294,7 +1296,7 @@ static void auth_cb(DBusError *derr, void *user_data) NULL, &err)) { error("bt_io_accept: %s", err->message); g_error_free(err); - avctp_set_state(session, AVCTP_STATE_DISCONNECTED); + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EIO); } } @@ -1356,10 +1358,17 @@ static void avctp_control_confirm(struct avctp *session, GIOChannel *chan, if (session->control != NULL) { error("Control: Refusing unexpected connect"); g_io_channel_shutdown(chan, TRUE, NULL); + + /* + * Close AVCTP channel if remote tried connect + * at the same time + * AVRCP SPEC V1.5 4.1.1 Connection Establishment + */ + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EAGAIN); return; } - avctp_set_state(session, AVCTP_STATE_CONNECTING); + avctp_set_state(session, AVCTP_STATE_CONNECTING, 0); session->control = avctp_channel_create(session, chan, NULL); src = btd_adapter_get_address(device_get_adapter(dev)); @@ -1382,7 +1391,7 @@ static void avctp_control_confirm(struct avctp *session, GIOChannel *chan, return; drop: - avctp_set_state(session, AVCTP_STATE_DISCONNECTED); + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EIO); } static void avctp_browsing_confirm(struct avctp *session, GIOChannel *chan, @@ -1398,7 +1407,7 @@ static void avctp_browsing_confirm(struct avctp *session, GIOChannel *chan, if (bt_io_accept(chan, avctp_connect_browsing_cb, session, NULL, &err)) { - avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING); + avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING, 0); return; } @@ -1988,7 +1997,7 @@ struct avctp *avctp_connect(struct btd_device *device) if (session->state > AVCTP_STATE_DISCONNECTED) return session; - avctp_set_state(session, AVCTP_STATE_CONNECTING); + avctp_set_state(session, AVCTP_STATE_CONNECTING, 0); src = btd_adapter_get_address(session->server->adapter); @@ -2000,7 +2009,7 @@ struct avctp *avctp_connect(struct btd_device *device) BT_IO_OPT_PSM, AVCTP_CONTROL_PSM, BT_IO_OPT_INVALID); if (err) { - avctp_set_state(session, AVCTP_STATE_DISCONNECTED); + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EIO); error("%s", err->message); g_error_free(err); return NULL; @@ -2025,7 +2034,7 @@ int avctp_connect_browsing(struct avctp *session) if (session->browsing != NULL) return 0; - avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING); + avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING, 0); src = btd_adapter_get_address(session->server->adapter); @@ -2055,7 +2064,7 @@ void avctp_disconnect(struct avctp *session) if (session->state == AVCTP_STATE_DISCONNECTED) return; - avctp_set_state(session, AVCTP_STATE_DISCONNECTED); + avctp_set_state(session, AVCTP_STATE_DISCONNECTED, -EIO); } struct avctp *avctp_get(struct btd_device *device) |