summaryrefslogtreecommitdiff
path: root/android/avrcp.c
diff options
context:
space:
mode:
authorAndrzej Kaczmarek <andrzej.kaczmarek@tieto.com>2014-03-04 21:43:22 +0100
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2014-03-05 10:32:49 +0200
commit45aa22f0f3d672c66b9777317c12c4196a9efd86 (patch)
treed029299c28b886c1027bd8d9c08ebef64477db3b /android/avrcp.c
parent5071d7dd621b5d04720c2decec2325c5777b872d (diff)
downloadbluez-45aa22f0f3d672c66b9777317c12c4196a9efd86.tar.gz
android/avrcp: Fix RegisterNotification response handling
For INTERIM RegisterNotification response we should keep request on list since it will be needed for CHANGED response. Requests on lists shall be matched by both pdu_id and event_id since we can have multiple queued RegisterNotification requests and will need to reply with proper transaction label.
Diffstat (limited to 'android/avrcp.c')
-rw-r--r--android/avrcp.c67
1 files changed, 40 insertions, 27 deletions
diff --git a/android/avrcp.c b/android/avrcp.c
index 7bd6165f2..504ce2b68 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -60,6 +60,7 @@ static struct ipc *hal_ipc = NULL;
struct avrcp_request {
struct avrcp_device *dev;
uint8_t pdu_id;
+ uint8_t event_id;
uint8_t transaction;
};
@@ -72,7 +73,8 @@ struct avrcp_device {
GQueue *queue;
};
-static struct avrcp_request *pop_request(uint8_t pdu_id)
+static struct avrcp_request *pop_request(uint8_t pdu_id, uint8_t event_id,
+ bool peek)
{
GSList *l;
@@ -84,10 +86,13 @@ static struct avrcp_request *pop_request(uint8_t pdu_id)
for (i = 0; reqs; reqs = g_list_next(reqs), i++) {
struct avrcp_request *req = reqs->data;
- if (req->pdu_id == pdu_id) {
+ if (req->pdu_id != pdu_id || req->event_id != event_id)
+ continue;
+
+ if (!peek)
g_queue_pop_nth(dev->queue, i);
- return req;
- }
+
+ return req;
}
}
@@ -103,7 +108,7 @@ static void handle_get_play_status(const void *buf, uint16_t len)
DBG("");
- req = pop_request(AVRCP_GET_PLAY_STATUS);
+ req = pop_request(AVRCP_GET_PLAY_STATUS, 0, false);
if (!req) {
status = HAL_STATUS_FAILED;
goto done;
@@ -218,7 +223,7 @@ static void handle_get_element_attrs_text(const void *buf, uint16_t len)
DBG("");
- req = pop_request(AVRCP_GET_ELEMENT_ATTRIBUTES);
+ req = pop_request(AVRCP_GET_ELEMENT_ATTRIBUTES, 0, false);
if (!req) {
status = HAL_STATUS_FAILED;
goto done;
@@ -260,11 +265,25 @@ static void handle_register_notification(const void *buf, uint16_t len)
uint8_t pdu[IPC_MTU];
size_t pdu_len;
uint8_t code;
+ bool peek = false;
int ret;
DBG("");
- req = pop_request(AVRCP_REGISTER_NOTIFICATION);
+ switch (cmd->type) {
+ case HAL_AVRCP_EVENT_TYPE_INTERIM:
+ code = AVC_CTYPE_INTERIM;
+ peek = true;
+ break;
+ case HAL_AVRCP_EVENT_TYPE_CHANGED:
+ code = AVC_CTYPE_CHANGED;
+ break;
+ default:
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ req = pop_request(AVRCP_REGISTER_NOTIFICATION, cmd->event, peek);
if (!req) {
status = HAL_STATUS_FAILED;
goto done;
@@ -285,29 +304,19 @@ static void handle_register_notification(const void *buf, uint16_t len)
goto done;
}
- switch (cmd->type) {
- case HAL_AVRCP_EVENT_TYPE_INTERIM:
- code = AVC_CTYPE_INTERIM;
- break;
- case HAL_AVRCP_EVENT_TYPE_CHANGED:
- code = AVC_CTYPE_CHANGED;
- break;
- default:
- status = HAL_STATUS_FAILED;
- goto done;
- }
-
ret = avrcp_register_notification_rsp(req->dev->session,
req->transaction, code,
pdu, pdu_len);
if (ret < 0) {
status = HAL_STATUS_FAILED;
- g_free(req);
+ if (!peek)
+ g_free(req);
goto done;
}
status = HAL_STATUS_SUCCESS;
- g_free(req);
+ if (!peek)
+ g_free(req);
done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
@@ -556,13 +565,14 @@ static ssize_t handle_get_capabilities_cmd(struct avrcp *session,
}
static void push_request(struct avrcp_device *dev, uint8_t pdu_id,
- uint8_t transaction)
+ uint8_t event_id, uint8_t transaction)
{
struct avrcp_request *req;
req = g_new0(struct avrcp_request, 1);
req->dev = dev;
req->pdu_id = pdu_id;
+ req->event_id = event_id;
req->transaction = transaction;
g_queue_push_tail(dev->queue, req);
@@ -584,7 +594,7 @@ static ssize_t handle_get_play_status_cmd(struct avrcp *session,
ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
HAL_EV_AVRCP_GET_PLAY_STATUS, 0, NULL);
- push_request(dev, AVRCP_GET_PLAY_STATUS, transaction);
+ push_request(dev, AVRCP_GET_PLAY_STATUS, 0, transaction);
return -EAGAIN;
}
@@ -620,7 +630,7 @@ static ssize_t handle_get_element_attrs_cmd(struct avrcp *session,
HAL_EV_AVRCP_GET_ELEMENT_ATTRS,
sizeof(*ev) + ev->number, ev);
- push_request(dev, AVRCP_GET_ELEMENT_ATTRIBUTES, transaction);
+ push_request(dev, AVRCP_GET_ELEMENT_ATTRIBUTES, 0, transaction);
return -EAGAIN;
@@ -634,14 +644,17 @@ static ssize_t handle_register_notification_cmd(struct avrcp *session,
{
struct avrcp_device *dev = user_data;
struct hal_ev_avrcp_register_notification ev;
+ uint8_t event_id;
DBG("");
if (params_len != 5)
return -EINVAL;
+ event_id = params[0];
+
/* TODO: Add any missing events supported by Android */
- switch (params[0]) {
+ switch (event_id) {
case AVRCP_EVENT_STATUS_CHANGED:
case AVRCP_EVENT_TRACK_CHANGED:
case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
@@ -650,14 +663,14 @@ static ssize_t handle_register_notification_cmd(struct avrcp *session,
return -EINVAL;
}
- ev.event = params[0];
+ ev.event = event_id;
ev.param = bt_get_be32(&params[1]);
ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP,
HAL_EV_AVRCP_REGISTER_NOTIFICATION,
sizeof(ev), &ev);
- push_request(dev, AVRCP_REGISTER_NOTIFICATION, transaction);
+ push_request(dev, AVRCP_REGISTER_NOTIFICATION, event_id, transaction);
return -EAGAIN;
}