From dc049cf35eaba61da2a4579456020cb96972cdc9 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Sat, 1 Mar 2014 19:03:34 +0200 Subject: [PATCH] android/avrcp: Add handler for GetPlayStatus command --- android/avrcp.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/android/avrcp.c b/android/avrcp.c index 14b223b2d..fae3d38a8 100644 --- a/android/avrcp.c +++ b/android/avrcp.c @@ -37,6 +37,7 @@ #include "avctp.h" #include "avrcp-lib.h" #include "hal-msg.h" +#include "ipc-common.h" #include "ipc.h" #include "bluetooth.h" #include "avrcp.h" @@ -54,18 +55,71 @@ static GSList *devices = NULL; static GIOChannel *server = NULL; static struct ipc *hal_ipc = NULL; +struct avrcp_request { + struct avrcp_device *dev; + uint8_t pdu_id; + uint8_t transaction; +}; + struct avrcp_device { bdaddr_t dst; struct avrcp *session; GIOChannel *io; + GQueue *queue; }; +static struct avrcp_request *pop_request(uint8_t pdu_id) +{ + GSList *l; + + for (l = devices; l; l = g_slist_next(l)) { + struct avrcp_device *dev = l->data; + GList *reqs = g_queue_peek_head_link(dev->queue); + int i; + + for (i = 0; reqs; reqs = g_list_next(reqs), i++) { + struct avrcp_request *req = reqs->data; + + if (req->pdu_id == pdu_id) { + g_queue_pop_nth(dev->queue, i); + return req; + } + } + } + + return NULL; +} + static void handle_get_play_status(const void *buf, uint16_t len) { + const struct hal_cmd_avrcp_get_play_status *cmd = buf; + uint8_t status; + struct avrcp_request *req; + int ret; + DBG(""); + req = pop_request(AVRCP_GET_PLAY_STATUS); + if (!req) { + status = HAL_STATUS_FAILED; + goto done; + } + + ret = avrcp_get_play_status_rsp(req->dev->session, req->transaction, + cmd->position, cmd->duration, + cmd->status); + if (ret < 0) { + status = HAL_STATUS_FAILED; + g_free(req); + goto done; + } + + status = HAL_STATUS_SUCCESS; + g_free(req); + +done: ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, - HAL_OP_AVRCP_GET_PLAY_STATUS, HAL_STATUS_FAILED); + HAL_OP_AVRCP_GET_PLAY_STATUS, status); } static void handle_list_player_attrs(const void *buf, uint16_t len) @@ -244,6 +298,9 @@ static void avrcp_device_free(void *data) { struct avrcp_device *dev = data; + g_queue_foreach(dev->queue, (GFunc) g_free, NULL); + g_queue_free(dev->queue); + if (dev->session) avrcp_shutdown(dev->session); @@ -370,10 +427,47 @@ static ssize_t handle_get_capabilities_cmd(struct avrcp *session, return -EINVAL; } +static void push_request(struct avrcp_device *dev, uint8_t pdu_id, + uint8_t transaction) +{ + struct avrcp_request *req; + + req = g_new0(struct avrcp_request, 1); + req->dev = dev; + req->pdu_id = pdu_id; + req->transaction = transaction; + + g_queue_push_tail(dev->queue, req); +} + +static ssize_t handle_get_play_status_cmd(struct avrcp *session, + uint8_t transaction, + uint16_t params_len, + uint8_t *params, + void *user_data) +{ + struct avrcp_device *dev = user_data; + + DBG(""); + + if (params_len != 0) + return -EINVAL; + + 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); + + return -EAGAIN; +} + static const struct avrcp_control_handler control_handlers[] = { { AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS, AVC_CTYPE_STABLE, handle_get_capabilities_cmd }, + { AVRCP_GET_PLAY_STATUS, + AVC_CTYPE_STATUS, AVC_CTYPE_STABLE, + handle_get_play_status_cmd }, { }, }; @@ -430,6 +524,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data) dev); avrcp_set_control_handlers(dev->session, control_handlers, dev); + dev->queue = g_queue_new(); + /* FIXME: get the real name of the device */ avrcp_init_uinput(dev->session, "bluetooth", address); -- 2.47.3