diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index 22bf35b..2a43d32 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
static void auth_cb(DBusError *derr, void *user_data);
static gboolean process_queue(gpointer user_data);
static gboolean avctp_passthrough_rsp(struct avctp *session, uint8_t code,
- uint8_t subunit, uint8_t *operands,
- size_t operand_count, void *user_data);
+ uint8_t subunit, uint8_t transaction,
+ uint8_t *operands, size_t operand_count,
+ void *user_data);
static int send_event(int fd, uint16_t type, uint16_t code, int32_t value)
{
if (p->err == 0 || req->func == NULL)
goto done;
- req->func(session, AVC_CTYPE_REJECTED, req->subunit, NULL, 0,
- req->user_data);
+ req->func(session, AVC_CTYPE_REJECTED, req->subunit, p->transaction,
+ NULL, 0, req->user_data);
done:
g_free(req->operands);
continue;
if (req->func && req->func(control->session, avc->code,
- avc->subunit_type,
- operands, operand_count,
- req->user_data))
+ avc->subunit_type, p->transaction,
+ operands, operand_count,
+ req->user_data))
return;
control->processed = g_slist_remove(control->processed, p);
}
static gboolean avctp_passthrough_rsp(struct avctp *session, uint8_t code,
- uint8_t subunit, uint8_t *operands,
- size_t operand_count, void *user_data)
+ uint8_t subunit, uint8_t transaction,
+ uint8_t *operands, size_t operand_count,
+ void *user_data)
{
if (code != AVC_CTYPE_ACCEPTED)
return FALSE;
diff --git a/profiles/audio/avctp.h b/profiles/audio/avctp.h
index 6c19ce4..68a2735 100644
--- a/profiles/audio/avctp.h
+++ b/profiles/audio/avctp.h
uint8_t *subunit, uint8_t *operands,
size_t operand_count, void *user_data);
typedef gboolean (*avctp_rsp_cb) (struct avctp *session, uint8_t code,
- uint8_t subunit, uint8_t *operands,
- size_t operand_count, void *user_data);
+ uint8_t subunit, uint8_t transaction,
+ uint8_t *operands, size_t operand_count,
+ void *user_data);
typedef gboolean (*avctp_browsing_rsp_cb) (struct avctp *session,
uint8_t *operands, size_t operand_count,
void *user_data);
diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 70c184b..6c8ed81 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
}
}
-static gboolean avrcp_get_play_status_rsp(struct avctp *conn,
- uint8_t code, uint8_t subunit,
+static gboolean avrcp_get_play_status_rsp(struct avctp *conn, uint8_t code,
+ uint8_t subunit, uint8_t transaction,
uint8_t *operands, size_t operand_count,
void *user_data)
{
}
}
-static gboolean avrcp_player_value_rsp(struct avctp *conn,
- uint8_t code, uint8_t subunit,
+static gboolean avrcp_player_value_rsp(struct avctp *conn, uint8_t code,
+ uint8_t subunit, uint8_t transaction,
uint8_t *operands, size_t operand_count,
void *user_data)
{
static gboolean avrcp_list_player_attributes_rsp(struct avctp *conn,
uint8_t code, uint8_t subunit,
- uint8_t *operands, size_t operand_count,
- void *user_data)
+ uint8_t transaction, uint8_t *operands,
+ size_t operand_count, void *user_data)
{
uint8_t attrs[AVRCP_ATTRIBUTE_LAST];
struct avrcp *session = user_data;
static gboolean avrcp_get_element_attributes_rsp(struct avctp *conn,
uint8_t code, uint8_t subunit,
+ uint8_t transaction,
uint8_t *operands,
size_t operand_count,
void *user_data)
player->uid_counter = get_be16(&pdu->params[1]);
}
-static gboolean avrcp_handle_event(struct avctp *conn,
- uint8_t code, uint8_t subunit,
+static gboolean avrcp_handle_event(struct avctp *conn, uint8_t code,
+ uint8_t subunit, uint8_t transaction,
uint8_t *operands, size_t operand_count,
void *user_data)
{
struct avrcp_header *pdu = (void *) operands;
uint8_t event;
- if ((code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED) ||
- pdu == NULL)
+ if (!pdu)
+ return FALSE;
+
+ if ((code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED)) {
+ if (pdu->params[0] == AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED &&
+ code == AVC_CTYPE_REJECTED) {
+ int i;
+
+ /* Lookup event by transaction */
+ for (i = 0; i <= AVRCP_EVENT_LAST; i++) {
+ if (session->transaction_events[i] ==
+ transaction) {
+ event = i;
+ goto changed;
+ }
+ }
+ }
return FALSE;
+ }
event = pdu->params[0];
if (code == AVC_CTYPE_CHANGED) {
- session->registered_events ^= (1 << event);
- avrcp_register_notification(session, event);
- return FALSE;
+ goto changed;
}
switch (event) {
}
session->registered_events |= (1 << event);
+ session->transaction_events[event] = transaction;
return TRUE;
+
+changed:
+ session->registered_events ^= (1 << event);
+ session->transaction_events[event] = 0;
+ avrcp_register_notification(session, event);
+ return FALSE;
}
static void avrcp_register_notification(struct avrcp *session, uint8_t event)
avrcp_handle_event, session);
}
-static gboolean avrcp_get_capabilities_resp(struct avctp *conn,
- uint8_t code, uint8_t subunit,
+static gboolean avrcp_get_capabilities_resp(struct avctp *conn, uint8_t code,
+ uint8_t subunit, uint8_t transaction,
uint8_t *operands, size_t operand_count,
void *user_data)
{
player_destroy(player);
}
-static gboolean avrcp_handle_set_volume(struct avctp *conn,
- uint8_t code, uint8_t subunit,
+static gboolean avrcp_handle_set_volume(struct avctp *conn, uint8_t code,
+ uint8_t subunit, uint8_t transaction,
uint8_t *operands, size_t operand_count,
void *user_data)
{